mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
Merge branch 'dev_' into dev_no_master_thermostat
This commit is contained in:
70
CHANGELOG.md
70
CHANGELOG.md
@@ -5,6 +5,76 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
# [3.3.1] January 20 2022
|
||||||
|
|
||||||
|
- lastcode broke MQTT JSON structure [#228](https://github.com/emsesp/EMS-ESP32/issues/228)
|
||||||
|
- overlapping while reading sequence of EMS1.0 telegrams
|
||||||
|
- redundant telegram readings (because of offset overflow)
|
||||||
|
- added missing RC30/Moduline400 [#243](https://github.com/emsesp/EMS-ESP32/issues/243)
|
||||||
|
- check received status before toggling fetch on empty telegram [#268][#282]
|
||||||
|
|
||||||
|
# [3.3.0] November 28 2021
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- Add system commands for syslog level and watch [#98](https://github.com/emsesp/EMS-ESP32/issues/98)
|
||||||
|
- Added pool data to telegrams 0x494 & 0x495 [#102](https://github.com/emsesp/EMS-ESP32/issues/102)
|
||||||
|
- Add RC300 second summermode telegram [#108](https://github.com/emsesp/EMS-ESP32/issues/108)
|
||||||
|
- Add support for the RC25 thermostat [#106](https://github.com/emsesp/EMS-ESP32/issues/106)
|
||||||
|
- Add new command 'entities' for a device, e.g. http://ems-esp/api/boiler/entities to show the shortname, description and HA Entity name (if HA enabled) [#116](https://github.com/emsesp/EMS-ESP32/issues/116)
|
||||||
|
- Support for Junkers program and remote (fb10/fb110) temperature
|
||||||
|
- Home Assistant `state_class` attribute for Wh, kWh, W and KW [#129](https://github.com/emsesp/EMS-ESP32/issues/129)
|
||||||
|
- Add current room influence for RC300 [#136](https://github.com/emsesp/EMS-ESP32/issues/136)
|
||||||
|
- Added Home Assistant device_class to sensor entities
|
||||||
|
- Added another Buderus RC10 thermostat with Product ID 65 [#160](https://github.com/emsesp/EMS-ESP32/issues/160)
|
||||||
|
- Added support for mDNS [#161](https://github.com/emsesp/EMS-ESP32/issues/161)
|
||||||
|
- Added last system ESP32 reset code to log (and `system info` output)
|
||||||
|
- Firmware Checker in WebUI [#168](https://github.com/emsesp/EMS-ESP32/issues/168)
|
||||||
|
- Added new MQTT setting for enabling 'response' topic
|
||||||
|
- Support for non-standard Thermostats like Tado [#174](https://github.com/emsesp/EMS-ESP32/issues/174)
|
||||||
|
- Include MQTT connection status in 'api/system/info'
|
||||||
|
- Include Network status in 'api/system/info' and also the MQTT topic `info` [#202](https://github.com/emsesp/EMS-ESP32/issues/202)
|
||||||
|
- Added Ethernet PHY module as an option in the Board Profile [#210](https://github.com/emsesp/EMS-ESP32/issues/210)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- MQTT reconnecting after WiFi reconnect [#99](https://github.com/emsesp/EMS-ESP32/issues/99)
|
||||||
|
- Manually Controlling Solar Circuit [#107](https://github.com/emsesp/EMS-ESP32/issues/107)
|
||||||
|
- Fix thermostat commands not defaulting to the master thermostat [#110](https://github.com/emsesp/EMS-ESP32/issues/110)
|
||||||
|
- Enlarge parse-buffer for long names like `cylinderpumpmodulation`
|
||||||
|
- MQTT not subscribing to all device entities [#166](https://github.com/emsesp/EMS-ESP32/issues/166)
|
||||||
|
- Help fix issues with WebUI unable to fully load UI over Ethernet [#177](https://github.com/emsesp/EMS-ESP32/issues/177)
|
||||||
|
- Shower alert never reset after limit reached when enabled [(PR #185)]
|
||||||
|
- Remove HA entity entries when a device value goes dormant [#196](https://github.com/emsesp/EMS-ESP32/issues/196)
|
||||||
|
- deciphering last error code dates on 0xC2 telegram [#204](https://github.com/emsesp/EMS-ESP32/issues/204)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- Syslog BOM only for utf-8 messages [#91](https://github.com/emsesp/EMS-ESP32/issues/91)
|
||||||
|
- Check for KM200 by device-id 0x48, remove tx-delay [#90](https://github.com/emsesp/EMS-ESP32/issues/90)
|
||||||
|
- rename `fastheatupfactor` to `fastheatup` and add percent [#122](https://github.com/emsesp/EMS-ESP32/issues/122)
|
||||||
|
- "unit" renamed to "uom" in API call to recall a Device Value
|
||||||
|
- initial backend React changes to replace the class components (HOCs) with React Hooks
|
||||||
|
- Use program-names instead of numbers
|
||||||
|
- Boiler's maintenancemessage always published in MQTT (to prevent HA missing entity)
|
||||||
|
- Unit of Measure 'times' added to MQTT Fails, Rx fails, Rx received, Tx fails, Tx reads & Tx writes
|
||||||
|
- Improved API. Restful HTTP API works in the same way as MQTT calls
|
||||||
|
- Removed settings for MQTT subscribe format [#173](https://github.com/emsesp/EMS-ESP32/issues/173)
|
||||||
|
- Improve Nefit Moduline 200 functionality [#183](https://github.com/emsesp/EMS-ESP32/issues/183)
|
||||||
|
- `status` in the MQTT heartbeat renamed to `bus_status`
|
||||||
|
- Layout changes in the WebUI, showing stripped table rows in Dashboard
|
||||||
|
- Alternative font for log window [#219](https://github.com/emsesp/EMS-ESP32/issues/219)
|
||||||
|
|
||||||
|
## **BREAKING CHANGES**
|
||||||
|
|
||||||
|
- API: "unit" renamed to "uom" in API call to recall a Device Value
|
||||||
|
- HA: `sensor.boiler_boiler_temperature` renamed to `sensor.actual_boiler_temperature`
|
||||||
|
- HA: `binary_sensor.boiler_ww_disinfecting` renamed to `binary_sensor.boiler_ww_disinfection`
|
||||||
|
- HA: # removed from counts in MQTT Fails, Rx fails, Rx received, Tx fails, Tx reads & Tx writes
|
||||||
|
- `txread` renamed to `txreads` and `txwrite` renamed to `txwrites` in MQTT heartbeat payload
|
||||||
|
- 'dallas sensors' in api/system/info moved to the "System" section. Renamed "uptime (seconds)" and "reset reason"
|
||||||
|
- `status` in the MQTT heartbeat renamed to `bus_status`
|
||||||
|
|
||||||
# [3.2.1] August 8 2021
|
# [3.2.1] August 8 2021
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|||||||
@@ -26,6 +26,15 @@
|
|||||||
- remove MQTT retained configs if discovery is disabled
|
- remove MQTT retained configs if discovery is disabled
|
||||||
- timeout 10 min for MQTT-QoS wait
|
- timeout 10 min for MQTT-QoS wait
|
||||||
- Moduline 300 auto-temperatures T1-T4, RC300 romminfluencefactor
|
- Moduline 300 auto-temperatures T1-T4, RC300 romminfluencefactor
|
||||||
|
- RC35 parameters [#392](https://github.com/emsesp/EMS-ESP32/issues/392), [#398](https://github.com/emsesp/EMS-ESP32/issues/398)
|
||||||
|
- sync time with thermostat [#386](https://github.com/emsesp/EMS-ESP32/issues/386), [#408](https://github.com/emsesp/EMS-ESP32/issues/408)
|
||||||
|
- set mode has immediate effect [#395](https://github.com/emsesp/EMS-ESP32/issues/395)
|
||||||
|
- min/max in web value setting
|
||||||
|
- Extend customization to select if an entity is to be shown in the WebUI or forced as read-only [#317](https://github.com/emsesp/EMS-ESP32/issues/317)
|
||||||
|
- Added Moduline 400 installation parameters [PR #449 by @kwertie01](https://github.com/emsesp/EMS-ESP32/pull/449)
|
||||||
|
- Read time from IVT-controller [#439](https://github.com/emsesp/EMS-ESP32/issues/439)
|
||||||
|
- Hybrid Heatpump product-id 168 [#459](https://github.com/emsesp/EMS-ESP32/issues/459), thermostat settings
|
||||||
|
- Junkers ISM2 and IPM in warm water mode [#437](https://github.com/emsesp/EMS-ESP32/issues/437)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
@@ -43,6 +52,7 @@
|
|||||||
- Non-nested MQTT would corrupt the json [#354](https://github.com/emsesp/EMS-ESP32/issues/354)
|
- Non-nested MQTT would corrupt the json [#354](https://github.com/emsesp/EMS-ESP32/issues/354)
|
||||||
- Burner selected max power can have a value higher than 100% [#314](https://github.com/emsesp/EMS-ESP32/issues/314)
|
- Burner selected max power can have a value higher than 100% [#314](https://github.com/emsesp/EMS-ESP32/issues/314)
|
||||||
- some missing fahrenheit calculations
|
- some missing fahrenheit calculations
|
||||||
|
- limited number of exclusions [#339](https://github.com/emsesp/EMS-ESP32/issues/339)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
@@ -59,6 +69,9 @@
|
|||||||
- removed system/pin command, new commands in analogsensors
|
- removed system/pin command, new commands in analogsensors
|
||||||
- system/info device-info split to name/version/brand
|
- system/info device-info split to name/version/brand
|
||||||
- remove master-thermostat
|
- remove master-thermostat
|
||||||
|
- exclude list uses short-names, possible flags for web/api/mqtt excludes, readonly and favorite (selection not yet implemented)
|
||||||
|
- thermostat clock formate date-time: dd.mm.yyyy hh:mm
|
||||||
|
- RC300 summermode as other thermostats `winter/summer` instead of `off/on`
|
||||||
|
|
||||||
## **BREAKING CHANGES:**
|
## **BREAKING CHANGES:**
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ This project is the specifically for the ESP32. Compared with the previous ESP82
|
|||||||
[](https://github.com/emsesp/EMS-ESP32/blob/main/CHANGELOG.md)
|
[](https://github.com/emsesp/EMS-ESP32/blob/main/CHANGELOG.md)
|
||||||
[](https://github.com/emsesp/EMS-ESP32/commits/main)
|
[](https://github.com/emsesp/EMS-ESP32/commits/main)
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
[](https://sonarcloud.io/summary/new_code?id=emsesp_EMS-ESP32)
|
||||||
[](https://www.codacy.com/gh/emsesp/EMS-ESP32/dashboard?utm_source=github.com&utm_medium=referral&utm_content=emsesp/EMS-ESP32&utm_campaign=Badge_Grade)
|
[](https://www.codacy.com/gh/emsesp/EMS-ESP32/dashboard?utm_source=github.com&utm_medium=referral&utm_content=emsesp/EMS-ESP32&utm_campaign=Badge_Grade)
|
||||||
[](https://github.com/emsesp/EMS-ESP32/releases)
|
[](https://github.com/emsesp/EMS-ESP32/releases)
|
||||||
[](https://discord.gg/3J3GgnzpyT)
|
[](https://discord.gg/3J3GgnzpyT)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ build_flags =
|
|||||||
-D FACTORY_MQTT_PASSWORD=\"\"
|
-D FACTORY_MQTT_PASSWORD=\"\"
|
||||||
-D FACTORY_MQTT_CLIENT_ID=\"ems-esp\"
|
-D FACTORY_MQTT_CLIENT_ID=\"ems-esp\"
|
||||||
-D FACTORY_MQTT_KEEP_ALIVE=60
|
-D FACTORY_MQTT_KEEP_ALIVE=60
|
||||||
-D FACTORY_MQTT_CLEAN_SESSION=true
|
-D FACTORY_MQTT_CLEAN_SESSION=false
|
||||||
-D FACTORY_MQTT_MAX_TOPIC_LENGTH=128
|
-D FACTORY_MQTT_MAX_TOPIC_LENGTH=128
|
||||||
|
|
||||||
; JWT Secret
|
; JWT Secret
|
||||||
|
|||||||
3212
interface/package-lock.json
generated
3212
interface/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,32 +4,32 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"proxy": "http://localhost:3080",
|
"proxy": "http://localhost:3080",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.8.1",
|
"@emotion/react": "^11.9.0",
|
||||||
"@emotion/styled": "^11.8.1",
|
"@emotion/styled": "^11.8.1",
|
||||||
"@msgpack/msgpack": "^2.7.2",
|
"@msgpack/msgpack": "^2.7.2",
|
||||||
"@mui/icons-material": "^5.5.0",
|
"@mui/icons-material": "^5.6.0",
|
||||||
"@mui/material": "^5.5.0",
|
"@mui/material": "^5.6.0",
|
||||||
"@types/lodash": "^4.14.179",
|
"@types/lodash": "^4.14.181",
|
||||||
"@types/node": "^17.0.21",
|
"@types/node": "^17.0.23",
|
||||||
"@types/react": "^17.0.40",
|
"@types/react": "^17.0.43",
|
||||||
"@types/react-dom": "^17.0.13",
|
"@types/react-dom": "^17.0.14",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"async-validator": "^4.0.7",
|
"async-validator": "^4.0.7",
|
||||||
"axios": "^0.26.1",
|
"axios": "^0.26.1",
|
||||||
"http-proxy-middleware": "^2.0.3",
|
"http-proxy-middleware": "^2.0.4",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"notistack": "^2.0.3",
|
"notistack": "^2.0.3",
|
||||||
"parse-ms": "^3.0.0",
|
"parse-ms": "^3.0.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-app-rewired": "^2.2.1",
|
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-app-rewired": "^2.2.1",
|
||||||
"react-dropzone": "^12.0.4",
|
"react-dropzone": "^12.0.4",
|
||||||
"react-icons": "^4.3.1",
|
"react-icons": "^4.3.1",
|
||||||
"react-router-dom": "^6.2.2",
|
"react-router-dom": "^6.3.0",
|
||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.0",
|
||||||
"sockette": "^2.0.6",
|
"sockette": "^2.0.6",
|
||||||
"typescript": "^4.6.2"
|
"typescript": "^4.6.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-app-rewired start",
|
"start": "react-app-rewired start",
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
control={<Checkbox name="send_response" checked={data.send_response} onChange={updateFormValue} />}
|
control={<Checkbox name="send_response" checked={data.send_response} onChange={updateFormValue} />}
|
||||||
label="Publish command output to a 'response' topic"
|
label="Publish command output to a 'response' topic"
|
||||||
/>
|
/>
|
||||||
|
{!data.ha_enabled && (
|
||||||
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
@@ -201,6 +202,8 @@ const MqttSettingsForm: FC = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
)}
|
||||||
|
{!data.publish_single && (
|
||||||
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
@@ -222,6 +225,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
)}
|
||||||
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
||||||
Publish Intervals (in seconds, 0=automatic)
|
Publish Intervals (in seconds, 0=automatic)
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -32,11 +32,14 @@ import { extractErrorMessage, formatDateTime, formatLocalDateTime, useRest } fro
|
|||||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||||
|
|
||||||
export const isNtpActive = ({ status }: NTPStatus) => status === NTPSyncStatus.NTP_ACTIVE;
|
export const isNtpActive = ({ status }: NTPStatus) => status === NTPSyncStatus.NTP_ACTIVE;
|
||||||
|
export const isNtpEnabled = ({ status }: NTPStatus) => status !== NTPSyncStatus.NTP_DISABLED;
|
||||||
|
|
||||||
export const ntpStatusHighlight = ({ status }: NTPStatus, theme: Theme) => {
|
export const ntpStatusHighlight = ({ status }: NTPStatus, theme: Theme) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case NTPSyncStatus.NTP_INACTIVE:
|
case NTPSyncStatus.NTP_DISABLED:
|
||||||
return theme.palette.info.main;
|
return theme.palette.info.main;
|
||||||
|
case NTPSyncStatus.NTP_INACTIVE:
|
||||||
|
return theme.palette.error.main;
|
||||||
case NTPSyncStatus.NTP_ACTIVE:
|
case NTPSyncStatus.NTP_ACTIVE:
|
||||||
return theme.palette.success.main;
|
return theme.palette.success.main;
|
||||||
default:
|
default:
|
||||||
@@ -46,6 +49,8 @@ export const ntpStatusHighlight = ({ status }: NTPStatus, theme: Theme) => {
|
|||||||
|
|
||||||
export const ntpStatus = ({ status }: NTPStatus) => {
|
export const ntpStatus = ({ status }: NTPStatus) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
case NTPSyncStatus.NTP_DISABLED:
|
||||||
|
return 'Disabled';
|
||||||
case NTPSyncStatus.NTP_INACTIVE:
|
case NTPSyncStatus.NTP_INACTIVE:
|
||||||
return 'Inactive';
|
return 'Inactive';
|
||||||
case NTPSyncStatus.NTP_ACTIVE:
|
case NTPSyncStatus.NTP_ACTIVE:
|
||||||
@@ -143,7 +148,7 @@ const NTPStatusForm: FC = () => {
|
|||||||
<ListItemText primary="Status" secondary={ntpStatus(data)} />
|
<ListItemText primary="Status" secondary={ntpStatus(data)} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
{isNtpActive(data) && (
|
{isNtpEnabled(data) && (
|
||||||
<>
|
<>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const UserForm: FC<UserFormProps> = ({ creating, validator, user, setUser, onDon
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog onClose={onCancelEditing} aria-labelledby="user-form-dialog-title" open={!!user} fullWidth maxWidth="sm">
|
<Dialog onClose={onCancelEditing} open={!!user} fullWidth maxWidth="sm">
|
||||||
{user && (
|
{user && (
|
||||||
<>
|
<>
|
||||||
<DialogTitle id="user-form-dialog-title">{creating ? 'Add' : 'Modify'} User</DialogTitle>
|
<DialogTitle id="user-form-dialog-title">{creating ? 'Add' : 'Modify'} User</DialogTitle>
|
||||||
|
|||||||
@@ -13,13 +13,14 @@ const FirmwareFileUpload: FC<UploadFirmwareProps> = ({ uploadFirmware }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{!uploading && (
|
||||||
<MessageBox
|
<MessageBox
|
||||||
message="Upload a new firmware (.bin) file below to replace the existing firmware"
|
message="Upload a new firmware (.bin) file below to replace the existing firmware"
|
||||||
level="warning"
|
level="warning"
|
||||||
my={2}
|
my={2}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
<SingleUpload
|
<SingleUpload
|
||||||
// accept="application/octet-stream"
|
|
||||||
accept=".bin"
|
accept=".bin"
|
||||||
onDrop={uploadFile}
|
onDrop={uploadFile}
|
||||||
onCancel={cancelUpload}
|
onCancel={cancelUpload}
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ import CancelIcon from '@mui/icons-material/Cancel';
|
|||||||
import SendIcon from '@mui/icons-material/TrendingFlat';
|
import SendIcon from '@mui/icons-material/TrendingFlat';
|
||||||
import SaveIcon from '@mui/icons-material/Save';
|
import SaveIcon from '@mui/icons-material/Save';
|
||||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
||||||
|
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
|
||||||
|
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
||||||
|
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
|
||||||
|
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
||||||
|
|
||||||
import DeviceIcon from './DeviceIcon';
|
import DeviceIcon from './DeviceIcon';
|
||||||
|
|
||||||
@@ -62,7 +66,8 @@ import {
|
|||||||
AnalogType,
|
AnalogType,
|
||||||
AnalogTypeNames,
|
AnalogTypeNames,
|
||||||
Sensor,
|
Sensor,
|
||||||
Analog
|
Analog,
|
||||||
|
DeviceEntityMask
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
||||||
@@ -153,6 +158,8 @@ const DashboardData: FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isCmdOnly = (dv: DeviceValue) => dv.v === undefined && dv.c;
|
||||||
|
|
||||||
function formatValue(value: any, uom: number) {
|
function formatValue(value: any, uom: number) {
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
return '';
|
return '';
|
||||||
@@ -213,12 +220,12 @@ const DashboardData: FC = () => {
|
|||||||
if (deviceValue) {
|
if (deviceValue) {
|
||||||
return (
|
return (
|
||||||
<Dialog open={deviceValue !== undefined} onClose={() => setDeviceValue(undefined)}>
|
<Dialog open={deviceValue !== undefined} onClose={() => setDeviceValue(undefined)}>
|
||||||
<DialogTitle>Change Value</DialogTitle>
|
<DialogTitle>{isCmdOnly(deviceValue) ? 'Run Command' : 'Change Value'}</DialogTitle>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
{deviceValue.l && (
|
{deviceValue.l && (
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
name="v"
|
name="v"
|
||||||
label={deviceValue.n}
|
label={deviceValue.n.slice(2)}
|
||||||
value={deviceValue.v}
|
value={deviceValue.v}
|
||||||
autoFocus
|
autoFocus
|
||||||
sx={{ width: '30ch' }}
|
sx={{ width: '30ch' }}
|
||||||
@@ -233,13 +240,13 @@ const DashboardData: FC = () => {
|
|||||||
{!deviceValue.l && (
|
{!deviceValue.l && (
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
name="v"
|
name="v"
|
||||||
label={deviceValue.n}
|
label={deviceValue.n.slice(2)}
|
||||||
value={deviceValue.u ? numberValue(deviceValue.v) : deviceValue.v}
|
value={deviceValue.u ? numberValue(deviceValue.v) : deviceValue.v}
|
||||||
autoFocus
|
autoFocus
|
||||||
sx={{ width: '30ch' }}
|
sx={{ width: '30ch' }}
|
||||||
type={deviceValue.u ? 'number' : 'text'}
|
type={deviceValue.u ? 'number' : 'text'}
|
||||||
onChange={updateValue(setDeviceValue)}
|
onChange={updateValue(setDeviceValue)}
|
||||||
inputProps={{ step: deviceValue.s }}
|
inputProps={deviceValue.u ? { min: deviceValue.m, max: deviceValue.x, step: deviceValue.s } : {}}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
startAdornment: <InputAdornment position="start">{DeviceValueUOM_s[deviceValue.u]}</InputAdornment>
|
startAdornment: <InputAdornment position="start">{DeviceValueUOM_s[deviceValue.u]}</InputAdornment>
|
||||||
}}
|
}}
|
||||||
@@ -485,26 +492,24 @@ const DashboardData: FC = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hasMask = (entityName: string, mask: number) => (parseInt(entityName.slice(0, 2), 16) & mask) === mask;
|
||||||
|
|
||||||
const sendCommand = (dv: DeviceValue) => {
|
const sendCommand = (dv: DeviceValue) => {
|
||||||
if (dv.c && me.admin) {
|
if (dv.c && me.admin && !hasMask(dv.n, DeviceEntityMask.DV_READONLY)) {
|
||||||
setDeviceValue(dv);
|
setDeviceValue(dv);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderNameCell = (dv: DeviceValue) => {
|
const renderNameCell = (dv: DeviceValue) => (
|
||||||
if (dv.v === undefined && dv.c) {
|
<>
|
||||||
return (
|
{dv.n.slice(2)}
|
||||||
<StyledTableCell component="th" scope="row" sx={{ color: 'yellow' }}>
|
{hasMask(dv.n, DeviceEntityMask.DV_FAVORITE) && <FavoriteBorderIcon color="success" sx={{ fontSize: 12 }} />}
|
||||||
command: {dv.n}
|
{hasMask(dv.n, DeviceEntityMask.DV_READONLY) && <EditOffOutlinedIcon color="primary" sx={{ fontSize: 12 }} />}
|
||||||
</StyledTableCell>
|
{hasMask(dv.n, DeviceEntityMask.DV_API_MQTT_EXCLUDE) && (
|
||||||
|
<CommentsDisabledOutlinedIcon color="primary" sx={{ fontSize: 12 }} />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
return (
|
|
||||||
<StyledTableCell component="th" scope="row">
|
|
||||||
{dv.n}
|
|
||||||
</StyledTableCell>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -515,7 +520,7 @@ const DashboardData: FC = () => {
|
|||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<StyledTableCell padding="checkbox" style={{ width: 18 }}></StyledTableCell>
|
<StyledTableCell padding="checkbox" style={{ width: 18 }}></StyledTableCell>
|
||||||
<StyledTableCell align="left">ENTITY NAME/COMMAND</StyledTableCell>
|
<StyledTableCell align="left">ENTITY NAME</StyledTableCell>
|
||||||
<StyledTableCell align="right">VALUE</StyledTableCell>
|
<StyledTableCell align="right">VALUE</StyledTableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
@@ -523,14 +528,18 @@ const DashboardData: FC = () => {
|
|||||||
{deviceData.data.map((dv, i) => (
|
{deviceData.data.map((dv, i) => (
|
||||||
<StyledTableRow key={i} onClick={() => sendCommand(dv)}>
|
<StyledTableRow key={i} onClick={() => sendCommand(dv)}>
|
||||||
<StyledTableCell padding="checkbox">
|
<StyledTableCell padding="checkbox">
|
||||||
{dv.c && me.admin && (
|
{dv.c && me.admin && !hasMask(dv.n, DeviceEntityMask.DV_READONLY) && (
|
||||||
<IconButton size="small" aria-label="Edit">
|
<IconButton size="small">
|
||||||
<EditIcon color="primary" fontSize="small" />
|
<EditIcon color="primary" fontSize="small" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
</StyledTableCell>
|
</StyledTableCell>
|
||||||
|
<StyledTableCell component="th" scope="row">
|
||||||
{renderNameCell(dv)}
|
{renderNameCell(dv)}
|
||||||
<StyledTableCell align="right">{formatValue(dv.v, dv.u)}</StyledTableCell>
|
</StyledTableCell>
|
||||||
|
<StyledTableCell align="right">
|
||||||
|
{isCmdOnly(dv) ? <PlayArrowIcon color="primary" sx={{ fontSize: 14 }} /> : formatValue(dv.v, dv.u)}
|
||||||
|
</StyledTableCell>
|
||||||
</StyledTableRow>
|
</StyledTableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
@@ -569,7 +578,7 @@ const DashboardData: FC = () => {
|
|||||||
<StyledTableRow key={sensor_data.n} onClick={() => updateSensor(sensor_data)}>
|
<StyledTableRow key={sensor_data.n} onClick={() => updateSensor(sensor_data)}>
|
||||||
<StyledTableCell padding="checkbox">
|
<StyledTableCell padding="checkbox">
|
||||||
{me.admin && (
|
{me.admin && (
|
||||||
<IconButton edge="start" size="small" aria-label="Edit">
|
<IconButton edge="start" size="small">
|
||||||
<EditIcon color="primary" fontSize="small" />
|
<EditIcon color="primary" fontSize="small" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
@@ -605,7 +614,7 @@ const DashboardData: FC = () => {
|
|||||||
<StyledTableRow key={analog_data.i} onClick={() => updateAnalog(analog_data)}>
|
<StyledTableRow key={analog_data.i} onClick={() => updateAnalog(analog_data)}>
|
||||||
<StyledTableCell padding="checkbox">
|
<StyledTableCell padding="checkbox">
|
||||||
{me.admin && (
|
{me.admin && (
|
||||||
<IconButton edge="start" size="small" aria-label="Edit">
|
<IconButton edge="start" size="small">
|
||||||
<EditIcon color="primary" fontSize="small" />
|
<EditIcon color="primary" fontSize="small" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import {
|
|||||||
Dialog,
|
Dialog,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle
|
DialogTitle,
|
||||||
|
ToggleButton,
|
||||||
|
ToggleButtonGroup
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
|
|
||||||
import TableCell, { tableCellClasses } from '@mui/material/TableCell';
|
import TableCell, { tableCellClasses } from '@mui/material/TableCell';
|
||||||
@@ -22,8 +24,11 @@ import { styled } from '@mui/material/styles';
|
|||||||
import { useSnackbar } from 'notistack';
|
import { useSnackbar } from 'notistack';
|
||||||
|
|
||||||
import SaveIcon from '@mui/icons-material/Save';
|
import SaveIcon from '@mui/icons-material/Save';
|
||||||
import CloseIcon from '@mui/icons-material/Close';
|
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
|
||||||
|
import FavoriteBorderOutlinedIcon from '@mui/icons-material/FavoriteBorderOutlined';
|
||||||
|
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
|
||||||
|
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
||||||
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
|
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
|
||||||
|
|
||||||
import { ButtonRow, FormLoader, ValidatedTextField, SectionContent } from '../components';
|
import { ButtonRow, FormLoader, ValidatedTextField, SectionContent } from '../components';
|
||||||
@@ -36,12 +41,7 @@ import { DeviceShort, Devices, DeviceEntity } from './types';
|
|||||||
|
|
||||||
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
||||||
[`&.${tableCellClasses.head}`]: {
|
[`&.${tableCellClasses.head}`]: {
|
||||||
backgroundColor: '#607d8b',
|
backgroundColor: '#607d8b'
|
||||||
color: theme.palette.common.white,
|
|
||||||
fontSize: 11
|
|
||||||
},
|
|
||||||
[`&.${tableCellClasses.body}`]: {
|
|
||||||
fontSize: 11
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -54,6 +54,9 @@ const SettingsCustomization: FC = () => {
|
|||||||
const [selectedDevice, setSelectedDevice] = useState<number>(0);
|
const [selectedDevice, setSelectedDevice] = useState<number>(0);
|
||||||
const [confirmReset, setConfirmReset] = useState<boolean>(false);
|
const [confirmReset, setConfirmReset] = useState<boolean>(false);
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
const [masks, setMasks] = useState(() => ['']);
|
||||||
|
|
||||||
const fetchDevices = useCallback(async () => {
|
const fetchDevices = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setDevices((await EMSESP.readDevices()).data);
|
setDevices((await EMSESP.readDevices()).data);
|
||||||
@@ -62,9 +65,14 @@ const SettingsCustomization: FC = () => {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const setInitialMask = (data: DeviceEntity[]) => {
|
||||||
|
setDeviceEntities(data.map((de) => ({ ...de, om: de.m })));
|
||||||
|
};
|
||||||
|
|
||||||
const fetchDeviceEntities = async (unique_id: number) => {
|
const fetchDeviceEntities = async (unique_id: number) => {
|
||||||
try {
|
try {
|
||||||
setDeviceEntities((await EMSESP.readDeviceEntities({ id: unique_id })).data);
|
const data = (await EMSESP.readDeviceEntities({ id: unique_id })).data;
|
||||||
|
setInitialMask(data);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
setErrorMessage(extractErrorMessage(error, 'Problem fetching device entities'));
|
setErrorMessage(extractErrorMessage(error, 'Problem fetching device entities'));
|
||||||
}
|
}
|
||||||
@@ -109,8 +117,22 @@ const SettingsCustomization: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box color="warning.main">
|
<Box color="warning.main">
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">Select a device and customize each of its entities using the options:</Typography>
|
||||||
Customize which entities to exclude from all all services (MQTT, API). This will have immediate effect.
|
<Typography mt={1} ml={2} display="block" variant="body2" sx={{ alignItems: 'center', display: 'flex' }}>
|
||||||
|
<FavoriteBorderOutlinedIcon color="success" sx={{ fontSize: 13 }} />
|
||||||
|
mark it as favorite to be listed at the top of the Dashboard
|
||||||
|
</Typography>
|
||||||
|
<Typography ml={2} display="block" variant="body2" sx={{ alignItems: 'center', display: 'flex' }}>
|
||||||
|
<EditOffOutlinedIcon color="secondary" sx={{ fontSize: 13 }} />
|
||||||
|
make it read-only, only if it has write operation available
|
||||||
|
</Typography>
|
||||||
|
<Typography ml={2} display="block" variant="body2" sx={{ alignItems: 'center', display: 'flex' }}>
|
||||||
|
<CommentsDisabledOutlinedIcon color="secondary" sx={{ fontSize: 13 }} />
|
||||||
|
excluded it from MQTT and API outputs
|
||||||
|
</Typography>
|
||||||
|
<Typography ml={2} mb={1} display="block" variant="body2" sx={{ alignItems: 'center', display: 'flex' }}>
|
||||||
|
<VisibilityOffOutlinedIcon color="secondary" sx={{ fontSize: 13 }} />
|
||||||
|
hide it from the Dashboard
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
@@ -138,11 +160,22 @@ const SettingsCustomization: FC = () => {
|
|||||||
|
|
||||||
const saveCustomization = async () => {
|
const saveCustomization = async () => {
|
||||||
if (deviceEntities && selectedDevice) {
|
if (deviceEntities && selectedDevice) {
|
||||||
const exclude_entities = deviceEntities.filter((de) => de.x).map((new_de) => new_de.i);
|
const masked_entities = deviceEntities
|
||||||
|
.filter((de) => de.m !== de.om)
|
||||||
|
.map((new_de) => new_de.m.toString(16).padStart(2, '0') + new_de.s);
|
||||||
|
|
||||||
|
if (masked_entities.length > 50) {
|
||||||
|
enqueueSnackbar(
|
||||||
|
'Too many selected entities (' + masked_entities.length + '). Limit is 50. Please Save in batches',
|
||||||
|
{ variant: 'warning' }
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await EMSESP.writeExcludeEntities({
|
const response = await EMSESP.writeMaskedEntities({
|
||||||
id: selectedDevice,
|
id: selectedDevice,
|
||||||
entity_ids: exclude_entities
|
entity_ids: masked_entities
|
||||||
});
|
});
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
enqueueSnackbar('Customization saved', { variant: 'success' });
|
enqueueSnackbar('Customization saved', { variant: 'success' });
|
||||||
@@ -152,6 +185,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, 'Problem sending entity list'), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, 'Problem sending entity list'), { variant: 'error' });
|
||||||
}
|
}
|
||||||
|
setInitialMask(deviceEntities);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -160,48 +194,76 @@ const SettingsCustomization: FC = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggleDeviceEntity = (id: number) => {
|
const setMask = (de: DeviceEntity, newMask: string[]) => {
|
||||||
setDeviceEntities(
|
var new_mask = 0;
|
||||||
deviceEntities.map((o) => {
|
for (let entry of newMask) {
|
||||||
if (o.i === id) {
|
new_mask |= Number(entry);
|
||||||
return { ...o, x: !o.x };
|
|
||||||
}
|
}
|
||||||
return o;
|
de.m = new_mask;
|
||||||
})
|
setMasks(newMask);
|
||||||
);
|
};
|
||||||
|
|
||||||
|
const getMask = (de: DeviceEntity) => {
|
||||||
|
var new_masks = [];
|
||||||
|
if ((de.m & 1) === 1 || de.n === '') {
|
||||||
|
new_masks.push('1');
|
||||||
|
}
|
||||||
|
if ((de.m & 2) === 2) {
|
||||||
|
new_masks.push('2');
|
||||||
|
}
|
||||||
|
if ((de.m & 4) === 4 && de.w) {
|
||||||
|
new_masks.push('4');
|
||||||
|
}
|
||||||
|
if ((de.m & 8) === 8) {
|
||||||
|
new_masks.push('8');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_masks;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Table size="small" padding="normal">
|
||||||
<Table size="small">
|
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<StyledTableCell>
|
<StyledTableCell align="center">OPTIONS</StyledTableCell>
|
||||||
({deviceEntities.reduce((a, v) => (v.x ? a + 1 : a), 0)}/{deviceEntities.length})
|
<StyledTableCell align="left">ENTITY NAME (CODE)</StyledTableCell>
|
||||||
</StyledTableCell>
|
|
||||||
<StyledTableCell align="left">ENTITY NAME</StyledTableCell>
|
|
||||||
<StyledTableCell>CODE</StyledTableCell>
|
|
||||||
<StyledTableCell align="right">VALUE</StyledTableCell>
|
<StyledTableCell align="right">VALUE</StyledTableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{deviceEntities.map((de) => (
|
{deviceEntities.map((de) => (
|
||||||
<TableRow
|
<TableRow key={de.s} hover>
|
||||||
key={de.i}
|
<StyledTableCell padding="none">
|
||||||
onClick={() => toggleDeviceEntity(de.i)}
|
<ToggleButtonGroup
|
||||||
sx={de.x ? { backgroundColor: '#f8696b' } : { backgroundColor: 'black' }}
|
size="small"
|
||||||
|
color="secondary"
|
||||||
|
value={getMask(de)}
|
||||||
|
onChange={(event, mask) => {
|
||||||
|
setMask(de, mask);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<StyledTableCell padding="checkbox">{de.x && <CloseIcon fontSize="small" />}</StyledTableCell>
|
<ToggleButton value="8" color="success" disabled={(de.m & 1) !== 0 || de.n === ''}>
|
||||||
<StyledTableCell component="th" scope="row">
|
<FavoriteBorderOutlinedIcon sx={{ fontSize: 14 }} />
|
||||||
{de.n}
|
</ToggleButton>
|
||||||
|
<ToggleButton value="4" disabled={!de.w}>
|
||||||
|
<EditOffOutlinedIcon sx={{ fontSize: 14 }} />
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton value="2">
|
||||||
|
<CommentsDisabledOutlinedIcon sx={{ fontSize: 14 }} />
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton value="1">
|
||||||
|
<VisibilityOffOutlinedIcon sx={{ fontSize: 14 }} />
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</StyledTableCell>
|
||||||
|
<StyledTableCell>
|
||||||
|
{de.n} ({de.s})
|
||||||
</StyledTableCell>
|
</StyledTableCell>
|
||||||
<StyledTableCell>{de.s}</StyledTableCell>
|
|
||||||
<StyledTableCell align="right">{formatValue(de.v)}</StyledTableCell>
|
<StyledTableCell align="right">{formatValue(de.v)}</StyledTableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
DeviceData,
|
DeviceData,
|
||||||
DeviceEntity,
|
DeviceEntity,
|
||||||
UniqueID,
|
UniqueID,
|
||||||
ExcludeEntities,
|
MaskedEntities,
|
||||||
WriteValue,
|
WriteValue,
|
||||||
WriteSensor,
|
WriteSensor,
|
||||||
WriteAnalog,
|
WriteAnalog,
|
||||||
@@ -63,8 +63,8 @@ export function readDeviceEntities(unique_id: UniqueID): AxiosPromise<DeviceEnti
|
|||||||
return AXIOS_BIN.post('/deviceEntities', unique_id);
|
return AXIOS_BIN.post('/deviceEntities', unique_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function writeExcludeEntities(excludeEntities: ExcludeEntities): AxiosPromise<void> {
|
export function writeMaskedEntities(maskedEntities: MaskedEntities): AxiosPromise<void> {
|
||||||
return AXIOS.post('/excludeEntities', excludeEntities);
|
return AXIOS.post('/maskedEntities', maskedEntities);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function writeValue(writevalue: WriteValue): AxiosPromise<void> {
|
export function writeValue(writevalue: WriteValue): AxiosPromise<void> {
|
||||||
@@ -83,7 +83,6 @@ export function resetCustomizations(): AxiosPromise<void> {
|
|||||||
return AXIOS.post('/resetCustomizations');
|
return AXIOS.post('/resetCustomizations');
|
||||||
}
|
}
|
||||||
|
|
||||||
// EMS-ESP API calls
|
|
||||||
export function API(apiCall: APIcall): AxiosPromise<void> {
|
export function API(apiCall: APIcall): AxiosPromise<void> {
|
||||||
return AXIOS_API.post('/', apiCall);
|
return AXIOS_API.post('/', apiCall);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,8 +130,10 @@ export interface DeviceValue {
|
|||||||
n: string; // name
|
n: string; // name
|
||||||
c: string; // command
|
c: string; // command
|
||||||
l: string[]; // list
|
l: string[]; // list
|
||||||
h?: string; // help text
|
h?: string; // help text, optional
|
||||||
s?: string; // steps for up/down
|
s?: string; // steps for up/down, optional
|
||||||
|
m?: string; // min, optional
|
||||||
|
x?: string; // max, optional
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeviceData {
|
export interface DeviceData {
|
||||||
@@ -143,13 +145,14 @@ export interface DeviceEntity {
|
|||||||
v?: any; // value, in any format
|
v?: any; // value, in any format
|
||||||
n: string; // name
|
n: string; // name
|
||||||
s: string; // shortname
|
s: string; // shortname
|
||||||
x: boolean; // excluded flag
|
m: number; // mask
|
||||||
i: number; // unique id
|
om?: number; // original mask before edits
|
||||||
|
w: boolean; // writeable
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExcludeEntities {
|
export interface MaskedEntities {
|
||||||
id: number;
|
id: number;
|
||||||
entity_ids: number[];
|
entity_ids: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UniqueID {
|
export interface UniqueID {
|
||||||
@@ -280,3 +283,11 @@ export interface WriteAnalog {
|
|||||||
uom: number;
|
uom: number;
|
||||||
type: number;
|
type: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum DeviceEntityMask {
|
||||||
|
DV_DEFAULT = 0,
|
||||||
|
DV_WEB_EXCLUDE = 1,
|
||||||
|
DV_API_MQTT_EXCLUDE = 2,
|
||||||
|
DV_READONLY = 4,
|
||||||
|
DV_FAVORITE = 8
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export enum NTPSyncStatus {
|
export enum NTPSyncStatus {
|
||||||
NTP_INACTIVE = 0,
|
NTP_DISABLED = 0,
|
||||||
NTP_ACTIVE = 1
|
NTP_INACTIVE = 1,
|
||||||
|
NTP_ACTIVE = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NTPStatus {
|
export interface NTPStatus {
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
|||||||
ArJsonRequestHandlerFunction _onRequest;
|
ArJsonRequestHandlerFunction _onRequest;
|
||||||
size_t _contentLength;
|
size_t _contentLength;
|
||||||
#ifndef ARDUINOJSON_5_COMPATIBILITY
|
#ifndef ARDUINOJSON_5_COMPATIBILITY
|
||||||
const size_t maxJsonBufferSize;
|
size_t _maxJsonBufferSize;
|
||||||
#endif
|
#endif
|
||||||
size_t _maxContentLength;
|
size_t _maxContentLength;
|
||||||
|
|
||||||
@@ -182,7 +182,7 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
|||||||
: _uri(uri)
|
: _uri(uri)
|
||||||
, _method(HTTP_POST | HTTP_PUT | HTTP_PATCH)
|
, _method(HTTP_POST | HTTP_PUT | HTTP_PATCH)
|
||||||
, _onRequest(onRequest)
|
, _onRequest(onRequest)
|
||||||
, maxJsonBufferSize(maxJsonBufferSize)
|
, _maxJsonBufferSize(maxJsonBufferSize)
|
||||||
, _maxContentLength(16384) {
|
, _maxContentLength(16384) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,6 +192,9 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
|||||||
void setMaxContentLength(int maxContentLength) {
|
void setMaxContentLength(int maxContentLength) {
|
||||||
_maxContentLength = maxContentLength;
|
_maxContentLength = maxContentLength;
|
||||||
}
|
}
|
||||||
|
void setMaxJsonBufferSize(size_t maxJsonBufferSize) {
|
||||||
|
_maxJsonBufferSize = maxJsonBufferSize;
|
||||||
|
}
|
||||||
void onRequest(ArJsonRequestHandlerFunction fn) {
|
void onRequest(ArJsonRequestHandlerFunction fn) {
|
||||||
_onRequest = fn;
|
_onRequest = fn;
|
||||||
}
|
}
|
||||||
@@ -216,7 +219,7 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
|||||||
virtual void handleRequest(AsyncWebServerRequest * request) override final {
|
virtual void handleRequest(AsyncWebServerRequest * request) override final {
|
||||||
if (_onRequest) {
|
if (_onRequest) {
|
||||||
if (request->_tempObject != NULL) {
|
if (request->_tempObject != NULL) {
|
||||||
DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize);
|
DynamicJsonDocument jsonBuffer(this->_maxJsonBufferSize);
|
||||||
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t *)(request->_tempObject));
|
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t *)(request->_tempObject));
|
||||||
if (!error) {
|
if (!error) {
|
||||||
JsonVariant json = jsonBuffer.as<JsonVariant>();
|
JsonVariant json = jsonBuffer.as<JsonVariant>();
|
||||||
|
|||||||
@@ -228,7 +228,15 @@ StateUpdateResult MqttSettings::update(JsonObject & root, MqttSettings & setting
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if both settings are stored from older version, HA has priority
|
||||||
|
if (newSettings.ha_enabled && newSettings.publish_single) {
|
||||||
|
newSettings.publish_single = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (newSettings.publish_single != settings.publish_single) {
|
if (newSettings.publish_single != settings.publish_single) {
|
||||||
|
if (newSettings.publish_single) {
|
||||||
|
newSettings.ha_enabled = false;
|
||||||
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,6 +250,9 @@ StateUpdateResult MqttSettings::update(JsonObject & root, MqttSettings & setting
|
|||||||
|
|
||||||
if (newSettings.ha_enabled != settings.ha_enabled) {
|
if (newSettings.ha_enabled != settings.ha_enabled) {
|
||||||
emsesp::EMSESP::mqtt_.ha_enabled(newSettings.ha_enabled);
|
emsesp::EMSESP::mqtt_.ha_enabled(newSettings.ha_enabled);
|
||||||
|
if (newSettings.ha_enabled) {
|
||||||
|
newSettings.publish_single = false;
|
||||||
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ static String generateClientId() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef FACTORY_MQTT_CLEAN_SESSION
|
#ifndef FACTORY_MQTT_CLEAN_SESSION
|
||||||
#define FACTORY_MQTT_CLEAN_SESSION true
|
#define FACTORY_MQTT_CLEAN_SESSION false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef FACTORY_MQTT_MAX_TOPIC_LENGTH
|
#ifndef FACTORY_MQTT_MAX_TOPIC_LENGTH
|
||||||
|
|||||||
@@ -46,8 +46,10 @@ void NTPSettingsService::WiFiEvent(WiFiEvent_t event) {
|
|||||||
|
|
||||||
// https://werner.rothschopf.net/microcontroller/202103_arduino_esp32_ntp_en.htm
|
// https://werner.rothschopf.net/microcontroller/202103_arduino_esp32_ntp_en.htm
|
||||||
void NTPSettingsService::configureNTP() {
|
void NTPSettingsService::configureNTP() {
|
||||||
|
emsesp::EMSESP::system_.ntp_connected(false);
|
||||||
if (connected_ && _state.enabled) {
|
if (connected_ && _state.enabled) {
|
||||||
emsesp::EMSESP::logger().info(F("Starting NTP"));
|
emsesp::EMSESP::logger().info(F("Starting NTP"));
|
||||||
|
sntp_set_time_sync_notification_cb(ntp_received);
|
||||||
configTzTime(_state.tzFormat.c_str(), _state.server.c_str());
|
configTzTime(_state.tzFormat.c_str(), _state.server.c_str());
|
||||||
} else {
|
} else {
|
||||||
setenv("TZ", _state.tzFormat.c_str(), 1);
|
setenv("TZ", _state.tzFormat.c_str(), 1);
|
||||||
@@ -57,11 +59,12 @@ void NTPSettingsService::configureNTP() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NTPSettingsService::configureTime(AsyncWebServerRequest * request, JsonVariant & json) {
|
void NTPSettingsService::configureTime(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||||
if (!sntp_enabled() && json.is<JsonObject>()) {
|
if (json.is<JsonObject>()) {
|
||||||
struct tm tm = {0};
|
struct tm tm = {0};
|
||||||
String timeLocal = json["local_time"];
|
String timeLocal = json["local_time"];
|
||||||
char * s = strptime(timeLocal.c_str(), "%Y-%m-%dT%H:%M:%S", &tm);
|
char * s = strptime(timeLocal.c_str(), "%Y-%m-%dT%H:%M:%S", &tm);
|
||||||
if (s != nullptr) {
|
if (s != nullptr) {
|
||||||
|
tm.tm_isdst = -1; // not set by strptime, tells mktime to determine daylightsaving
|
||||||
time_t time = mktime(&tm);
|
time_t time = mktime(&tm);
|
||||||
struct timeval now = {.tv_sec = time};
|
struct timeval now = {.tv_sec = time};
|
||||||
settimeofday(&now, nullptr);
|
settimeofday(&now, nullptr);
|
||||||
@@ -74,3 +77,8 @@ void NTPSettingsService::configureTime(AsyncWebServerRequest * request, JsonVari
|
|||||||
AsyncWebServerResponse * response = request->beginResponse(400);
|
AsyncWebServerResponse * response = request->beginResponse(400);
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NTPSettingsService::ntp_received(struct timeval * tv) {
|
||||||
|
// emsesp::EMSESP::logger().info(F("NTP sync to %d sec"), tv->tv_sec);
|
||||||
|
emsesp::EMSESP::system_.ntp_connected(true);
|
||||||
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ class NTPSettingsService : public StatefulService<NTPSettings> {
|
|||||||
NTPSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
|
NTPSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
|
static void ntp_received(struct timeval * tv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HttpEndpoint<NTPSettings> _httpEndpoint;
|
HttpEndpoint<NTPSettings> _httpEndpoint;
|
||||||
@@ -67,6 +68,7 @@ class NTPSettingsService : public StatefulService<NTPSettings> {
|
|||||||
void WiFiEvent(WiFiEvent_t event);
|
void WiFiEvent(WiFiEvent_t event);
|
||||||
void configureNTP();
|
void configureNTP();
|
||||||
void configureTime(AsyncWebServerRequest * request, JsonVariant & json);
|
void configureTime(AsyncWebServerRequest * request, JsonVariant & json);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <NTPStatus.h>
|
#include <NTPStatus.h>
|
||||||
|
#include "../../src/emsesp_stub.hpp" // proddy added
|
||||||
|
|
||||||
using namespace std::placeholders; // for `_1` etc
|
using namespace std::placeholders; // for `_1` etc
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ void NTPStatus::ntpStatus(AsyncWebServerRequest * request) {
|
|||||||
time_t now = time(nullptr);
|
time_t now = time(nullptr);
|
||||||
|
|
||||||
// only provide enabled/disabled status for now
|
// only provide enabled/disabled status for now
|
||||||
root["status"] = sntp_enabled() ? 1 : 0;
|
root["status"] = sntp_enabled() ? emsesp::EMSESP::system_.ntp_connected() ? 2 : 1 : 0;
|
||||||
|
|
||||||
// the current time in UTC
|
// the current time in UTC
|
||||||
root["utc_time"] = toUTCTimeString(gmtime(&now));
|
root["utc_time"] = toUTCTimeString(gmtime(&now));
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
|||||||
ArJsonRequestHandlerFunction _onRequest;
|
ArJsonRequestHandlerFunction _onRequest;
|
||||||
size_t _contentLength;
|
size_t _contentLength;
|
||||||
size_t _maxContentLength;
|
size_t _maxContentLength;
|
||||||
|
size_t _maxJsonBufferSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AsyncCallbackJsonWebHandler(const String & uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE)
|
AsyncCallbackJsonWebHandler(const String & uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE)
|
||||||
@@ -202,6 +203,9 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
|||||||
void setMaxContentLength(int maxContentLength) {
|
void setMaxContentLength(int maxContentLength) {
|
||||||
_maxContentLength = maxContentLength;
|
_maxContentLength = maxContentLength;
|
||||||
}
|
}
|
||||||
|
void setMaxJsonBufferSize(int maxJsonBufferSize) {
|
||||||
|
_maxJsonBufferSize = maxJsonBufferSize;
|
||||||
|
}
|
||||||
void onRequest(ArJsonRequestHandlerFunction fn) {
|
void onRequest(ArJsonRequestHandlerFunction fn) {
|
||||||
_onRequest = fn;
|
_onRequest = fn;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ const EMSESP_BOARDPROFILE_ENDPOINT = REST_ENDPOINT_ROOT + 'boardProfile'
|
|||||||
const EMSESP_WRITE_VALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeValue'
|
const EMSESP_WRITE_VALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeValue'
|
||||||
const EMSESP_WRITE_SENSOR_ENDPOINT = REST_ENDPOINT_ROOT + 'writeSensor'
|
const EMSESP_WRITE_SENSOR_ENDPOINT = REST_ENDPOINT_ROOT + 'writeSensor'
|
||||||
const EMSESP_WRITE_ANALOG_ENDPOINT = REST_ENDPOINT_ROOT + 'writeAnalog'
|
const EMSESP_WRITE_ANALOG_ENDPOINT = REST_ENDPOINT_ROOT + 'writeAnalog'
|
||||||
const EMSESP_EXCLUDE_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'excludeEntities'
|
const EMSESP_MASKED_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'maskedEntities'
|
||||||
const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'resetCustomizations'
|
const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'resetCustomizations'
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
@@ -343,19 +343,19 @@ const emsesp_devices = {
|
|||||||
i: 1,
|
i: 1,
|
||||||
d: 23,
|
d: 23,
|
||||||
p: 77,
|
p: 77,
|
||||||
s: 'Thermostat1',
|
s: 'Thermostat (RC20/Moduline 300)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
i: 2,
|
i: 2,
|
||||||
d: 8,
|
d: 8,
|
||||||
p: 123,
|
p: 123,
|
||||||
s: 'Boiler',
|
s: 'Boiler (Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
i: 4,
|
i: 4,
|
||||||
d: 16,
|
d: 16,
|
||||||
p: 165,
|
p: 165,
|
||||||
s: 'Thermostat2',
|
s: 'Thermostat (RC100/Moduline 1000/1010)',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@@ -376,7 +376,7 @@ const emsesp_coredata = {
|
|||||||
{
|
{
|
||||||
i: 1,
|
i: 1,
|
||||||
t: 'Thermostat',
|
t: 'Thermostat',
|
||||||
s: 'Thermostat1',
|
s: 'Thermostat',
|
||||||
b: '',
|
b: '',
|
||||||
n: 'RC20/Moduline 300',
|
n: 'RC20/Moduline 300',
|
||||||
d: 23,
|
d: 23,
|
||||||
@@ -387,7 +387,7 @@ const emsesp_coredata = {
|
|||||||
{
|
{
|
||||||
i: 4,
|
i: 4,
|
||||||
t: 'Thermostat',
|
t: 'Thermostat',
|
||||||
s: 'Thermostat2',
|
s: 'Thermostat',
|
||||||
b: 'Buderus',
|
b: 'Buderus',
|
||||||
n: 'RC100/Moduline 1000/1010',
|
n: 'RC100/Moduline 1000/1010',
|
||||||
d: 16,
|
d: 16,
|
||||||
@@ -449,36 +449,36 @@ const status = {
|
|||||||
|
|
||||||
// Dashboard data
|
// Dashboard data
|
||||||
const emsesp_devicedata_1 = {
|
const emsesp_devicedata_1 = {
|
||||||
label: 'RC20/Moduline 300',
|
label: 'Thermostat: RC20/Moduline 300',
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
v: '(0)',
|
v: '(0)',
|
||||||
u: 0,
|
u: 0,
|
||||||
n: 'error code',
|
n: '00error code',
|
||||||
c: '',
|
c: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
v: '14:54:39 06/06/2021',
|
v: '14:54:39 06/06/2021',
|
||||||
u: 0,
|
u: 0,
|
||||||
n: 'date/time',
|
n: '00date/time',
|
||||||
c: '',
|
c: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
v: 18,
|
v: 18,
|
||||||
u: 1,
|
u: 1,
|
||||||
n: 'hc1 selected room temperature',
|
n: '00hc1 selected room temperature',
|
||||||
c: 'hc1/seltemp',
|
c: 'hc1/seltemp',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
v: 22.6,
|
v: 22.6,
|
||||||
u: 1,
|
u: 1,
|
||||||
n: 'hc1 current room temperature',
|
n: '00hc1 current room temperature',
|
||||||
c: '',
|
c: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
v: 'auto',
|
v: 'auto',
|
||||||
u: 0,
|
u: 0,
|
||||||
n: 'hc1 mode',
|
n: '00hc1 mode',
|
||||||
c: 'hc1/mode',
|
c: 'hc1/mode',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -487,107 +487,104 @@ const emsesp_devicedata_1 = {
|
|||||||
const emsesp_devicedata_2 = {
|
const emsesp_devicedata_2 = {
|
||||||
label: 'Boiler: Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i',
|
label: 'Boiler: Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i',
|
||||||
data: [
|
data: [
|
||||||
{ u: 0, n: 'reset', c: 'reset', l: ['-', 'maintenance', 'error'] },
|
{ u: 0, n: '08reset', c: 'reset', l: ['-', 'maintenance', 'error'] },
|
||||||
{ v: 'false', u: 0, n: 'heating active' },
|
{ v: 'false', u: 0, n: '08heating active' },
|
||||||
{ v: 'false', u: 0, n: 'tapwater active' },
|
{ v: 'false', u: 0, n: '04tapwater active' },
|
||||||
{ v: 5, u: 1, n: 'selected flow temperature', c: 'selflowtemp' },
|
{ v: 5, u: 1, n: '04selected flow temperature', c: 'selflowtemp' },
|
||||||
{ v: 0, u: 3, n: 'burner selected max power', c: 'selburnpow' },
|
{ v: 0, u: 3, n: '0Eburner selected max power', c: 'selburnpow' },
|
||||||
{ v: 0, u: 3, n: 'heating pump modulation' },
|
{ v: 0, u: 3, n: '00heating pump modulation' },
|
||||||
{ v: 53.4, u: 1, n: 'current flow temperature' },
|
{ v: 53.4, u: 1, n: '00current flow temperature' },
|
||||||
{ v: 52.7, u: 1, n: 'return temperature' },
|
{ v: 52.7, u: 1, n: '00return temperature' },
|
||||||
{ v: 1.3, u: 10, n: 'system pressure' },
|
{ v: 1.3, u: 10, n: '00system pressure' },
|
||||||
{ v: 54.9, u: 1, n: 'actual boiler temperature' },
|
{ v: 54.9, u: 1, n: '00actual boiler temperature' },
|
||||||
{ v: 'false', u: 0, n: 'gas' },
|
{ v: 'false', u: 0, n: '00gas' },
|
||||||
{ v: 'false', u: 0, n: 'gas stage 2' },
|
{ v: 'false', u: 0, n: '00gas stage 2' },
|
||||||
{ v: 0, u: 9, n: 'flame current' },
|
{ v: 0, u: 9, n: '00flame current' },
|
||||||
{ v: 'false', u: 0, n: 'heating pump' },
|
{ v: 'false', u: 0, n: '00heating pump' },
|
||||||
{ v: 'false', u: 0, n: 'fan' },
|
{ v: 'false', u: 0, n: '00fan' },
|
||||||
{ v: 'false', u: 0, n: 'ignition' },
|
{ v: 'false', u: 0, n: '00ignition' },
|
||||||
{ v: 'false', u: 0, n: 'oil preheating' },
|
{ v: 'false', u: 0, n: '00oil preheating' },
|
||||||
{ v: 'true', u: 0, n: 'heating activated', c: 'heatingactivated', l: ['off', 'on'] },
|
{ v: 'true', u: 0, n: '00heating activated', c: 'heatingactivated', l: ['off', 'on'] },
|
||||||
{ v: 80, u: 1, n: 'heating temperature', c: 'heatingtemp' },
|
{ v: 80, u: 1, n: '00heating temperature', c: 'heatingtemp' },
|
||||||
{ v: 70, u: 3, n: 'burner pump max power', c: 'pumpmodmax' },
|
{ v: 70, u: 3, n: '00burner pump max power', c: 'pumpmodmax' },
|
||||||
{ v: 30, u: 3, n: 'burner pump min power', c: 'pumpmodmin' },
|
{ v: 30, u: 3, n: '00burner pump min power', c: 'pumpmodmin' },
|
||||||
{ v: 1, u: 8, n: 'pump delay', c: 'pumpdelay' },
|
{ v: 1, u: 8, n: '00pump delay', c: 'pumpdelay' },
|
||||||
{ v: 10, u: 8, n: 'burner min period', c: 'burnminperiod' },
|
{ v: 10, u: 8, n: '00burner min period', c: 'burnminperiod' },
|
||||||
{ v: 0, u: 3, n: 'burner min power', c: 'burnminpower' },
|
{ v: 0, u: 3, n: '00burner min power', c: 'burnminpower' },
|
||||||
{ v: 50, u: 3, n: 'burner max power', c: 'burnmaxpower' },
|
{ v: 50, u: 3, n: '00burner max power', c: 'burnmaxpower' },
|
||||||
{ v: -6, u: 2, n: 'hysteresis on temperature', c: 'boilhyston' },
|
{ v: -6, u: 2, n: '00hysteresis on temperature', c: 'boilhyston' },
|
||||||
{ v: 6, u: 2, n: 'hysteresis off temperature', c: 'boilhystoff' },
|
{ v: 6, u: 2, n: '00hysteresis off temperature', c: 'boilhystoff' },
|
||||||
{ v: 0, u: 1, n: 'set flow temperature' },
|
{ v: 0, u: 1, n: '00set flow temperature' },
|
||||||
{ v: 0, u: 3, n: 'burner set power' },
|
{ v: 0, u: 3, n: '00burner set power' },
|
||||||
{ v: 0, u: 3, n: 'burner current power' },
|
{ v: 0, u: 3, n: '00burner current power' },
|
||||||
{ v: 326323, u: 0, n: 'burner starts' },
|
{ v: 326323, u: 0, n: '00burner starts' },
|
||||||
{ v: 553437, u: 8, n: 'total burner operating time' },
|
{ v: 553437, u: 8, n: '00total burner operating time' },
|
||||||
{ v: 451286, u: 8, n: 'total heat operating time' },
|
{ v: 451286, u: 8, n: '00total heat operating time' },
|
||||||
{ v: 4672173, u: 8, n: 'total UBA operating time' },
|
{ v: 4672173, u: 8, n: '00total UBA operating time' },
|
||||||
{ v: '1C(210) 06.06.2020 12:07 (0 min)', u: 0, n: 'last error code' },
|
{ v: '1C(210) 06.06.2020 12:07 (0 min)', u: 0, n: '00last error code' },
|
||||||
{ v: '0H', u: 0, n: 'service code' },
|
{ v: '0H', u: 0, n: '00service code' },
|
||||||
{ v: 203, u: 0, n: 'service code number' },
|
{ v: 203, u: 0, n: '00service code number' },
|
||||||
{ v: 'H00', u: 0, n: 'maintenance message' },
|
{ v: 'H00', u: 0, n: '00maintenance message' },
|
||||||
{ v: 'manual', u: 0, n: 'maintenance scheduled', c: 'maintenance', l: ['off', 'time', 'date', 'manual'] },
|
{ v: 'manual', u: 0, n: '00maintenance scheduled', c: 'maintenance', l: ['off', 'time', 'date', 'manual'] },
|
||||||
{ v: 6000, u: 7, n: 'time to next maintenance', c: 'maintenancetime' },
|
{ v: 6000, u: 7, n: '00time to next maintenance', c: 'maintenancetime' },
|
||||||
{ v: '01.01.2012', u: 0, n: 'next maintenance date', c: 'maintenancedate', o: 'Format: < dd.mm.yyyy >' },
|
{ v: '01.01.2012', u: 0, n: '00next maintenance date', c: 'maintenancedate', o: 'Format: < dd.mm.yyyy >' },
|
||||||
{ v: 'true', u: 0, n: 'dhw turn on/off', c: 'wwtapactivated', l: ['off', 'on'] },
|
{ v: 'true', u: 0, n: '00dhw turn on/off', c: 'wwtapactivated', l: ['off', 'on'] },
|
||||||
{ v: 62, u: 1, n: 'dhw set temperature' },
|
{ v: 62, u: 1, n: '00dhw set temperature' },
|
||||||
{ v: 60, u: 1, n: 'dhw selected temperature', c: 'wwseltemp' },
|
{ v: 60, u: 1, n: '00dhw selected temperature', c: 'wwseltemp' },
|
||||||
{ v: 'flow', u: 0, n: 'dhw type' },
|
{ v: 'flow', u: 0, n: '00dhw type' },
|
||||||
{ v: 'hot', u: 0, n: 'dhw comfort', c: 'wwcomfort', l: ['hot', 'eco', 'intelligent'] },
|
{ v: 'hot', u: 0, n: '00dhw comfort', c: 'wwcomfort', l: ['hot', 'eco', 'intelligent'] },
|
||||||
{ v: 40, u: 2, n: 'dhw flow temperature offset', c: 'wwflowtempoffset' },
|
{ v: 40, u: 2, n: '00dhw flow temperature offset', c: 'wwflowtempoffset' },
|
||||||
{ v: 100, u: 3, n: 'dhw max power', c: 'wwmaxpower' },
|
{ v: 100, u: 3, n: '00dhw max power', c: 'wwmaxpower' },
|
||||||
{ v: 'false', u: 0, n: 'dhw circulation pump available', c: 'wwcircpump', l: ['off', 'on'] },
|
{ v: 'false', u: 0, n: '00dhw circulation pump available', c: 'wwcircpump', l: ['off', 'on'] },
|
||||||
{ v: '3-way valve', u: 0, n: 'dhw charging type' },
|
{ v: '3-way valve', u: 0, n: '00dhw charging type' },
|
||||||
{ v: -5, u: 2, n: 'dhw hysteresis on temperature', c: 'wwhyston' },
|
{ v: -5, u: 2, n: '00dhw hysteresis on temperature', c: 'wwhyston' },
|
||||||
{ v: 0, u: 2, n: 'dhw hysteresis off temperature', c: 'wwhystoff' },
|
{ v: 0, u: 2, n: '00dhw hysteresis off temperature', c: 'wwhystoff' },
|
||||||
{ v: 70, u: 1, n: 'dhw disinfection temperature', c: 'wwdisinfectiontemp' },
|
{ v: 70, u: 1, n: '00dhw disinfection temperature', c: 'wwdisinfectiontemp' },
|
||||||
{
|
{
|
||||||
v: 'off',
|
v: 'off',
|
||||||
u: 0,
|
u: 0,
|
||||||
n: 'dhw circulation pump mode',
|
n: '00dhw circulation pump mode',
|
||||||
c: 'wwcircmode',
|
c: 'wwcircmode',
|
||||||
l: ['off', '1x3min', '2x3min', '3x3min', '4x3min', '5x3min', '6x3min', 'continuous'],
|
l: ['off', '1x3min', '2x3min', '3x3min', '4x3min', '5x3min', '6x3min', 'continuous'],
|
||||||
},
|
},
|
||||||
{ v: 'false', u: 0, n: 'dhw circulation active', c: 'wwcirc', l: ['off', 'on'] },
|
{ v: 'false', u: 0, n: '00dhw circulation active', c: 'wwcirc', l: ['off', 'on'] },
|
||||||
{ v: 47.3, u: 1, n: 'dhw current intern temperature' },
|
{ v: 47.3, u: 1, n: '00dhw current intern temperature' },
|
||||||
{ v: 0, u: 4, n: 'dhw current tap water flow' },
|
{ v: 0, u: 4, n: '00dhw current tap water flow' },
|
||||||
{ v: 47.3, u: 1, n: 'dhw storage intern temperature' },
|
{ v: 47.3, u: 1, n: '00dhw storage intern temperature' },
|
||||||
{ v: 'true', u: 0, n: 'dhw activated', c: 'wwactivated', l: ['off', 'on'] },
|
{ v: 'true', u: 0, n: '00dhw activated', c: 'wwactivated', l: ['off', 'on'] },
|
||||||
{ v: 'false', u: 0, n: 'dhw one time charging', c: 'wwonetime', l: ['off', 'on'] },
|
{ v: 'false', u: 0, n: '00dhw one time charging', c: 'wwonetime', l: ['off', 'on'] },
|
||||||
{ v: 'false', u: 0, n: 'dhw disinfecting', c: 'wwdisinfecting', l: ['off', 'on'] },
|
{ v: 'false', u: 0, n: '00dhw disinfecting', c: 'wwdisinfecting', l: ['off', 'on'] },
|
||||||
{ v: 'false', u: 0, n: 'dhw charging' },
|
{ v: 'false', u: 0, n: '00dhw charging' },
|
||||||
{ v: 'false', u: 0, n: 'dhw recharging' },
|
{ v: 'false', u: 0, n: '00dhw recharging' },
|
||||||
{ v: 'true', u: 0, n: 'dhw temperature ok' },
|
{ v: 'true', u: 0, n: '00dhw temperature ok' },
|
||||||
{ v: 'false', u: 0, n: 'dhw active' },
|
{ v: 'false', u: 0, n: '00dhw active' },
|
||||||
{ v: 'true', u: 0, n: 'dhw 3way valve active' },
|
{ v: 'true', u: 0, n: '00dhw 3way valve active' },
|
||||||
{ v: 0, u: 3, n: 'dhw set pump power' },
|
{ v: 0, u: 3, n: '00dhw set pump power' },
|
||||||
{ v: 288768, u: 0, n: 'dhw starts' },
|
{ v: 288768, u: 0, n: '00dhw starts' },
|
||||||
{ v: 102151, u: 8, n: 'dhw active time' },
|
{ v: 102151, u: 8, n: '00dhw active time' },
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
const emsesp_devicedata_4 = {
|
const emsesp_devicedata_4 = {
|
||||||
label: 'RC100/Moduline 1000/1010',
|
label: 'Thermostat: RC100/Moduline 1000/1010',
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
v: 16,
|
v: 16,
|
||||||
u: 1,
|
u: 1,
|
||||||
n: 'hc2 selected room temperature',
|
n: '00hc2 selected room temperature',
|
||||||
c: 'hc2/seltemp',
|
c: 'hc2/seltemp',
|
||||||
x: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
v: 18.6,
|
v: 18.6,
|
||||||
u: 1,
|
u: 1,
|
||||||
n: 'hc2 current room temperature',
|
n: '00hc2 current room temperature',
|
||||||
c: '',
|
c: '',
|
||||||
x: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
v: 'off',
|
v: 'off',
|
||||||
u: 0,
|
u: 0,
|
||||||
n: 'hc2 mode',
|
n: '00hc2 mode',
|
||||||
c: 'hc2/mode',
|
c: 'hc2/mode',
|
||||||
x: true,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@@ -597,119 +594,119 @@ const emsesp_deviceentities_1 = [
|
|||||||
v: '(0)',
|
v: '(0)',
|
||||||
n: 'error code',
|
n: 'error code',
|
||||||
s: 'errorcode',
|
s: 'errorcode',
|
||||||
x: false,
|
m: 0,
|
||||||
i: 1,
|
w: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
v: '14:54:39 06/06/2021',
|
v: '14:54:39 06/06/2021',
|
||||||
n: 'date/time',
|
n: 'date/time',
|
||||||
s: 'datetime',
|
s: 'datetime',
|
||||||
x: false,
|
m: 0,
|
||||||
i: 2,
|
w: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
v: 18.22,
|
v: 18.2,
|
||||||
n: 'hc1 selected room temperature',
|
n: 'hc1 selected room temperature',
|
||||||
s: 'hc1/seltemp',
|
s: 'hc1/seltemp',
|
||||||
x: false,
|
m: 0,
|
||||||
i: 3,
|
w: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
v: 22.6,
|
v: 22.6,
|
||||||
n: 'hc1 current room temperature',
|
n: 'hc1 current room temperature',
|
||||||
s: 'hc1/curtemp',
|
s: 'hc1/curtemp',
|
||||||
x: false,
|
m: 0,
|
||||||
i: 4,
|
w: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
v: 'auto',
|
v: 'auto',
|
||||||
n: 'hc1 mode',
|
n: 'hc1 mode',
|
||||||
s: 'hc1/mode',
|
s: 'hc1/mode',
|
||||||
x: false,
|
m: 0,
|
||||||
i: 5,
|
w: true,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const emsesp_deviceentities_2 = [
|
const emsesp_deviceentities_2 = [
|
||||||
{ v: false, n: 'heating active', s: 'heatingactive', x: false, i: 1 },
|
{ v: false, n: 'heating active', s: 'heatingactive', m: 0 },
|
||||||
{ v: false, n: 'tapwater active', s: 'tapwateractive', x: false, i: 2 },
|
{ v: false, n: 'tapwater active', s: 'tapwateractive', m: 0 },
|
||||||
{ v: 5, n: 'selected flow temperature', s: 'selflowtemp', x: false, i: 3 },
|
{ v: 5, n: 'selected flow temperature', s: 'selflowtemp', m: 0 },
|
||||||
{ v: 0, n: 'burner selected max power', s: 'selburnpow', x: false, i: 4 },
|
{ v: 0, n: 'burner selected max power', s: 'selburnpow', m: 0 },
|
||||||
{ v: 0, n: 'heating pump modulation', s: 'heatingpumpmod', x: false, i: 5 },
|
{ v: 0, n: 'heating pump modulation', s: 'heatingpumpmod', m: 0 },
|
||||||
{ n: 'heating pump 2 modulation', s: 'heatingpump2mod', x: true, i: 6 },
|
{ n: 'heating pump 2 modulation', s: 'heatingpump2mod', m: 0 },
|
||||||
{ n: 'outside temperature', s: 'outdoortemp', x: true, i: 7 },
|
{ n: 'outside temperature', s: 'outdoortemp', m: 0 },
|
||||||
{ v: 53, n: 'current flow temperature', s: 'curflowtemp', x: false, i: 8 },
|
{ v: 53, n: 'current flow temperature', s: 'curflowtemp', m: 0 },
|
||||||
{ v: 51.8, n: 'return temperature', s: 'rettemp', x: false, i: 9 },
|
{ v: 51.8, n: 'return temperature', s: 'rettemp', m: 0 },
|
||||||
{ n: 'mixing switch temperature', s: 'switchtemp', x: true, i: 10 },
|
{ n: 'mixing switch temperature', s: 'switchtemp', m: 0 },
|
||||||
{ v: 1.3, n: 'system pressure', s: 'syspress', x: false, i: 11 },
|
{ v: 1.3, n: 'system pressure', s: 'syspress', m: 0 },
|
||||||
{ v: 54.6, n: 'actual boiler temperature', s: 'boiltemp', x: false, i: 12 },
|
{ v: 54.6, n: 'actual boiler temperature', s: 'boiltemp', m: 0 },
|
||||||
{ n: 'exhaust temperature', s: 'exhausttemp', x: true, i: 13 },
|
{ n: 'exhaust temperature', s: 'exhausttemp', m: 0 },
|
||||||
{ v: false, n: 'gas', s: 'burngas', x: false, i: 14 },
|
{ v: false, n: 'gas', s: 'burngas', m: 0 },
|
||||||
{ v: false, n: 'gas stage 2', s: 'burngas2', x: false, i: 15 },
|
{ v: false, n: 'gas stage 2', s: 'burngas2', m: 0 },
|
||||||
{ v: 0, n: 'flame current', s: 'flamecurr', x: false, i: 16 },
|
{ v: 0, n: 'flame current', s: 'flamecurr', m: 0 },
|
||||||
{ v: false, n: 'heating pump', s: 'heatingpump', x: false, i: 17 },
|
{ v: false, n: 'heating pump', s: 'heatingpump', m: 0 },
|
||||||
{ v: false, n: 'fan', s: 'fanwork', x: false, i: 18 },
|
{ v: false, n: 'fan', s: 'fanwork', m: 0 },
|
||||||
{ v: false, n: 'ignition', s: 'ignwork', x: false, i: 19 },
|
{ v: false, n: 'ignition', s: 'ignwork', m: 0 },
|
||||||
{ v: false, n: 'oil preheating', s: 'oilpreheat', x: false, i: 20 },
|
{ v: false, n: 'oil preheating', s: 'oilpreheat', m: 0 },
|
||||||
{ v: true, n: 'heating activated', s: 'heatingactivated', x: false, i: 21 },
|
{ v: true, n: 'heating activated', s: 'heatingactivated', m: 0 },
|
||||||
{ v: 80, n: 'heating temperature', s: 'heatingtemp', x: false, i: 22 },
|
{ v: 80, n: 'heating temperature', s: 'heatingtemp', m: 0 },
|
||||||
{ v: 70, n: 'burner pump max power', s: 'pumpmodmax', x: false, i: 23 },
|
{ v: 70, n: 'burner pump max power', s: 'pumpmodmax', m: 0 },
|
||||||
{ v: 30, n: 'burner pump min power', s: 'pumpmodmin', x: false, i: 24 },
|
{ v: 30, n: 'burner pump min power', s: 'pumpmodmin', m: 0 },
|
||||||
{ v: 1, n: 'pump delay', s: 'pumpdelay', x: false, i: 25 },
|
{ v: 1, n: 'pump delay', s: 'pumpdelay', m: 0 },
|
||||||
{ v: 10, n: 'burner min period', s: 'burnminperiod', x: false, i: 26 },
|
{ v: 10, n: 'burner min period', s: 'burnminperiod', m: 0 },
|
||||||
{ v: 0, n: 'burner min power', s: 'burnminpower', x: false, i: 27 },
|
{ v: 0, n: 'burner min power', s: 'burnminpower', m: 0 },
|
||||||
{ v: 50, n: 'burner max power', s: 'burnmaxpower', x: false, i: 28 },
|
{ v: 50, n: 'burner max power', s: 'burnmaxpower', m: 0 },
|
||||||
{ v: -6, n: 'hysteresis on temperature', s: 'boilhyston', x: false, i: 29 },
|
{ v: -6, n: 'hysteresis on temperature', s: 'boilhyston', m: 0 },
|
||||||
{ v: 6, n: 'hysteresis off temperature', s: 'boilhystoff', x: false, i: 30 },
|
{ v: 6, n: 'hysteresis off temperature', s: 'boilhystoff', m: 0 },
|
||||||
{ v: 0, n: 'set flow temperature', s: 'setflowtemp', x: false, i: 31 },
|
{ v: 0, n: 'set flow temperature', s: 'setflowtemp', m: 0 },
|
||||||
{ v: 0, n: 'burner set power', s: 'setburnpow', x: false, i: 32 },
|
{ v: 0, n: 'burner set power', s: 'setburnpow', m: 0 },
|
||||||
{ v: 0, n: 'burner current power', s: 'curburnpow', x: false, i: 33 },
|
{ v: 0, n: 'burner current power', s: 'curburnpow', m: 0 },
|
||||||
{ v: 326323, n: 'burner starts', s: 'burnstarts', x: false, i: 34 },
|
{ v: 326323, n: 'burner starts', s: 'burnstarts', m: 0 },
|
||||||
{ v: 553437, n: 'total burner operating time', s: 'burnworkmin', x: false, i: 35 },
|
{ v: 553437, n: 'total burner operating time', s: 'burnworkmin', m: 0 },
|
||||||
{ v: 451286, n: 'total heat operating time', s: 'heatworkmin', x: false, i: 36 },
|
{ v: 451286, n: 'total heat operating time', s: 'heatworkmin', m: 0 },
|
||||||
{ v: 4672175, n: 'total UBA operating time', s: 'ubauptime', x: false, i: 37 },
|
{ v: 4672175, n: 'total UBA operating time', s: 'ubauptime', m: 0 },
|
||||||
{ v: '1C(210) 06.06.2020 12:07 (0 min)', n: 'last error code', s: 'lastcode', x: false, i: 38 },
|
{ v: '1C(210) 06.06.2020 12:07 (0 min)', n: 'last error code', s: 'lastcode', m: 0 },
|
||||||
{ v: '0H', n: 'service code', s: 'servicecode', x: false, i: 39 },
|
{ v: '0H', n: 'service code', s: 'servicecode', m: 0 },
|
||||||
{ v: 203, n: 'service code number', s: 'servicecodenumber', x: false, i: 40 },
|
{ v: 203, n: 'service code number', s: 'servicecodenumber', m: 0 },
|
||||||
{ v: 'H00', n: 'maintenance message', s: 'maintenancemessage', x: false, i: 41 },
|
{ v: 'H00', n: 'maintenance message', s: 'maintenancemessage', m: 0 },
|
||||||
{ v: 'manual', n: 'maintenance scheduled', s: 'maintenance', x: false, i: 42 },
|
{ v: 'manual', n: 'maintenance scheduled', s: 'maintenance', m: 0 },
|
||||||
{ v: 6000, n: 'time to next maintenance', s: 'maintenancetime', x: false, i: 43 },
|
{ v: 6000, n: 'time to next maintenance', s: 'maintenancetime', m: 0 },
|
||||||
{ v: '01.01.2012', n: 'next maintenance date', s: 'maintenancedate', x: false, i: 44 },
|
{ v: '01.01.2012', n: 'next maintenance date', s: 'maintenancedate', m: 0 },
|
||||||
{ v: true, n: 'dhw turn on/off', s: 'wwtapactivated', x: false, i: 45 },
|
{ v: true, n: 'dhw turn on/off', s: 'wwtapactivated', m: 0 },
|
||||||
{ v: 62, n: 'dhw set temperature', s: 'wwsettemp', x: false, i: 46 },
|
{ v: 62, n: 'dhw set temperature', s: 'wwsettemp', m: 0 },
|
||||||
{ v: 60, n: 'dhw selected temperature', s: 'wwseltemp', x: false, i: 47 },
|
{ v: 60, n: 'dhw selected temperature', s: 'wwseltemp', m: 0 },
|
||||||
{ n: 'dhw selected lower temperature', s: 'wwseltemplow', x: true, i: 48 },
|
{ n: 'dhw selected lower temperature', s: 'wwseltemplow', m: 2 },
|
||||||
{ n: 'dhw selected temperature for off', s: 'wwseltempoff', x: true, i: 49 },
|
{ n: 'dhw selected temperature for off', s: 'wwseltempoff', m: 2 },
|
||||||
{ n: 'dhw single charge temperature', s: 'wwseltempsingle', x: true, i: 50 },
|
{ n: 'dhw single charge temperature', s: 'wwseltempsingle', m: 2 },
|
||||||
{ v: 'flow', n: 'dhw type', s: 'wwtype', x: false, i: 51 },
|
{ v: 'flow', n: 'dhw type', s: 'wwtype', m: 0 },
|
||||||
{ v: 'hot', n: 'dhw comfort', s: 'wwcomfort', x: false, i: 52 },
|
{ v: 'hot', n: 'dhw comfort', s: 'wwcomfort', m: 0 },
|
||||||
{ v: 40, n: 'dhw flow temperature offset', s: 'wwflowtempoffset', x: false, i: 53 },
|
{ v: 40, n: 'dhw flow temperature offset', s: 'wwflowtempoffset', m: 0 },
|
||||||
{ v: 100, n: 'dhw max power', s: 'wwmaxpower', x: false, i: 54 },
|
{ v: 100, n: 'dhw max power', s: 'wwmaxpower', m: 0 },
|
||||||
{ v: false, n: 'dhw circulation pump available', s: 'wwcircpump', x: false, i: 55 },
|
{ v: false, n: 'dhw circulation pump available', s: 'wwcircpump', m: 0 },
|
||||||
{ v: '3-way valve', n: 'dhw charging type', s: 'wwchargetype', x: false, i: 56 },
|
{ v: '3-way valve', n: 'dhw charging type', s: 'wwchargetype', m: 0 },
|
||||||
{ v: -5, n: 'dhw hysteresis on temperature', s: 'wwhyston', x: false, i: 57 },
|
{ v: -5, n: 'dhw hysteresis on temperature', s: 'wwhyston', m: 0 },
|
||||||
{ v: 0, n: 'dhw hysteresis off temperature', s: 'wwhystoff', x: false, i: 58 },
|
{ v: 0, n: 'dhw hysteresis off temperature', s: 'wwhystoff', m: 0 },
|
||||||
{ v: 70, n: 'dhw disinfection temperature', s: 'wwdisinfectiontemp', x: false, i: 59 },
|
{ v: 70, n: 'dhw disinfection temperature', s: 'wwdisinfectiontemp', m: 0 },
|
||||||
{ v: 'off', n: 'dhw circulation pump mode', s: 'wwcircmode', x: false, i: 60 },
|
{ v: 'off', n: 'dhw circulation pump mode', s: 'wwcircmode', m: 0 },
|
||||||
{ v: false, n: 'dhw circulation active', s: 'wwcirc', x: false, i: 61 },
|
{ v: false, n: 'dhw circulation active', s: 'wwcirc', m: 0 },
|
||||||
{ v: 46.4, n: 'dhw current intern temperature', s: 'wwcurtemp', x: false, i: 62 },
|
{ v: 46.4, n: 'dhw current intern temperature', s: 'wwcurtemp', m: 0 },
|
||||||
{ n: 'dhw current extern temperature', s: 'wwcurtemp2', x: true, i: 63 },
|
{ n: 'dhw current extern temperature', s: 'wwcurtemp2', m: 2 },
|
||||||
{ v: 0, n: 'dhw current tap water flow', s: 'wwcurflow', x: false, i: 64 },
|
{ v: 0, n: 'dhw current tap water flow', s: 'wwcurflow', m: 0 },
|
||||||
{ v: 46.3, n: 'dhw storage intern temperature', s: 'wwstoragetemp1', x: false, i: 65 },
|
{ v: 46.3, n: 'dhw storage intern temperature', s: 'wwstoragetemp1', m: 0 },
|
||||||
{ n: 'dhw storage extern temperature', s: 'wwstoragetemp2', x: true, i: 66 },
|
{ n: 'dhw storage extern temperature', s: 'wwstoragetemp2', m: 2 },
|
||||||
{ v: true, n: 'dhw activated', s: 'wwactivated', x: false, i: 67 },
|
{ v: true, n: 'dhw activated', s: 'wwactivated', m: 0 },
|
||||||
{ v: false, n: 'dhw one time charging', s: 'wwonetime', x: false, i: 68 },
|
{ v: false, n: 'dhw one time charging', s: 'wwonetime', m: 0 },
|
||||||
{ v: false, n: 'dhw disinfecting', s: 'wwdisinfecting', x: false, i: 69 },
|
{ v: false, n: 'dhw disinfecting', s: 'wwdisinfecting', m: 0 },
|
||||||
{ v: false, n: 'dhw charging', s: 'wwcharging', x: false, i: 70 },
|
{ v: false, n: 'dhw charging', s: 'wwcharging', m: 0 },
|
||||||
{ v: false, n: 'dhw recharging', s: 'wwrecharging', x: false, i: 71 },
|
{ v: false, n: 'dhw recharging', s: 'wwrecharging', m: 0 },
|
||||||
{ v: true, n: 'dhw temperature ok', s: 'wwtempok', x: false, i: 72 },
|
{ v: true, n: 'dhw temperature ok', s: 'wwtempok', m: 0 },
|
||||||
{ v: false, n: 'dhw active', s: 'wwactive', x: false, i: 73 },
|
{ v: false, n: 'dhw active', s: 'wwactive', m: 0 },
|
||||||
{ v: true, n: 'dhw 3way valve active', s: 'ww3wayvalve', x: false, i: 74 },
|
{ v: true, n: 'dhw 3way valve active', s: 'ww3wayvalve', m: 0 },
|
||||||
{ v: 0, n: 'dhw set pump power', s: 'wwsetpumppower', x: false, i: 75 },
|
{ v: 0, n: 'dhw set pump power', s: 'wwsetpumppower', m: 0 },
|
||||||
{ n: 'dhw mixer temperature', s: 'wwmixertemp', x: true, i: 76 },
|
{ n: 'dhw mixer temperature', s: 'wwmixertemp', m: 2 },
|
||||||
{ n: 'dhw cylinder middle temperature (TS3)', s: 'wwcylmiddletemp', x: true, i: 77 },
|
{ n: 'dhw cylinder middle temperature (TS3)', s: 'wwcylmiddletemp', m: 2 },
|
||||||
{ v: 288768, n: 'dhw starts', s: 'wwstarts', x: false, i: 78 },
|
{ v: 288768, n: 'dhw starts', s: 'wwstarts', m: 0 },
|
||||||
{ v: 102151, n: 'dhw active time', s: 'wwworkm', x: false, i: 79 },
|
{ v: 102151, n: 'dhw active time', s: 'wwworkm', m: 0 },
|
||||||
]
|
]
|
||||||
|
|
||||||
const emsesp_deviceentities_4 = [
|
const emsesp_deviceentities_4 = [
|
||||||
@@ -717,21 +714,22 @@ const emsesp_deviceentities_4 = [
|
|||||||
v: 16,
|
v: 16,
|
||||||
n: 'hc2 selected room temperature',
|
n: 'hc2 selected room temperature',
|
||||||
s: 'hc2/seltemp',
|
s: 'hc2/seltemp',
|
||||||
x: false,
|
m: 0,
|
||||||
i: 1,
|
w: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
v: 18.5,
|
||||||
n: 'hc2 current room temperature',
|
n: 'hc2 current room temperature',
|
||||||
s: 'hc2/curtemp',
|
s: 'hc2/curtemp',
|
||||||
x: true,
|
m: 3,
|
||||||
i: 2,
|
w: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
v: 'off',
|
v: 'off',
|
||||||
n: 'hc2 mode',
|
n: 'hc2 mode',
|
||||||
s: 'hc2/mode',
|
s: 'hc2/mode',
|
||||||
x: true,
|
m: 3,
|
||||||
i: 3,
|
w: true,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -924,9 +922,41 @@ rest_server.post(EMSESP_DEVICEENTITIES_ENDPOINT, (req, res) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
rest_server.post(EMSESP_EXCLUDE_ENTITIES_ENDPOINT, (req, res) => {
|
function updateMask(entity, de, dd) {
|
||||||
console.log('exclude list for productid ' + req.body.product_id + ' device_id ' + req.body.device_id + ' entities:')
|
const name = entity.slice(2)
|
||||||
|
const new_mask = parseInt(entity.slice(0, 2), 16)
|
||||||
|
|
||||||
|
objIndex = de.findIndex((obj) => obj.s == name)
|
||||||
|
if (objIndex !== -1) {
|
||||||
|
de[objIndex].m = new_mask
|
||||||
|
const fullname = de[objIndex].n
|
||||||
|
objIndex = dd.data.findIndex((obj) => obj.n.slice(2) == fullname)
|
||||||
|
if (objIndex !== -1) {
|
||||||
|
// see if the mask has changed
|
||||||
|
const old_mask = parseInt(dd.data[objIndex].n.slice(0, 2), 16)
|
||||||
|
if (old_mask !== new_mask) {
|
||||||
|
const mask_hex = entity.slice(0, 2)
|
||||||
|
console.log('Updating ' + dd.data[objIndex].n + ' -> ' + mask_hex + fullname)
|
||||||
|
dd.data[objIndex].n = mask_hex + fullname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log("can't locate record for id " + id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rest_server.post(EMSESP_MASKED_ENTITIES_ENDPOINT, (req, res) => {
|
||||||
|
const id = req.body.id
|
||||||
console.log(req.body.entity_ids)
|
console.log(req.body.entity_ids)
|
||||||
|
for (const entity of req.body.entity_ids) {
|
||||||
|
if (id === 1) {
|
||||||
|
updateMask(entity, emsesp_deviceentities_1, emsesp_devicedata_1)
|
||||||
|
} else if (id === 2) {
|
||||||
|
updateMask(entity, emsesp_deviceentities_2, emsesp_devicedata_2)
|
||||||
|
} else if (id === 4) {
|
||||||
|
updateMask(entity, emsesp_deviceentities_4, emsesp_devicedata_4)
|
||||||
|
}
|
||||||
|
}
|
||||||
res.sendStatus(200)
|
res.sendStatus(200)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
|||||||
return_code = ((cf->cmdfunction_json_)(value, id, output)) ? CommandRet::OK : CommandRet::ERROR;
|
return_code = ((cf->cmdfunction_json_)(value, id, output)) ? CommandRet::OK : CommandRet::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cf->cmdfunction_) {
|
if (cf->cmdfunction_ && !EMSESP::cmd_is_readonly(device_type, cmd, id)) {
|
||||||
return_code = ((cf->cmdfunction_)(value, id)) ? CommandRet::OK : CommandRet::ERROR;
|
return_code = ((cf->cmdfunction_)(value, id)) ? CommandRet::OK : CommandRet::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,13 +139,10 @@ class Command {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using KeyValueMap_t = std::unordered_map<std::string, std::string>;
|
|
||||||
using Folder_t = std::vector<std::string>;
|
|
||||||
|
|
||||||
class SUrlParser {
|
class SUrlParser {
|
||||||
private:
|
private:
|
||||||
KeyValueMap_t m_keysvalues;
|
std::unordered_map<std::string, std::string> m_keysvalues;
|
||||||
Folder_t m_folders;
|
std::vector<std::string> m_folders;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SUrlParser() = default;
|
SUrlParser() = default;
|
||||||
@@ -153,11 +150,11 @@ class SUrlParser {
|
|||||||
|
|
||||||
bool parse(const char * url);
|
bool parse(const char * url);
|
||||||
|
|
||||||
Folder_t & paths() {
|
std::vector<std::string> & paths() {
|
||||||
return m_folders;
|
return m_folders;
|
||||||
};
|
};
|
||||||
|
|
||||||
KeyValueMap_t & params() {
|
std::unordered_map<std::string, std::string> & params() {
|
||||||
return m_keysvalues;
|
return m_keysvalues;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
{132, DeviceType::BOILER, F("GC7000F"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{132, DeviceType::BOILER, F("GC7000F"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{133, DeviceType::BOILER, F("Logano GB125/KB195i/Logamatic MC110"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{133, DeviceType::BOILER, F("Logano GB125/KB195i/Logamatic MC110"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{167, DeviceType::BOILER, F("Cerapur Aero"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{167, DeviceType::BOILER, F("Cerapur Aero"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
{168, DeviceType::BOILER, F("Hybrid Heatpump"), DeviceFlags::EMS_DEVICE_FLAG_HYBRID},
|
||||||
{170, DeviceType::BOILER, F("Logano GB212"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{170, DeviceType::BOILER, F("Logano GB212"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{172, DeviceType::BOILER, F("Enviline/Compress 6000AW/Hybrid 7000iAW/SupraEco/Geo 5xx"), DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
{172, DeviceType::BOILER, F("Enviline/Compress 6000AW/Hybrid 7000iAW/SupraEco/Geo 5xx"), DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
||||||
{173, DeviceType::BOILER, F("Geo 5xx"), DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
{173, DeviceType::BOILER, F("Geo 5xx"), DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
||||||
@@ -56,6 +57,7 @@
|
|||||||
{114, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{114, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{125, DeviceType::CONTROLLER, F("BC25"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{125, DeviceType::CONTROLLER, F("BC25"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{152, DeviceType::CONTROLLER, F("Controller"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{152, DeviceType::CONTROLLER, F("Controller"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
|
{168, DeviceType::CONTROLLER, F("Hybrid Heatpump"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{169, DeviceType::CONTROLLER, F("BC40"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{169, DeviceType::CONTROLLER, F("BC40"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{190, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{190, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{194, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{194, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
@@ -90,6 +92,7 @@
|
|||||||
{165, DeviceType::THERMOSTAT, F("RC100/Moduline 1000/1010"), DeviceFlags::EMS_DEVICE_FLAG_RC100}, // 0x18, 0x38
|
{165, DeviceType::THERMOSTAT, F("RC100/Moduline 1000/1010"), DeviceFlags::EMS_DEVICE_FLAG_RC100}, // 0x18, 0x38
|
||||||
{172, DeviceType::THERMOSTAT, F("Rego 2000/3000"), DeviceFlags::EMS_DEVICE_FLAG_RC300}, // 0x10
|
{172, DeviceType::THERMOSTAT, F("Rego 2000/3000"), DeviceFlags::EMS_DEVICE_FLAG_RC300}, // 0x10
|
||||||
{216, DeviceType::THERMOSTAT, F("CRF200S"), DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
{216, DeviceType::THERMOSTAT, F("CRF200S"), DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
||||||
|
{246, DeviceType::THERMOSTAT, F("Comfort+2RF"), DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
||||||
|
|
||||||
// Thermostat - Sieger - 0x10 / 0x17
|
// Thermostat - Sieger - 0x10 / 0x17
|
||||||
{ 66, DeviceType::THERMOSTAT, F("ES72/RC20"), DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17 or remote
|
{ 66, DeviceType::THERMOSTAT, F("ES72/RC20"), DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17 or remote
|
||||||
@@ -108,15 +111,17 @@
|
|||||||
{191, DeviceType::THERMOSTAT, F("FR120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD}, // older model
|
{191, DeviceType::THERMOSTAT, F("FR120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD}, // older model
|
||||||
{192, DeviceType::THERMOSTAT, F("FW120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
{192, DeviceType::THERMOSTAT, F("FW120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
||||||
|
|
||||||
// Solar Modules - 0x30, 0x2A (for ww)
|
// Solar Modules - 0x30 (for solar), 0x2A, 0x41 (for ww)
|
||||||
{ 73, DeviceType::SOLAR, F("SM10"), DeviceFlags::EMS_DEVICE_FLAG_SM10},
|
{ 73, DeviceType::SOLAR, F("SM10"), DeviceFlags::EMS_DEVICE_FLAG_SM10},
|
||||||
{101, DeviceType::SOLAR, F("ISM1"), DeviceFlags::EMS_DEVICE_FLAG_ISM},
|
{101, DeviceType::SOLAR, F("ISM1"), DeviceFlags::EMS_DEVICE_FLAG_ISM},
|
||||||
|
{103, DeviceType::SOLAR, F("ISM2"), DeviceFlags::EMS_DEVICE_FLAG_ISM},
|
||||||
{162, DeviceType::SOLAR, F("SM50"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
|
{162, DeviceType::SOLAR, F("SM50"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
|
||||||
{163, DeviceType::SOLAR, F("SM100/MS100"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
|
{163, DeviceType::SOLAR, F("SM100/MS100"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
|
||||||
{164, DeviceType::SOLAR, F("SM200/MS200"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
|
{164, DeviceType::SOLAR, F("SM200/MS200"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
|
||||||
|
|
||||||
// Mixer Modules - 0x20-0x27 for HC, 0x28-0x29 for WWC and 0x11 for the MP100
|
// Mixer Modules - 0x20-0x27 for HC, 0x28-0x29 for WWC and 0x11 for the MP100
|
||||||
{ 69, DeviceType::MIXER, F("MM10"), DeviceFlags::EMS_DEVICE_FLAG_MM10},
|
{ 69, DeviceType::MIXER, F("MM10"), DeviceFlags::EMS_DEVICE_FLAG_MM10},
|
||||||
|
{100, DeviceType::MIXER, F("IPM"), DeviceFlags::EMS_DEVICE_FLAG_IPM},
|
||||||
{102, DeviceType::MIXER, F("IPM"), DeviceFlags::EMS_DEVICE_FLAG_IPM},
|
{102, DeviceType::MIXER, F("IPM"), DeviceFlags::EMS_DEVICE_FLAG_IPM},
|
||||||
{159, DeviceType::MIXER, F("MM50"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
{159, DeviceType::MIXER, F("MM50"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
||||||
{160, DeviceType::MIXER, F("MM100"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
{160, DeviceType::MIXER, F("MM100"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
||||||
@@ -134,6 +139,7 @@
|
|||||||
|
|
||||||
// Wireless sensor base - 0x50
|
// Wireless sensor base - 0x50
|
||||||
{236, DeviceType::CONNECT, F("Wireless sensor base"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{236, DeviceType::CONNECT, F("Wireless sensor base"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
{238, DeviceType::CONNECT, F("Wireless sensor base"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Switches - 0x11
|
// Switches - 0x11
|
||||||
{ 71, DeviceType::SWITCH, F("WM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 71, DeviceType::SWITCH, F("WM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
|
|
||||||
// the telegram handlers...
|
// the telegram handlers...
|
||||||
// common for all boilers
|
// common for all boilers
|
||||||
|
register_telegram_type(0xBF, F("ErrorMessage"), false, MAKE_PF_CB(process_ErrorMessage));
|
||||||
register_telegram_type(0x10, F("UBAErrorMessage1"), false, MAKE_PF_CB(process_UBAErrorMessage));
|
register_telegram_type(0x10, F("UBAErrorMessage1"), false, MAKE_PF_CB(process_UBAErrorMessage));
|
||||||
register_telegram_type(0x11, F("UBAErrorMessage2"), false, MAKE_PF_CB(process_UBAErrorMessage));
|
register_telegram_type(0x11, F("UBAErrorMessage2"), false, MAKE_PF_CB(process_UBAErrorMessage));
|
||||||
register_telegram_type(0xC2, F("UBAErrorMessage3"), false, MAKE_PF_CB(process_UBAErrorMessage2));
|
register_telegram_type(0xC2, F("UBAErrorMessage3"), false, MAKE_PF_CB(process_UBAErrorMessage2));
|
||||||
@@ -70,7 +71,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// only EMS+
|
// only EMS+
|
||||||
if (model() != EMSdevice::EMS_DEVICE_FLAG_EMS && model() != EMSdevice::EMS_DEVICE_FLAG_HT3) {
|
if (model() != EMSdevice::EMS_DEVICE_FLAG_EMS && model() != EMSdevice::EMS_DEVICE_FLAG_HT3 && model() != EMSdevice::EMS_DEVICE_FLAG_HYBRID) {
|
||||||
register_telegram_type(0xD1, F("UBAOutdoorTemp"), false, MAKE_PF_CB(process_UBAOutdoorTemp));
|
register_telegram_type(0xD1, F("UBAOutdoorTemp"), false, MAKE_PF_CB(process_UBAOutdoorTemp));
|
||||||
register_telegram_type(0xE3, F("UBAMonitorSlowPlus2"), false, MAKE_PF_CB(process_UBAMonitorSlowPlus2));
|
register_telegram_type(0xE3, F("UBAMonitorSlowPlus2"), false, MAKE_PF_CB(process_UBAMonitorSlowPlus2));
|
||||||
register_telegram_type(0xE4, F("UBAMonitorFastPlus"), false, MAKE_PF_CB(process_UBAMonitorFastPlus));
|
register_telegram_type(0xE4, F("UBAMonitorFastPlus"), false, MAKE_PF_CB(process_UBAMonitorFastPlus));
|
||||||
@@ -88,6 +89,11 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
register_telegram_type(0x48A, F("HpPool"), true, MAKE_PF_CB(process_HpPool));
|
register_telegram_type(0x48A, F("HpPool"), true, MAKE_PF_CB(process_HpPool));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (model() == EMSdevice::EMS_DEVICE_FLAG_HYBRID) {
|
||||||
|
register_telegram_type(0xBB, F("HybridHp"), true, MAKE_PF_CB(process_HybridHp));
|
||||||
|
}
|
||||||
|
*/
|
||||||
// reset is a command uses a dummy variable which is always zero, shown as blank, but provides command enum options
|
// reset is a command uses a dummy variable which is always zero, shown as blank, but provides command enum options
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &reset_, DeviceValueType::CMD, FL_(enum_reset), FL_(reset), DeviceValueUOM::NONE, MAKE_CF_CB(set_reset));
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &reset_, DeviceValueType::CMD, FL_(enum_reset), FL_(reset), DeviceValueUOM::NONE, MAKE_CF_CB(set_reset));
|
||||||
has_update(reset_, 0);
|
has_update(reset_, 0);
|
||||||
@@ -196,6 +202,72 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_maintenancedate));
|
MAKE_CF_CB(set_maintenancedate));
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Hybrid Heatpump
|
||||||
|
if (model() == EMSdevice::EMS_DEVICE_FLAG_HYBRID) {
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&hybridStrategy_,
|
||||||
|
DeviceValueType::ENUM,
|
||||||
|
FL_(enum_hybridStrategy),
|
||||||
|
FL_(hybridStrategy),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_hybridStrategy));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&switchOverTemp_,
|
||||||
|
DeviceValueType::INT,
|
||||||
|
nullptr,
|
||||||
|
FL_(switchOverTemp),
|
||||||
|
DeviceValueUOM::DEGREES,
|
||||||
|
MAKE_CF_CB(set_switchOverTemp),
|
||||||
|
-20,
|
||||||
|
20);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&energyCostRatio_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
FL_(div10),
|
||||||
|
FL_(energyCostRatio),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_energyCostRatio),
|
||||||
|
0,
|
||||||
|
19.9);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&fossileFactor_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
FL_(div10),
|
||||||
|
FL_(fossileFactor),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_fossileFactor),
|
||||||
|
0,
|
||||||
|
5);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&electricFactor_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
FL_(div10),
|
||||||
|
FL_(electricFactor),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_electricFactor),
|
||||||
|
0,
|
||||||
|
5);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&delayBoiler_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
nullptr,
|
||||||
|
FL_(delayBoiler),
|
||||||
|
DeviceValueUOM::MINUTES,
|
||||||
|
MAKE_CF_CB(set_delayBoiler),
|
||||||
|
5,
|
||||||
|
120);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&tempDiffBoiler_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
nullptr,
|
||||||
|
FL_(tempDiffBoiler),
|
||||||
|
DeviceValueUOM::DEGREES_R,
|
||||||
|
MAKE_CF_CB(set_tempDiffBoiler),
|
||||||
|
1,
|
||||||
|
99);
|
||||||
|
}
|
||||||
|
*/
|
||||||
// heatpump info
|
// heatpump info
|
||||||
if (model() == EMS_DEVICE_FLAG_HEATPUMP) {
|
if (model() == EMS_DEVICE_FLAG_HEATPUMP) {
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &upTimeControl_, DeviceValueType::TIME, FL_(div60), FL_(upTimeControl), DeviceValueUOM::MINUTES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &upTimeControl_, DeviceValueType::TIME, FL_(div60), FL_(upTimeControl), DeviceValueUOM::MINUTES);
|
||||||
@@ -631,6 +703,7 @@ void Boiler::process_UBAMonitorSlow(std::shared_ptr<const Telegram> telegram) {
|
|||||||
has_update(telegram, heatingPumpMod_, 9);
|
has_update(telegram, heatingPumpMod_, 9);
|
||||||
has_update(telegram, burnStarts_, 10, 3); // force to 3 bytes
|
has_update(telegram, burnStarts_, 10, 3); // force to 3 bytes
|
||||||
has_update(telegram, burnWorkMin_, 13, 3); // force to 3 bytes
|
has_update(telegram, burnWorkMin_, 13, 3); // force to 3 bytes
|
||||||
|
has_update(telegram, burn2WorkMin_, 16, 3); // force to 3 bytes
|
||||||
has_update(telegram, heatWorkMin_, 19, 3); // force to 3 bytes
|
has_update(telegram, heatWorkMin_, 19, 3); // force to 3 bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -655,6 +728,7 @@ void Boiler::process_UBAMonitorSlowPlus(std::shared_ptr<const Telegram> telegram
|
|||||||
has_update(telegram, exhaustTemp_, 6);
|
has_update(telegram, exhaustTemp_, 6);
|
||||||
has_update(telegram, burnStarts_, 10, 3); // force to 3 bytes
|
has_update(telegram, burnStarts_, 10, 3); // force to 3 bytes
|
||||||
has_update(telegram, burnWorkMin_, 13, 3); // force to 3 bytes
|
has_update(telegram, burnWorkMin_, 13, 3); // force to 3 bytes
|
||||||
|
has_update(telegram, burn2WorkMin_, 16, 3); // force to 3 bytes
|
||||||
has_update(telegram, heatWorkMin_, 19, 3); // force to 3 bytes
|
has_update(telegram, heatWorkMin_, 19, 3); // force to 3 bytes
|
||||||
has_update(telegram, heatingPumpMod_, 25);
|
has_update(telegram, heatingPumpMod_, 25);
|
||||||
// temperature measurements at 4, see #620
|
// temperature measurements at 4, see #620
|
||||||
@@ -869,6 +943,11 @@ void Boiler::process_UBAMaintenanceStatus(std::shared_ptr<const Telegram> telegr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0xBF
|
||||||
|
void Boiler::process_ErrorMessage(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
EMSESP::send_read_request(0xC2, device_id()); // read last errorcode
|
||||||
|
}
|
||||||
|
|
||||||
// 0x10, 0x11
|
// 0x10, 0x11
|
||||||
void Boiler::process_UBAErrorMessage(std::shared_ptr<const Telegram> telegram) {
|
void Boiler::process_UBAErrorMessage(std::shared_ptr<const Telegram> telegram) {
|
||||||
if (telegram->offset > 0 || telegram->message_length < 11) {
|
if (telegram->offset > 0 || telegram->message_length < 11) {
|
||||||
@@ -984,6 +1063,86 @@ void Boiler::process_UBAMaintenanceData(std::shared_ptr<const Telegram> telegram
|
|||||||
has_update(maintenanceDate_, date, sizeof(maintenanceDate_));
|
has_update(maintenanceDate_, date, sizeof(maintenanceDate_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
// 0xBB Heatpump optimization
|
||||||
|
// Boiler(0x08) -> Me(0x0B), ?(0xBB), data: 00 00 00 00 00 00 00 00 00 00 00 FF 02 0F 1E 0B 1A 00 14 03
|
||||||
|
void Boiler::process_HybridHp(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
has_enumupdate(telegram, hybridStrategy_, 12, 1); // cost = 2, temperature = 3, mix = 4
|
||||||
|
has_update(telegram, switchOverTemp_, 13); // full degrees
|
||||||
|
has_update(telegram, energyCostRatio_, 14); // is *10
|
||||||
|
has_update(telegram, fossileFactor_, 15); // is * 10
|
||||||
|
has_update(telegram, electricFactor_, 16); // is * 10
|
||||||
|
has_update(telegram, delayBoiler_, 18); // minutes
|
||||||
|
has_update(telegram, tempDiffBoiler_, 19); // relative degrees
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Settings
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
bool Boiler::set_hybridStrategy(const char * value, const int8_t id) {
|
||||||
|
uint8_t v;
|
||||||
|
if (!Helpers::value2enum(value, v, FL_(enum_hybridStrategy))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 12, v + 1, 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Boiler::set_switchOverTemp(const char * value, const int8_t id) {
|
||||||
|
int v;
|
||||||
|
if (!Helpers::value2temperature(value, v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 13, v, 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Boiler::set_energyCostRatio(const char * value, const int8_t id) {
|
||||||
|
float v;
|
||||||
|
if (!Helpers::value2float(value, v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 14, (uint8_t)(v * 10), 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Boiler::set_fossileFactor(const char * value, const int8_t id) {
|
||||||
|
float v;
|
||||||
|
if (!Helpers::value2float(value, v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 15, (uint8_t)(v * 10), 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Boiler::set_electricFactor(const char * value, const int8_t id) {
|
||||||
|
float v;
|
||||||
|
if (!Helpers::value2float(value, v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 16, (uint8_t)(v * 10), 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Boiler::set_delayBoiler(const char * value, const int8_t id) {
|
||||||
|
int v;
|
||||||
|
if (!Helpers::value2number(value, v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 18, v, 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Boiler::set_tempDiffBoiler(const char * value, const int8_t id) {
|
||||||
|
int v;
|
||||||
|
if (!Helpers::value2temperature(value, v, true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 19, v, 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Set the dhw temperature 0x33/0x35 or 0xEA
|
// Set the dhw temperature 0x33/0x35 or 0xEA
|
||||||
bool Boiler::set_ww_temp(const char * value, const int8_t id) {
|
bool Boiler::set_ww_temp(const char * value, const int8_t id) {
|
||||||
@@ -1475,12 +1634,12 @@ bool Boiler::set_reset(const char * value, const int8_t id) {
|
|||||||
if (num == 1) {
|
if (num == 1) {
|
||||||
// LOG_INFO(F("Reset boiler maintenance message"));
|
// LOG_INFO(F("Reset boiler maintenance message"));
|
||||||
write_command(0x05, 0x08, 0xFF, 0x1C);
|
write_command(0x05, 0x08, 0xFF, 0x1C);
|
||||||
has_update(reset_);
|
has_update(&reset_);
|
||||||
return true;
|
return true;
|
||||||
} else if (num == 2) {
|
} else if (num == 2) {
|
||||||
// LOG_INFO(F("Reset boiler error message"));
|
// LOG_INFO(F("Reset boiler error message"));
|
||||||
write_command(0x05, 0x00, 0x5A); // error reset
|
write_command(0x05, 0x00, 0x5A); // error reset
|
||||||
has_update(reset_);
|
has_update(&reset_);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -125,9 +125,10 @@ class Boiler : public EMSdevice {
|
|||||||
uint8_t setBurnPow_; // max output power in %
|
uint8_t setBurnPow_; // max output power in %
|
||||||
uint32_t burnStarts_; // burner restarts
|
uint32_t burnStarts_; // burner restarts
|
||||||
uint32_t burnWorkMin_; // Total burner operating time
|
uint32_t burnWorkMin_; // Total burner operating time
|
||||||
|
uint32_t burn2WorkMin_; // burner stage 2 operating time
|
||||||
uint32_t heatWorkMin_; // Total heat operating time
|
uint32_t heatWorkMin_; // Total heat operating time
|
||||||
uint32_t UBAuptime_; // Total UBA working hours
|
uint32_t UBAuptime_; // Total UBA working hours
|
||||||
char lastCode_[75]; // last error code
|
char lastCode_[50]; // last error code
|
||||||
char serviceCode_[4]; // 3 character status/service code
|
char serviceCode_[4]; // 3 character status/service code
|
||||||
uint16_t serviceCodeNumber_; // error/service code
|
uint16_t serviceCodeNumber_; // error/service code
|
||||||
|
|
||||||
@@ -192,6 +193,17 @@ class Boiler : public EMSdevice {
|
|||||||
// Pool unit
|
// Pool unit
|
||||||
int8_t poolSetTemp_;
|
int8_t poolSetTemp_;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// HybridHP
|
||||||
|
uint8_t hybridStrategy_; // cost = 2, temperature = 3, mix = 4
|
||||||
|
int8_t switchOverTemp_; // degrees
|
||||||
|
uint8_t energyCostRatio_; // is *10
|
||||||
|
uint8_t fossileFactor_; // is * 10
|
||||||
|
uint8_t electricFactor_; // is * 10
|
||||||
|
uint8_t delayBoiler_; // minutes
|
||||||
|
uint8_t tempDiffBoiler_; // relative temperature degrees
|
||||||
|
*/
|
||||||
|
|
||||||
void process_UBAParameterWW(std::shared_ptr<const Telegram> telegram);
|
void process_UBAParameterWW(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_UBAMonitorFast(std::shared_ptr<const Telegram> telegram);
|
void process_UBAMonitorFast(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_UBATotalUptime(std::shared_ptr<const Telegram> telegram);
|
void process_UBATotalUptime(std::shared_ptr<const Telegram> telegram);
|
||||||
@@ -209,6 +221,7 @@ class Boiler : public EMSdevice {
|
|||||||
void process_MC110Status(std::shared_ptr<const Telegram> telegram);
|
void process_MC110Status(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_UBAMaintenanceStatus(std::shared_ptr<const Telegram> telegram);
|
void process_UBAMaintenanceStatus(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_UBAMaintenanceData(std::shared_ptr<const Telegram> telegram);
|
void process_UBAMaintenanceData(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_ErrorMessage(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_UBAErrorMessage(std::shared_ptr<const Telegram> telegram);
|
void process_UBAErrorMessage(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_UBAErrorMessage2(std::shared_ptr<const Telegram> telegram);
|
void process_UBAErrorMessage2(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_UBAMonitorWWPlus(std::shared_ptr<const Telegram> telegram);
|
void process_UBAMonitorWWPlus(std::shared_ptr<const Telegram> telegram);
|
||||||
@@ -219,6 +232,7 @@ class Boiler : public EMSdevice {
|
|||||||
void process_HpPower(std::shared_ptr<const Telegram> telegram);
|
void process_HpPower(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_HpOutdoor(std::shared_ptr<const Telegram> telegram);
|
void process_HpOutdoor(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_HpPool(std::shared_ptr<const Telegram> telegram);
|
void process_HpPool(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_HybridHp(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|
||||||
// commands - none of these use the additional id parameter
|
// commands - none of these use the additional id parameter
|
||||||
bool set_ww_mode(const char * value, const int8_t id);
|
bool set_ww_mode(const char * value, const int8_t id);
|
||||||
@@ -254,6 +268,15 @@ class Boiler : public EMSdevice {
|
|||||||
bool set_ww_hyst_on(const char * value, const int8_t id);
|
bool set_ww_hyst_on(const char * value, const int8_t id);
|
||||||
bool set_ww_hyst_off(const char * value, const int8_t id);
|
bool set_ww_hyst_off(const char * value, const int8_t id);
|
||||||
bool set_pool_temp(const char * value, const int8_t id);
|
bool set_pool_temp(const char * value, const int8_t id);
|
||||||
|
/*
|
||||||
|
bool set_hybridStrategy(const char * value, const int8_t id);
|
||||||
|
bool set_switchOverTemp(const char * value, const int8_t id);
|
||||||
|
bool set_energyCostRatio(const char * value, const int8_t id);
|
||||||
|
bool set_fossileFactor(const char * value, const int8_t id);
|
||||||
|
bool set_electricFactor(const char * value, const int8_t id);
|
||||||
|
bool set_delayBoiler(const char * value, const int8_t id);
|
||||||
|
bool set_tempDiffBoiler(const char * value, const int8_t id);
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -24,6 +24,28 @@ REGISTER_FACTORY(Controller, EMSdevice::DeviceType::CONTROLLER);
|
|||||||
|
|
||||||
Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
|
// IVT broadcasts Thermostat time from controller (0x09) if display is off.
|
||||||
|
register_telegram_type(0x06, F("RCTime"), false, MAKE_PF_CB(process_dateTime));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_NONE, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// process_dateTime - type 0x06 - date and time from a thermostat - 14 bytes long, IVT only
|
||||||
|
void Controller::process_dateTime(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
if (telegram->offset > 0 || telegram->message_length < 5) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char newdatetime[sizeof(dateTime_)];
|
||||||
|
// publich as dd.mm.yyyy hh:mmF
|
||||||
|
snprintf(newdatetime,
|
||||||
|
sizeof(dateTime_),
|
||||||
|
"%02d.%02d.%04d %02d:%02d",
|
||||||
|
telegram->message_data[3],
|
||||||
|
telegram->message_data[1] - 1,
|
||||||
|
(telegram->message_data[0] & 0x7F) + 2000,
|
||||||
|
telegram->message_data[2],
|
||||||
|
telegram->message_data[4]);
|
||||||
|
has_update(dateTime_, newdatetime, sizeof(dateTime_));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
@@ -26,6 +26,10 @@ namespace emsesp {
|
|||||||
class Controller : public EMSdevice {
|
class Controller : public EMSdevice {
|
||||||
public:
|
public:
|
||||||
Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
|
Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
|
||||||
|
|
||||||
|
void process_dateTime(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|
||||||
|
char dateTime_[25];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -99,6 +99,39 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
|
|
||||||
// HT3
|
// HT3
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_IPM) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_IPM) {
|
||||||
|
if (device_id >= 0x40) { // special DHW pos 10
|
||||||
|
register_telegram_type(0x34, F("UBAMonitorWW"), false, MAKE_PF_CB(process_IPMMonitorWW));
|
||||||
|
register_telegram_type(0x1E, F("HydrTemp"), false, MAKE_PF_CB(process_IPMHydrTemp));
|
||||||
|
register_telegram_type(0x33, F("UBAParameterWW"), true, MAKE_PF_CB(process_IPMParameterWW));
|
||||||
|
// register_telegram_type(0x10D, F("wwNTCStatus"), false, MAKE_PF_CB(process_wwNTCStatus));
|
||||||
|
type_ = Type::WWC;
|
||||||
|
hc_ = device_id - 0x40 + 1;
|
||||||
|
uint8_t tag = DeviceValueTAG::TAG_WWC9 + hc_ - 1;
|
||||||
|
register_device_value(tag, &wwSelTemp_, DeviceValueType::UINT, nullptr, FL_(wwSelTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwSelTemp));
|
||||||
|
register_device_value(tag, &wwCurTemp_1_, DeviceValueType::USHORT, FL_(div10), FL_(wwCurTemp), DeviceValueUOM::DEGREES);
|
||||||
|
register_device_value(tag, &wwCurTemp_2_, DeviceValueType::USHORT, FL_(div10), FL_(wwCurTemp2), DeviceValueUOM::DEGREES);
|
||||||
|
register_device_value(tag, &HydrTemp_, DeviceValueType::USHORT, FL_(div10), FL_(hydrTemp), DeviceValueUOM::DEGREES);
|
||||||
|
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::NONE);
|
||||||
|
register_device_value(
|
||||||
|
tag, &wwFlowTempOffset_, DeviceValueType::UINT, nullptr, FL_(wwFlowTempOffset), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwFlowTempOffset));
|
||||||
|
register_device_value(tag, &wwHystOn_, DeviceValueType::INT, nullptr, FL_(wwHystOn), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwHystOn));
|
||||||
|
register_device_value(tag, &wwHystOff_, DeviceValueType::INT, nullptr, FL_(wwHystOff), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwHystOff));
|
||||||
|
register_device_value(tag,
|
||||||
|
&wwDisinfectionTemp_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
nullptr,
|
||||||
|
FL_(wwDisinfectionTemp),
|
||||||
|
DeviceValueUOM::DEGREES,
|
||||||
|
MAKE_CF_CB(set_wwDisinfectionTemp));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW,
|
||||||
|
&wwCircPump_,
|
||||||
|
DeviceValueType::BOOL,
|
||||||
|
nullptr,
|
||||||
|
FL_(wwCircPump),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_wwCircPump));
|
||||||
|
register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode));
|
||||||
|
} else {
|
||||||
register_telegram_type(0x010C, F("IPMStatusMessage"), false, MAKE_PF_CB(process_IPMStatusMessage));
|
register_telegram_type(0x010C, F("IPMStatusMessage"), false, MAKE_PF_CB(process_IPMStatusMessage));
|
||||||
register_telegram_type(0x011E, F("IPMTempMessage"), false, MAKE_PF_CB(process_IPMTempMessage));
|
register_telegram_type(0x011E, F("IPMTempMessage"), false, MAKE_PF_CB(process_IPMTempMessage));
|
||||||
// register_telegram_type(0x0123, F("IPMSetMessage"), false, MAKE_PF_CB(process_IPMSetMessage));
|
// register_telegram_type(0x0123, F("IPMSetMessage"), false, MAKE_PF_CB(process_IPMSetMessage));
|
||||||
@@ -111,6 +144,7 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump));
|
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump));
|
||||||
register_device_value(tag, &flowTempVf_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempVf), DeviceValueUOM::DEGREES);
|
register_device_value(tag, &flowTempVf_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempVf), DeviceValueUOM::DEGREES);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// heating circuits 0x02D7, 0x02D8 etc...
|
// heating circuits 0x02D7, 0x02D8 etc...
|
||||||
@@ -203,6 +237,35 @@ void Mixer::process_MMPLUSConfigMessage_WWC(std::shared_ptr<const Telegram> tele
|
|||||||
has_update(telegram, wwMaxTemp_, 10);
|
has_update(telegram, wwMaxTemp_, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0x34 only 8 bytes long
|
||||||
|
// Mixer(0x41) -> All(0x00), UBAMonitorWW(0x34), data: 37 02 1E 02 1E 00 00 00 00
|
||||||
|
void Mixer::process_IPMMonitorWW(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
has_update(telegram, wwSelTemp_, 0);
|
||||||
|
has_update(telegram, wwCurTemp_1_, 1);
|
||||||
|
has_update(telegram, wwCurTemp_2_, 3);
|
||||||
|
has_bitupdate(telegram, pumpStatus_, 5, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mixer(0x41) -> Me(0x0B), UBAParameterWW(0x33), data: 08 FF 46 FB FF 28 FF 07 46 00 FF 00
|
||||||
|
void Mixer::process_IPMParameterWW(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
// has_update(telegram, wwActivated_, 1); // 0xFF means on
|
||||||
|
// has_update(telegram, wwSelTemp_, 2);
|
||||||
|
has_update(telegram, wwHystOn_, 3); // Hyst on (default -5)
|
||||||
|
has_update(telegram, wwHystOff_, 4); // Hyst off (default -1)
|
||||||
|
has_update(telegram, wwFlowTempOffset_, 5); // default 40
|
||||||
|
has_update(telegram, wwCircPump_, 6); // 0xFF means on
|
||||||
|
has_update(telegram, wwCircMode_, 7); // 1=1x3min 6=6x3min 7=continuous
|
||||||
|
has_update(telegram, wwDisinfectionTemp_, 8);
|
||||||
|
// has_bitupdate(telegram, wwChargeType_, 10, 0); // 0 = charge pump, 0xff = 3-way valve
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 0x1E, only16 bit temperature
|
||||||
|
// Mixer(0x41) -> Boiler(0x08), HydrTemp(0x1E), data: 01 D8
|
||||||
|
void Mixer::process_IPMHydrTemp(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
has_update(telegram, HydrTemp_, 0);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
@@ -241,6 +304,15 @@ void Mixer::process_IPMSetMessage(std::shared_ptr<const Telegram> telegram) {
|
|||||||
|
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
bool Mixer::set_wwSelTemp(const char * value, const int8_t id) {
|
||||||
|
int temperature;
|
||||||
|
if (!Helpers::value2temperature(value, temperature)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0x35, 3, (uint8_t)temperature, 0x34);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Mixer::set_flowSetTemp(const char * value, const int8_t id) {
|
bool Mixer::set_flowSetTemp(const char * value, const int8_t id) {
|
||||||
int v;
|
int v;
|
||||||
if (!Helpers::value2number(value, v)) {
|
if (!Helpers::value2number(value, v)) {
|
||||||
@@ -349,34 +421,72 @@ bool Mixer::set_wwRequiredTemp(const char * value, const int8_t id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Mixer::set_wwDisinfectionTemp(const char * value, const int8_t id) {
|
bool Mixer::set_wwDisinfectionTemp(const char * value, const int8_t id) {
|
||||||
uint8_t wwc = device_id() - 0x28;
|
|
||||||
float v = 0;
|
float v = 0;
|
||||||
if (!Helpers::value2temperature(value, v)) {
|
if (!Helpers::value2temperature(value, v)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) {
|
||||||
|
write_command(0x33, 8, (uint8_t)v, 0x33);
|
||||||
|
} else {
|
||||||
|
uint8_t wwc = device_id() - 0x28;
|
||||||
write_command(0x313 + wwc, 9, (uint8_t)v, 0x313 + wwc);
|
write_command(0x313 + wwc, 9, (uint8_t)v, 0x313 + wwc);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mixer::set_wwCircPump(const char * value, const int8_t id) {
|
bool Mixer::set_wwCircPump(const char * value, const int8_t id) {
|
||||||
uint8_t wwc = device_id() - 0x28;
|
|
||||||
bool v = false;
|
bool v = false;
|
||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, v)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) {
|
||||||
|
write_command(0x33, 6, v ? 0xFF : 0x00, 0x33);
|
||||||
|
} else {
|
||||||
|
uint8_t wwc = device_id() - 0x28;
|
||||||
write_command(0x33B + wwc, 0, v ? 0x01 : 0x00, 0x33B + wwc);
|
write_command(0x33B + wwc, 0, v ? 0x01 : 0x00, 0x33B + wwc);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mixer::set_wwCircMode(const char * value, const int8_t id) {
|
bool Mixer::set_wwCircMode(const char * value, const int8_t id) {
|
||||||
uint8_t wwc = device_id() - 0x28;
|
|
||||||
uint8_t n;
|
uint8_t n;
|
||||||
if (!Helpers::value2enum(value, n, FL_(enum_wwCircMode))) {
|
if (!Helpers::value2enum(value, n, FL_(enum_wwCircMode))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) {
|
||||||
|
write_command(0x33, 7, n, 0x33);
|
||||||
|
} else {
|
||||||
|
uint8_t wwc = device_id() - 0x28;
|
||||||
write_command(0x313 + wwc, 0, n, 0x313 + wwc);
|
write_command(0x313 + wwc, 0, n, 0x313 + wwc);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Mixer::set_wwFlowTempOffset(const char * value, const int8_t id) {
|
||||||
|
int n;
|
||||||
|
if (!Helpers::value2number(value, n)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0x33, 5, n, 0x33);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mixer::set_wwHystOn(const char * value, const int8_t id) {
|
||||||
|
int n;
|
||||||
|
if (!Helpers::value2number(value, n)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0x33, 3, n, 0x33);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mixer::set_wwHystOff(const char * value, const int8_t id) {
|
||||||
|
int n;
|
||||||
|
if (!Helpers::value2number(value, n)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0x33, 4, n, 0x33);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ class Mixer : public EMSdevice {
|
|||||||
void process_MMSetMessage(std::shared_ptr<const Telegram> telegram);
|
void process_MMSetMessage(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_HpPoolStatus(std::shared_ptr<const Telegram> telegram);
|
void process_HpPoolStatus(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|
||||||
|
void process_IPMMonitorWW(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_IPMHydrTemp(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_IPMParameterWW(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|
||||||
bool set_flowSetTemp(const char * value, const int8_t id);
|
bool set_flowSetTemp(const char * value, const int8_t id);
|
||||||
bool set_pump(const char * value, const int8_t id);
|
bool set_pump(const char * value, const int8_t id);
|
||||||
bool set_activated(const char * value, const int8_t id);
|
bool set_activated(const char * value, const int8_t id);
|
||||||
@@ -56,6 +60,10 @@ class Mixer : public EMSdevice {
|
|||||||
bool set_wwCircPump(const char * value, const int8_t id);
|
bool set_wwCircPump(const char * value, const int8_t id);
|
||||||
bool set_wwCircMode(const char * value, const int8_t id);
|
bool set_wwCircMode(const char * value, const int8_t id);
|
||||||
|
|
||||||
|
bool set_wwSelTemp(const char * value, const int8_t id);
|
||||||
|
bool set_wwFlowTempOffset(const char * value, const int8_t id);
|
||||||
|
bool set_wwHystOn(const char * value, const int8_t id);
|
||||||
|
bool set_wwHystOff(const char * value, const int8_t id);
|
||||||
|
|
||||||
enum class Type {
|
enum class Type {
|
||||||
NONE,
|
NONE,
|
||||||
@@ -90,6 +98,14 @@ class Mixer : public EMSdevice {
|
|||||||
Type type_ = Type::NONE;
|
Type type_ = Type::NONE;
|
||||||
uint16_t hc_ = EMS_VALUE_USHORT_NOTSET;
|
uint16_t hc_ = EMS_VALUE_USHORT_NOTSET;
|
||||||
uint8_t poolShuntStatus__ = EMS_VALUE_UINT_NOTSET; // temp value
|
uint8_t poolShuntStatus__ = EMS_VALUE_UINT_NOTSET; // temp value
|
||||||
|
|
||||||
|
uint8_t wwSelTemp_;
|
||||||
|
uint16_t wwCurTemp_1_;
|
||||||
|
uint16_t wwCurTemp_2_;
|
||||||
|
uint16_t HydrTemp_;
|
||||||
|
int8_t wwHystOn_; // Hyst on (default -5)
|
||||||
|
int8_t wwHystOff_; // Hyst off (default -1)
|
||||||
|
uint8_t wwFlowTempOffset_; // default 40
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) {
|
||||||
if (device_id == 0x2A) {
|
if (device_id == 0x2A) { // SM100 DHW
|
||||||
register_telegram_type(0x07D6, F("SM100wwTemperature"), false, MAKE_PF_CB(process_SM100wwTemperature));
|
register_telegram_type(0x07D6, F("SM100wwTemperature"), false, MAKE_PF_CB(process_SM100wwTemperature));
|
||||||
register_telegram_type(0x07AA, F("SM100wwStatus"), false, MAKE_PF_CB(process_SM100wwStatus));
|
register_telegram_type(0x07AA, F("SM100wwStatus"), false, MAKE_PF_CB(process_SM100wwStatus));
|
||||||
register_telegram_type(0x07AB, F("SM100wwCommand"), false, MAKE_PF_CB(process_SM100wwCommand));
|
register_telegram_type(0x07AB, F("SM100wwCommand"), false, MAKE_PF_CB(process_SM100wwCommand));
|
||||||
@@ -65,11 +65,11 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) {
|
||||||
register_telegram_type(0x0103, F("ISM1StatusMessage"), true, MAKE_PF_CB(process_ISM1StatusMessage));
|
register_telegram_type(0x0103, F("ISM1StatusMessage"), true, MAKE_PF_CB(process_ISM1StatusMessage));
|
||||||
register_telegram_type(0x0101, F("ISM1Set"), true, MAKE_PF_CB(process_ISM1Set));
|
register_telegram_type(0x0101, F("ISM1Set"), true, MAKE_PF_CB(process_ISM1Set));
|
||||||
|
register_telegram_type(0x0104, F("ISM2StatusMessage"), false, MAKE_PF_CB(process_ISM2StatusMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
// device values...
|
// device values...
|
||||||
|
// special case for a SM100 DHW device_id with 0x2A where it's not actual a solar module
|
||||||
// special case for a device_id with 0x2A where it's not actual a solar module
|
|
||||||
if (device_id == 0x2A) {
|
if (device_id == 0x2A) {
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwTemp_1_, DeviceValueType::USHORT, FL_(div10), FL_(wwTemp1), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwTemp_1_, DeviceValueType::USHORT, FL_(div10), FL_(wwTemp1), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwTemp_3_, DeviceValueType::USHORT, FL_(div10), FL_(wwTemp3), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwTemp_3_, DeviceValueType::USHORT, FL_(div10), FL_(wwTemp3), DeviceValueUOM::DEGREES);
|
||||||
@@ -84,8 +84,13 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
FL_(wwMaxTemp),
|
FL_(wwMaxTemp),
|
||||||
DeviceValueUOM::DEGREES,
|
DeviceValueUOM::DEGREES,
|
||||||
MAKE_CF_CB(set_wwMaxTemp));
|
MAKE_CF_CB(set_wwMaxTemp));
|
||||||
register_device_value(
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW,
|
||||||
DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwTemp_, DeviceValueType::UINT, nullptr, FL_(wwTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwTemp));
|
&wwSelTemp_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
nullptr,
|
||||||
|
FL_(wwSelTemp),
|
||||||
|
DeviceValueUOM::DEGREES,
|
||||||
|
MAKE_CF_CB(set_wwSelTemp));
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW,
|
||||||
&wwRedTemp_,
|
&wwRedTemp_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
@@ -128,6 +133,7 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// common solar values for all modules (except dhw)
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &collectorTemp_, DeviceValueType::SHORT, FL_(div10), FL_(collectorTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &collectorTemp_, DeviceValueType::SHORT, FL_(div10), FL_(collectorTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylBottomTemp_, DeviceValueType::SHORT, FL_(div10), FL_(cylBottomTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylBottomTemp_, DeviceValueType::SHORT, FL_(div10), FL_(cylBottomTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &solarPump_, DeviceValueType::BOOL, nullptr, FL_(solarPump), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &solarPump_, DeviceValueType::BOOL, nullptr, FL_(solarPump), DeviceValueUOM::NONE);
|
||||||
@@ -137,6 +143,7 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylHeated_, DeviceValueType::BOOL, nullptr, FL_(cylHeated), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylHeated_, DeviceValueType::BOOL, nullptr, FL_(cylHeated), DeviceValueUOM::NONE);
|
||||||
|
|
||||||
|
// values per device flag
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM10) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM10) {
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &solarPumpMod_, DeviceValueType::UINT, nullptr, FL_(solarPumpMod), DeviceValueUOM::PERCENT);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &solarPumpMod_, DeviceValueType::UINT, nullptr, FL_(solarPumpMod), DeviceValueUOM::PERCENT);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
@@ -191,6 +198,9 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) {
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylMiddleTemp_, DeviceValueType::SHORT, FL_(div10), FL_(cylMiddleTemp), DeviceValueUOM::DEGREES);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &retHeatAssist_, DeviceValueType::SHORT, FL_(div10), FL_(retHeatAssist), DeviceValueUOM::DEGREES);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &m1Valve_, DeviceValueType::BOOL, nullptr, FL_(m1Valve), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &energyLastHour_, DeviceValueType::ULONG, FL_(div10), FL_(energyLastHour), DeviceValueUOM::WH);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &energyLastHour_, DeviceValueType::ULONG, FL_(div10), FL_(energyLastHour), DeviceValueUOM::WH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,7 +618,7 @@ void Solar::process_SM100wwStatus(std::shared_ptr<const Telegram> telegram) {
|
|||||||
// data: FF 05 0F 5F 00 01 3C 3C 3C 3C 28 12 46 01 3C 1E 03 07 3C 00 0F 00 05
|
// data: FF 05 0F 5F 00 01 3C 3C 3C 3C 28 12 46 01 3C 1E 03 07 3C 00 0F 00 05
|
||||||
void Solar::process_SM100wwParam(std::shared_ptr<const Telegram> telegram) {
|
void Solar::process_SM100wwParam(std::shared_ptr<const Telegram> telegram) {
|
||||||
has_update(telegram, wwMaxTemp_, 8);
|
has_update(telegram, wwMaxTemp_, 8);
|
||||||
has_update(telegram, wwTemp_, 9);
|
has_update(telegram, wwSelTemp_, 9);
|
||||||
has_update(telegram, wwRedTemp_, 10);
|
has_update(telegram, wwRedTemp_, 10);
|
||||||
has_update(telegram, wwDailyTemp_, 6);
|
has_update(telegram, wwDailyTemp_, 6);
|
||||||
has_update(telegram, wwDisinfectionTemp_, 12);
|
has_update(telegram, wwDisinfectionTemp_, 12);
|
||||||
@@ -788,6 +798,18 @@ void Solar::process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram)
|
|||||||
has_bitupdate(telegram, cylHeated_, 9, 2); // cyl full
|
has_bitupdate(telegram, cylHeated_, 9, 2); // cyl full
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Junkers ISM12 Solar Module - type 0x0104 EMS+ for heat assist
|
||||||
|
* ?(0x103), data: 00 00 00 00 00 7A 01 15 00 00 05 37 F0
|
||||||
|
* ?(0x104), data: 01 A9 01 22 27 0F 27 0F 27 0F 27 0F 27 0F 27 0F
|
||||||
|
* ?(0x104), data: 01 01 00 00 00 00 00 27 0F 27 0F (offset 16)
|
||||||
|
*/
|
||||||
|
void Solar::process_ISM2StatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
has_update(telegram, cylMiddleTemp_, 0); // Temperature Middle of Solar Boiler cyl
|
||||||
|
has_update(telegram, retHeatAssist_, 2); // return temperature from heating T4
|
||||||
|
has_bitupdate(telegram, m1Valve_, 17, 0); // return valve DUW1 (also 16,0)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Junkers ISM1 Solar Module - type 0x0101 EMS+ for setting values
|
* Junkers ISM1 Solar Module - type 0x0101 EMS+ for setting values
|
||||||
*/
|
*/
|
||||||
@@ -943,54 +965,54 @@ bool Solar::set_SM10MaxFlow(const char * value, const int8_t id) {
|
|||||||
|
|
||||||
// switch heat transfer system on/off
|
// switch heat transfer system on/off
|
||||||
bool Solar::set_heatTransferSystem(const char * value, const int8_t id) {
|
bool Solar::set_heatTransferSystem(const char * value, const int8_t id) {
|
||||||
bool v = false;
|
bool b;
|
||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, b)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x358, 5, v ? 0x01 : 0x00, 0x358);
|
write_command(0x358, 5, b ? 0x01 : 0x00, 0x358);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch external cylinder on/off
|
// switch external cylinder on/off
|
||||||
bool Solar::set_externalCyl(const char * value, const int8_t id) {
|
bool Solar::set_externalCyl(const char * value, const int8_t id) {
|
||||||
bool v = false;
|
bool b;
|
||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, b)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x358, 9, v ? 0x01 : 0x00, 0x358);
|
write_command(0x358, 9, b ? 0x01 : 0x00, 0x358);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch thermal disinfection on/off
|
// switch thermal disinfection on/off
|
||||||
bool Solar::set_thermalDisinfect(const char * value, const int8_t id) {
|
bool Solar::set_thermalDisinfect(const char * value, const int8_t id) {
|
||||||
bool v = false;
|
bool b;
|
||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, b)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x358, 10, v ? 0x01 : 0x00, 0x358);
|
write_command(0x358, 10, b ? 0x01 : 0x00, 0x358);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch heat metering on/off
|
// switch heat metering on/off
|
||||||
bool Solar::set_heatMetering(const char * value, const int8_t id) {
|
bool Solar::set_heatMetering(const char * value, const int8_t id) {
|
||||||
bool v = false;
|
bool b;
|
||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, b)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x358, 14, v ? 0x01 : 0x00, 0x358);
|
write_command(0x358, 14, b ? 0x01 : 0x00, 0x358);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch solar system on/off
|
// switch solar system on/off
|
||||||
bool Solar::set_solarEnabled(const char * value, const int8_t id) {
|
bool Solar::set_solarEnabled(const char * value, const int8_t id) {
|
||||||
bool v = false;
|
bool b;
|
||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, b)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (flags() == EMSdevice::EMS_DEVICE_FLAG_SM10) {
|
if (flags() == EMSdevice::EMS_DEVICE_FLAG_SM10) {
|
||||||
write_command(0x96, 0, v ? 0xFF : 0x00, 0x96);
|
write_command(0x96, 0, b ? 0xFF : 0x00, 0x96);
|
||||||
} else {
|
} else {
|
||||||
write_command(0x358, 19, v ? 0x01 : 0x00, 0x358);
|
write_command(0x358, 19, b ? 0x01 : 0x00, 0x358);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1018,71 +1040,71 @@ bool Solar::set_solarMode2(const char * value, const int8_t id) {
|
|||||||
|
|
||||||
// switch pumpkick on/off
|
// switch pumpkick on/off
|
||||||
bool Solar::set_solarPumpKick(const char * value, const int8_t id) {
|
bool Solar::set_solarPumpKick(const char * value, const int8_t id) {
|
||||||
bool v = false;
|
bool b;
|
||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, b)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x35A, 9, v ? 0x01 : 0x00, 0x35A);
|
write_command(0x35A, 9, b ? 0x01 : 0x00, 0x35A);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch pump2kick on/off
|
// switch pump2kick on/off
|
||||||
bool Solar::set_solarPump2Kick(const char * value, const int8_t id) {
|
bool Solar::set_solarPump2Kick(const char * value, const int8_t id) {
|
||||||
bool v = false;
|
bool b;
|
||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, b)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x35D, 0, v ? 0x01 : 0x00, 0x35D);
|
write_command(0x35D, 0, b ? 0x01 : 0x00, 0x35D);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch plain water mode on/off
|
// switch plain water mode on/off
|
||||||
bool Solar::set_plainWaterMode(const char * value, const int8_t id) {
|
bool Solar::set_plainWaterMode(const char * value, const int8_t id) {
|
||||||
bool v = false;
|
bool b;
|
||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, b)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x35A, 10, v ? 0x01 : 0x00, 0x35A);
|
write_command(0x35A, 10, b ? 0x01 : 0x00, 0x35A);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch double match flow on/off
|
// switch double match flow on/off
|
||||||
bool Solar::set_doubleMatchFlow(const char * value, const int8_t id) {
|
bool Solar::set_doubleMatchFlow(const char * value, const int8_t id) {
|
||||||
bool v = false;
|
bool b;
|
||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, b)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x35A, 11, v ? 0x01 : 0x00, 0x35A);
|
write_command(0x35A, 11, b ? 0x01 : 0x00, 0x35A);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set climate zone number
|
// set climate zone number
|
||||||
bool Solar::set_climateZone(const char * value, const int8_t id) {
|
bool Solar::set_climateZone(const char * value, const int8_t id) {
|
||||||
int v = 0;
|
int zone;
|
||||||
if (!Helpers::value2number(value, v)) {
|
if (!Helpers::value2number(value, zone)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x380, 0, v, 0x380);
|
write_command(0x380, 0, zone, 0x380);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// collector area in squaremeters
|
// collector area in squaremeters
|
||||||
bool Solar::set_collector1Area(const char * value, const int8_t id) {
|
bool Solar::set_collector1Area(const char * value, const int8_t id) {
|
||||||
float v = 0;
|
float area;
|
||||||
if (!Helpers::value2float(value, v)) {
|
if (!Helpers::value2float(value, area)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x380, 3, (uint16_t)(v * 10), 0x380);
|
write_command(0x380, 3, (uint16_t)(area * 10), 0x380);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// collector area in squaremeters
|
// collector area in squaremeters
|
||||||
bool Solar::set_collector2Area(const char * value, const int8_t id) {
|
bool Solar::set_collector2Area(const char * value, const int8_t id) {
|
||||||
float v = 0;
|
float area;
|
||||||
if (!Helpers::value2float(value, v)) {
|
if (!Helpers::value2float(value, area)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x380, 6, (uint16_t)(v * 10), 0x380);
|
write_command(0x380, 6, (uint16_t)(area * 10), 0x380);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1108,101 +1130,101 @@ bool Solar::set_collector2Type(const char * value, const int8_t id) {
|
|||||||
|
|
||||||
// priority of cylinders if there are 2
|
// priority of cylinders if there are 2
|
||||||
bool Solar::set_cylPriority(const char * value, const int8_t id) {
|
bool Solar::set_cylPriority(const char * value, const int8_t id) {
|
||||||
uint8_t n;
|
uint8_t num;
|
||||||
if (!Helpers::value2enum(value, n, FL_(enum_cylprio))) {
|
if (!Helpers::value2enum(value, num, FL_(enum_cylprio))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x35F, 3, n, 0x35F);
|
write_command(0x35F, 3, num, 0x35F);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Solar::set_heatAssist(const char * value, const int8_t id) {
|
bool Solar::set_heatAssist(const char * value, const int8_t id) {
|
||||||
float v = 0;
|
float temperature;
|
||||||
if (!Helpers::value2temperature(value, v)) {
|
if (!Helpers::value2temperature(value, temperature)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x35C, 0, (uint8_t)(v * 10), 0x35C);
|
write_command(0x35C, 0, (uint8_t)(temperature * 10), 0x35C);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Solar::set_diffControl(const char * value, const int8_t id) {
|
bool Solar::set_diffControl(const char * value, const int8_t id) {
|
||||||
float v = 0;
|
float temperature;
|
||||||
if (!Helpers::value2temperature(value, v)) {
|
if (!Helpers::value2temperature(value, temperature)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x361, 4, (uint8_t)(v * 10), 0x361);
|
write_command(0x361, 4, (uint8_t)(temperature * 10), 0x361);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Solar::set_wwTemp(const char * value, const int8_t id) {
|
bool Solar::set_wwSelTemp(const char * value, const int8_t id) {
|
||||||
float v = 0;
|
int temperature;
|
||||||
if (!Helpers::value2temperature(value, v)) {
|
if (!Helpers::value2temperature(value, temperature)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x7A6, 9, (uint8_t)v, 0x7A6);
|
write_command(0x7A6, 9, (uint8_t)temperature, 0x7A6);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Solar::set_wwMaxTemp(const char * value, const int8_t id) {
|
bool Solar::set_wwMaxTemp(const char * value, const int8_t id) {
|
||||||
float v = 0;
|
int temperature;
|
||||||
if (!Helpers::value2temperature(value, v)) {
|
if (!Helpers::value2temperature(value, temperature)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x7A6, 8, (uint8_t)v, 0x7A6);
|
write_command(0x7A6, 8, (uint8_t)temperature, 0x7A6);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Solar::set_wwRedTemp(const char * value, const int8_t id) {
|
bool Solar::set_wwRedTemp(const char * value, const int8_t id) {
|
||||||
float v = 0;
|
int temperature;
|
||||||
if (!Helpers::value2temperature(value, v)) {
|
if (!Helpers::value2temperature(value, temperature)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x7A6, 10, (uint8_t)v, 0x7A6);
|
write_command(0x7A6, 10, (uint8_t)temperature, 0x7A6);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Solar::set_wwDailyTemp(const char * value, const int8_t id) {
|
bool Solar::set_wwDailyTemp(const char * value, const int8_t id) {
|
||||||
float v = 0;
|
int temperature;
|
||||||
if (!Helpers::value2temperature(value, v)) {
|
if (!Helpers::value2temperature(value, temperature)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x7A6, 6, (uint8_t)v, 0x7A6);
|
write_command(0x7A6, 6, (uint8_t)temperature, 0x7A6);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Solar::set_wwDisinfectionTemp(const char * value, const int8_t id) {
|
bool Solar::set_wwDisinfectionTemp(const char * value, const int8_t id) {
|
||||||
float v = 0;
|
int temperature;
|
||||||
if (!Helpers::value2temperature(value, v)) {
|
if (!Helpers::value2temperature(value, temperature)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x7A6, 12, (uint8_t)v, 0x7A6);
|
write_command(0x7A6, 12, (uint8_t)temperature, 0x7A6);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Solar::set_wwCirc(const char * value, const int8_t id) {
|
bool Solar::set_wwCirc(const char * value, const int8_t id) {
|
||||||
bool v = false;
|
bool b;
|
||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, b)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x7A5, 0, v ? 0xFF : 0x00, 0x7A5);
|
write_command(0x7A5, 0, b ? 0xFF : 0x00, 0x7A5);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Solar::set_wwCircMode(const char * value, const int8_t id) {
|
bool Solar::set_wwCircMode(const char * value, const int8_t id) {
|
||||||
uint8_t n;
|
uint8_t num;
|
||||||
if (!Helpers::value2enum(value, n, FL_(enum_wwCircMode))) {
|
if (!Helpers::value2enum(value, num, FL_(enum_wwCircMode))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x7A5, 3, n, 0x7A5);
|
write_command(0x7A5, 3, num, 0x7A5);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Solar::set_wwKeepWarm(const char * value, const int8_t id) {
|
bool Solar::set_wwKeepWarm(const char * value, const int8_t id) {
|
||||||
bool v = false;
|
bool b;
|
||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, b)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write_command(0x7AE, 0, v ? 0xFF : 0x00, 0x7AE);
|
write_command(0x7AE, 0, b ? 0xFF : 0x00, 0x7AE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ class Solar : public EMSdevice {
|
|||||||
|
|
||||||
// SM100wwParam - 0x07A6
|
// SM100wwParam - 0x07A6
|
||||||
uint8_t wwMaxTemp_;
|
uint8_t wwMaxTemp_;
|
||||||
uint8_t wwTemp_;
|
uint8_t wwSelTemp_;
|
||||||
uint8_t wwRedTemp_;
|
uint8_t wwRedTemp_;
|
||||||
uint8_t wwDailyTemp_;
|
uint8_t wwDailyTemp_;
|
||||||
uint8_t wwDisinfectionTemp_;
|
uint8_t wwDisinfectionTemp_;
|
||||||
@@ -187,8 +187,9 @@ class Solar : public EMSdevice {
|
|||||||
|
|
||||||
void process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram);
|
void process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_ISM1Set(std::shared_ptr<const Telegram> telegram);
|
void process_ISM1Set(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_ISM2StatusMessage(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|
||||||
|
// settings
|
||||||
bool set_CollectorMaxTemp(const char * value, const int8_t id);
|
bool set_CollectorMaxTemp(const char * value, const int8_t id);
|
||||||
bool set_CollectorMinTemp(const char * value, const int8_t id);
|
bool set_CollectorMinTemp(const char * value, const int8_t id);
|
||||||
bool set_cylMaxTemp(const char * value, const int8_t id);
|
bool set_cylMaxTemp(const char * value, const int8_t id);
|
||||||
@@ -224,7 +225,7 @@ class Solar : public EMSdevice {
|
|||||||
bool set_heatAssist(const char * value, const int8_t id);
|
bool set_heatAssist(const char * value, const int8_t id);
|
||||||
bool set_diffControl(const char * value, const int8_t id);
|
bool set_diffControl(const char * value, const int8_t id);
|
||||||
|
|
||||||
bool set_wwTemp(const char * value, const int8_t id);
|
bool set_wwSelTemp(const char * value, const int8_t id);
|
||||||
bool set_wwMaxTemp(const char * value, const int8_t id);
|
bool set_wwMaxTemp(const char * value, const int8_t id);
|
||||||
bool set_wwRedTemp(const char * value, const int8_t id);
|
bool set_wwRedTemp(const char * value, const int8_t id);
|
||||||
bool set_wwCirc(const char * value, const int8_t id);
|
bool set_wwCirc(const char * value, const int8_t id);
|
||||||
|
|||||||
@@ -146,6 +146,8 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
|||||||
register_telegram_type(set_typeids[i], F("JunkersSet"), false, MAKE_PF_CB(process_JunkersSet));
|
register_telegram_type(set_typeids[i], F("JunkersSet"), false, MAKE_PF_CB(process_JunkersSet));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
register_telegram_type(0xBB, F("HybridSettings"), true, MAKE_PF_CB(process_JunkersHybridSettings));
|
||||||
|
register_telegram_type(0x23, F("JunkersSetMixer"), true, MAKE_PF_CB(process_JunkersSetMixer));
|
||||||
register_telegram_type(0x123, F("JunkersRemote"), false, MAKE_PF_CB(process_JunkersRemoteMonitor));
|
register_telegram_type(0x123, F("JunkersRemote"), false, MAKE_PF_CB(process_JunkersRemoteMonitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,6 +272,11 @@ std::shared_ptr<Thermostat::HeatingCircuit> Thermostat::heating_circuit(std::sha
|
|||||||
toggle_ = true;
|
toggle_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// not found, search device-id types for remote thermostats
|
||||||
|
if (telegram->dest >= 0x20 && telegram->dest <= 0x27) {
|
||||||
|
hc_num = telegram->dest - 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
// still didn't recognize it, ignore it
|
// still didn't recognize it, ignore it
|
||||||
if (hc_num == 0) {
|
if (hc_num == 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -342,8 +349,8 @@ void Thermostat::add_ha_climate(std::shared_ptr<HeatingCircuit> hc) const {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Helpers::hasValue(hc->selTemp) && is_visible(&hc->selTemp)) {
|
if (Helpers::hasValue(hc->selTemp) && is_readable(&hc->selTemp)) {
|
||||||
if (Helpers::hasValue(hc->roomTemp) && is_visible(&hc->roomTemp)) {
|
if (Helpers::hasValue(hc->roomTemp) && is_readable(&hc->roomTemp)) {
|
||||||
hc->climate = 1;
|
hc->climate = 1;
|
||||||
} else {
|
} else {
|
||||||
hc->climate = 0;
|
hc->climate = 0;
|
||||||
@@ -587,7 +594,7 @@ void Thermostat::process_RC20Timer(std::shared_ptr<const Telegram> telegram) {
|
|||||||
char data[sizeof(hc->switchtime1)];
|
char data[sizeof(hc->switchtime1)];
|
||||||
uint8_t no = telegram->offset / 2;
|
uint8_t no = telegram->offset / 2;
|
||||||
uint8_t day = telegram->message_data[0] >> 5;
|
uint8_t day = telegram->message_data[0] >> 5;
|
||||||
uint8_t temp = telegram->message_data[0] & 1;
|
uint8_t temp = telegram->message_data[0] & 7;
|
||||||
uint8_t time = telegram->message_data[1];
|
uint8_t time = telegram->message_data[1];
|
||||||
|
|
||||||
std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day]);
|
std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day]);
|
||||||
@@ -805,6 +812,27 @@ void Thermostat::process_JunkersMonitor(std::shared_ptr<const Telegram> telegram
|
|||||||
add_ha_climate(hc);
|
add_ha_climate(hc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0xBB Heatpump optimization
|
||||||
|
// ?(0xBB), data: 00 00 00 00 00 00 00 00 00 00 00 FF 02 0F 1E 0B 1A 00 14 03
|
||||||
|
void Thermostat::process_JunkersHybridSettings(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
has_enumupdate(telegram, hybridStrategy_, 12, 1); // cost = 2, temperature = 3, mix = 4
|
||||||
|
has_update(telegram, switchOverTemp_, 13); // full degrees
|
||||||
|
has_update(telegram, energyCostRatio_, 14); // is *10
|
||||||
|
has_update(telegram, fossileFactor_, 15); // is * 10
|
||||||
|
has_update(telegram, electricFactor_, 16); // is * 10
|
||||||
|
has_update(telegram, delayBoiler_, 18); // minutes
|
||||||
|
has_update(telegram, tempDiffBoiler_, 19); // relative degrees
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thermostat::process_JunkersSetMixer(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(telegram);
|
||||||
|
if (hc == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
has_update(telegram, hc->targetflowtemp, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// type 0x02A5 - data from Worchester CRF200
|
// type 0x02A5 - data from Worchester CRF200
|
||||||
void Thermostat::process_CRFMonitor(std::shared_ptr<const Telegram> telegram) {
|
void Thermostat::process_CRFMonitor(std::shared_ptr<const Telegram> telegram) {
|
||||||
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(telegram);
|
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(telegram);
|
||||||
@@ -1009,7 +1037,18 @@ void Thermostat::process_RC30Set(std::shared_ptr<const Telegram> telegram) {
|
|||||||
if (hc == nullptr) {
|
if (hc == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
has_update(telegram, ibaLanguage_, 0); // language on Thermostat: 0 german, 1 dutch, 2 french, 3 italian
|
||||||
|
has_update(telegram, ibaCalIntTemperature_, 1); // offset int. temperature sensor, by * 0.1 Kelvin
|
||||||
|
has_update(telegram, autodst_, 2); // Automatic change Daylight Saving time: (0x00 = off, 0xFF = on)
|
||||||
|
has_update(telegram, ibaBuildingType_, 4); // building type: 0 = light, 1 = medium, 2 = heavy
|
||||||
|
has_update(telegram, ibaClockOffset_, 10); // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
|
||||||
|
has_update(telegram, backlight_, 12); // Keyboard lighting: (0x00 = off, 0xFF = on)
|
||||||
|
has_update(telegram, mixingvalves_, 17); // Number of Mixing Valves: (0x00=0, 0x01=1, 0x02=2)
|
||||||
|
has_update(telegram, brightness_, 18); // Screen brightness 0F=dark F1=light
|
||||||
has_update(telegram, hc->mode, 23);
|
has_update(telegram, hc->mode, 23);
|
||||||
|
has_update(telegram, offtemp_, 24); // Set Temperature when mode is Off / 10 (e.g.: 0x0F = 7.5 degrees Celsius)
|
||||||
|
has_update(telegram, heatingpid_, 25); // PID setting 00=1 01=2 02=3
|
||||||
|
has_update(telegram, preheating_, 26); // Preheating in the clock program: (0x00 = off, 0xFF = on)
|
||||||
}
|
}
|
||||||
|
|
||||||
// type 0x3E (HC1), 0x48 (HC2), 0x52 (HC3), 0x5C (HC4) - data from the RC35 thermostat (0x10) - 16 bytes
|
// type 0x3E (HC1), 0x48 (HC2), 0x52 (HC3), 0x5C (HC4) - data from the RC35 thermostat (0x10) - 16 bytes
|
||||||
@@ -1065,12 +1104,16 @@ void Thermostat::process_RC35Set(std::shared_ptr<const Telegram> telegram) {
|
|||||||
has_update(telegram, hc->wwprio, 21); // 0xFF for on
|
has_update(telegram, hc->wwprio, 21); // 0xFF for on
|
||||||
has_update(telegram, hc->summertemp, 22); // is * 1
|
has_update(telegram, hc->summertemp, 22); // is * 1
|
||||||
has_update(telegram, hc->nofrosttemp, 23); // is * 1
|
has_update(telegram, hc->nofrosttemp, 23); // is * 1
|
||||||
|
has_update(telegram, hc->nofrostmode, 28); // 0-off, 1-outdoor, 2-roomtemp 5°C
|
||||||
has_update(telegram, hc->flowtempoffset, 24); // is * 1, only in mixed circuits
|
has_update(telegram, hc->flowtempoffset, 24); // is * 1, only in mixed circuits
|
||||||
has_update(telegram, hc->reducemode, 25); // 0-nofrost, 1-reduce, 2-roomhold, 3-outdoorhold
|
has_update(telegram, hc->reducemode, 25); // 0-nofrost, 1-reduce, 2-roomhold, 3-outdoorhold
|
||||||
has_update(telegram, hc->control, 26); // 0-off, 1-RC20 (remote), 2-RC35
|
has_update(telegram, hc->control, 26); // 0-off, 1-RC20 (remote), 2-RC35
|
||||||
has_update(telegram, hc->controlmode, 33); // 0-outdoortemp, 1-roomtemp
|
has_update(telegram, hc->controlmode, 33); // 0-outdoortemp, 1-roomtemp
|
||||||
has_update(telegram, hc->tempautotemp, 37);
|
has_update(telegram, hc->tempautotemp, 37);
|
||||||
has_update(telegram, hc->noreducetemp, 38); // outdoor temperature for no reduce
|
has_update(telegram, hc->noreducetemp, 38); // outdoor temperature for no reduce
|
||||||
|
has_update(telegram, hc->reducetemp, 39); // temperature for off/reduce
|
||||||
|
has_update(telegram, hc->vacreducetemp, 40); // temperature for off/reduce in vacations
|
||||||
|
has_update(telegram, hc->vacreducemode, 41); // vacations reduce mode
|
||||||
has_update(telegram, hc->minflowtemp, 16);
|
has_update(telegram, hc->minflowtemp, 16);
|
||||||
|
|
||||||
if (hc->heatingtype == 3) { // floor heating
|
if (hc->heatingtype == 3) { // floor heating
|
||||||
@@ -1164,32 +1207,49 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (telegram->message_data[7] & 0x0C) { // date and time not valid
|
if ((telegram->message_data[7] & 0x0C) && has_command(&dateTime_)) { // date and time not valid
|
||||||
set_datetime("ntp", -1); // set from NTP
|
set_datetime("ntp", -1); // set from NTP
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// render date to HH:MM:SS DD/MM/YYYY
|
// check clock
|
||||||
// had to create separate buffers because of how printf works
|
time_t now = time(nullptr);
|
||||||
char date[25];
|
tm * tm_ = localtime(&now);
|
||||||
char buf1[6];
|
bool tset_ = tm_->tm_year > 110; // year 2010 and up, time is valid
|
||||||
char buf2[6];
|
tm_->tm_year = (telegram->message_data[0] & 0x7F) + 100; // IVT
|
||||||
char buf3[6];
|
tm_->tm_mon = telegram->message_data[1] - 1;
|
||||||
char buf4[6];
|
tm_->tm_mday = telegram->message_data[3];
|
||||||
char buf5[6];
|
tm_->tm_hour = telegram->message_data[2];
|
||||||
char buf6[6];
|
tm_->tm_min = telegram->message_data[4];
|
||||||
snprintf(date,
|
tm_->tm_sec = telegram->message_data[5];
|
||||||
sizeof(date),
|
tm_->tm_isdst = telegram->message_data[7] & 0x01;
|
||||||
"%s:%s:%s %s.%s.%s",
|
|
||||||
Helpers::smallitoa(buf1, telegram->message_data[2]), // hour
|
// render date to DD.MM.YYYY HH:MM and publish
|
||||||
Helpers::smallitoa(buf2, telegram->message_data[4]), // minute
|
char newdatetime[sizeof(dateTime_)];
|
||||||
Helpers::smallitoa(buf3, telegram->message_data[5]), // second
|
strftime(newdatetime, sizeof(dateTime_), "%d.%m.%G %H:%M", tm_);
|
||||||
Helpers::smallitoa(buf4, telegram->message_data[3]), // day
|
has_update(dateTime_, newdatetime, sizeof(dateTime_));
|
||||||
Helpers::smallitoa(buf5, telegram->message_data[1]), // month
|
|
||||||
// IVT reports Year with high bit set.?
|
bool ivtclock = (telegram->message_data[0] & 0x80) == 0x80; // dont sync ivt-clock, #439
|
||||||
Helpers::itoa((telegram->message_data[0] & 0x7F) + 2000, buf6) // year
|
time_t ttime = mktime(tm_); // thermostat time
|
||||||
);
|
// correct thermostat clock if we have valid ntp time, and could write the command
|
||||||
has_update(dateTime_, date, sizeof(dateTime_));
|
if (!ivtclock && tset_ && EMSESP::system_.ntp_connected() && !EMSESP::system_.readonly_mode() && has_command(&dateTime_)) {
|
||||||
|
double difference = difftime(now, ttime);
|
||||||
|
if (difference > 15 || difference < -15) {
|
||||||
|
set_datetime("ntp", -1); // set from NTP
|
||||||
|
LOG_INFO(F("thermostat time correction from ntp"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef EMSESP_STANDALONE
|
||||||
|
if (!tset_ && tm_->tm_year > 110) { // emsesp clock not set, but thermostat clock
|
||||||
|
if (ivtclock) {
|
||||||
|
tm_->tm_isdst = -1; // determine dst
|
||||||
|
ttime = mktime(tm_); // thermostat time
|
||||||
|
}
|
||||||
|
struct timeval newnow = {.tv_sec = ttime};
|
||||||
|
settimeofday(&newnow, nullptr);
|
||||||
|
LOG_INFO(F("ems-esp time set from thermostat"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// process_RCError - type 0xA2 - error message - 14 bytes long
|
// process_RCError - type 0xA2 - error message - 14 bytes long
|
||||||
@@ -1237,6 +1297,76 @@ void Thermostat::process_RCErrorMessage(std::shared_ptr<const Telegram> telegram
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* *** settings ***
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 0xBB Hybrid pump
|
||||||
|
bool Thermostat::set_hybridStrategy(const char * value, const int8_t id) {
|
||||||
|
uint8_t v;
|
||||||
|
if (!Helpers::value2enum(value, v, FL_(enum_hybridStrategy))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 12, v + 1, 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_switchOverTemp(const char * value, const int8_t id) {
|
||||||
|
int v;
|
||||||
|
if (!Helpers::value2temperature(value, v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 13, v, 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_energyCostRatio(const char * value, const int8_t id) {
|
||||||
|
float v;
|
||||||
|
if (!Helpers::value2float(value, v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 14, (uint8_t)(v * 10), 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_fossileFactor(const char * value, const int8_t id) {
|
||||||
|
float v;
|
||||||
|
if (!Helpers::value2float(value, v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 15, (uint8_t)(v * 10), 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_electricFactor(const char * value, const int8_t id) {
|
||||||
|
float v;
|
||||||
|
if (!Helpers::value2float(value, v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 16, (uint8_t)(v * 10), 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_delayBoiler(const char * value, const int8_t id) {
|
||||||
|
int v;
|
||||||
|
if (!Helpers::value2number(value, v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 18, v, 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_tempDiffBoiler(const char * value, const int8_t id) {
|
||||||
|
int v;
|
||||||
|
if (!Helpers::value2temperature(value, v, true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(0xBB, 19, v, 0xBB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// 0xA5 - Set minimum external temperature
|
// 0xA5 - Set minimum external temperature
|
||||||
bool Thermostat::set_minexttemp(const char * value, const int8_t id) {
|
bool Thermostat::set_minexttemp(const char * value, const int8_t id) {
|
||||||
int mt = 0;
|
int mt = 0;
|
||||||
@@ -1255,19 +1385,23 @@ bool Thermostat::set_minexttemp(const char * value, const int8_t id) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0xA5 - Clock offset
|
// 0xA5/0xA7 - Clock offset
|
||||||
bool Thermostat::set_clockoffset(const char * value, const int8_t id) {
|
bool Thermostat::set_clockoffset(const char * value, const int8_t id) {
|
||||||
int co = 0;
|
int co = 0;
|
||||||
if (!Helpers::value2number(value, co)) {
|
if (!Helpers::value2number(value, co)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (model() == EMS_DEVICE_FLAG_RC30) {
|
||||||
|
write_command(EMS_TYPE_RC30Settings, 10, co, EMS_TYPE_RC30Settings);
|
||||||
|
} else {
|
||||||
write_command(EMS_TYPE_IBASettings, 12, co, EMS_TYPE_IBASettings);
|
write_command(EMS_TYPE_IBASettings, 12, co, EMS_TYPE_IBASettings);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0xA5 - Calibrate internal temperature
|
// 0xA5/0xA7 - Calibrate internal temperature
|
||||||
bool Thermostat::set_calinttemp(const char * value, const int8_t id) {
|
bool Thermostat::set_calinttemp(const char * value, const int8_t id) {
|
||||||
float ct = 0;
|
float ct = 0;
|
||||||
if (!Helpers::value2temperature(value, ct, true)) {
|
if (!Helpers::value2temperature(value, ct, true)) {
|
||||||
@@ -1279,6 +1413,8 @@ bool Thermostat::set_calinttemp(const char * value, const int8_t id) {
|
|||||||
|
|
||||||
if (model() == EMS_DEVICE_FLAG_RC10) {
|
if (model() == EMS_DEVICE_FLAG_RC10) {
|
||||||
write_command(0xB0, 0, t, 0xB0);
|
write_command(0xB0, 0, t, 0xB0);
|
||||||
|
} else if (model() == EMS_DEVICE_FLAG_RC30) {
|
||||||
|
write_command(EMS_TYPE_RC30Settings, 1, t, EMS_TYPE_RC30Settings);
|
||||||
} else {
|
} else {
|
||||||
write_command(EMS_TYPE_IBASettings, 2, t, EMS_TYPE_IBASettings);
|
write_command(EMS_TYPE_IBASettings, 2, t, EMS_TYPE_IBASettings);
|
||||||
}
|
}
|
||||||
@@ -1298,6 +1434,18 @@ bool Thermostat::set_display(const char * value, const int8_t id) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0xA7 - Set Screen brightness
|
||||||
|
bool Thermostat::set_brightness(const char * value, const int8_t id) {
|
||||||
|
int bo = 0;
|
||||||
|
if (!Helpers::value2number(value, bo, -15, 15)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_command(EMS_TYPE_RC30Settings, 18, bo, EMS_TYPE_RC30Settings);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Thermostat::set_remotetemp(const char * value, const int8_t id) {
|
bool Thermostat::set_remotetemp(const char * value, const int8_t id) {
|
||||||
float f = 0;
|
float f = 0;
|
||||||
if (!Helpers::value2temperature(value, f)) {
|
if (!Helpers::value2temperature(value, f)) {
|
||||||
@@ -1321,7 +1469,7 @@ bool Thermostat::set_remotetemp(const char * value, const int8_t id) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0xA5 - Set the building settings
|
// 0xA5/0xA7 - Set the building settings
|
||||||
bool Thermostat::set_building(const char * value, const int8_t id) {
|
bool Thermostat::set_building(const char * value, const int8_t id) {
|
||||||
uint8_t bd = 0;
|
uint8_t bd = 0;
|
||||||
if (!Helpers::value2enum(value, bd, FL_(enum_ibaBuildingType))) {
|
if (!Helpers::value2enum(value, bd, FL_(enum_ibaBuildingType))) {
|
||||||
@@ -1330,6 +1478,8 @@ bool Thermostat::set_building(const char * value, const int8_t id) {
|
|||||||
|
|
||||||
if ((model() == EMS_DEVICE_FLAG_RC300) || (model() == EMS_DEVICE_FLAG_RC100)) {
|
if ((model() == EMS_DEVICE_FLAG_RC300) || (model() == EMS_DEVICE_FLAG_RC100)) {
|
||||||
write_command(0x240, 9, bd + 1, 0x240);
|
write_command(0x240, 9, bd + 1, 0x240);
|
||||||
|
} else if (model() == EMS_DEVICE_FLAG_RC30) {
|
||||||
|
write_command(EMS_TYPE_RC30Settings, 4, bd, EMS_TYPE_RC30Settings);
|
||||||
} else {
|
} else {
|
||||||
write_command(EMS_TYPE_IBASettings, 6, bd, EMS_TYPE_IBASettings);
|
write_command(EMS_TYPE_IBASettings, 6, bd, EMS_TYPE_IBASettings);
|
||||||
}
|
}
|
||||||
@@ -1337,7 +1487,7 @@ bool Thermostat::set_building(const char * value, const int8_t id) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0xB0 - Set RC10 heating pid
|
// 0xB0/0xA7 - Set RC10 heating pid
|
||||||
bool Thermostat::set_heatingpid(const char * value, const int8_t id) {
|
bool Thermostat::set_heatingpid(const char * value, const int8_t id) {
|
||||||
uint8_t pid = 0;
|
uint8_t pid = 0;
|
||||||
if (!Helpers::value2enum(value, pid, FL_(enum_PID))) {
|
if (!Helpers::value2enum(value, pid, FL_(enum_PID))) {
|
||||||
@@ -1346,12 +1496,14 @@ bool Thermostat::set_heatingpid(const char * value, const int8_t id) {
|
|||||||
|
|
||||||
if (model() == EMS_DEVICE_FLAG_RC10) {
|
if (model() == EMS_DEVICE_FLAG_RC10) {
|
||||||
write_command(0xB0, 6, pid, 0xB0);
|
write_command(0xB0, 6, pid, 0xB0);
|
||||||
|
} else if (model() == EMS_DEVICE_FLAG_RC30) {
|
||||||
|
write_command(EMS_TYPE_RC30Settings, 25, pid, EMS_TYPE_RC30Settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0xA5 - Set the building settings
|
// 0xA5 - Set the damping settings
|
||||||
bool Thermostat::set_damping(const char * value, const int8_t id) {
|
bool Thermostat::set_damping(const char * value, const int8_t id) {
|
||||||
bool dmp;
|
bool dmp;
|
||||||
if (Helpers::value2bool(value, dmp)) {
|
if (Helpers::value2bool(value, dmp)) {
|
||||||
@@ -1362,14 +1514,21 @@ bool Thermostat::set_damping(const char * value, const int8_t id) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0xA5 Set the language settings
|
// 0xA5/0xA7 Set the language settings
|
||||||
bool Thermostat::set_language(const char * value, const int8_t id) {
|
bool Thermostat::set_language(const char * value, const int8_t id) {
|
||||||
uint8_t lg = 0;
|
uint8_t lg = 0;
|
||||||
|
|
||||||
|
if (model() == EMS_DEVICE_FLAG_RC30) {
|
||||||
|
if (!Helpers::value2enum(value, lg, FL_(enum_ibaLanguage_RC30))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(EMS_TYPE_RC30Settings, 0, lg, EMS_TYPE_RC30Settings);
|
||||||
|
} else {
|
||||||
if (!Helpers::value2enum(value, lg, FL_(enum_ibaLanguage))) {
|
if (!Helpers::value2enum(value, lg, FL_(enum_ibaLanguage))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_command(EMS_TYPE_IBASettings, 1, lg, EMS_TYPE_IBASettings);
|
write_command(EMS_TYPE_IBASettings, 1, lg, EMS_TYPE_IBASettings);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1389,7 +1548,7 @@ bool Thermostat::set_control(const char * value, const int8_t id) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (Helpers::value2enum(value, ctrl, FL_(enum_control))) {
|
} else if (Helpers::value2enum(value, ctrl, FL_(enum_control))) {
|
||||||
write_command(set_typeids[hc->hc()], 26, ctrl);
|
write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_control, ctrl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1602,14 +1761,63 @@ bool Thermostat::set_wwOneTimeKey(const char * value, const int8_t id) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only RC10, 0xB0
|
// for RC10, 0xB0 or RC30, 0xA7
|
||||||
bool Thermostat::set_backlight(const char * value, const int8_t id) {
|
bool Thermostat::set_backlight(const char * value, const int8_t id) {
|
||||||
bool b = false;
|
bool b = false;
|
||||||
if (!Helpers::value2bool(value, b)) {
|
if (!Helpers::value2bool(value, b)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (model() == EMS_DEVICE_FLAG_RC30) {
|
||||||
|
write_command(EMS_TYPE_RC30Settings, 12, b ? 0xFF : 0x00, EMS_TYPE_RC30Settings);
|
||||||
|
} else {
|
||||||
write_command(0xB0, 1, b ? 0xFF : 0x00, 0xB0);
|
write_command(0xB0, 1, b ? 0xFF : 0x00, 0xB0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_autodst(const char * value, const int8_t id) {
|
||||||
|
bool b = false;
|
||||||
|
if (!Helpers::value2bool(value, b)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_command(EMS_TYPE_RC30Settings, 2, b ? 0xFF : 0x00, EMS_TYPE_RC30Settings);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_preheating(const char * value, const int8_t id) {
|
||||||
|
bool b = false;
|
||||||
|
if (!Helpers::value2bool(value, b)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_command(EMS_TYPE_RC30Settings, 26, b ? 0xFF : 0x00, EMS_TYPE_RC30Settings);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_offtemp(const char * value, const int8_t id) {
|
||||||
|
int ot = 0;
|
||||||
|
if (!Helpers::value2temperature(value, ot, true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto t = (int8_t)(ot * 2);
|
||||||
|
write_command(EMS_TYPE_RC30Settings, 24, t, EMS_TYPE_RC30Settings);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_mixingvalves(const char * value, const int8_t id) {
|
||||||
|
int m = 0;
|
||||||
|
if (!Helpers::value2number(value, m, 0, 2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_command(EMS_TYPE_RC30Settings, 17, m, EMS_TYPE_RC30Settings);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1715,7 +1923,7 @@ bool Thermostat::set_party(const char * value, const int8_t id) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set date&time as string hh:mm:ss-dd.mm.yyyy-dw-dst or "NTP" for setting to internet-time
|
// set date&time as string dd.mm.yyyy-hh:mm:ss-dw-dst or "NTP" for setting to internet-time
|
||||||
// dw - day of week (0..6), dst- summertime (0/1)
|
// dw - day of week (0..6), dst- summertime (0/1)
|
||||||
// id is ignored
|
// id is ignored
|
||||||
bool Thermostat::set_datetime(const char * value, const int8_t id) {
|
bool Thermostat::set_datetime(const char * value, const int8_t id) {
|
||||||
@@ -1728,9 +1936,12 @@ bool Thermostat::set_datetime(const char * value, const int8_t id) {
|
|||||||
if (dt == "ntp") {
|
if (dt == "ntp") {
|
||||||
time_t now = time(nullptr);
|
time_t now = time(nullptr);
|
||||||
tm * tm_ = localtime(&now);
|
tm * tm_ = localtime(&now);
|
||||||
if (tm_->tm_year < 110) { // no NTP time
|
if (tm_->tm_year < 110) { // no valid time
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!EMSESP::system_.ntp_connected()) {
|
||||||
|
LOG_WARNING(F("Set date: no valid NTP data, setting from ESP Clock"));
|
||||||
|
}
|
||||||
|
|
||||||
data[0] = tm_->tm_year - 100; // Bosch counts from 2000
|
data[0] = tm_->tm_year - 100; // Bosch counts from 2000
|
||||||
data[1] = tm_->tm_mon + 1;
|
data[1] = tm_->tm_mon + 1;
|
||||||
@@ -1740,25 +1951,20 @@ bool Thermostat::set_datetime(const char * value, const int8_t id) {
|
|||||||
data[5] = tm_->tm_sec;
|
data[5] = tm_->tm_sec;
|
||||||
data[6] = (tm_->tm_wday + 6) % 7; // Bosch counts from Mo, time from Su
|
data[6] = (tm_->tm_wday + 6) % 7; // Bosch counts from Mo, time from Su
|
||||||
data[7] = tm_->tm_isdst + 2; // set DST and flag for ext. clock
|
data[7] = tm_->tm_isdst + 2; // set DST and flag for ext. clock
|
||||||
// char time_string[25];
|
|
||||||
// strftime(time_string, 25, "%FT%T%z", tm_);
|
|
||||||
// LOG_INFO(F("Date and time: %s"), time_string);
|
|
||||||
} else if (dt.length() == 23) {
|
} else if (dt.length() == 23) {
|
||||||
data[0] = (dt[16] - '0') * 100 + (dt[17] - '0') * 10 + (dt[18] - '0'); // year
|
data[0] = (dt[7] - '0') * 100 + (dt[8] - '0') * 10 + (dt[9] - '0'); // year
|
||||||
data[1] = (dt[12] - '0') * 10 + (dt[13] - '0'); // month
|
data[1] = (dt[3] - '0') * 10 + (dt[4] - '0'); // month
|
||||||
data[2] = (dt[0] - '0') * 10 + (dt[1] - '0'); // hour
|
data[2] = (dt[11] - '0') * 10 + (dt[12] - '0'); // hour
|
||||||
data[3] = (dt[9] - '0') * 10 + (dt[10] - '0'); // day
|
data[3] = (dt[0] - '0') * 10 + (dt[1] - '0'); // day
|
||||||
data[4] = (dt[3] - '0') * 10 + (dt[4] - '0'); // min
|
data[4] = (dt[14] - '0') * 10 + (dt[15] - '0'); // min
|
||||||
data[5] = (dt[6] - '0') * 10 + (dt[7] - '0'); // sec
|
data[5] = (dt[17] - '0') * 10 + (dt[18] - '0'); // sec
|
||||||
data[6] = (dt[20] - '0'); // day of week, Mo:0
|
data[6] = (dt[20] - '0'); // day of week, Mo:0
|
||||||
data[7] = (dt[22] - '0') + 2; // DST and flag
|
data[7] = (dt[22] - '0') + 2; // DST and flag
|
||||||
// LOG_INFO(F("Date and time: %02d.%02d.2%03d-%02d:%02d:%02d"), data[3], data[1], data[0], data[2], data[4], data[5]);
|
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING(F("Set date: invalid data, wrong length"));
|
LOG_WARNING(F("Set date: invalid data, wrong length"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (data[1] == 0 || data[1] > 12 || data[2] > 23 || data[3] == 0 || data[3] > 31 || data[4] > 59 || data[5] > 59 || data[6] > 6 || data[7] > 3) {
|
if (data[1] == 0 || data[1] > 12 || data[2] > 23 || data[3] == 0 || data[3] > 31 || data[4] > 59 || data[5] > 59 || data[6] > 6 || data[7] > 3) {
|
||||||
// LOG_WARNING(F("Set date: invalid data"));
|
|
||||||
LOG_WARNING(F("Invalid date/time: %02d.%02d.2%03d-%02d:%02d:%02d-%d-%d"), data[3], data[1], data[0], data[2], data[4], data[5], data[6], data[7]);
|
LOG_WARNING(F("Invalid date/time: %02d.%02d.2%03d-%02d:%02d:%02d-%d-%d"), data[3], data[1], data[0], data[2], data[4], data[5], data[6], data[7]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1896,7 +2102,8 @@ bool Thermostat::set_mode_n(const uint8_t mode, const uint8_t hc_num) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (model()) {
|
uint8_t model_ = model();
|
||||||
|
switch (model_) {
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_RC10:
|
case EMSdevice::EMS_DEVICE_FLAG_RC10:
|
||||||
offset = 0;
|
offset = 0;
|
||||||
validate_typeid = 0xB1;
|
validate_typeid = 0xB1;
|
||||||
@@ -1959,6 +2166,18 @@ bool Thermostat::set_mode_n(const uint8_t mode, const uint8_t hc_num) {
|
|||||||
// post validate is the corresponding monitor or set type IDs as they can differ per model
|
// post validate is the corresponding monitor or set type IDs as they can differ per model
|
||||||
write_command(set_typeid, offset, set_mode_value, validate_typeid);
|
write_command(set_typeid, offset, set_mode_value, validate_typeid);
|
||||||
|
|
||||||
|
// set hc->mode temporary until validate is received
|
||||||
|
if (model_ == EMSdevice::EMS_DEVICE_FLAG_RC10) {
|
||||||
|
hc->mode = set_mode_value >> 1;
|
||||||
|
} else if (model_ == EMSdevice::EMS_DEVICE_FLAG_RC300 || model_ == EMSdevice::EMS_DEVICE_FLAG_RC100) {
|
||||||
|
hc->mode = set_mode_value ? 1 : 0;
|
||||||
|
} else if (model_ == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
|
||||||
|
hc->mode = set_mode_value - 1;
|
||||||
|
} else {
|
||||||
|
hc->mode = set_mode_value;
|
||||||
|
}
|
||||||
|
has_update(&hc->mode);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2015,7 +2234,41 @@ bool Thermostat::set_reducemode(const char * value, const int8_t id) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_command(set_typeids[hc->hc()], 25, set, set_typeids[hc->hc()]);
|
write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_reducemode, set, set_typeids[hc->hc()]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets the thermostat reducemode for RC35 vacations
|
||||||
|
bool Thermostat::set_vacreducemode(const char * value, const int8_t id) {
|
||||||
|
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id;
|
||||||
|
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num);
|
||||||
|
if (hc == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t set = 0xFF;
|
||||||
|
if (!Helpers::value2enum(value, set, FL_(enum_reducemode))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_vacreducemode, set, set_typeids[hc->hc()]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets the thermostat nofrost mode for RC35
|
||||||
|
bool Thermostat::set_nofrostmode(const char * value, const int8_t id) {
|
||||||
|
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id;
|
||||||
|
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num);
|
||||||
|
if (hc == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t set = 0xFF;
|
||||||
|
if (!Helpers::value2enum(value, set, FL_(enum_nofrostmode))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_nofrostmode, set, set_typeids[hc->hc()]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2159,6 +2412,8 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char
|
|||||||
}
|
}
|
||||||
if (strlen(value) > 13 && value[12] == 'o') {
|
if (strlen(value) > 13 && value[12] == 'o') {
|
||||||
on = value[13] == 'n' ? 1 : 0;
|
on = value[13] == 'n' ? 1 : 0;
|
||||||
|
} else if (strlen(value) > 13 && value[12] == 'T') {
|
||||||
|
on = value[13] - '0';
|
||||||
} else if (strlen(value) == 13) {
|
} else if (strlen(value) == 13) {
|
||||||
on = value[12] - '0';
|
on = value[12] - '0';
|
||||||
}
|
}
|
||||||
@@ -2175,8 +2430,8 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char
|
|||||||
data[1] = time;
|
data[1] = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t max_on = 3;
|
uint8_t max_on = 4;
|
||||||
if ((model() == EMS_DEVICE_FLAG_RC35) || (model() == EMS_DEVICE_FLAG_RC30_N)) {
|
if (model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N) {
|
||||||
max_on = 1;
|
max_on = 1;
|
||||||
}
|
}
|
||||||
if (no > 41 || time > 0x90 || (on > max_on && on != 7)) {
|
if (no > 41 || time > 0x90 || (on > max_on && on != 7)) {
|
||||||
@@ -2186,7 +2441,7 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char
|
|||||||
}
|
}
|
||||||
if (data[0] != 0xE7) {
|
if (data[0] != 0xE7) {
|
||||||
std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day]);
|
std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day]);
|
||||||
if ((model() == EMS_DEVICE_FLAG_RC35) || (model() == EMS_DEVICE_FLAG_RC30_N)) {
|
if (model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N) {
|
||||||
snprintf(out, len, "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off");
|
snprintf(out, len, "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off");
|
||||||
} else if (model() == EMS_DEVICE_FLAG_RC20) {
|
} else if (model() == EMS_DEVICE_FLAG_RC20) {
|
||||||
snprintf(out, len, "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on);
|
snprintf(out, len, "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on);
|
||||||
@@ -2540,6 +2795,14 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
|
|||||||
offset = EMS_OFFSET_RC35Set_noreducetemp;
|
offset = EMS_OFFSET_RC35Set_noreducetemp;
|
||||||
factor = 1;
|
factor = 1;
|
||||||
break;
|
break;
|
||||||
|
case HeatingCircuit::Mode::REDUCE:
|
||||||
|
offset = EMS_OFFSET_RC35Set_reducetemp;
|
||||||
|
factor = 1;
|
||||||
|
break;
|
||||||
|
case HeatingCircuit::Mode::VACREDUCE:
|
||||||
|
offset = EMS_OFFSET_RC35Set_vacreducetemp;
|
||||||
|
factor = 1;
|
||||||
|
break;
|
||||||
case HeatingCircuit::Mode::TEMPAUTO:
|
case HeatingCircuit::Mode::TEMPAUTO:
|
||||||
offset = EMS_OFFSET_RC35Set_seltemp;
|
offset = EMS_OFFSET_RC35Set_seltemp;
|
||||||
break;
|
break;
|
||||||
@@ -2558,16 +2821,15 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
|
|||||||
default:
|
default:
|
||||||
// automatic selection, if no type is defined, we use the standard code
|
// automatic selection, if no type is defined, we use the standard code
|
||||||
validate_typeid = monitor_typeids[hc->hc()]; //get setpoint roomtemp back
|
validate_typeid = monitor_typeids[hc->hc()]; //get setpoint roomtemp back
|
||||||
if (model == EMS_DEVICE_FLAG_RC35) {
|
|
||||||
uint8_t mode_ = hc->get_mode();
|
uint8_t mode_ = hc->get_mode();
|
||||||
if (mode_ == HeatingCircuit::Mode::NIGHT) {
|
if (mode_ == HeatingCircuit::Mode::NIGHT) {
|
||||||
offset = EMS_OFFSET_RC35Set_temp_night;
|
offset = EMS_OFFSET_RC35Set_temp_night;
|
||||||
} else if (mode_ == HeatingCircuit::Mode::DAY) {
|
} else if (mode_ == HeatingCircuit::Mode::DAY) {
|
||||||
offset = EMS_OFFSET_RC35Set_temp_day;
|
offset = EMS_OFFSET_RC35Set_temp_day;
|
||||||
} else {
|
} else if (model == EMS_DEVICE_FLAG_RC35) {
|
||||||
offset = EMS_OFFSET_RC35Set_seltemp; // https://github.com/emsesp/EMS-ESP/issues/310
|
offset = EMS_OFFSET_RC35Set_seltemp; // https://github.com/emsesp/EMS-ESP/issues/310
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
// RC30_N missing temporary auto temperature https://github.com/emsesp/EMS-ESP32/issues/395
|
||||||
uint8_t modetype = hc->get_mode_type();
|
uint8_t modetype = hc->get_mode_type();
|
||||||
offset = (modetype == HeatingCircuit::Mode::NIGHT) ? EMS_OFFSET_RC35Set_temp_night : EMS_OFFSET_RC35Set_temp_day;
|
offset = (modetype == HeatingCircuit::Mode::NIGHT) ? EMS_OFFSET_RC35Set_temp_night : EMS_OFFSET_RC35Set_temp_day;
|
||||||
}
|
}
|
||||||
@@ -2592,7 +2854,16 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
|
|||||||
offset = EMS_OFFSET_JunkersSetMessage_day_temp;
|
offset = EMS_OFFSET_JunkersSetMessage_day_temp;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// automatic selection, if no type is defined, we use the standard code
|
// automatic selection, if no type is defined, we check mode and modetype
|
||||||
|
uint8_t mode_ = hc->get_mode();
|
||||||
|
if (mode_ == HeatingCircuit::Mode::NIGHT || mode_ == HeatingCircuit::Mode::ECO) {
|
||||||
|
offset = EMS_OFFSET_JunkersSetMessage_night_temp;
|
||||||
|
} else if (mode_ == HeatingCircuit::Mode::DAY || mode_ == HeatingCircuit::Mode::HEAT) {
|
||||||
|
offset = EMS_OFFSET_JunkersSetMessage_day_temp;
|
||||||
|
} else if (mode_ == HeatingCircuit::Mode::NOFROST) {
|
||||||
|
offset = EMS_OFFSET_JunkersSetMessage_no_frost_temp;
|
||||||
|
} else {
|
||||||
|
// auto mode, missing temporary parameter, use modetype https://github.com/emsesp/EMS-ESP32/issues/400
|
||||||
uint8_t modetype = hc->get_mode_type();
|
uint8_t modetype = hc->get_mode_type();
|
||||||
if (modetype == HeatingCircuit::Mode::NIGHT || modetype == HeatingCircuit::Mode::ECO) {
|
if (modetype == HeatingCircuit::Mode::NIGHT || modetype == HeatingCircuit::Mode::ECO) {
|
||||||
offset = EMS_OFFSET_JunkersSetMessage_night_temp;
|
offset = EMS_OFFSET_JunkersSetMessage_night_temp;
|
||||||
@@ -2601,6 +2872,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
|
|||||||
} else {
|
} else {
|
||||||
offset = EMS_OFFSET_JunkersSetMessage_no_frost_temp;
|
offset = EMS_OFFSET_JunkersSetMessage_no_frost_temp;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2619,7 +2891,16 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
|
|||||||
offset = EMS_OFFSET_JunkersSetMessage2_heat_temp;
|
offset = EMS_OFFSET_JunkersSetMessage2_heat_temp;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// automatic selection, if no type is defined, we use the standard code
|
// automatic selection, if no type is defined, we check mode and modetype
|
||||||
|
uint8_t mode_ = hc->get_mode();
|
||||||
|
if (mode_ == HeatingCircuit::Mode::NIGHT || mode_ == HeatingCircuit::Mode::ECO) {
|
||||||
|
offset = EMS_OFFSET_JunkersSetMessage2_eco_temp;
|
||||||
|
} else if (mode_ == HeatingCircuit::Mode::DAY || mode_ == HeatingCircuit::Mode::HEAT) {
|
||||||
|
offset = EMS_OFFSET_JunkersSetMessage2_heat_temp;
|
||||||
|
} else if (mode_ == HeatingCircuit::Mode::NOFROST) {
|
||||||
|
offset = EMS_OFFSET_JunkersSetMessage2_no_frost_temp;
|
||||||
|
} else {
|
||||||
|
// auto mode, missing temporary parameter, use modetype https://github.com/emsesp/EMS-ESP32/issues/400
|
||||||
uint8_t modetype = hc->get_mode_type();
|
uint8_t modetype = hc->get_mode_type();
|
||||||
if (modetype == HeatingCircuit::Mode::NIGHT || modetype == HeatingCircuit::Mode::ECO) {
|
if (modetype == HeatingCircuit::Mode::NIGHT || modetype == HeatingCircuit::Mode::ECO) {
|
||||||
offset = EMS_OFFSET_JunkersSetMessage2_eco_temp;
|
offset = EMS_OFFSET_JunkersSetMessage2_eco_temp;
|
||||||
@@ -2628,6 +2909,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
|
|||||||
} else {
|
} else {
|
||||||
offset = EMS_OFFSET_JunkersSetMessage2_no_frost_temp;
|
offset = EMS_OFFSET_JunkersSetMessage2_no_frost_temp;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2718,6 +3000,14 @@ bool Thermostat::set_noreducetemp(const char * value, const int8_t id) {
|
|||||||
return set_temperature_value(value, id, HeatingCircuit::Mode::NOREDUCE);
|
return set_temperature_value(value, id, HeatingCircuit::Mode::NOREDUCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_reducetemp(const char * value, const int8_t id) {
|
||||||
|
return set_temperature_value(value, id, HeatingCircuit::Mode::REDUCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_vacreducetemp(const char * value, const int8_t id) {
|
||||||
|
return set_temperature_value(value, id, HeatingCircuit::Mode::VACREDUCE);
|
||||||
|
}
|
||||||
|
|
||||||
bool Thermostat::set_flowtempoffset(const char * value, const int8_t id) {
|
bool Thermostat::set_flowtempoffset(const char * value, const int8_t id) {
|
||||||
return set_temperature_value(value, id, HeatingCircuit::Mode::FLOWOFFSET, true);
|
return set_temperature_value(value, id, HeatingCircuit::Mode::FLOWOFFSET, true);
|
||||||
}
|
}
|
||||||
@@ -2867,19 +3157,72 @@ void Thermostat::register_device_values() {
|
|||||||
break;
|
break;
|
||||||
case EMS_DEVICE_FLAG_RC30:
|
case EMS_DEVICE_FLAG_RC30:
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE); // can't set datetime
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE); // can't set datetime
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&ibaClockOffset_,
|
||||||
|
DeviceValueType::INT,
|
||||||
|
nullptr,
|
||||||
|
FL_(ibaClockOffset),
|
||||||
|
DeviceValueUOM::SECONDS,
|
||||||
|
MAKE_CF_CB(set_clockoffset)); // offset (in sec) to clock, 0xff=-1s, 0x02=2s
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &autodst_, DeviceValueType::BOOL, nullptr, FL_(autodst), DeviceValueUOM::NONE, MAKE_CF_CB(set_autodst));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&ibaLanguage_,
|
||||||
|
DeviceValueType::ENUM,
|
||||||
|
FL_(enum_ibaLanguage_RC30),
|
||||||
|
FL_(ibaLanguage),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_language));
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&ibaMainDisplay_,
|
&ibaMainDisplay_,
|
||||||
DeviceValueType::ENUM,
|
DeviceValueType::ENUM,
|
||||||
FL_(enum_ibaMainDisplay),
|
FL_(enum_ibaMainDisplay),
|
||||||
FL_(ibaMainDisplay),
|
FL_(ibaMainDisplay),
|
||||||
DeviceValueUOM::NONE);
|
DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &ibaLanguage_, DeviceValueType::ENUM, FL_(enum_ibaLanguage), FL_(ibaLanguage), DeviceValueUOM::NONE);
|
register_device_value(
|
||||||
|
DeviceValueTAG::TAG_DEVICE_DATA, &backlight_, DeviceValueType::BOOL, nullptr, FL_(backlight), DeviceValueUOM::NONE, MAKE_CF_CB(set_backlight));
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&ibaClockOffset_,
|
&brightness_,
|
||||||
DeviceValueType::INT,
|
DeviceValueType::INT,
|
||||||
nullptr,
|
nullptr,
|
||||||
FL_(ibaClockOffset),
|
FL_(brightness),
|
||||||
DeviceValueUOM::SECONDS); // offset (in sec) to clock, 0xff=-1s, 0x02=2s
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_brightness),
|
||||||
|
-15,
|
||||||
|
15);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&mixingvalves_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
nullptr,
|
||||||
|
FL_(mixingvalves),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_mixingvalves),
|
||||||
|
0,
|
||||||
|
2);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&ibaBuildingType_,
|
||||||
|
DeviceValueType::ENUM,
|
||||||
|
FL_(enum_ibaBuildingType),
|
||||||
|
FL_(ibaBuildingType),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_building));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&heatingpid_,
|
||||||
|
DeviceValueType::ENUM,
|
||||||
|
FL_(enum_PID),
|
||||||
|
FL_(heatingPID),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_heatingpid));
|
||||||
|
register_device_value(
|
||||||
|
DeviceValueTAG::TAG_DEVICE_DATA, &preheating_, DeviceValueType::BOOL, nullptr, FL_(preheating), DeviceValueUOM::NONE, MAKE_CF_CB(set_preheating));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&ibaCalIntTemperature_,
|
||||||
|
DeviceValueType::INT,
|
||||||
|
FL_(div10),
|
||||||
|
FL_(ibaCalIntTemperature),
|
||||||
|
DeviceValueUOM::DEGREES_R,
|
||||||
|
MAKE_CF_CB(set_calinttemp));
|
||||||
|
register_device_value(
|
||||||
|
DeviceValueTAG::TAG_DEVICE_DATA, &offtemp_, DeviceValueType::UINT, FL_(div2), FL_(offtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_offtemp), 5, 30);
|
||||||
break;
|
break;
|
||||||
case EMS_DEVICE_FLAG_RC30_N:
|
case EMS_DEVICE_FLAG_RC30_N:
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE); // can't set datetime
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE); // can't set datetime
|
||||||
@@ -3112,6 +3455,67 @@ void Thermostat::register_device_values() {
|
|||||||
FL_(dateTime),
|
FL_(dateTime),
|
||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_datetime));
|
MAKE_CF_CB(set_datetime));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&hybridStrategy_,
|
||||||
|
DeviceValueType::ENUM,
|
||||||
|
FL_(enum_hybridStrategy),
|
||||||
|
FL_(hybridStrategy),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_hybridStrategy));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&switchOverTemp_,
|
||||||
|
DeviceValueType::INT,
|
||||||
|
nullptr,
|
||||||
|
FL_(switchOverTemp),
|
||||||
|
DeviceValueUOM::DEGREES,
|
||||||
|
MAKE_CF_CB(set_switchOverTemp),
|
||||||
|
-20,
|
||||||
|
20);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&energyCostRatio_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
FL_(div10),
|
||||||
|
FL_(energyCostRatio),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_energyCostRatio),
|
||||||
|
0,
|
||||||
|
19.9);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&fossileFactor_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
FL_(div10),
|
||||||
|
FL_(fossileFactor),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_fossileFactor),
|
||||||
|
0,
|
||||||
|
5);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&electricFactor_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
FL_(div10),
|
||||||
|
FL_(electricFactor),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_electricFactor),
|
||||||
|
0,
|
||||||
|
5);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&delayBoiler_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
nullptr,
|
||||||
|
FL_(delayBoiler),
|
||||||
|
DeviceValueUOM::MINUTES,
|
||||||
|
MAKE_CF_CB(set_delayBoiler),
|
||||||
|
5,
|
||||||
|
120);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&tempDiffBoiler_,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
nullptr,
|
||||||
|
FL_(tempDiffBoiler),
|
||||||
|
DeviceValueUOM::DEGREES_R,
|
||||||
|
MAKE_CF_CB(set_tempDiffBoiler),
|
||||||
|
1,
|
||||||
|
99);
|
||||||
break;
|
break;
|
||||||
case EMS_DEVICE_FLAG_EASY:
|
case EMS_DEVICE_FLAG_EASY:
|
||||||
// Easy TC100 have no date/time, see issue #100, not sure about CT200, so leave it.
|
// Easy TC100 have no date/time, see issue #100, not sure about CT200, so leave it.
|
||||||
@@ -3183,7 +3587,7 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
|
|||||||
tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), FL_(heatingtype), DeviceValueUOM::NONE, MAKE_CF_CB(set_heatingtype));
|
tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), FL_(heatingtype), DeviceValueUOM::NONE, MAKE_CF_CB(set_heatingtype));
|
||||||
register_device_value(
|
register_device_value(
|
||||||
tag, &hc->summer_setmode, DeviceValueType::ENUM, FL_(enum_summermode), FL_(summersetmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_summermode));
|
tag, &hc->summer_setmode, DeviceValueType::ENUM, FL_(enum_summermode), FL_(summersetmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_summermode));
|
||||||
register_device_value(tag, &hc->summermode, DeviceValueType::BOOL, nullptr, FL_(summermode), DeviceValueUOM::NONE);
|
register_device_value(tag, &hc->summermode, DeviceValueType::ENUM, FL_(enum_summer), FL_(summermode), DeviceValueUOM::NONE);
|
||||||
register_device_value(
|
register_device_value(
|
||||||
tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode), FL_(controlmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_controlmode));
|
tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode), FL_(controlmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_controlmode));
|
||||||
register_device_value(tag, &hc->program, DeviceValueType::ENUM, FL_(enum_progMode), FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program));
|
register_device_value(tag, &hc->program, DeviceValueType::ENUM, FL_(enum_progMode), FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program));
|
||||||
@@ -3251,6 +3655,8 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
|
|||||||
register_device_value(tag, &hc->summermode, DeviceValueType::ENUM, FL_(enum_summer), FL_(summermode), DeviceValueUOM::NONE);
|
register_device_value(tag, &hc->summermode, DeviceValueType::ENUM, FL_(enum_summer), FL_(summermode), DeviceValueUOM::NONE);
|
||||||
register_device_value(tag, &hc->holidaymode, DeviceValueType::BOOL, nullptr, FL_(holidaymode), DeviceValueUOM::NONE);
|
register_device_value(tag, &hc->holidaymode, DeviceValueType::BOOL, nullptr, FL_(holidaymode), DeviceValueUOM::NONE);
|
||||||
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, FL_(nofrosttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nofrosttemp));
|
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, FL_(nofrosttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nofrosttemp));
|
||||||
|
register_device_value(
|
||||||
|
tag, &hc->nofrostmode, DeviceValueType::ENUM, FL_(enum_nofrostmode), FL_(nofrostmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_nofrostmode));
|
||||||
register_device_value(tag, &hc->roominfluence, DeviceValueType::UINT, nullptr, FL_(roominfluence), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_roominfluence));
|
register_device_value(tag, &hc->roominfluence, DeviceValueType::UINT, nullptr, FL_(roominfluence), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_roominfluence));
|
||||||
register_device_value(tag, &hc->minflowtemp, DeviceValueType::UINT, nullptr, FL_(minflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_minflowtemp));
|
register_device_value(tag, &hc->minflowtemp, DeviceValueType::UINT, nullptr, FL_(minflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_minflowtemp));
|
||||||
register_device_value(tag, &hc->maxflowtemp, DeviceValueType::UINT, nullptr, FL_(maxflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_maxflowtemp));
|
register_device_value(tag, &hc->maxflowtemp, DeviceValueType::UINT, nullptr, FL_(maxflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_maxflowtemp));
|
||||||
@@ -3269,6 +3675,10 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
|
|||||||
register_device_value(tag, &hc->party, DeviceValueType::UINT, nullptr, FL_(party), DeviceValueUOM::HOURS, MAKE_CF_CB(set_party));
|
register_device_value(tag, &hc->party, DeviceValueType::UINT, nullptr, FL_(party), DeviceValueUOM::HOURS, MAKE_CF_CB(set_party));
|
||||||
register_device_value(tag, &hc->tempautotemp, DeviceValueType::UINT, FL_(div2), FL_(tempautotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_tempautotemp));
|
register_device_value(tag, &hc->tempautotemp, DeviceValueType::UINT, FL_(div2), FL_(tempautotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_tempautotemp));
|
||||||
register_device_value(tag, &hc->noreducetemp, DeviceValueType::INT, nullptr, FL_(noreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_noreducetemp));
|
register_device_value(tag, &hc->noreducetemp, DeviceValueType::INT, nullptr, FL_(noreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_noreducetemp));
|
||||||
|
register_device_value(tag, &hc->reducetemp, DeviceValueType::INT, nullptr, FL_(reducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_reducetemp));
|
||||||
|
register_device_value(tag, &hc->vacreducetemp, DeviceValueType::INT, nullptr, FL_(vacreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_vacreducetemp));
|
||||||
|
register_device_value(
|
||||||
|
tag, &hc->vacreducemode, DeviceValueType::ENUM, FL_(enum_reducemode), FL_(vacreducemode), DeviceValueUOM::NONE, MAKE_CF_CB(set_vacreducemode));
|
||||||
register_device_value(tag, &hc->remotetemp, DeviceValueType::SHORT, FL_(div10), FL_(remotetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_remotetemp));
|
register_device_value(tag, &hc->remotetemp, DeviceValueType::SHORT, FL_(div10), FL_(remotetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_remotetemp));
|
||||||
register_device_value(tag, &hc->wwprio, DeviceValueType::BOOL, nullptr, FL_(wwprio), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwprio));
|
register_device_value(tag, &hc->wwprio, DeviceValueType::BOOL, nullptr, FL_(wwprio), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwprio));
|
||||||
register_device_value(
|
register_device_value(
|
||||||
@@ -3285,6 +3695,7 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
|
|||||||
register_device_value(tag, &hc->control, DeviceValueType::ENUM, FL_(enum_j_control), FL_(control), DeviceValueUOM::NONE, MAKE_CF_CB(set_control));
|
register_device_value(tag, &hc->control, DeviceValueType::ENUM, FL_(enum_j_control), FL_(control), DeviceValueUOM::NONE, MAKE_CF_CB(set_control));
|
||||||
register_device_value(tag, &hc->program, DeviceValueType::ENUM, FL_(enum_progMode4), FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program));
|
register_device_value(tag, &hc->program, DeviceValueType::ENUM, FL_(enum_progMode4), FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program));
|
||||||
register_device_value(tag, &hc->remotetemp, DeviceValueType::SHORT, FL_(div10), FL_(remotetemp), DeviceValueUOM::DEGREES);
|
register_device_value(tag, &hc->remotetemp, DeviceValueType::SHORT, FL_(div10), FL_(remotetemp), DeviceValueUOM::DEGREES);
|
||||||
|
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, FL_(targetflowtemp), DeviceValueUOM::DEGREES);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -62,12 +62,16 @@ class Thermostat : public EMSdevice {
|
|||||||
uint8_t minflowtemp;
|
uint8_t minflowtemp;
|
||||||
uint8_t maxflowtemp;
|
uint8_t maxflowtemp;
|
||||||
uint8_t reducemode;
|
uint8_t reducemode;
|
||||||
|
uint8_t nofrostmode;
|
||||||
uint8_t program;
|
uint8_t program;
|
||||||
uint8_t controlmode;
|
uint8_t controlmode;
|
||||||
uint8_t control;
|
uint8_t control;
|
||||||
uint8_t pause;
|
uint8_t pause;
|
||||||
uint8_t party;
|
uint8_t party;
|
||||||
int8_t noreducetemp; // signed -20°C to +10°C
|
int8_t noreducetemp; // signed -20°C to +10°C
|
||||||
|
int8_t reducetemp;
|
||||||
|
int8_t vacreducetemp;
|
||||||
|
uint8_t vacreducemode;
|
||||||
uint8_t wwprio;
|
uint8_t wwprio;
|
||||||
uint8_t fastHeatup;
|
uint8_t fastHeatup;
|
||||||
char holiday[26];
|
char holiday[26];
|
||||||
@@ -120,6 +124,8 @@ class Thermostat : public EMSdevice {
|
|||||||
ROOMINFLUENCE,
|
ROOMINFLUENCE,
|
||||||
TEMPAUTO,
|
TEMPAUTO,
|
||||||
NOREDUCE,
|
NOREDUCE,
|
||||||
|
REDUCE,
|
||||||
|
VACREDUCE,
|
||||||
ON,
|
ON,
|
||||||
DAYLOW,
|
DAYLOW,
|
||||||
DAYMID,
|
DAYMID,
|
||||||
@@ -176,6 +182,11 @@ class Thermostat : public EMSdevice {
|
|||||||
uint8_t ibaDamping_; // damping 0-off, 0xff-on
|
uint8_t ibaDamping_; // damping 0-off, 0xff-on
|
||||||
uint8_t backlight_;
|
uint8_t backlight_;
|
||||||
uint8_t heatingpid_;
|
uint8_t heatingpid_;
|
||||||
|
int8_t brightness_; // Screen brightness 0F=dark F1=light
|
||||||
|
uint8_t preheating_; // Preheating in the clock program: (0x00 = off, 0xFF = on)
|
||||||
|
uint8_t autodst_; // Automatic change Daylight Saving time: (0x00 = off, 0xFF = on)
|
||||||
|
uint8_t offtemp_; // Set Temperature when mode is Off / 10 (e.g.: 0x0F = 7.5 degrees Celsius)
|
||||||
|
uint8_t mixingvalves_; // Number of Mixing Valves: (0x00=0, 0x01=1, 0x02=2)
|
||||||
|
|
||||||
int8_t dampedoutdoortemp_;
|
int8_t dampedoutdoortemp_;
|
||||||
uint16_t tempsensor1_;
|
uint16_t tempsensor1_;
|
||||||
@@ -205,6 +216,15 @@ class Thermostat : public EMSdevice {
|
|||||||
uint8_t wwDailyHeating_;
|
uint8_t wwDailyHeating_;
|
||||||
uint8_t wwDailyHeatTime_;
|
uint8_t wwDailyHeatTime_;
|
||||||
|
|
||||||
|
// HybridHP
|
||||||
|
uint8_t hybridStrategy_; // co2 = 1, cost = 2, temperature = 3, mix = 4
|
||||||
|
int8_t switchOverTemp_; // degrees
|
||||||
|
uint8_t energyCostRatio_; // is *10
|
||||||
|
uint8_t fossileFactor_; // is * 10
|
||||||
|
uint8_t electricFactor_; // is * 10
|
||||||
|
uint8_t delayBoiler_; // minutes
|
||||||
|
uint8_t tempDiffBoiler_; // relative temperature degrees
|
||||||
|
|
||||||
std::vector<std::shared_ptr<HeatingCircuit>> heating_circuits_; // each thermostat can have multiple heating circuits
|
std::vector<std::shared_ptr<HeatingCircuit>> heating_circuits_; // each thermostat can have multiple heating circuits
|
||||||
|
|
||||||
uint8_t zero_value_ = 0; // for fixing current room temperature to 0 for HA
|
uint8_t zero_value_ = 0; // for fixing current room temperature to 0 for HA
|
||||||
@@ -245,6 +265,12 @@ class Thermostat : public EMSdevice {
|
|||||||
static constexpr uint8_t EMS_OFFSET_RC35Set_targetflowtemp = 14; // target flow temperature
|
static constexpr uint8_t EMS_OFFSET_RC35Set_targetflowtemp = 14; // target flow temperature
|
||||||
static constexpr uint8_t EMS_OFFSET_RC35Set_seltemp = 37; // selected temp
|
static constexpr uint8_t EMS_OFFSET_RC35Set_seltemp = 37; // selected temp
|
||||||
static constexpr uint8_t EMS_OFFSET_RC35Set_noreducetemp = 38; // temp to stop reducing
|
static constexpr uint8_t EMS_OFFSET_RC35Set_noreducetemp = 38; // temp to stop reducing
|
||||||
|
static constexpr uint8_t EMS_OFFSET_RC35Set_reducetemp = 39; // temp reducing/hold
|
||||||
|
static constexpr uint8_t EMS_OFFSET_RC35Set_vacreducetemp = 40; // temp reducing/hold in vacations
|
||||||
|
static constexpr uint8_t EMS_OFFSET_RC35Set_vacreducemode = 41; // reduce mode in vacations
|
||||||
|
static constexpr uint8_t EMS_OFFSET_RC35Set_reducemode = 25; // reduce mode in normal operation
|
||||||
|
static constexpr uint8_t EMS_OFFSET_RC35Set_nofrostmode = 28; // 0-off, 1-room, 2-outdoor
|
||||||
|
static constexpr uint8_t EMS_OFFSET_RC35Set_control = 26; // 0-off, 1-RC20, 2-RC3x
|
||||||
static constexpr uint8_t EMS_OFFSET_RC35Set_temp_offset = 6;
|
static constexpr uint8_t EMS_OFFSET_RC35Set_temp_offset = 6;
|
||||||
static constexpr uint8_t EMS_OFFSET_RC35Set_temp_flowoffset = 24;
|
static constexpr uint8_t EMS_OFFSET_RC35Set_temp_flowoffset = 24;
|
||||||
static constexpr uint8_t EMS_OFFSET_RC35Set_temp_design = 17;
|
static constexpr uint8_t EMS_OFFSET_RC35Set_temp_design = 17;
|
||||||
@@ -284,6 +310,7 @@ class Thermostat : public EMSdevice {
|
|||||||
|
|
||||||
// Installation settings
|
// Installation settings
|
||||||
static constexpr uint8_t EMS_TYPE_IBASettings = 0xA5; // installation settings
|
static constexpr uint8_t EMS_TYPE_IBASettings = 0xA5; // installation settings
|
||||||
|
static constexpr uint8_t EMS_TYPE_RC30Settings = 0xA7; // RC30 settings
|
||||||
static constexpr uint8_t EMS_TYPE_wwSettings = 0x37; // ww settings
|
static constexpr uint8_t EMS_TYPE_wwSettings = 0x37; // ww settings
|
||||||
static constexpr uint8_t EMS_TYPE_time = 0x06; // time
|
static constexpr uint8_t EMS_TYPE_time = 0x06; // time
|
||||||
|
|
||||||
@@ -333,6 +360,8 @@ class Thermostat : public EMSdevice {
|
|||||||
void process_JunkersSet2(std::shared_ptr<const Telegram> telegram);
|
void process_JunkersSet2(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_EasyMonitor(std::shared_ptr<const Telegram> telegram);
|
void process_EasyMonitor(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_JunkersRemoteMonitor(std::shared_ptr<const Telegram> telegram);
|
void process_JunkersRemoteMonitor(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_JunkersHybridSettings(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_JunkersSetMixer(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|
||||||
// internal helper functions
|
// internal helper functions
|
||||||
bool set_mode_n(const uint8_t mode, const uint8_t hc_num);
|
bool set_mode_n(const uint8_t mode, const uint8_t hc_num);
|
||||||
@@ -368,6 +397,11 @@ class Thermostat : public EMSdevice {
|
|||||||
bool set_manualtemp(const char * value, const int8_t id);
|
bool set_manualtemp(const char * value, const int8_t id);
|
||||||
bool set_tempautotemp(const char * value, const int8_t id);
|
bool set_tempautotemp(const char * value, const int8_t id);
|
||||||
bool set_noreducetemp(const char * value, const int8_t id);
|
bool set_noreducetemp(const char * value, const int8_t id);
|
||||||
|
bool set_reducetemp(const char * value, const int8_t id);
|
||||||
|
bool set_vacreducetemp(const char * value, const int8_t id);
|
||||||
|
bool set_vacreducemode(const char * value, const int8_t id);
|
||||||
|
bool set_nofrostmode(const char * value, const int8_t id);
|
||||||
|
|
||||||
bool set_remotetemp(const char * value, const int8_t id);
|
bool set_remotetemp(const char * value, const int8_t id);
|
||||||
bool set_roominfluence(const char * value, const int8_t id);
|
bool set_roominfluence(const char * value, const int8_t id);
|
||||||
bool set_roominfl_factor(const char * value, const int8_t id);
|
bool set_roominfl_factor(const char * value, const int8_t id);
|
||||||
@@ -413,6 +447,19 @@ class Thermostat : public EMSdevice {
|
|||||||
bool set_reducehours(const char * value, const int8_t id);
|
bool set_reducehours(const char * value, const int8_t id);
|
||||||
bool set_backlight(const char * value, const int8_t id);
|
bool set_backlight(const char * value, const int8_t id);
|
||||||
bool set_heatingpid(const char * value, const int8_t id);
|
bool set_heatingpid(const char * value, const int8_t id);
|
||||||
|
bool set_brightness(const char * value, const int8_t id);
|
||||||
|
bool set_autodst(const char * value, const int8_t id);
|
||||||
|
bool set_preheating(const char * value, const int8_t id);
|
||||||
|
bool set_mixingvalves(const char * value, const int8_t id);
|
||||||
|
bool set_offtemp(const char * value, const int8_t id);
|
||||||
|
|
||||||
|
bool set_hybridStrategy(const char * value, const int8_t id);
|
||||||
|
bool set_switchOverTemp(const char * value, const int8_t id);
|
||||||
|
bool set_energyCostRatio(const char * value, const int8_t id);
|
||||||
|
bool set_fossileFactor(const char * value, const int8_t id);
|
||||||
|
bool set_electricFactor(const char * value, const int8_t id);
|
||||||
|
bool set_delayBoiler(const char * value, const int8_t id);
|
||||||
|
bool set_tempDiffBoiler(const char * value, const int8_t id);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace emsesp {
|
|||||||
uint8_t EMSdevice::count_entities() {
|
uint8_t EMSdevice::count_entities() {
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
for (auto & dv : devicevalues_) {
|
for (auto & dv : devicevalues_) {
|
||||||
if (dv.has_state(DeviceValueState::DV_VISIBLE) && dv.hasValue()) {
|
if (!dv.has_state(DeviceValueState::DV_WEB_EXCLUDE) && dv.hasValue()) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,7 +258,7 @@ bool EMSdevice::has_tag(const uint8_t tag) {
|
|||||||
// called from the command 'entities'
|
// called from the command 'entities'
|
||||||
void EMSdevice::list_device_entries(JsonObject & output) const {
|
void EMSdevice::list_device_entries(JsonObject & output) const {
|
||||||
for (const auto & dv : devicevalues_) {
|
for (const auto & dv : devicevalues_) {
|
||||||
if (dv.has_state(DeviceValueState::DV_VISIBLE) && dv.type != DeviceValueType::CMD && dv.full_name) {
|
if (!dv.has_state(DeviceValueState::DV_WEB_EXCLUDE) && dv.type != DeviceValueType::CMD && dv.full_name) {
|
||||||
// if we have a tag prefix it
|
// if we have a tag prefix it
|
||||||
char key[50];
|
char key[50];
|
||||||
if (!EMSdevice::tag_to_mqtt(dv.tag).empty()) {
|
if (!EMSdevice::tag_to_mqtt(dv.tag).empty()) {
|
||||||
@@ -321,6 +321,11 @@ void EMSdevice::show_telegram_handlers(uuid::console::Shell & shell) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
shell.println();
|
shell.println();
|
||||||
|
shell.printf(F(" Ignored telegram type IDs: "));
|
||||||
|
for (auto handlers : handlers_ignored_) {
|
||||||
|
shell.printf(F("0x%02X "), handlers);
|
||||||
|
}
|
||||||
|
shell.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
// list all the telegram type IDs for this device, outputting to a string (max size 200)
|
// list all the telegram type IDs for this device, outputting to a string (max size 200)
|
||||||
@@ -343,10 +348,27 @@ char * EMSdevice::show_telegram_handlers(char * result, const size_t len, const
|
|||||||
strlcat(result, Helpers::hextoa(tf.telegram_type_id_, true).c_str(), len);
|
strlcat(result, Helpers::hextoa(tf.telegram_type_id_, true).c_str(), len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (handlers == Handlers::ALL || handlers == Handlers::IGNORED) {
|
||||||
|
i = 0;
|
||||||
|
for (auto handlers : handlers_ignored_) {
|
||||||
|
if (i++ > 0) {
|
||||||
|
strlcat(result, " ", len);
|
||||||
|
}
|
||||||
|
strlcat(result, Helpers::hextoa(handlers).c_str(), len);
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EMSdevice::add_handlers_ignored(const uint16_t handler) {
|
||||||
|
for (auto handlers : handlers_ignored_) {
|
||||||
|
if (handler == handlers) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handlers_ignored_.push_back(handler);
|
||||||
|
}
|
||||||
|
|
||||||
// list all the mqtt handlers for this device
|
// list all the mqtt handlers for this device
|
||||||
void EMSdevice::show_mqtt_handlers(uuid::console::Shell & shell) const {
|
void EMSdevice::show_mqtt_handlers(uuid::console::Shell & shell) const {
|
||||||
Mqtt::show_topic_handlers(shell, device_type_);
|
Mqtt::show_topic_handlers(shell, device_type_);
|
||||||
@@ -405,19 +427,18 @@ void EMSdevice::register_device_value(uint8_t tag,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is the unique id set for the device entity. it's a simple sequence number
|
|
||||||
uint8_t dv_id = get_next_dv_id();
|
|
||||||
|
|
||||||
// determine state
|
// determine state
|
||||||
uint8_t state = DeviceValueState::DV_VISIBLE; // default to visible
|
uint8_t state = DeviceValueState::DV_DEFAULT;
|
||||||
|
|
||||||
// scan through customizations to see if it's on the exclusion list by matching the productID and deviceID
|
// scan through customizations to see if it's on the exclusion list by matching the productID and deviceID
|
||||||
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
|
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
|
||||||
for (EntityCustomization entityCustomization : settings.entityCustomizations) {
|
for (EntityCustomization entityCustomization : settings.entityCustomizations) {
|
||||||
if ((entityCustomization.product_id == product_id()) && (entityCustomization.device_id == device_id())) {
|
if ((entityCustomization.product_id == product_id()) && (entityCustomization.device_id == device_id())) {
|
||||||
for (uint8_t entity_id : entityCustomization.entity_ids) {
|
std::string entity = tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(short_name) : tag_to_string(tag) + "/" + read_flash_string(short_name);
|
||||||
if (entity_id == dv_id) {
|
for (std::string entity_id : entityCustomization.entity_ids) {
|
||||||
state = DeviceValueState::DV_DEFAULT; // it's on the exclude list, turn off active and visible flags
|
if (entity_id.substr(2) == entity) {
|
||||||
|
uint8_t mask = Helpers::hextoint(entity_id.substr(0, 2).c_str());
|
||||||
|
state = mask << 4; // set state high bits to flag, turn off active and ha flags
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,7 +447,7 @@ void EMSdevice::register_device_value(uint8_t tag,
|
|||||||
});
|
});
|
||||||
|
|
||||||
// add the device
|
// add the device
|
||||||
devicevalues_.emplace_back(device_type_, tag, value_p, type, options, options_size, short_name, full_name, uom, 0, has_cmd, min, max, state, dv_id);
|
devicevalues_.emplace_back(device_type_, tag, value_p, type, options, options_size, short_name, full_name, uom, 0, has_cmd, min, max, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// function with min and max values
|
// function with min and max values
|
||||||
@@ -454,7 +475,7 @@ void EMSdevice::register_device_value(uint8_t tag,
|
|||||||
|
|
||||||
if (tag >= DeviceValueTAG::TAG_HC1 && tag <= DeviceValueTAG::TAG_HC8) {
|
if (tag >= DeviceValueTAG::TAG_HC1 && tag <= DeviceValueTAG::TAG_HC8) {
|
||||||
flags |= CommandFlag::MQTT_SUB_FLAG_HC;
|
flags |= CommandFlag::MQTT_SUB_FLAG_HC;
|
||||||
} else if (tag >= DeviceValueTAG::TAG_WWC1 && tag <= DeviceValueTAG::TAG_WWC4) {
|
} else if (tag >= DeviceValueTAG::TAG_WWC1 && tag <= DeviceValueTAG::TAG_WWC10) {
|
||||||
flags |= CommandFlag::MQTT_SUB_FLAG_WWC;
|
flags |= CommandFlag::MQTT_SUB_FLAG_WWC;
|
||||||
} else if (tag == DeviceValueTAG::TAG_DEVICE_DATA_WW || tag == DeviceValueTAG::TAG_BOILER_DATA_WW) {
|
} else if (tag == DeviceValueTAG::TAG_DEVICE_DATA_WW || tag == DeviceValueTAG::TAG_BOILER_DATA_WW) {
|
||||||
flags |= CommandFlag::MQTT_SUB_FLAG_WW;
|
flags |= CommandFlag::MQTT_SUB_FLAG_WW;
|
||||||
@@ -486,11 +507,33 @@ void EMSdevice::register_device_value(uint8_t tag,
|
|||||||
register_device_value(tag, value_p, type, options, name, uom, nullptr, 0, 0);
|
register_device_value(tag, value_p, type, options, name, uom, nullptr, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if value is visible
|
// check if value is readable via mqtt/api
|
||||||
bool EMSdevice::is_visible(const void * value_p) const {
|
bool EMSdevice::is_readable(const void * value_p) const {
|
||||||
for (const auto & dv : devicevalues_) {
|
for (const auto & dv : devicevalues_) {
|
||||||
if (dv.value_p == value_p) {
|
if (dv.value_p == value_p) {
|
||||||
return dv.has_state(DeviceValueState::DV_VISIBLE);
|
return !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if value/command is readonly
|
||||||
|
bool EMSdevice::is_readonly(const std::string & cmd, const int8_t id) const {
|
||||||
|
uint8_t tag = id > 0 ? DeviceValueTAG::TAG_HC1 + id - 1 : DeviceValueTAG::TAG_NONE;
|
||||||
|
for (const auto & dv : devicevalues_) {
|
||||||
|
// check command name and tag, id -1 is default hc and only checks name
|
||||||
|
if (dv.has_cmd && read_flash_string(dv.short_name) == cmd && (dv.tag < DeviceValueTAG::TAG_HC1 || dv.tag == tag || id == -1)) {
|
||||||
|
return dv.has_state(DeviceValueState::DV_READONLY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true; // not found, no write
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if value has a registered command
|
||||||
|
bool EMSdevice::has_command(const void * value_p) const {
|
||||||
|
for (const auto & dv : devicevalues_) {
|
||||||
|
if (dv.value_p == value_p) {
|
||||||
|
return dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -503,7 +546,7 @@ void EMSdevice::publish_value(void * value_p) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const auto & dv : devicevalues_) {
|
for (const auto & dv : devicevalues_) {
|
||||||
if (dv.value_p == value_p && dv.has_state(DeviceValueState::DV_VISIBLE)) {
|
if (dv.value_p == value_p && !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) {
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
if (Mqtt::publish_single2cmd()) {
|
if (Mqtt::publish_single2cmd()) {
|
||||||
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
@@ -528,7 +571,7 @@ void EMSdevice::publish_value(void * value_p) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int8_t divider = (dv.options_size == 1) ? Helpers::atoint(read_flash_string(dv.options[0]).c_str()) : 0;
|
int8_t divider = (dv.options_size == 1) ? Helpers::atoint(read_flash_string(dv.options[0]).c_str()) : 0;
|
||||||
char payload[30] = {'\0'};
|
char payload[50] = {'\0'};
|
||||||
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
|
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
|
||||||
|
|
||||||
switch (dv.type) {
|
switch (dv.type) {
|
||||||
@@ -561,7 +604,7 @@ void EMSdevice::publish_value(void * value_p) const {
|
|||||||
Helpers::render_value(payload, *(uint32_t *)(value_p), divider, fahrenheit);
|
Helpers::render_value(payload, *(uint32_t *)(value_p), divider, fahrenheit);
|
||||||
break;
|
break;
|
||||||
case DeviceValueType::BOOL: {
|
case DeviceValueType::BOOL: {
|
||||||
Helpers::render_boolean(payload, (bool)(*(uint8_t *)(value_p)));
|
Helpers::render_boolean(payload, (bool)*(uint8_t *)(value_p));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DeviceValueType::TIME:
|
case DeviceValueType::TIME:
|
||||||
@@ -603,7 +646,7 @@ std::string EMSdevice::get_value_uom(const char * key) const {
|
|||||||
|
|
||||||
// look up key in our device value list
|
// look up key in our device value list
|
||||||
for (const auto & dv : devicevalues_) {
|
for (const auto & dv : devicevalues_) {
|
||||||
if ((dv.has_state(DeviceValueState::DV_VISIBLE) && dv.full_name) && (read_flash_string(dv.full_name) == key_p)) {
|
if ((!dv.has_state(DeviceValueState::DV_WEB_EXCLUDE) && dv.full_name) && (read_flash_string(dv.full_name) == key_p)) {
|
||||||
// ignore TIME since "minutes" is already added to the string value
|
// ignore TIME since "minutes" is already added to the string value
|
||||||
if ((dv.uom == DeviceValueUOM::NONE) || (dv.uom == DeviceValueUOM::MINUTES)) {
|
if ((dv.uom == DeviceValueUOM::NONE) || (dv.uom == DeviceValueUOM::MINUTES)) {
|
||||||
break;
|
break;
|
||||||
@@ -618,26 +661,27 @@ std::string EMSdevice::get_value_uom(const char * key) const {
|
|||||||
// prepare array of device values used for the WebUI
|
// prepare array of device values used for the WebUI
|
||||||
// this is loosely based of the function generate_values used for the MQTT and Console
|
// this is loosely based of the function generate_values used for the MQTT and Console
|
||||||
// except additional data is stored in the JSON document needed for the Web UI like the UOM and command
|
// except additional data is stored in the JSON document needed for the Web UI like the UOM and command
|
||||||
// v = value, u=uom, n=name, c=cmd
|
// v=value, u=uom, n=name, c=cmd, h=help string, s=step, m=min, x=max
|
||||||
void EMSdevice::generate_values_web(JsonObject & output) {
|
void EMSdevice::generate_values_web(JsonObject & output) {
|
||||||
output["label"] = to_string_short();
|
output["label"] = to_string_short();
|
||||||
JsonArray data = output.createNestedArray("data");
|
JsonArray data = output.createNestedArray("data");
|
||||||
|
|
||||||
|
// do two passes. First for all entities marked as favorites, then for all others. This sorts the list.
|
||||||
|
for (int8_t fav = 1; fav >= 0; fav--) {
|
||||||
for (auto & dv : devicevalues_) {
|
for (auto & dv : devicevalues_) {
|
||||||
// check conditions:
|
// check conditions:
|
||||||
// 1. full_name cannot be empty
|
// 1. full_name cannot be empty
|
||||||
// 2. it must have a valid value, if it is not a command like 'reset'
|
// 2. it must have a valid value, if it is not a command like 'reset'
|
||||||
|
// 3. show favorites first
|
||||||
if (dv.has_state(DeviceValueState::DV_VISIBLE) && dv.full_name && (dv.hasValue() || (dv.type == DeviceValueType::CMD))) {
|
bool show = (fav && dv.has_state(DeviceValueState::DV_FAVORITE)) || (!fav && !dv.has_state(DeviceValueState::DV_FAVORITE));
|
||||||
|
if (show && !dv.has_state(DeviceValueState::DV_WEB_EXCLUDE) && dv.full_name && (dv.hasValue() || (dv.type == DeviceValueType::CMD))) {
|
||||||
JsonObject obj = data.createNestedObject(); // create the object, we know there is a value
|
JsonObject obj = data.createNestedObject(); // create the object, we know there is a value
|
||||||
uint8_t fahrenheit = 0;
|
uint8_t fahrenheit = 0;
|
||||||
|
|
||||||
// handle Booleans (true, false)
|
// handle Booleans (true, false), use strings, no native true/false)
|
||||||
if (dv.type == DeviceValueType::BOOL) {
|
if (dv.type == DeviceValueType::BOOL) {
|
||||||
bool value_b = *(bool *)(dv.value_p);
|
bool value_b = (bool)*(uint8_t *)(dv.value_p);
|
||||||
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
||||||
obj["v"] = value_b ? "true" : "false";
|
|
||||||
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
|
||||||
obj["v"] = value_b ? 1 : 0;
|
obj["v"] = value_b ? 1 : 0;
|
||||||
} else {
|
} else {
|
||||||
char s[7];
|
char s[7];
|
||||||
@@ -682,17 +726,19 @@ void EMSdevice::generate_values_web(JsonObject & output) {
|
|||||||
// add the unit of measure (uom)
|
// add the unit of measure (uom)
|
||||||
obj["u"] = fahrenheit ? (uint8_t)DeviceValueUOM::FAHRENHEIT : dv.uom;
|
obj["u"] = fahrenheit ? (uint8_t)DeviceValueUOM::FAHRENHEIT : dv.uom;
|
||||||
|
|
||||||
|
auto mask = Helpers::hextoa((uint8_t)(dv.state >> 4), false); // create mask to a 2-char string
|
||||||
|
|
||||||
// add name, prefixing the tag if it exists
|
// add name, prefixing the tag if it exists
|
||||||
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
|
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
|
||||||
obj["n"] = dv.full_name;
|
obj["n"] = mask + read_flash_string(dv.full_name);
|
||||||
} else if (dv.tag < DeviceValueTAG::TAG_HC1) {
|
} else if (dv.tag < DeviceValueTAG::TAG_HC1) {
|
||||||
obj["n"] = tag_to_string(dv.tag) + " " + read_flash_string(dv.full_name);
|
obj["n"] = mask + tag_to_string(dv.tag) + " " + read_flash_string(dv.full_name);
|
||||||
} else {
|
} else {
|
||||||
obj["n"] = tag_to_string(dv.tag) + " " + read_flash_string(dv.full_name);
|
obj["n"] = mask + tag_to_string(dv.tag) + " " + read_flash_string(dv.full_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add commands and options
|
// add commands and options
|
||||||
if (dv.has_cmd) {
|
if (dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY)) {
|
||||||
// add the name of the Command function
|
// add the name of the Command function
|
||||||
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
obj["c"] = tag_to_mqtt(dv.tag) + "/" + read_flash_string(dv.short_name);
|
obj["c"] = tag_to_mqtt(dv.tag) + "/" + read_flash_string(dv.short_name);
|
||||||
@@ -709,8 +755,9 @@ void EMSdevice::generate_values_web(JsonObject & output) {
|
|||||||
}
|
}
|
||||||
} else if (dv.type == DeviceValueType::BOOL) {
|
} else if (dv.type == DeviceValueType::BOOL) {
|
||||||
JsonArray l = obj.createNestedArray("l");
|
JsonArray l = obj.createNestedArray("l");
|
||||||
l.add("off");
|
char result[10];
|
||||||
l.add("on");
|
l.add(Helpers::render_boolean(result, false));
|
||||||
|
l.add(Helpers::render_boolean(result, true));
|
||||||
}
|
}
|
||||||
// add command help template
|
// add command help template
|
||||||
else if (dv.type == DeviceValueType::STRING || dv.type == DeviceValueType::CMD) {
|
else if (dv.type == DeviceValueType::STRING || dv.type == DeviceValueType::CMD) {
|
||||||
@@ -727,48 +774,31 @@ void EMSdevice::generate_values_web(JsonObject & output) {
|
|||||||
} else if (divider < 0) {
|
} else if (divider < 0) {
|
||||||
obj["s"] = Helpers::render_value(s, (-1) * divider, 0);
|
obj["s"] = Helpers::render_value(s, (-1) * divider, 0);
|
||||||
}
|
}
|
||||||
|
int16_t dv_set_min, dv_set_max;
|
||||||
|
if (dv.get_min_max(dv_set_min, dv_set_max)) {
|
||||||
|
obj["m"] = Helpers::render_value(s, dv_set_min, 0);
|
||||||
|
obj["x"] = Helpers::render_value(s, dv_set_max, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// reset all entities to being visible
|
|
||||||
// this is called before loading in the exclude entities list from the customization service
|
|
||||||
void EMSdevice::reset_exclude_entities() {
|
|
||||||
for (auto & dv : devicevalues_) {
|
|
||||||
dv.add_state(DeviceValueState::DV_VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable/exclude a device entity based on its unique id
|
|
||||||
void EMSdevice::exclude_entity(uint8_t id) {
|
|
||||||
for (auto & dv : devicevalues_) {
|
|
||||||
if (dv.id == id) {
|
|
||||||
#if defined(EMSESP_USE_SERIAL)
|
|
||||||
Serial.print("exclude_entity() Removing Visible for device value: ");
|
|
||||||
Serial.println(read_flash_string(dv.full_name).c_str());
|
|
||||||
#endif
|
|
||||||
dv.remove_state(DeviceValueState::DV_VISIBLE); // this will remove from MQTT payloads and showing in web & console
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// as generate_values_web() but stripped down to only show all entities and their state
|
// as generate_values_web() but stripped down to only show all entities and their state
|
||||||
|
// this is used only for WebCustomizationService::device_entities()
|
||||||
void EMSdevice::generate_values_web_all(JsonArray & output) {
|
void EMSdevice::generate_values_web_all(JsonArray & output) {
|
||||||
for (auto & dv : devicevalues_) {
|
for (const auto & dv : devicevalues_) {
|
||||||
// also show commands and entities that have an empty full name
|
// also show commands and entities that have an empty full name
|
||||||
JsonObject obj = output.createNestedObject();
|
JsonObject obj = output.createNestedObject();
|
||||||
|
|
||||||
// create the value
|
// create the value
|
||||||
if (dv.hasValue()) {
|
if (dv.hasValue()) {
|
||||||
// handle Booleans (true, false)
|
// handle Booleans (true, false), use strings, no native true/false)
|
||||||
if (dv.type == DeviceValueType::BOOL) {
|
if (dv.type == DeviceValueType::BOOL) {
|
||||||
bool value_b = *(bool *)(dv.value_p);
|
bool value_b = (bool)*(uint8_t *)(dv.value_p);
|
||||||
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
||||||
obj["v"] = value_b;
|
|
||||||
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
|
||||||
obj["v"] = value_b ? 1 : 0;
|
obj["v"] = value_b ? 1 : 0;
|
||||||
} else {
|
} else {
|
||||||
char s[7];
|
char s[7];
|
||||||
@@ -830,8 +860,9 @@ void EMSdevice::generate_values_web_all(JsonArray & output) {
|
|||||||
obj["n"] = name;
|
obj["n"] = name;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
obj["n"] = "(hidden)";
|
obj["n"] = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// shortname
|
// shortname
|
||||||
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
obj["s"] = tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
|
obj["s"] = tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
|
||||||
@@ -839,14 +870,45 @@ void EMSdevice::generate_values_web_all(JsonArray & output) {
|
|||||||
obj["s"] = dv.short_name;
|
obj["s"] = dv.short_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
// is it marked as excluded?
|
obj["m"] = dv.state >> 4; // send back the mask state. We're only interested in the high nibble
|
||||||
obj["x"] = !dv.has_state(DeviceValueState::DV_VISIBLE);
|
obj["w"] = dv.has_cmd; // if writable
|
||||||
|
|
||||||
// add the unique ID
|
|
||||||
obj["i"] = dv.id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set mask per device entity based on the id which is prefixed with the 2 char hex mask value
|
||||||
|
// returns true if the entity has a mask set (not 0 the default)
|
||||||
|
void EMSdevice::mask_entity(const std::string & entity_id) {
|
||||||
|
for (auto & dv : devicevalues_) {
|
||||||
|
std::string entity_name =
|
||||||
|
dv.tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(dv.short_name) : tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
|
||||||
|
if (entity_name == entity_id.substr(2)) {
|
||||||
|
// this entity has a new mask set
|
||||||
|
uint8_t current_mask = dv.state >> 4;
|
||||||
|
uint8_t new_mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); // first character contains mask flags
|
||||||
|
if (Mqtt::ha_enabled() && ((current_mask ^ new_mask) & (DeviceValueState::DV_READONLY >> 4))) {
|
||||||
|
// remove ha config on change of dv_readonly flag
|
||||||
|
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||||
|
Mqtt::publish_ha_sensor_config(dv, "", "", true); // delete topic (remove = true)
|
||||||
|
}
|
||||||
|
dv.state = ((dv.state & 0x0F) | (new_mask << 4)); // set state high bits to flag
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// populate a string vector with entities that have masks set
|
||||||
|
void EMSdevice::getMaskedEntities(std::vector<std::string> & entity_ids) {
|
||||||
|
for (auto & dv : devicevalues_) {
|
||||||
|
std::string entity_name =
|
||||||
|
dv.tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(dv.short_name) : tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
|
||||||
|
uint8_t mask = dv.state >> 4;
|
||||||
|
if (mask) {
|
||||||
|
entity_ids.push_back(Helpers::hextoa(mask, false) + entity_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// builds json for a specific device value / entity
|
// builds json for a specific device value / entity
|
||||||
// cmd is the endpoint or name of the device entity
|
// cmd is the endpoint or name of the device entity
|
||||||
// returns false if failed, otherwise true
|
// returns false if failed, otherwise true
|
||||||
@@ -855,7 +917,7 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
|
|||||||
int8_t tag = id;
|
int8_t tag = id;
|
||||||
|
|
||||||
// check if we have hc or wwc or hs
|
// check if we have hc or wwc or hs
|
||||||
if (id >= 1 && id <= 29) {
|
if (id >= 1 && id <= 34) {
|
||||||
tag = DeviceValueTAG::TAG_HC1 + id - 1;
|
tag = DeviceValueTAG::TAG_HC1 + id - 1;
|
||||||
} else if (id != -1) {
|
} else if (id != -1) {
|
||||||
return false; // error
|
return false; // error
|
||||||
@@ -939,7 +1001,7 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
|
|||||||
|
|
||||||
case DeviceValueType::BOOL:
|
case DeviceValueType::BOOL:
|
||||||
if (Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) {
|
if (Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) {
|
||||||
auto value_b = (bool)(*(uint8_t *)(dv.value_p));
|
bool value_b = (bool)*(uint8_t *)(dv.value_p);
|
||||||
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
||||||
json[value] = value_b;
|
json[value] = value_b;
|
||||||
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
||||||
@@ -993,8 +1055,9 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
|
|||||||
json["uom"] = uom_to_string(dv.uom);
|
json["uom"] = uom_to_string(dv.uom);
|
||||||
}
|
}
|
||||||
|
|
||||||
json["writeable"] = dv.has_cmd;
|
json["readable"] = !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE);
|
||||||
json["visible"] = dv.has_state(DeviceValueState::DV_VISIBLE);
|
json["writeable"] = dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY);
|
||||||
|
json["visible"] = !dv.has_state(DeviceValueState::DV_WEB_EXCLUDE);
|
||||||
|
|
||||||
// if there is no value, mention it
|
// if there is no value, mention it
|
||||||
if (!json.containsKey(value)) {
|
if (!json.containsKey(value)) {
|
||||||
@@ -1038,14 +1101,11 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
|
|||||||
|
|
||||||
// check conditions:
|
// check conditions:
|
||||||
// 1. it must have a valid value (state is active)
|
// 1. it must have a valid value (state is active)
|
||||||
// 2. it must have a visible, unless the output_target is MQTT
|
// 2. it must have a visible flag
|
||||||
// 3. it must match the given tag filter or have an empty tag
|
// 3. it must match the given tag filter or have an empty tag
|
||||||
bool conditions = ((tag_filter == DeviceValueTAG::TAG_NONE) || (tag_filter == dv.tag)) && dv.has_state(DeviceValueState::DV_ACTIVE);
|
// 4. it must not have the exclude flag set or outputs to console
|
||||||
// 4. for MQTT we want to always show the special HA entities (they have an empty fullname)
|
if (dv.has_state(DeviceValueState::DV_ACTIVE) && dv.full_name && (tag_filter == DeviceValueTAG::TAG_NONE || tag_filter == dv.tag)
|
||||||
bool visible = ((dv.has_state(DeviceValueState::DV_VISIBLE)) || ((output_target == OUTPUT_TARGET::MQTT) && (!dv.full_name)));
|
&& (output_target == OUTPUT_TARGET::CONSOLE || !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE))) {
|
||||||
conditions &= visible;
|
|
||||||
|
|
||||||
if (conditions) {
|
|
||||||
has_values = true; // flagged if we actually have data
|
has_values = true; // flagged if we actually have data
|
||||||
|
|
||||||
// we have a tag if it matches the filter given, and that the tag name is not empty/""
|
// we have a tag if it matches the filter given, and that the tag name is not empty/""
|
||||||
@@ -1053,7 +1113,7 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
|
|||||||
|
|
||||||
// create the name for the JSON key
|
// create the name for the JSON key
|
||||||
char name[80];
|
char name[80];
|
||||||
if (output_target == OUTPUT_TARGET::API_VERBOSE) {
|
if (output_target == OUTPUT_TARGET::API_VERBOSE || output_target == OUTPUT_TARGET::CONSOLE) {
|
||||||
if (have_tag) {
|
if (have_tag) {
|
||||||
snprintf(name, 80, "%s %s", tag_to_string(dv.tag).c_str(), read_flash_string(dv.full_name).c_str()); // prefix the tag
|
snprintf(name, 80, "%s %s", tag_to_string(dv.tag).c_str(), read_flash_string(dv.full_name).c_str()); // prefix the tag
|
||||||
} else {
|
} else {
|
||||||
@@ -1074,7 +1134,7 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
|
|||||||
// handle Booleans
|
// handle Booleans
|
||||||
if (dv.type == DeviceValueType::BOOL && Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) {
|
if (dv.type == DeviceValueType::BOOL && Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) {
|
||||||
// see how to render the value depending on the setting
|
// see how to render the value depending on the setting
|
||||||
auto value_b = (bool)*(uint8_t *)(dv.value_p);
|
bool value_b = (bool)*(uint8_t *)(dv.value_p);
|
||||||
if (Mqtt::ha_enabled() && (output_target == OUTPUT_TARGET::MQTT)) {
|
if (Mqtt::ha_enabled() && (output_target == OUTPUT_TARGET::MQTT)) {
|
||||||
char s[7];
|
char s[7];
|
||||||
json[name] = Helpers::render_boolean(s, value_b); // for HA always render as string
|
json[name] = Helpers::render_boolean(s, value_b); // for HA always render as string
|
||||||
@@ -1166,7 +1226,7 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
|
|||||||
} else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
} else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||||
uint32_t time_value = *(uint32_t *)(dv.value_p);
|
uint32_t time_value = *(uint32_t *)(dv.value_p);
|
||||||
time_value = Helpers::round2(time_value, divider); // sometimes we need to divide by 60
|
time_value = Helpers::round2(time_value, divider); // sometimes we need to divide by 60
|
||||||
if (output_target == EMSdevice::OUTPUT_TARGET::API_VERBOSE) {
|
if (output_target == OUTPUT_TARGET::API_VERBOSE || output_target == OUTPUT_TARGET::CONSOLE) {
|
||||||
char time_s[40];
|
char time_s[40];
|
||||||
snprintf(time_s,
|
snprintf(time_s,
|
||||||
sizeof(time_s),
|
sizeof(time_s),
|
||||||
@@ -1193,12 +1253,12 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
|
|||||||
return has_values;
|
return has_values;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the Home Assistant configs for each device value/entity if its not visible or active
|
// remove the Home Assistant configs for each device value/entity if its not visible or active or marked as read-only
|
||||||
// this is called when an MQTT publish is done via an EMS Device in emsesp.cpp::publish_device_values()
|
// this is called when an MQTT publish is done via an EMS Device in emsesp.cpp::publish_device_values()
|
||||||
void EMSdevice::mqtt_ha_entity_config_remove() {
|
void EMSdevice::mqtt_ha_entity_config_remove() {
|
||||||
for (auto & dv : devicevalues_) {
|
for (auto & dv : devicevalues_) {
|
||||||
if (dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED)
|
if (dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED)
|
||||||
&& ((!dv.has_state(DeviceValueState::DV_VISIBLE)) || (!dv.has_state(DeviceValueState::DV_ACTIVE)))) {
|
&& ((dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) || (!dv.has_state(DeviceValueState::DV_ACTIVE)))) {
|
||||||
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||||
if (dv.short_name == FL_(climate)[0]) {
|
if (dv.short_name == FL_(climate)[0]) {
|
||||||
Mqtt::publish_ha_climate_config(dv.tag, false, true); // delete topic (remove = true)
|
Mqtt::publish_ha_climate_config(dv.tag, false, true); // delete topic (remove = true)
|
||||||
@@ -1218,7 +1278,7 @@ void EMSdevice::mqtt_ha_entity_config_create() {
|
|||||||
// create climate if roomtemp is visible
|
// create climate if roomtemp is visible
|
||||||
// create the discovery topic if if hasn't already been created, not a command (like reset) and is active and visible
|
// create the discovery topic if if hasn't already been created, not a command (like reset) and is active and visible
|
||||||
for (auto & dv : devicevalues_) {
|
for (auto & dv : devicevalues_) {
|
||||||
if ((dv.short_name == FL_(climate)[0]) && dv.has_state(DeviceValueState::DV_VISIBLE) && dv.has_state(DeviceValueState::DV_ACTIVE)) {
|
if ((dv.short_name == FL_(climate)[0]) && !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE) && dv.has_state(DeviceValueState::DV_ACTIVE)) {
|
||||||
if (*(int8_t *)(dv.value_p) == 1 && (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) || dv.has_state(DeviceValueState::DV_HA_CLIMATE_NO_RT))) {
|
if (*(int8_t *)(dv.value_p) == 1 && (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) || dv.has_state(DeviceValueState::DV_HA_CLIMATE_NO_RT))) {
|
||||||
dv.remove_state(DeviceValueState::DV_HA_CLIMATE_NO_RT);
|
dv.remove_state(DeviceValueState::DV_HA_CLIMATE_NO_RT);
|
||||||
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||||
@@ -1231,7 +1291,7 @@ void EMSdevice::mqtt_ha_entity_config_create() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && (dv.type != DeviceValueType::CMD) && dv.has_state(DeviceValueState::DV_ACTIVE)
|
if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && (dv.type != DeviceValueType::CMD) && dv.has_state(DeviceValueState::DV_ACTIVE)
|
||||||
&& dv.has_state(DeviceValueState::DV_VISIBLE)) {
|
&& !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) {
|
||||||
// create_device_config is only done once for the EMS device. It can added to any entity, so we take the first
|
// create_device_config is only done once for the EMS device. It can added to any entity, so we take the first
|
||||||
Mqtt::publish_ha_sensor_config(dv, name(), brand_to_string(), false, create_device_config);
|
Mqtt::publish_ha_sensor_config(dv, name(), brand_to_string(), false, create_device_config);
|
||||||
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||||
|
|||||||
@@ -179,14 +179,16 @@ class EMSdevice {
|
|||||||
std::string to_string() const;
|
std::string to_string() const;
|
||||||
std::string to_string_short() const;
|
std::string to_string_short() const;
|
||||||
|
|
||||||
enum Handlers : uint8_t { ALL, RECEIVED, FETCHED, PENDING };
|
enum Handlers : uint8_t { ALL, RECEIVED, FETCHED, PENDING, IGNORED };
|
||||||
|
|
||||||
void show_telegram_handlers(uuid::console::Shell & shell) const;
|
void show_telegram_handlers(uuid::console::Shell & shell) const;
|
||||||
char * show_telegram_handlers(char * result, const size_t len, const uint8_t handlers);
|
char * show_telegram_handlers(char * result, const size_t len, const uint8_t handlers);
|
||||||
void show_mqtt_handlers(uuid::console::Shell & shell) const;
|
void show_mqtt_handlers(uuid::console::Shell & shell) const;
|
||||||
void list_device_entries(JsonObject & output) const;
|
void list_device_entries(JsonObject & output) const;
|
||||||
void exclude_entity(uint8_t entity_id);
|
void add_handlers_ignored(const uint16_t handler);
|
||||||
void reset_exclude_entities();
|
|
||||||
|
void mask_entity(const std::string & entity_id);
|
||||||
|
void getMaskedEntities(std::vector<std::string> & entity_ids);
|
||||||
|
|
||||||
using process_function_p = std::function<void(std::shared_ptr<const Telegram>)>;
|
using process_function_p = std::function<void(std::shared_ptr<const Telegram>)>;
|
||||||
|
|
||||||
@@ -197,7 +199,7 @@ class EMSdevice {
|
|||||||
bool get_value_info(JsonObject & root, const char * cmd, const int8_t id);
|
bool get_value_info(JsonObject & root, const char * cmd, const int8_t id);
|
||||||
void get_dv_info(JsonObject & json);
|
void get_dv_info(JsonObject & json);
|
||||||
|
|
||||||
enum OUTPUT_TARGET : uint8_t { API_VERBOSE, API_SHORTNAMES, MQTT };
|
enum OUTPUT_TARGET : uint8_t { API_VERBOSE, API_SHORTNAMES, MQTT, CONSOLE };
|
||||||
bool generate_values(JsonObject & output, const uint8_t tag_filter, const bool nested, const uint8_t output_target);
|
bool generate_values(JsonObject & output, const uint8_t tag_filter, const bool nested, const uint8_t output_target);
|
||||||
void generate_values_web(JsonObject & output);
|
void generate_values_web(JsonObject & output);
|
||||||
void generate_values_web_all(JsonArray & output);
|
void generate_values_web_all(JsonArray & output);
|
||||||
@@ -244,7 +246,9 @@ class EMSdevice {
|
|||||||
|
|
||||||
void read_command(const uint16_t type_id, uint8_t offset = 0, uint8_t length = 0) const;
|
void read_command(const uint16_t type_id, uint8_t offset = 0, uint8_t length = 0) const;
|
||||||
|
|
||||||
bool is_visible(const void * value_p) const;
|
bool is_readable(const void * value_p) const;
|
||||||
|
bool is_readonly(const std::string & cmd, const int8_t id) const;
|
||||||
|
bool has_command(const void * value_p) const;
|
||||||
void publish_value(void * value_p) const;
|
void publish_value(void * value_p) const;
|
||||||
void publish_all_values();
|
void publish_all_values();
|
||||||
|
|
||||||
@@ -318,6 +322,7 @@ class EMSdevice {
|
|||||||
static constexpr uint8_t EMS_DEVICE_FLAG_EMSPLUS = 2;
|
static constexpr uint8_t EMS_DEVICE_FLAG_EMSPLUS = 2;
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_HT3 = 3;
|
static constexpr uint8_t EMS_DEVICE_FLAG_HT3 = 3;
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_HEATPUMP = 4;
|
static constexpr uint8_t EMS_DEVICE_FLAG_HEATPUMP = 4;
|
||||||
|
static constexpr uint8_t EMS_DEVICE_FLAG_HYBRID = 5;
|
||||||
|
|
||||||
// Solar Module
|
// Solar Module
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_SM10 = 1;
|
static constexpr uint8_t EMS_DEVICE_FLAG_SM10 = 1;
|
||||||
@@ -384,10 +389,7 @@ class EMSdevice {
|
|||||||
// device values
|
// device values
|
||||||
std::vector<DeviceValue> devicevalues_;
|
std::vector<DeviceValue> devicevalues_;
|
||||||
|
|
||||||
uint8_t dv_index_ = 0; // unique counter for each added device value
|
std::vector<uint16_t> handlers_ignored_;
|
||||||
uint8_t get_next_dv_id() {
|
|
||||||
return (dv_index_++);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ const __FlashStringHelper * const DeviceValue::DeviceValueTAG_s[] PROGMEM = {
|
|||||||
F_(tag_wwc2), // "Wwc2"
|
F_(tag_wwc2), // "Wwc2"
|
||||||
F_(tag_wwc3), // "wwc3"
|
F_(tag_wwc3), // "wwc3"
|
||||||
F_(tag_wwc4), // "wwc4"
|
F_(tag_wwc4), // "wwc4"
|
||||||
|
F_(tag_wwc5), // "wwc5"
|
||||||
|
F_(tag_wwc6), // "wwc6"
|
||||||
|
F_(tag_wwc7), // "wwc7"
|
||||||
|
F_(tag_wwc8), // "wwc8"
|
||||||
|
F_(tag_wwc9), // "wwc9"
|
||||||
|
F_(tag_wwc10), // "wwc10"
|
||||||
F_(tag_hs1), // "hs1"
|
F_(tag_hs1), // "hs1"
|
||||||
F_(tag_hs2), // "hs2"
|
F_(tag_hs2), // "hs2"
|
||||||
F_(tag_hs3), // "hs3"
|
F_(tag_hs3), // "hs3"
|
||||||
@@ -109,6 +115,12 @@ const __FlashStringHelper * const DeviceValue::DeviceValueTAG_mqtt[] PROGMEM = {
|
|||||||
F_(tag_wwc2), // "Wwc2"
|
F_(tag_wwc2), // "Wwc2"
|
||||||
F_(tag_wwc3), // "wwc3"
|
F_(tag_wwc3), // "wwc3"
|
||||||
F_(tag_wwc4), // "wwc4"
|
F_(tag_wwc4), // "wwc4"
|
||||||
|
F_(tag_wwc5), // "wwc5"
|
||||||
|
F_(tag_wwc6), // "wwc6"
|
||||||
|
F_(tag_wwc7), // "wwc7"
|
||||||
|
F_(tag_wwc8), // "wwc8"
|
||||||
|
F_(tag_wwc9), // "wwc9"
|
||||||
|
F_(tag_wwc10), // "wwc10"
|
||||||
F_(tag_hs1), // "hs1"
|
F_(tag_hs1), // "hs1"
|
||||||
F_(tag_hs2), // "hs2"
|
F_(tag_hs2), // "hs2"
|
||||||
F_(tag_hs3), // "hs3"
|
F_(tag_hs3), // "hs3"
|
||||||
@@ -134,7 +146,7 @@ size_t DeviceValue::tag_count = sizeof(DeviceValue::DeviceValueTAG_s) / sizeof(_
|
|||||||
// checks whether the device value has an actual value
|
// checks whether the device value has an actual value
|
||||||
// returns true if its valid
|
// returns true if its valid
|
||||||
// state is stored in the dv object
|
// state is stored in the dv object
|
||||||
bool DeviceValue::hasValue() {
|
bool DeviceValue::hasValue() const {
|
||||||
bool has_value = false;
|
bool has_value = false;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DeviceValueType::BOOL:
|
case DeviceValueType::BOOL:
|
||||||
|
|||||||
@@ -90,6 +90,12 @@ class DeviceValue {
|
|||||||
TAG_WWC2,
|
TAG_WWC2,
|
||||||
TAG_WWC3,
|
TAG_WWC3,
|
||||||
TAG_WWC4,
|
TAG_WWC4,
|
||||||
|
TAG_WWC5,
|
||||||
|
TAG_WWC6,
|
||||||
|
TAG_WWC7,
|
||||||
|
TAG_WWC8,
|
||||||
|
TAG_WWC9,
|
||||||
|
TAG_WWC10,
|
||||||
TAG_HS1,
|
TAG_HS1,
|
||||||
TAG_HS2,
|
TAG_HS2,
|
||||||
TAG_HS3,
|
TAG_HS3,
|
||||||
@@ -110,11 +116,17 @@ class DeviceValue {
|
|||||||
|
|
||||||
// states of a device value
|
// states of a device value
|
||||||
enum DeviceValueState : uint8_t {
|
enum DeviceValueState : uint8_t {
|
||||||
|
// low nibble active state of the device value
|
||||||
DV_DEFAULT = 0, // 0 - does not yet have a value
|
DV_DEFAULT = 0, // 0 - does not yet have a value
|
||||||
DV_ACTIVE = (1 << 0), // 1 - has a validated real value
|
DV_ACTIVE = (1 << 0), // 1 - has a validated real value
|
||||||
DV_VISIBLE = (1 << 1), // 2 - shown on web, console and on MQTT payload. Otherwise hidden
|
DV_HA_CONFIG_CREATED = (1 << 1), // 2 - set if the HA config topic has been created
|
||||||
DV_HA_CONFIG_CREATED = (1 << 2), // 4 - set if the HA config topic has been created
|
DV_HA_CLIMATE_NO_RT = (1 << 2), // 4 - climate created without roomTemp
|
||||||
DV_HA_CLIMATE_NO_RT = (1 << 3) // 8 - climate created without roomTemp
|
|
||||||
|
// high nibble as mask for exclusions & special functions
|
||||||
|
DV_WEB_EXCLUDE = (1 << 4), // 16 - not shown on web
|
||||||
|
DV_API_MQTT_EXCLUDE = (1 << 5), // 32 - not shown on mqtt, API
|
||||||
|
DV_READONLY = (1 << 6), // 64 - read only
|
||||||
|
DV_FAVORITE = (1 << 7) // 128 - sort to front
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t device_type; // EMSdevice::DeviceType
|
uint8_t device_type; // EMSdevice::DeviceType
|
||||||
@@ -131,7 +143,6 @@ class DeviceValue {
|
|||||||
int16_t min; // min range
|
int16_t min; // min range
|
||||||
uint16_t max; // max range
|
uint16_t max; // max range
|
||||||
uint8_t state; // DeviceValueState::*
|
uint8_t state; // DeviceValueState::*
|
||||||
uint8_t id; // internal unique counter
|
|
||||||
|
|
||||||
DeviceValue(uint8_t device_type,
|
DeviceValue(uint8_t device_type,
|
||||||
uint8_t tag,
|
uint8_t tag,
|
||||||
@@ -146,8 +157,7 @@ class DeviceValue {
|
|||||||
bool has_cmd,
|
bool has_cmd,
|
||||||
int16_t min,
|
int16_t min,
|
||||||
uint16_t max,
|
uint16_t max,
|
||||||
uint8_t state,
|
uint8_t state)
|
||||||
uint8_t id)
|
|
||||||
: device_type(device_type)
|
: device_type(device_type)
|
||||||
, tag(tag)
|
, tag(tag)
|
||||||
, value_p(value_p)
|
, value_p(value_p)
|
||||||
@@ -161,24 +171,23 @@ class DeviceValue {
|
|||||||
, has_cmd(has_cmd)
|
, has_cmd(has_cmd)
|
||||||
, min(min)
|
, min(min)
|
||||||
, max(max)
|
, max(max)
|
||||||
, state(state)
|
, state(state) {
|
||||||
, id(id) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasValue();
|
bool hasValue() const;
|
||||||
bool get_min_max(int16_t & dv_set_min, int16_t & dv_set_max);
|
bool get_min_max(int16_t & dv_set_min, int16_t & dv_set_max);
|
||||||
|
|
||||||
// state flags
|
// state flags
|
||||||
inline void add_state(uint8_t s) {
|
void add_state(uint8_t s) {
|
||||||
state |= s;
|
state |= s;
|
||||||
}
|
}
|
||||||
inline bool has_state(uint8_t s) const {
|
bool has_state(uint8_t s) const {
|
||||||
return (state & s) == s;
|
return (state & s) == s;
|
||||||
}
|
}
|
||||||
inline void remove_state(uint8_t s) {
|
void remove_state(uint8_t s) {
|
||||||
state &= ~s;
|
state &= ~s;
|
||||||
}
|
}
|
||||||
inline uint8_t get_state() const {
|
uint8_t get_state() const {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,15 @@ void EMSESP::fetch_device_values_type(const uint8_t device_type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EMSESP::cmd_is_readonly(const uint8_t device_type, const char * cmd, const int8_t id) {
|
||||||
|
for (const auto & emsdevice : emsdevices) {
|
||||||
|
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
||||||
|
return emsdevice->is_readonly(cmd, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// clears list of recognized devices
|
// clears list of recognized devices
|
||||||
void EMSESP::clear_all_devices() {
|
void EMSESP::clear_all_devices() {
|
||||||
// temporarily removed: clearing the list causes a crash, the associated commands and mqtt should also be removed.
|
// temporarily removed: clearing the list causes a crash, the associated commands and mqtt should also be removed.
|
||||||
@@ -308,7 +317,7 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) {
|
|||||||
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XXLARGE_DYN); // use max size
|
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XXLARGE_DYN); // use max size
|
||||||
JsonObject json = doc.to<JsonObject>();
|
JsonObject json = doc.to<JsonObject>();
|
||||||
|
|
||||||
emsdevice->generate_values(json, DeviceValueTAG::TAG_NONE, true, EMSdevice::OUTPUT_TARGET::API_VERBOSE); // verbose mode and nested
|
emsdevice->generate_values(json, DeviceValueTAG::TAG_NONE, true, EMSdevice::OUTPUT_TARGET::CONSOLE); // verbose mode and nested
|
||||||
|
|
||||||
// print line
|
// print line
|
||||||
uint8_t id = 0;
|
uint8_t id = 0;
|
||||||
@@ -845,6 +854,9 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
|
|||||||
if (wait_validate_ == telegram->type_id) {
|
if (wait_validate_ == telegram->type_id) {
|
||||||
wait_validate_ = 0;
|
wait_validate_ = 0;
|
||||||
}
|
}
|
||||||
|
if (!found && emsdevice->is_device_id(telegram->src) && telegram->message_length > 0) {
|
||||||
|
emsdevice->add_handlers_ignored(telegram->type_id);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1090,7 +1102,7 @@ bool EMSESP::command_commands(uint8_t device_type, JsonObject & output, const in
|
|||||||
bool EMSESP::command_info(uint8_t device_type, JsonObject & output, const int8_t id, const uint8_t output_target) {
|
bool EMSESP::command_info(uint8_t device_type, JsonObject & output, const int8_t id, const uint8_t output_target) {
|
||||||
bool has_value = false;
|
bool has_value = false;
|
||||||
uint8_t tag;
|
uint8_t tag;
|
||||||
if (id >= 1 && id <= 29) {
|
if (id >= 1 && id <= 34) {
|
||||||
tag = DeviceValueTAG::TAG_HC1 + id - 1; // this sets also WWC and HS
|
tag = DeviceValueTAG::TAG_HC1 + id - 1; // this sets also WWC and HS
|
||||||
} else if (id == -1 || id == 0) {
|
} else if (id == -1 || id == 0) {
|
||||||
tag = DeviceValueTAG::TAG_NONE;
|
tag = DeviceValueTAG::TAG_NONE;
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ class EMSESP {
|
|||||||
|
|
||||||
static void send_raw_telegram(const char * data);
|
static void send_raw_telegram(const char * data);
|
||||||
static bool device_exists(const uint8_t device_id);
|
static bool device_exists(const uint8_t device_id);
|
||||||
|
static bool cmd_is_readonly(const uint8_t device_type, const char * cmd, const int8_t id);
|
||||||
|
|
||||||
static uint8_t count_devices(const uint8_t device_type);
|
static uint8_t count_devices(const uint8_t device_type);
|
||||||
static uint8_t count_devices();
|
static uint8_t count_devices();
|
||||||
|
|||||||
@@ -189,12 +189,6 @@ char * Helpers::render_boolean(char * result, bool value) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// // render for native char strings
|
|
||||||
// char * Helpers::render_value(char * result, const char * value, const int8_t format __attribute__((unused))) {
|
|
||||||
// strcpy(result, value); // un-safe but we don't care
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// convert unsigned int (single byte) to text value and returns it
|
// convert unsigned int (single byte) to text value and returns it
|
||||||
// format: 255(0xFF)=boolean, 0=no formatting, otherwise divide by format
|
// format: 255(0xFF)=boolean, 0=no formatting, otherwise divide by format
|
||||||
char * Helpers::render_value(char * result, uint8_t value, int8_t format, const uint8_t fahrenheit) {
|
char * Helpers::render_value(char * result, uint8_t value, int8_t format, const uint8_t fahrenheit) {
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ class Helpers {
|
|||||||
static char * render_value(char * result, const uint32_t value, const int8_t format, const uint8_t fahrenheit = 0);
|
static char * render_value(char * result, const uint32_t value, const int8_t format, const uint8_t fahrenheit = 0);
|
||||||
static char * render_value(char * result, const int16_t value, const int8_t format, const uint8_t fahrenheit = 0);
|
static char * render_value(char * result, const int16_t value, const int8_t format, const uint8_t fahrenheit = 0);
|
||||||
static char * render_value(char * result, const int32_t value, const int8_t format, const uint8_t fahrenheit = 0);
|
static char * render_value(char * result, const int32_t value, const int8_t format, const uint8_t fahrenheit = 0);
|
||||||
// static char * render_value(char * result, const char * value, const int8_t format);
|
|
||||||
static char * render_boolean(char * result, bool value);
|
static char * render_boolean(char * result, bool value);
|
||||||
|
|
||||||
static char * hextoa(char * result, const uint8_t value);
|
static char * hextoa(char * result, const uint8_t value);
|
||||||
|
|||||||
@@ -218,6 +218,12 @@ MAKE_PSTR(tag_wwc1, "wwc1")
|
|||||||
MAKE_PSTR(tag_wwc2, "wwc2")
|
MAKE_PSTR(tag_wwc2, "wwc2")
|
||||||
MAKE_PSTR(tag_wwc3, "wwc3")
|
MAKE_PSTR(tag_wwc3, "wwc3")
|
||||||
MAKE_PSTR(tag_wwc4, "wwc4")
|
MAKE_PSTR(tag_wwc4, "wwc4")
|
||||||
|
MAKE_PSTR(tag_wwc5, "wwc5")
|
||||||
|
MAKE_PSTR(tag_wwc6, "wwc6")
|
||||||
|
MAKE_PSTR(tag_wwc7, "wwc7")
|
||||||
|
MAKE_PSTR(tag_wwc8, "wwc8")
|
||||||
|
MAKE_PSTR(tag_wwc9, "wwc9")
|
||||||
|
MAKE_PSTR(tag_wwc10, "wwc10")
|
||||||
MAKE_PSTR(tag_hs1, "hs1")
|
MAKE_PSTR(tag_hs1, "hs1")
|
||||||
MAKE_PSTR(tag_hs2, "hs2")
|
MAKE_PSTR(tag_hs2, "hs2")
|
||||||
MAKE_PSTR(tag_hs3, "hs3")
|
MAKE_PSTR(tag_hs3, "hs3")
|
||||||
@@ -330,7 +336,7 @@ MAKE_PSTR(functioning_mode, "functioning mode")
|
|||||||
MAKE_PSTR(smoke_temperature, "Abgastemperatur")
|
MAKE_PSTR(smoke_temperature, "Abgastemperatur")
|
||||||
|
|
||||||
// thermostat lists
|
// thermostat lists
|
||||||
MAKE_PSTR_LIST(tpl_datetime, F("Format: < hh:mm:ss dd/mm/yyyy-dw-dst | NTP >"))
|
MAKE_PSTR_LIST(tpl_datetime, F("Format: < NTP | dd.mm.yyyy-hh:mm:ss-dw-dst >"))
|
||||||
MAKE_PSTR_LIST(tpl_switchtime, F("Format: < nn.d.o.hh:mm >"))
|
MAKE_PSTR_LIST(tpl_switchtime, F("Format: < nn.d.o.hh:mm >"))
|
||||||
MAKE_PSTR_LIST(tpl_holidays, F("Format: < dd.mm.yyyy-dd.mm.yyyy >"))
|
MAKE_PSTR_LIST(tpl_holidays, F("Format: < dd.mm.yyyy-dd.mm.yyyy >"))
|
||||||
MAKE_PSTR_LIST(enum_ibaMainDisplay,
|
MAKE_PSTR_LIST(enum_ibaMainDisplay,
|
||||||
@@ -344,6 +350,7 @@ MAKE_PSTR_LIST(enum_ibaMainDisplay,
|
|||||||
F_(date),
|
F_(date),
|
||||||
F_(smoke_temperature))
|
F_(smoke_temperature))
|
||||||
MAKE_PSTR_LIST(enum_ibaLanguage, F_(german), F_(dutch), F_(french), F_(italian))
|
MAKE_PSTR_LIST(enum_ibaLanguage, F_(german), F_(dutch), F_(french), F_(italian))
|
||||||
|
MAKE_PSTR_LIST(enum_ibaLanguage_RC30, F_(german), F_(dutch))
|
||||||
MAKE_PSTR_LIST(enum_floordrystatus, F_(off), F_(start), F_(heat), F_(hold), F_(cool), F_(end))
|
MAKE_PSTR_LIST(enum_floordrystatus, F_(off), F_(start), F_(heat), F_(hold), F_(cool), F_(end))
|
||||||
MAKE_PSTR_LIST(enum_ibaBuildingType, F_(light), F_(medium), F_(heavy)) // RC300
|
MAKE_PSTR_LIST(enum_ibaBuildingType, F_(light), F_(medium), F_(heavy)) // RC300
|
||||||
MAKE_PSTR_LIST(enum_PID, F("fast"), F_(medium), F("slow"))
|
MAKE_PSTR_LIST(enum_PID, F("fast"), F_(medium), F("slow"))
|
||||||
@@ -369,6 +376,7 @@ MAKE_PSTR_LIST(enum_modetype4, F_(nofrost), F_(eco), F_(heat))
|
|||||||
MAKE_PSTR_LIST(enum_modetype5, F_(off), F_(on))
|
MAKE_PSTR_LIST(enum_modetype5, F_(off), F_(on))
|
||||||
|
|
||||||
MAKE_PSTR_LIST(enum_reducemode, F_(nofrost), F_(reduce), F_(room), F_(outdoor))
|
MAKE_PSTR_LIST(enum_reducemode, F_(nofrost), F_(reduce), F_(room), F_(outdoor))
|
||||||
|
MAKE_PSTR_LIST(enum_nofrostmode, F_(off), F_(room), F_(outdoor))
|
||||||
|
|
||||||
MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(optimized), F_(simple), F_(mpc), F_(room), F_(power), F_(constant))
|
MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(optimized), F_(simple), F_(mpc), F_(room), F_(power), F_(constant))
|
||||||
MAKE_PSTR_LIST(enum_controlmode2, F_(outdoor), F_(room))
|
MAKE_PSTR_LIST(enum_controlmode2, F_(outdoor), F_(room))
|
||||||
@@ -451,6 +459,7 @@ MAKE_PSTR_LIST(setBurnPow, F("setburnpow"), F("Sollwert Brennerleistung"))
|
|||||||
MAKE_PSTR_LIST(curBurnPow, F("curburnpow"), F("Brennerleistung"))
|
MAKE_PSTR_LIST(curBurnPow, F("curburnpow"), F("Brennerleistung"))
|
||||||
MAKE_PSTR_LIST(burnStarts, F("burnstarts"), F("Brenner # starts"))
|
MAKE_PSTR_LIST(burnStarts, F("burnstarts"), F("Brenner # starts"))
|
||||||
MAKE_PSTR_LIST(burnWorkMin, F("burnworkmin"), F("Brenner Laufzeit"))
|
MAKE_PSTR_LIST(burnWorkMin, F("burnworkmin"), F("Brenner Laufzeit"))
|
||||||
|
MAKE_PSTR_LIST(burn2WorkMin, F("burn2workmin"), F("Brenner Stufe 2 Laufzeit"))
|
||||||
MAKE_PSTR_LIST(heatWorkMin, F("heatworkmin"), F("Heizung Laufzeit"))
|
MAKE_PSTR_LIST(heatWorkMin, F("heatworkmin"), F("Heizung Laufzeit"))
|
||||||
MAKE_PSTR_LIST(UBAuptime, F("ubauptime"), F("gesamte Laufzeit"))
|
MAKE_PSTR_LIST(UBAuptime, F("ubauptime"), F("gesamte Laufzeit"))
|
||||||
MAKE_PSTR_LIST(lastCode, F("lastcode"), F("Fehlerspeicher"))
|
MAKE_PSTR_LIST(lastCode, F("lastcode"), F("Fehlerspeicher"))
|
||||||
@@ -514,6 +523,16 @@ MAKE_PSTR_LIST(hpTl2, F("hptl2"), F("Außenlufttemperaturfühler (TL2)"))
|
|||||||
MAKE_PSTR_LIST(hpPl1, F("hppl1"), F("Niedrigdruckfühler (PL1)"))
|
MAKE_PSTR_LIST(hpPl1, F("hppl1"), F("Niedrigdruckfühler (PL1)"))
|
||||||
MAKE_PSTR_LIST(hpPh1, F("hpph1"), F("Hochdruckfühler (PH1)"))
|
MAKE_PSTR_LIST(hpPh1, F("hpph1"), F("Hochdruckfühler (PH1)"))
|
||||||
|
|
||||||
|
// hybrid heatpump
|
||||||
|
MAKE_PSTR_LIST(enum_hybridStrategy, F("co2-optimized"), F("cost-optimized"), F("outside-temp-switched"), F("co2-cost-mix"))
|
||||||
|
MAKE_PSTR_LIST(hybridStrategy, F("hybridstrategy"), F("hybrid control strategy"))
|
||||||
|
MAKE_PSTR_LIST(switchOverTemp, F("switchovertemp"), F("outside switchover temperature"))
|
||||||
|
MAKE_PSTR_LIST(energyCostRatio, F("energycostratio"), F("energy cost ratio"))
|
||||||
|
MAKE_PSTR_LIST(fossileFactor, F("fossilefactor"), F("fossile energy factor"))
|
||||||
|
MAKE_PSTR_LIST(electricFactor, F("electricfactor"), F("electric energy factor"))
|
||||||
|
MAKE_PSTR_LIST(delayBoiler, F("delayboiler"), F("delay boiler support"))
|
||||||
|
MAKE_PSTR_LIST(tempDiffBoiler, F("tempdiffboiler"), F("tempediff boiler support"))
|
||||||
|
|
||||||
// the following are dhw for the boiler and automatically tagged with 'ww'
|
// the following are dhw for the boiler and automatically tagged with 'ww'
|
||||||
MAKE_PSTR_LIST(wWSelTemp, F("wwseltemp"), F("gewählte Temperatur"))
|
MAKE_PSTR_LIST(wWSelTemp, F("wwseltemp"), F("gewählte Temperatur"))
|
||||||
MAKE_PSTR_LIST(wwSelTempLow, F("wwseltemplow"), F("selected lower temperature"))
|
MAKE_PSTR_LIST(wwSelTempLow, F("wwseltemplow"), F("selected lower temperature"))
|
||||||
@@ -556,6 +575,7 @@ MAKE_PSTR_LIST(wwMaxTemp, F("wwmaxtemp"), F("Maximale Temperatur"))
|
|||||||
MAKE_PSTR_LIST(wwOneTimeKey, F("wwonetimekey"), F("Einmalladungstaste"))
|
MAKE_PSTR_LIST(wwOneTimeKey, F("wwonetimekey"), F("Einmalladungstaste"))
|
||||||
|
|
||||||
// mqtt values / commands
|
// mqtt values / commands
|
||||||
|
MAKE_PSTR_LIST(switchtime, F("switchtime"), F("program switchtime"))
|
||||||
MAKE_PSTR_LIST(switchtime1, F("switchtime1"), F("own1 program switchtime"))
|
MAKE_PSTR_LIST(switchtime1, F("switchtime1"), F("own1 program switchtime"))
|
||||||
MAKE_PSTR_LIST(switchtime2, F("switchtime2"), F("own2 program switchtime"))
|
MAKE_PSTR_LIST(switchtime2, F("switchtime2"), F("own2 program switchtime"))
|
||||||
MAKE_PSTR_LIST(wwswitchtime, F("wwswitchtime"), F("program switchtime"))
|
MAKE_PSTR_LIST(wwswitchtime, F("wwswitchtime"), F("program switchtime"))
|
||||||
@@ -576,6 +596,11 @@ MAKE_PSTR_LIST(tempsensor2, F("inttemp2"), F("Temperatursensor 2"))
|
|||||||
MAKE_PSTR_LIST(dampedoutdoortemp, F("dampedoutdoortemp"), F("gedämpfte Aussentemperatur"))
|
MAKE_PSTR_LIST(dampedoutdoortemp, F("dampedoutdoortemp"), F("gedämpfte Aussentemperatur"))
|
||||||
MAKE_PSTR_LIST(floordrystatus, F("floordry"), F("Estrichtrocknung"))
|
MAKE_PSTR_LIST(floordrystatus, F("floordry"), F("Estrichtrocknung"))
|
||||||
MAKE_PSTR_LIST(floordrytemp, F("floordrytemp"), F("Estrichtrocknungs Temperatur"))
|
MAKE_PSTR_LIST(floordrytemp, F("floordrytemp"), F("Estrichtrocknungs Temperatur"))
|
||||||
|
MAKE_PSTR_LIST(brightness, F("brightness"), F("bildschirmhelligkeit"))
|
||||||
|
MAKE_PSTR_LIST(autodst, F("autodst"), F("automatische sommerzeit umstellung"))
|
||||||
|
MAKE_PSTR_LIST(preheating, F("preheating"), F("vorheizen im uhrenprogramm"))
|
||||||
|
MAKE_PSTR_LIST(offtemp, F("offtemp"), F("temperatur bei ausgeschaltetem modus"))
|
||||||
|
MAKE_PSTR_LIST(mixingvalves, F("mixingvalves"), F("mischventile"))
|
||||||
// thermostat ww
|
// thermostat ww
|
||||||
MAKE_PSTR_LIST(wwMode, F("wwmode"), F("modus"))
|
MAKE_PSTR_LIST(wwMode, F("wwmode"), F("modus"))
|
||||||
MAKE_PSTR_LIST(wwSetTempLow, F("wwsettemplow"), F("untere Solltemperatur"))
|
MAKE_PSTR_LIST(wwSetTempLow, F("wwsettemplow"), F("untere Solltemperatur"))
|
||||||
@@ -632,6 +657,10 @@ MAKE_PSTR_LIST(holidaymode, F("holidaymode"), F("Urlaubsbetrieb"))
|
|||||||
MAKE_PSTR_LIST(flowtempoffset, F("flowtempoffset"), F("Flusstemperaturanhebung"))
|
MAKE_PSTR_LIST(flowtempoffset, F("flowtempoffset"), F("Flusstemperaturanhebung"))
|
||||||
MAKE_PSTR_LIST(reducemode, F("reducemode"), F("Absenkmodus"))
|
MAKE_PSTR_LIST(reducemode, F("reducemode"), F("Absenkmodus"))
|
||||||
MAKE_PSTR_LIST(noreducetemp, F("noreducetemp"), F("Absenkung unterbrechen unter Temperatur"))
|
MAKE_PSTR_LIST(noreducetemp, F("noreducetemp"), F("Absenkung unterbrechen unter Temperatur"))
|
||||||
|
MAKE_PSTR_LIST(reducetemp, F("reducetemp"), F("Absenkmodus unter Temperatur"))
|
||||||
|
MAKE_PSTR_LIST(vacreducetemp, F("vacreducetemp"), F("Urlaub Absenkmodus unter Temperatur"))
|
||||||
|
MAKE_PSTR_LIST(vacreducemode, F("vacreducemode"), F("Urlaub Absenkmodus"))
|
||||||
|
MAKE_PSTR_LIST(nofrostmode, F("nofrostmode"), F("Frostschutz Modus"))
|
||||||
MAKE_PSTR_LIST(remotetemp, F("remotetemp"), F("Raumtemperatur der Fernsteuerung"))
|
MAKE_PSTR_LIST(remotetemp, F("remotetemp"), F("Raumtemperatur der Fernsteuerung"))
|
||||||
MAKE_PSTR_LIST(reducehours, F("reducehours"), F("duration for nighttemp"))
|
MAKE_PSTR_LIST(reducehours, F("reducehours"), F("duration for nighttemp"))
|
||||||
MAKE_PSTR_LIST(reduceminutes, F("reduceminutes"), F("remaining time for nightmode"))
|
MAKE_PSTR_LIST(reduceminutes, F("reduceminutes"), F("remaining time for nightmode"))
|
||||||
@@ -656,6 +685,7 @@ MAKE_PSTR_LIST(poolSetTemp, F("poolsettemp"), F("pool set temperature"))
|
|||||||
MAKE_PSTR_LIST(poolTemp, F("pooltemp"), F("pool temperature"))
|
MAKE_PSTR_LIST(poolTemp, F("pooltemp"), F("pool temperature"))
|
||||||
MAKE_PSTR_LIST(poolShuntStatus, F("poolshuntstatus"), F("pool shunt status opening/closing"))
|
MAKE_PSTR_LIST(poolShuntStatus, F("poolshuntstatus"), F("pool shunt status opening/closing"))
|
||||||
MAKE_PSTR_LIST(poolShunt, F("poolshunt"), F("pool shunt open/close (0% = pool / 100% = heat)"))
|
MAKE_PSTR_LIST(poolShunt, F("poolshunt"), F("pool shunt open/close (0% = pool / 100% = heat)"))
|
||||||
|
MAKE_PSTR_LIST(hydrTemp, F("hydrTemp"), F("hydraulic header temperature"))
|
||||||
|
|
||||||
// solar
|
// solar
|
||||||
MAKE_PSTR_LIST(collectorTemp, F("collectortemp"), F("Kollektortemperatur (TS1)"))
|
MAKE_PSTR_LIST(collectorTemp, F("collectortemp"), F("Kollektortemperatur (TS1)"))
|
||||||
|
|||||||
@@ -218,6 +218,12 @@ MAKE_PSTR(tag_wwc1, "wwc1")
|
|||||||
MAKE_PSTR(tag_wwc2, "wwc2")
|
MAKE_PSTR(tag_wwc2, "wwc2")
|
||||||
MAKE_PSTR(tag_wwc3, "wwc3")
|
MAKE_PSTR(tag_wwc3, "wwc3")
|
||||||
MAKE_PSTR(tag_wwc4, "wwc4")
|
MAKE_PSTR(tag_wwc4, "wwc4")
|
||||||
|
MAKE_PSTR(tag_wwc5, "wwc5")
|
||||||
|
MAKE_PSTR(tag_wwc6, "wwc6")
|
||||||
|
MAKE_PSTR(tag_wwc7, "wwc7")
|
||||||
|
MAKE_PSTR(tag_wwc8, "wwc8")
|
||||||
|
MAKE_PSTR(tag_wwc9, "wwc9")
|
||||||
|
MAKE_PSTR(tag_wwc10, "wwc10")
|
||||||
MAKE_PSTR(tag_hs1, "hs1")
|
MAKE_PSTR(tag_hs1, "hs1")
|
||||||
MAKE_PSTR(tag_hs2, "hs2")
|
MAKE_PSTR(tag_hs2, "hs2")
|
||||||
MAKE_PSTR(tag_hs3, "hs3")
|
MAKE_PSTR(tag_hs3, "hs3")
|
||||||
@@ -331,7 +337,7 @@ MAKE_PSTR(functioning_mode, "functioning mode")
|
|||||||
MAKE_PSTR(smoke_temperature, "smoke temperature")
|
MAKE_PSTR(smoke_temperature, "smoke temperature")
|
||||||
|
|
||||||
// thermostat lists
|
// thermostat lists
|
||||||
MAKE_PSTR_LIST(tpl_datetime, F("Format: < NTP | hh:mm:ss dd.mm.yyyy-dw-dst >"))
|
MAKE_PSTR_LIST(tpl_datetime, F("Format: < NTP | dd.mm.yyyy-hh:mm:ss-dw-dst >"))
|
||||||
MAKE_PSTR_LIST(tpl_switchtime, F("Format: <nn> [ not_set | day hh:mm on|off ]"))
|
MAKE_PSTR_LIST(tpl_switchtime, F("Format: <nn> [ not_set | day hh:mm on|off ]"))
|
||||||
MAKE_PSTR_LIST(tpl_holidays, F("format: < dd.mm.yyyy-dd.mm.yyyy >"))
|
MAKE_PSTR_LIST(tpl_holidays, F("format: < dd.mm.yyyy-dd.mm.yyyy >"))
|
||||||
MAKE_PSTR_LIST(enum_ibaMainDisplay,
|
MAKE_PSTR_LIST(enum_ibaMainDisplay,
|
||||||
@@ -345,6 +351,7 @@ MAKE_PSTR_LIST(enum_ibaMainDisplay,
|
|||||||
F_(date),
|
F_(date),
|
||||||
F_(smoke_temperature))
|
F_(smoke_temperature))
|
||||||
MAKE_PSTR_LIST(enum_ibaLanguage, F_(german), F_(dutch), F_(french), F_(italian))
|
MAKE_PSTR_LIST(enum_ibaLanguage, F_(german), F_(dutch), F_(french), F_(italian))
|
||||||
|
MAKE_PSTR_LIST(enum_ibaLanguage_RC30, F_(german), F_(dutch))
|
||||||
MAKE_PSTR_LIST(enum_floordrystatus, F_(off), F_(start), F_(heat), F_(hold), F_(cool), F_(end))
|
MAKE_PSTR_LIST(enum_floordrystatus, F_(off), F_(start), F_(heat), F_(hold), F_(cool), F_(end))
|
||||||
MAKE_PSTR_LIST(enum_ibaBuildingType, F_(light), F_(medium), F_(heavy))
|
MAKE_PSTR_LIST(enum_ibaBuildingType, F_(light), F_(medium), F_(heavy))
|
||||||
MAKE_PSTR_LIST(enum_PID, F("fast"), F_(medium), F("slow"))
|
MAKE_PSTR_LIST(enum_PID, F("fast"), F_(medium), F("slow"))
|
||||||
@@ -370,6 +377,7 @@ MAKE_PSTR_LIST(enum_modetype4, F_(nofrost), F_(eco), F_(heat))
|
|||||||
MAKE_PSTR_LIST(enum_modetype5, F_(off), F_(on))
|
MAKE_PSTR_LIST(enum_modetype5, F_(off), F_(on))
|
||||||
|
|
||||||
MAKE_PSTR_LIST(enum_reducemode, F_(nofrost), F_(reduce), F_(room), F_(outdoor))
|
MAKE_PSTR_LIST(enum_reducemode, F_(nofrost), F_(reduce), F_(room), F_(outdoor))
|
||||||
|
MAKE_PSTR_LIST(enum_nofrostmode, F_(off), F_(room), F_(outdoor))
|
||||||
|
|
||||||
MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(optimized), F_(simple), F_(mpc), F_(room), F_(power), F_(constant))
|
MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(optimized), F_(simple), F_(mpc), F_(room), F_(power), F_(constant))
|
||||||
MAKE_PSTR_LIST(enum_controlmode2, F_(outdoor), F_(room))
|
MAKE_PSTR_LIST(enum_controlmode2, F_(outdoor), F_(room))
|
||||||
@@ -441,6 +449,7 @@ MAKE_PSTR_LIST(setBurnPow, F("setburnpow"), F("burner set power"))
|
|||||||
MAKE_PSTR_LIST(curBurnPow, F("curburnpow"), F("burner current power"))
|
MAKE_PSTR_LIST(curBurnPow, F("curburnpow"), F("burner current power"))
|
||||||
MAKE_PSTR_LIST(burnStarts, F("burnstarts"), F("burner starts"))
|
MAKE_PSTR_LIST(burnStarts, F("burnstarts"), F("burner starts"))
|
||||||
MAKE_PSTR_LIST(burnWorkMin, F("burnworkmin"), F("total burner operating time"))
|
MAKE_PSTR_LIST(burnWorkMin, F("burnworkmin"), F("total burner operating time"))
|
||||||
|
MAKE_PSTR_LIST(burn2WorkMin, F("burn2workmin"), F("burner stage 2 operating time"))
|
||||||
MAKE_PSTR_LIST(heatWorkMin, F("heatworkmin"), F("total heat operating time"))
|
MAKE_PSTR_LIST(heatWorkMin, F("heatworkmin"), F("total heat operating time"))
|
||||||
MAKE_PSTR_LIST(UBAuptime, F("ubauptime"), F("total UBA operating time"))
|
MAKE_PSTR_LIST(UBAuptime, F("ubauptime"), F("total UBA operating time"))
|
||||||
MAKE_PSTR_LIST(lastCode, F("lastcode"), F("last error code"))
|
MAKE_PSTR_LIST(lastCode, F("lastcode"), F("last error code"))
|
||||||
@@ -452,7 +461,7 @@ MAKE_PSTR_LIST(maintenanceType, F_(maintenance), F("maintenance scheduled"))
|
|||||||
MAKE_PSTR_LIST(maintenanceTime, F("maintenancetime"), F("time to next maintenance"))
|
MAKE_PSTR_LIST(maintenanceTime, F("maintenancetime"), F("time to next maintenance"))
|
||||||
|
|
||||||
// heatpump/compress specific
|
// heatpump/compress specific
|
||||||
MAKE_PSTR_LIST(upTimeControl, F("uptimecontrol"), F("operating time total heat"))
|
MAKE_PSTR_LIST(upTimeControl, F("uptimecontrol"), F("total operating time heat"))
|
||||||
MAKE_PSTR_LIST(upTimeCompHeating, F("uptimecompheating"), F("operating time compressor heating"))
|
MAKE_PSTR_LIST(upTimeCompHeating, F("uptimecompheating"), F("operating time compressor heating"))
|
||||||
MAKE_PSTR_LIST(upTimeCompCooling, F("uptimecompcooling"), F("operating time compressor cooling"))
|
MAKE_PSTR_LIST(upTimeCompCooling, F("uptimecompcooling"), F("operating time compressor cooling"))
|
||||||
MAKE_PSTR_LIST(upTimeCompWw, F("uptimecompww"), F("operating time compressor dhw"))
|
MAKE_PSTR_LIST(upTimeCompWw, F("uptimecompww"), F("operating time compressor dhw"))
|
||||||
@@ -462,7 +471,7 @@ MAKE_PSTR_LIST(heatingStarts, F("heatingstarts"), F("heating control starts"))
|
|||||||
MAKE_PSTR_LIST(coolingStarts, F("coolingstarts"), F("cooling control starts"))
|
MAKE_PSTR_LIST(coolingStarts, F("coolingstarts"), F("cooling control starts"))
|
||||||
MAKE_PSTR_LIST(poolStarts, F("poolstarts"), F("pool control starts"))
|
MAKE_PSTR_LIST(poolStarts, F("poolstarts"), F("pool control starts"))
|
||||||
MAKE_PSTR_LIST(nrgConsTotal, F("nrgconstotal"), F("total energy consumption"))
|
MAKE_PSTR_LIST(nrgConsTotal, F("nrgconstotal"), F("total energy consumption"))
|
||||||
MAKE_PSTR_LIST(nrgConsCompTotal, F("nrgconscomptotal"), F("energy consumption compressor total"))
|
MAKE_PSTR_LIST(nrgConsCompTotal, F("nrgconscomptotal"), F("total energy consumption compressor"))
|
||||||
MAKE_PSTR_LIST(nrgConsCompHeating, F("nrgconscompheating"), F("energy consumption compressor heating"))
|
MAKE_PSTR_LIST(nrgConsCompHeating, F("nrgconscompheating"), F("energy consumption compressor heating"))
|
||||||
MAKE_PSTR_LIST(nrgConsCompWw, F("nrgconscompww"), F("energy consumption compressor dhw"))
|
MAKE_PSTR_LIST(nrgConsCompWw, F("nrgconscompww"), F("energy consumption compressor dhw"))
|
||||||
MAKE_PSTR_LIST(nrgConsCompCooling, F("nrgconscompcooling"), F("energy consumption compressor cooling"))
|
MAKE_PSTR_LIST(nrgConsCompCooling, F("nrgconscompcooling"), F("energy consumption compressor cooling"))
|
||||||
@@ -472,7 +481,7 @@ MAKE_PSTR_LIST(nrgSuppHeating, F("nrgsuppheating"), F("total energy supplied hea
|
|||||||
MAKE_PSTR_LIST(nrgSuppWw, F("nrgsuppww"), F("total energy warm supplied dhw"))
|
MAKE_PSTR_LIST(nrgSuppWw, F("nrgsuppww"), F("total energy warm supplied dhw"))
|
||||||
MAKE_PSTR_LIST(nrgSuppCooling, F("nrgsuppcooling"), F("total energy supplied cooling"))
|
MAKE_PSTR_LIST(nrgSuppCooling, F("nrgsuppcooling"), F("total energy supplied cooling"))
|
||||||
MAKE_PSTR_LIST(nrgSuppPool, F("nrgsupppool"), F("total energy supplied pool"))
|
MAKE_PSTR_LIST(nrgSuppPool, F("nrgsupppool"), F("total energy supplied pool"))
|
||||||
MAKE_PSTR_LIST(auxElecHeatNrgConsTotal, F("auxelecheatnrgconstotal"), F("auxiliary electrical heater energy consumption total"))
|
MAKE_PSTR_LIST(auxElecHeatNrgConsTotal, F("auxelecheatnrgconstotal"), F("total auxiliary electrical heater energy consumption"))
|
||||||
MAKE_PSTR_LIST(auxElecHeatNrgConsHeating, F("auxelecheatnrgconsheating"), F("auxiliary electrical heater energy consumption heating"))
|
MAKE_PSTR_LIST(auxElecHeatNrgConsHeating, F("auxelecheatnrgconsheating"), F("auxiliary electrical heater energy consumption heating"))
|
||||||
MAKE_PSTR_LIST(auxElecHeatNrgConsWW, F("auxelecheatnrgconsww"), F("auxiliary electrical heater energy consumption dhw"))
|
MAKE_PSTR_LIST(auxElecHeatNrgConsWW, F("auxelecheatnrgconsww"), F("auxiliary electrical heater energy consumption dhw"))
|
||||||
MAKE_PSTR_LIST(auxElecHeatNrgConsPool, F("auxelecheatnrgconspool"), F("auxiliary electrical heater energy consumption pool"))
|
MAKE_PSTR_LIST(auxElecHeatNrgConsPool, F("auxelecheatnrgconspool"), F("auxiliary electrical heater energy consumption pool"))
|
||||||
@@ -504,6 +513,16 @@ MAKE_PSTR_LIST(hpTl2, F("hptl2"), F("air inlet temperature (TL2)"))
|
|||||||
MAKE_PSTR_LIST(hpPl1, F("hppl1"), F("low pressure side temperature (PL1)"))
|
MAKE_PSTR_LIST(hpPl1, F("hppl1"), F("low pressure side temperature (PL1)"))
|
||||||
MAKE_PSTR_LIST(hpPh1, F("hpph1"), F("high pressure side temperature (PH1)"))
|
MAKE_PSTR_LIST(hpPh1, F("hpph1"), F("high pressure side temperature (PH1)"))
|
||||||
|
|
||||||
|
// hybrid heatpump
|
||||||
|
MAKE_PSTR_LIST(enum_hybridStrategy, F("co2-optimized"), F("cost-optimized"), F("outside-temp-switched"), F("co2-cost-mix"))
|
||||||
|
MAKE_PSTR_LIST(hybridStrategy, F("hybridstrategy"), F("hybrid control strategy"))
|
||||||
|
MAKE_PSTR_LIST(switchOverTemp, F("switchovertemp"), F("outside switchover temperature"))
|
||||||
|
MAKE_PSTR_LIST(energyCostRatio, F("energycostratio"), F("energy cost ratio"))
|
||||||
|
MAKE_PSTR_LIST(fossileFactor, F("fossilefactor"), F("fossile energy factor"))
|
||||||
|
MAKE_PSTR_LIST(electricFactor, F("electricfactor"), F("electric energy factor"))
|
||||||
|
MAKE_PSTR_LIST(delayBoiler, F("delayboiler"), F("delay boiler support"))
|
||||||
|
MAKE_PSTR_LIST(tempDiffBoiler, F("tempdiffboiler"), F("tempediff boiler support"))
|
||||||
|
|
||||||
// the following are dhw for the boiler and automatically tagged with 'ww'
|
// the following are dhw for the boiler and automatically tagged with 'ww'
|
||||||
MAKE_PSTR_LIST(wwSelTemp, F("wwseltemp"), F("selected temperature"))
|
MAKE_PSTR_LIST(wwSelTemp, F("wwseltemp"), F("selected temperature"))
|
||||||
MAKE_PSTR_LIST(wwSelTempLow, F("wwseltemplow"), F("selected lower temperature"))
|
MAKE_PSTR_LIST(wwSelTempLow, F("wwseltemplow"), F("selected lower temperature"))
|
||||||
@@ -536,7 +555,7 @@ MAKE_PSTR_LIST(wwSetPumpPower, F("wwsetpumppower"), F("set pump power"))
|
|||||||
MAKE_PSTR_LIST(wwMixerTemp, F("wwmixertemp"), F("mixer temperature"))
|
MAKE_PSTR_LIST(wwMixerTemp, F("wwmixertemp"), F("mixer temperature"))
|
||||||
MAKE_PSTR_LIST(wwCylMiddleTemp, F("wwcylmiddletemp"), F("cylinder middle temperature (TS3)"))
|
MAKE_PSTR_LIST(wwCylMiddleTemp, F("wwcylmiddletemp"), F("cylinder middle temperature (TS3)"))
|
||||||
MAKE_PSTR_LIST(wwStarts, F("wwstarts"), F("starts"))
|
MAKE_PSTR_LIST(wwStarts, F("wwstarts"), F("starts"))
|
||||||
MAKE_PSTR_LIST(wwStarts2, F("wwstarts2"), F("control starts"))
|
MAKE_PSTR_LIST(wwStarts2, F("wwstarts2"), F("control starts2"))
|
||||||
MAKE_PSTR_LIST(wwWorkM, F("wwworkm"), F("active time"))
|
MAKE_PSTR_LIST(wwWorkM, F("wwworkm"), F("active time"))
|
||||||
MAKE_PSTR_LIST(wwHystOn, F("wwhyston"), F("hysteresis on temperature"))
|
MAKE_PSTR_LIST(wwHystOn, F("wwhyston"), F("hysteresis on temperature"))
|
||||||
MAKE_PSTR_LIST(wwHystOff, F("wwhystoff"), F("hysteresis off temperature"))
|
MAKE_PSTR_LIST(wwHystOff, F("wwhystoff"), F("hysteresis off temperature"))
|
||||||
@@ -567,6 +586,11 @@ MAKE_PSTR_LIST(tempsensor2, F("inttemp2"), F("temperature sensor 2"))
|
|||||||
MAKE_PSTR_LIST(dampedoutdoortemp, F("dampedoutdoortemp"), F("damped outdoor temperature"))
|
MAKE_PSTR_LIST(dampedoutdoortemp, F("dampedoutdoortemp"), F("damped outdoor temperature"))
|
||||||
MAKE_PSTR_LIST(floordrystatus, F("floordry"), F("floor drying"))
|
MAKE_PSTR_LIST(floordrystatus, F("floordry"), F("floor drying"))
|
||||||
MAKE_PSTR_LIST(floordrytemp, F("floordrytemp"), F("floor drying temperature"))
|
MAKE_PSTR_LIST(floordrytemp, F("floordrytemp"), F("floor drying temperature"))
|
||||||
|
MAKE_PSTR_LIST(brightness, F("brightness"), F("screen brightness"))
|
||||||
|
MAKE_PSTR_LIST(autodst, F("autodst"), F("automatic change daylight saving time"))
|
||||||
|
MAKE_PSTR_LIST(preheating, F("preheating"), F("preheating in the clock program"))
|
||||||
|
MAKE_PSTR_LIST(offtemp, F("offtemp"), F("temperature when mode is off"))
|
||||||
|
MAKE_PSTR_LIST(mixingvalves, F("mixingvalves"), F("mixing valves"))
|
||||||
// thermostat ww
|
// thermostat ww
|
||||||
MAKE_PSTR_LIST(wwMode, F("wwmode"), F("mode"))
|
MAKE_PSTR_LIST(wwMode, F("wwmode"), F("mode"))
|
||||||
MAKE_PSTR_LIST(wwSetTempLow, F("wwsettemplow"), F("set low temperature"))
|
MAKE_PSTR_LIST(wwSetTempLow, F("wwsettemplow"), F("set low temperature"))
|
||||||
@@ -623,6 +647,10 @@ MAKE_PSTR_LIST(holidaymode, F("holidaymode"), F("holiday mode"))
|
|||||||
MAKE_PSTR_LIST(flowtempoffset, F("flowtempoffset"), F("flow temperature offset for mixer"))
|
MAKE_PSTR_LIST(flowtempoffset, F("flowtempoffset"), F("flow temperature offset for mixer"))
|
||||||
MAKE_PSTR_LIST(reducemode, F("reducemode"), F("reduce mode"))
|
MAKE_PSTR_LIST(reducemode, F("reducemode"), F("reduce mode"))
|
||||||
MAKE_PSTR_LIST(noreducetemp, F("noreducetemp"), F("no reduce below temperature"))
|
MAKE_PSTR_LIST(noreducetemp, F("noreducetemp"), F("no reduce below temperature"))
|
||||||
|
MAKE_PSTR_LIST(reducetemp, F("reducetemp"), F("off/reduce switch temperature"))
|
||||||
|
MAKE_PSTR_LIST(vacreducetemp, F("vacreducetemp"), F("vacations off/reduce switch temperature"))
|
||||||
|
MAKE_PSTR_LIST(vacreducemode, F("vacreducemode"), F("vacations reduce mode"))
|
||||||
|
MAKE_PSTR_LIST(nofrostmode, F("nofrostmode"), F("nofrost mode"))
|
||||||
MAKE_PSTR_LIST(remotetemp, F("remotetemp"), F("room temperature from remote"))
|
MAKE_PSTR_LIST(remotetemp, F("remotetemp"), F("room temperature from remote"))
|
||||||
MAKE_PSTR_LIST(reducehours, F("reducehours"), F("duration for nighttemp"))
|
MAKE_PSTR_LIST(reducehours, F("reducehours"), F("duration for nighttemp"))
|
||||||
MAKE_PSTR_LIST(reduceminutes, F("reduceminutes"), F("remaining time for nightmode"))
|
MAKE_PSTR_LIST(reduceminutes, F("reduceminutes"), F("remaining time for nightmode"))
|
||||||
@@ -647,6 +675,7 @@ MAKE_PSTR_LIST(poolSetTemp, F("poolsettemp"), F("pool set temperature"))
|
|||||||
MAKE_PSTR_LIST(poolTemp, F("pooltemp"), F("pool temperature"))
|
MAKE_PSTR_LIST(poolTemp, F("pooltemp"), F("pool temperature"))
|
||||||
MAKE_PSTR_LIST(poolShuntStatus, F("poolshuntstatus"), F("pool shunt status opening/closing"))
|
MAKE_PSTR_LIST(poolShuntStatus, F("poolshuntstatus"), F("pool shunt status opening/closing"))
|
||||||
MAKE_PSTR_LIST(poolShunt, F("poolshunt"), F("pool shunt open/close (0% = pool / 100% = heat)"))
|
MAKE_PSTR_LIST(poolShunt, F("poolshunt"), F("pool shunt open/close (0% = pool / 100% = heat)"))
|
||||||
|
MAKE_PSTR_LIST(hydrTemp, F("hydrTemp"), F("hydraulic header temperature"))
|
||||||
|
|
||||||
// solar
|
// solar
|
||||||
MAKE_PSTR_LIST(collectorTemp, F("collectortemp"), F("collector temperature (TS1)"))
|
MAKE_PSTR_LIST(collectorTemp, F("collectortemp"), F("collector temperature (TS1)"))
|
||||||
@@ -675,8 +704,8 @@ MAKE_PSTR_LIST(pumpWorkTime, F("pumpworktime"), F("pump working time"))
|
|||||||
MAKE_PSTR_LIST(pump2WorkTime, F("pump2worktime"), F("pump 2 working time"))
|
MAKE_PSTR_LIST(pump2WorkTime, F("pump2worktime"), F("pump 2 working time"))
|
||||||
MAKE_PSTR_LIST(m1WorkTime, F("m1worktime"), F("differential control working time"))
|
MAKE_PSTR_LIST(m1WorkTime, F("m1worktime"), F("differential control working time"))
|
||||||
MAKE_PSTR_LIST(energyLastHour, F("energylasthour"), F("energy last hour"))
|
MAKE_PSTR_LIST(energyLastHour, F("energylasthour"), F("energy last hour"))
|
||||||
MAKE_PSTR_LIST(energyTotal, F("energytotal"), F("energy total"))
|
MAKE_PSTR_LIST(energyTotal, F("energytotal"), F("total energy"))
|
||||||
MAKE_PSTR_LIST(energyToday, F("energytoday"), F("energy today"))
|
MAKE_PSTR_LIST(energyToday, F("energytoday"), F("total energy today"))
|
||||||
MAKE_PSTR_LIST(pumpMinMod, F("pumpminmod"), F("minimum pump modulation"))
|
MAKE_PSTR_LIST(pumpMinMod, F("pumpminmod"), F("minimum pump modulation"))
|
||||||
MAKE_PSTR_LIST(maxFlow, F("maxflow"), F("maximum solar flow"))
|
MAKE_PSTR_LIST(maxFlow, F("maxflow"), F("maximum solar flow"))
|
||||||
MAKE_PSTR_LIST(solarPower, F("solarpower"), F("actual solar power"))
|
MAKE_PSTR_LIST(solarPower, F("solarpower"), F("actual solar power"))
|
||||||
|
|||||||
17
src/mqtt.cpp
17
src/mqtt.cpp
@@ -386,6 +386,10 @@ void Mqtt::on_publish(uint16_t packetId) const {
|
|||||||
|
|
||||||
// called when MQTT settings have changed via the Web forms
|
// called when MQTT settings have changed via the Web forms
|
||||||
void Mqtt::reset_mqtt() {
|
void Mqtt::reset_mqtt() {
|
||||||
|
if (!mqtt_enabled_) {
|
||||||
|
mqtt_messages_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
if (!mqttClient_) {
|
if (!mqttClient_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -648,6 +652,7 @@ void Mqtt::ha_status() {
|
|||||||
}
|
}
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("Uptime"), F("uptime"), DeviceValueUOM::NONE);
|
publish_system_ha_sensor_config(DeviceValueType::INT, F("Uptime"), F("uptime"), DeviceValueUOM::NONE);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("Uptime (sec)"), F("uptime_sec"), DeviceValueUOM::SECONDS);
|
publish_system_ha_sensor_config(DeviceValueType::INT, F("Uptime (sec)"), F("uptime_sec"), DeviceValueUOM::SECONDS);
|
||||||
|
publish_system_ha_sensor_config(DeviceValueType::BOOL, F("NTP status"), F("ntp_status"), DeviceValueUOM::NONE);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("Free memory"), F("freemem"), DeviceValueUOM::KB);
|
publish_system_ha_sensor_config(DeviceValueType::INT, F("Free memory"), F("freemem"), DeviceValueUOM::KB);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("MQTT fails"), F("mqttfails"), DeviceValueUOM::NONE);
|
publish_system_ha_sensor_config(DeviceValueType::INT, F("MQTT fails"), F("mqttfails"), DeviceValueUOM::NONE);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("Rx received"), F("rxreceived"), DeviceValueUOM::NONE);
|
publish_system_ha_sensor_config(DeviceValueType::INT, F("Rx received"), F("rxreceived"), DeviceValueUOM::NONE);
|
||||||
@@ -918,6 +923,10 @@ void Mqtt::publish_ha_sensor_config(DeviceValue & dv, const std::string & model,
|
|||||||
int16_t dv_set_min, dv_set_max;
|
int16_t dv_set_min, dv_set_max;
|
||||||
(void)dv.get_min_max(dv_set_min, dv_set_max);
|
(void)dv.get_min_max(dv_set_min, dv_set_max);
|
||||||
|
|
||||||
|
// determine if we're creating the command topics which we use special HA configs
|
||||||
|
// unless the entity has been marked as read-only and so it'll default to using the sensor/ type
|
||||||
|
bool has_cmd = dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY);
|
||||||
|
|
||||||
publish_ha_sensor_config(dv.type,
|
publish_ha_sensor_config(dv.type,
|
||||||
dv.tag,
|
dv.tag,
|
||||||
dv.full_name,
|
dv.full_name,
|
||||||
@@ -925,7 +934,7 @@ void Mqtt::publish_ha_sensor_config(DeviceValue & dv, const std::string & model,
|
|||||||
dv.short_name,
|
dv.short_name,
|
||||||
dv.uom,
|
dv.uom,
|
||||||
remove,
|
remove,
|
||||||
dv.has_cmd,
|
has_cmd,
|
||||||
dv.options,
|
dv.options,
|
||||||
dv.options_size,
|
dv.options_size,
|
||||||
dv_set_min,
|
dv_set_min,
|
||||||
@@ -988,7 +997,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
|
|||||||
// create the topic, depending on the type and whether the device entity is writable (a command)
|
// create the topic, depending on the type and whether the device entity is writable (a command)
|
||||||
// https://developers.home-assistant.io/docs/core/entity
|
// https://developers.home-assistant.io/docs/core/entity
|
||||||
char topic[MQTT_TOPIC_MAX_SIZE];
|
char topic[MQTT_TOPIC_MAX_SIZE];
|
||||||
// if it's a command then we can use Number, Switch. Otherwise stick to Sensor
|
// if it's a command then we can use Number, Switch, Select. Otherwise stick to Sensor
|
||||||
if (has_cmd) {
|
if (has_cmd) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DeviceValueType::INT:
|
case DeviceValueType::INT:
|
||||||
@@ -996,13 +1005,13 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
|
|||||||
case DeviceValueType::SHORT:
|
case DeviceValueType::SHORT:
|
||||||
case DeviceValueType::USHORT:
|
case DeviceValueType::USHORT:
|
||||||
case DeviceValueType::ULONG:
|
case DeviceValueType::ULONG:
|
||||||
// number - https://www.home-assistant.io/integrations/number.mqtt/
|
// number - https://www.home-assistant.io/integrations/number.mqtt
|
||||||
// https://developers.home-assistant.io/docs/core/entity/number
|
// https://developers.home-assistant.io/docs/core/entity/number
|
||||||
|
|
||||||
snprintf(topic, sizeof(topic), "number/%s/%s/config", mqtt_base_.c_str(), uniq);
|
snprintf(topic, sizeof(topic), "number/%s/%s/config", mqtt_base_.c_str(), uniq);
|
||||||
break;
|
break;
|
||||||
case DeviceValueType::BOOL:
|
case DeviceValueType::BOOL:
|
||||||
// switch - https://www.home-assistant.io/integrations/switch.mqtt/
|
// switch - https://www.home-assistant.io/integrations/switch.mqtt
|
||||||
snprintf(topic, sizeof(topic), "switch/%s/%s/config", mqtt_base_.c_str(), uniq);
|
snprintf(topic, sizeof(topic), "switch/%s/%s/config", mqtt_base_.c_str(), uniq);
|
||||||
break;
|
break;
|
||||||
case DeviceValueType::ENUM:
|
case DeviceValueType::ENUM:
|
||||||
|
|||||||
@@ -543,6 +543,18 @@ bool System::heartbeat_json(JsonObject & output) {
|
|||||||
|
|
||||||
output["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
|
output["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
|
||||||
output["uptime_sec"] = uuid::get_uptime_sec();
|
output["uptime_sec"] = uuid::get_uptime_sec();
|
||||||
|
bool value_b = EMSESP::system_.ntp_connected();
|
||||||
|
if (Mqtt::ha_enabled()) {
|
||||||
|
char s[7];
|
||||||
|
output["ntp_status"] = Helpers::render_boolean(s, value_b); // for HA always render as string
|
||||||
|
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
||||||
|
output["ntp_status"] = value_b;
|
||||||
|
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
||||||
|
output["ntp_status"] = value_b ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
char s[7];
|
||||||
|
output["ntp_status"] = Helpers::render_boolean(s, value_b);
|
||||||
|
}
|
||||||
output["rxreceived"] = EMSESP::rxservice_.telegram_count();
|
output["rxreceived"] = EMSESP::rxservice_.telegram_count();
|
||||||
output["rxfails"] = EMSESP::rxservice_.telegram_error_count();
|
output["rxfails"] = EMSESP::rxservice_.telegram_error_count();
|
||||||
output["txreads"] = EMSESP::txservice_.telegram_read_count();
|
output["txreads"] = EMSESP::txservice_.telegram_read_count();
|
||||||
@@ -949,6 +961,7 @@ bool System::command_settings(const char * value, const int8_t id, JsonObject &
|
|||||||
node["publish_time_other"] = settings.publish_time_other;
|
node["publish_time_other"] = settings.publish_time_other;
|
||||||
node["publish_time_sensor"] = settings.publish_time_sensor;
|
node["publish_time_sensor"] = settings.publish_time_sensor;
|
||||||
node["publish_single"] = settings.publish_single;
|
node["publish_single"] = settings.publish_single;
|
||||||
|
node["publish_2_command"] = settings.publish_single2cmd;
|
||||||
node["send_response"] = settings.send_response;
|
node["send_response"] = settings.send_response;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1016,7 +1029,6 @@ bool System::command_customizations(const char * value, const int8_t id, JsonObj
|
|||||||
|
|
||||||
JsonObject node = output.createNestedObject("Customizations");
|
JsonObject node = output.createNestedObject("Customizations");
|
||||||
|
|
||||||
// hide ssid from this list
|
|
||||||
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
|
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
|
||||||
// sensors
|
// sensors
|
||||||
JsonArray sensorsJson = node.createNestedArray("sensors");
|
JsonArray sensorsJson = node.createNestedArray("sensors");
|
||||||
@@ -1051,16 +1063,16 @@ bool System::command_customizations(const char * value, const int8_t id, JsonObj
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// exclude entities
|
// masked entities
|
||||||
JsonArray exclude_entitiesJson = node.createNestedArray("exclude_entities");
|
JsonArray mask_entitiesJson = node.createNestedArray("masked_entities");
|
||||||
for (const auto & entityCustomization : settings.entityCustomizations) {
|
for (const auto & entityCustomization : settings.entityCustomizations) {
|
||||||
JsonObject entityJson = exclude_entitiesJson.createNestedObject();
|
JsonObject entityJson = mask_entitiesJson.createNestedObject();
|
||||||
entityJson["product_id"] = entityCustomization.product_id;
|
entityJson["product_id"] = entityCustomization.product_id;
|
||||||
entityJson["device_id"] = entityCustomization.device_id;
|
entityJson["device_id"] = entityCustomization.device_id;
|
||||||
|
|
||||||
JsonArray exclude_entityJson = entityJson.createNestedArray("entity_ids");
|
JsonArray mask_entityJson = entityJson.createNestedArray("entities");
|
||||||
for (uint8_t entity_id : entityCustomization.entity_ids) {
|
for (std::string entity_id : entityCustomization.entity_ids) {
|
||||||
exclude_entityJson.add(entity_id);
|
mask_entityJson.add(entity_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1079,6 +1091,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
|
|||||||
node["version"] = EMSESP_APP_VERSION;
|
node["version"] = EMSESP_APP_VERSION;
|
||||||
node["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
|
node["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
|
||||||
node["uptime (seconds)"] = uuid::get_uptime_sec();
|
node["uptime (seconds)"] = uuid::get_uptime_sec();
|
||||||
|
node["network time"] = EMSESP::system_.ntp_connected() ? "connected" : "disconnected";
|
||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
node["freemem"] = ESP.getFreeHeap() / 1000L; // kilobytes
|
node["freemem"] = ESP.getFreeHeap() / 1000L; // kilobytes
|
||||||
@@ -1191,7 +1204,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
|
|||||||
obj["product id"] = emsdevice->product_id();
|
obj["product id"] = emsdevice->product_id();
|
||||||
obj["version"] = emsdevice->version();
|
obj["version"] = emsdevice->version();
|
||||||
obj["entities"] = emsdevice->count_entities();
|
obj["entities"] = emsdevice->count_entities();
|
||||||
char result[250];
|
char result[300];
|
||||||
(void)emsdevice->show_telegram_handlers(result, sizeof(result), EMSdevice::Handlers::RECEIVED);
|
(void)emsdevice->show_telegram_handlers(result, sizeof(result), EMSdevice::Handlers::RECEIVED);
|
||||||
if (result[0] != '\0') {
|
if (result[0] != '\0') {
|
||||||
obj["handlers received"] = result; // don't show handlers if there aren't any
|
obj["handlers received"] = result; // don't show handlers if there aren't any
|
||||||
@@ -1204,6 +1217,10 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
|
|||||||
if (result[0] != '\0') {
|
if (result[0] != '\0') {
|
||||||
obj["handlers pending"] = result;
|
obj["handlers pending"] = result;
|
||||||
}
|
}
|
||||||
|
(void)emsdevice->show_telegram_handlers(result, sizeof(result), EMSdevice::Handlers::IGNORED);
|
||||||
|
if (result[0] != '\0') {
|
||||||
|
obj["handlers ignored"] = result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1321,4 +1338,13 @@ std::string System::reset_reason(uint8_t cpu) const {
|
|||||||
return ("Unkonwn");
|
return ("Unkonwn");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set NTP status
|
||||||
|
void System::ntp_connected(bool b) {
|
||||||
|
if (b != ntp_connected_) {
|
||||||
|
LOG_INFO(b ? F("NTP connected") : F("NTP disconnected"));
|
||||||
|
}
|
||||||
|
ntp_connected_ = b;
|
||||||
|
ntp_last_check_ = b ? uuid::get_uptime_sec() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
13
src/system.h
13
src/system.h
@@ -154,6 +154,16 @@ class System {
|
|||||||
ethernet_connected_ = b;
|
ethernet_connected_ = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ntp_connected(bool b);
|
||||||
|
|
||||||
|
bool ntp_connected() {
|
||||||
|
// timeout 2 hours, ntp sync is normally every hour.
|
||||||
|
if ((uuid::get_uptime_sec() - ntp_last_check_ > 7201) && ntp_connected_) {
|
||||||
|
ntp_connected(false);
|
||||||
|
}
|
||||||
|
return ntp_connected_;
|
||||||
|
}
|
||||||
|
|
||||||
bool network_connected() {
|
bool network_connected() {
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
return (ethernet_connected() || WiFi.isConnected());
|
return (ethernet_connected() || WiFi.isConnected());
|
||||||
@@ -218,6 +228,9 @@ class System {
|
|||||||
bool upload_status_ = false; // true if we're in the middle of a OTA firmware upload
|
bool upload_status_ = false; // true if we're in the middle of a OTA firmware upload
|
||||||
bool ethernet_connected_ = false;
|
bool ethernet_connected_ = false;
|
||||||
|
|
||||||
|
bool ntp_connected_ = false;
|
||||||
|
uint32_t ntp_last_check_ = 0;
|
||||||
|
|
||||||
// EMS-ESP settings
|
// EMS-ESP settings
|
||||||
// copies from WebSettings class in WebSettingsService.h and loaded with reload_settings()
|
// copies from WebSettings class in WebSettingsService.h and loaded with reload_settings()
|
||||||
std::string hostname_ = FACTORY_WIFI_HOSTNAME;
|
std::string hostname_ = FACTORY_WIFI_HOSTNAME;
|
||||||
|
|||||||
@@ -595,8 +595,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
EMSESP::system_.healthcheck(n);
|
EMSESP::system_.healthcheck(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command == "exclude") {
|
if (command == "masked") {
|
||||||
shell.printfln(F("Testing exclude entities"));
|
shell.printfln(F("Testing masked entities"));
|
||||||
|
|
||||||
Mqtt::ha_enabled(true);
|
Mqtt::ha_enabled(true);
|
||||||
Mqtt::send_response(false);
|
Mqtt::send_response(false);
|
||||||
@@ -609,8 +609,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
// toggle mode
|
// toggle mode
|
||||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||||
if (emsdevice->unique_id() == 1) { // boiler
|
if (emsdevice->unique_id() == 1) { // boiler
|
||||||
uint8_t entity_id = 47; // wwseltemp
|
std::string a = "07wwseltemp";
|
||||||
emsdevice->exclude_entity(entity_id);
|
emsdevice->mask_entity(a);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,12 +31,12 @@ namespace emsesp {
|
|||||||
// #define EMSESP_DEBUG_DEFAULT "mixer"
|
// #define EMSESP_DEBUG_DEFAULT "mixer"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "web"
|
// #define EMSESP_DEBUG_DEFAULT "web"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "mqtt"
|
// #define EMSESP_DEBUG_DEFAULT "mqtt"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "general"
|
#define EMSESP_DEBUG_DEFAULT "general"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "boiler"
|
// #define EMSESP_DEBUG_DEFAULT "boiler"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "mqtt2"
|
// #define EMSESP_DEBUG_DEFAULT "mqtt2"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "mqtt_nested"
|
// #define EMSESP_DEBUG_DEFAULT "mqtt_nested"
|
||||||
#define EMSESP_DEBUG_DEFAULT "ha"
|
// #define EMSESP_DEBUG_DEFAULT "ha"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "exclude"
|
// #define EMSESP_DEBUG_DEFAULT "masked"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "board_profile"
|
// #define EMSESP_DEBUG_DEFAULT "board_profile"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "shower_alert"
|
// #define EMSESP_DEBUG_DEFAULT "shower_alert"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "310"
|
// #define EMSESP_DEBUG_DEFAULT "310"
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "3.4.0b8"
|
#define EMSESP_APP_VERSION "3.4.0b12"
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
|
|||||||
securityManager,
|
securityManager,
|
||||||
AuthenticationPredicates::IS_AUTHENTICATED)
|
AuthenticationPredicates::IS_AUTHENTICATED)
|
||||||
, _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE)
|
, _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE)
|
||||||
, _exclude_entities_handler(EXCLUDE_ENTITIES_PATH,
|
, _masked_entities_handler(MASKED_ENTITIES_PATH,
|
||||||
securityManager->wrapCallback(std::bind(&WebCustomizationService::exclude_entities, this, _1, _2),
|
securityManager->wrapCallback(std::bind(&WebCustomizationService::masked_entities, this, _1, _2),
|
||||||
AuthenticationPredicates::IS_AUTHENTICATED))
|
AuthenticationPredicates::IS_AUTHENTICATED))
|
||||||
, _device_entities_handler(DEVICE_ENTITIES_PATH,
|
, _device_entities_handler(DEVICE_ENTITIES_PATH,
|
||||||
securityManager->wrapCallback(std::bind(&WebCustomizationService::device_entities, this, _1, _2),
|
securityManager->wrapCallback(std::bind(&WebCustomizationService::device_entities, this, _1, _2),
|
||||||
@@ -45,16 +45,17 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
|
|||||||
HTTP_POST,
|
HTTP_POST,
|
||||||
securityManager->wrapRequest(std::bind(&WebCustomizationService::reset_customization, this, _1), AuthenticationPredicates::IS_ADMIN));
|
securityManager->wrapRequest(std::bind(&WebCustomizationService::reset_customization, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||||
|
|
||||||
_exclude_entities_handler.setMethod(HTTP_POST);
|
_masked_entities_handler.setMethod(HTTP_POST);
|
||||||
_exclude_entities_handler.setMaxContentLength(1024);
|
_masked_entities_handler.setMaxContentLength(4096);
|
||||||
server->addHandler(&_exclude_entities_handler);
|
_masked_entities_handler.setMaxJsonBufferSize(4096);
|
||||||
|
server->addHandler(&_masked_entities_handler);
|
||||||
|
|
||||||
_device_entities_handler.setMethod(HTTP_POST);
|
_device_entities_handler.setMethod(HTTP_POST);
|
||||||
_device_entities_handler.setMaxContentLength(256);
|
_device_entities_handler.setMaxContentLength(256);
|
||||||
server->addHandler(&_device_entities_handler);
|
server->addHandler(&_device_entities_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this creates the customization file, saving to the FS
|
// this creates the customization file, saving it to the FS
|
||||||
void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
|
void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
|
||||||
// Dallas Sensor customization
|
// Dallas Sensor customization
|
||||||
JsonArray sensorsJson = root.createNestedArray("sensors");
|
JsonArray sensorsJson = root.createNestedArray("sensors");
|
||||||
@@ -77,21 +78,21 @@ void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
|
|||||||
sensorJson["type"] = sensor.type; // t
|
sensorJson["type"] = sensor.type; // t
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude entities customization
|
// Masked entities customization
|
||||||
JsonArray exclude_entitiesJson = root.createNestedArray("exclude_entities");
|
JsonArray masked_entitiesJson = root.createNestedArray("masked_entities");
|
||||||
for (const EntityCustomization & entityCustomization : settings.entityCustomizations) {
|
for (const EntityCustomization & entityCustomization : settings.entityCustomizations) {
|
||||||
JsonObject entityJson = exclude_entitiesJson.createNestedObject();
|
JsonObject entityJson = masked_entitiesJson.createNestedObject();
|
||||||
entityJson["product_id"] = entityCustomization.product_id;
|
entityJson["product_id"] = entityCustomization.product_id;
|
||||||
entityJson["device_id"] = entityCustomization.device_id;
|
entityJson["device_id"] = entityCustomization.device_id;
|
||||||
|
|
||||||
JsonArray exclude_entityJson = entityJson.createNestedArray("entity_ids");
|
JsonArray masked_entityJson = entityJson.createNestedArray("entity_ids");
|
||||||
for (uint8_t entity_id : entityCustomization.entity_ids) {
|
for (std::string entity_id : entityCustomization.entity_ids) {
|
||||||
exclude_entityJson.add(entity_id);
|
masked_entityJson.add(entity_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// call on initialization and also when the page is saved via web
|
// call on initialization and also when the page is saved via web UI
|
||||||
// this loads the data into the internal class
|
// this loads the data into the internal class
|
||||||
StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & settings) {
|
StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & settings) {
|
||||||
// Dallas Sensor customization
|
// Dallas Sensor customization
|
||||||
@@ -123,17 +124,20 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// load array of entities id's to exclude, building up the object class
|
// load array of entities id's with masks, building up the object class
|
||||||
settings.entityCustomizations.clear();
|
settings.entityCustomizations.clear();
|
||||||
if (root["exclude_entities"].is<JsonArray>()) {
|
if (root["masked_entities"].is<JsonArray>()) {
|
||||||
for (const JsonObject exclude_entities : root["exclude_entities"].as<JsonArray>()) {
|
for (const JsonObject masked_entities : root["masked_entities"].as<JsonArray>()) {
|
||||||
auto new_entry = EntityCustomization();
|
auto new_entry = EntityCustomization();
|
||||||
new_entry.product_id = exclude_entities["product_id"];
|
new_entry.product_id = masked_entities["product_id"];
|
||||||
new_entry.device_id = exclude_entities["device_id"];
|
new_entry.device_id = masked_entities["device_id"];
|
||||||
|
|
||||||
for (const JsonVariant exclude_entity_id : exclude_entities["entity_ids"].as<JsonArray>()) {
|
for (const JsonVariant masked_entity_id : masked_entities["entity_ids"].as<JsonArray>()) {
|
||||||
new_entry.entity_ids.push_back(exclude_entity_id.as<uint8_t>()); // add entity list
|
if (masked_entity_id.is<std::string>()) {
|
||||||
|
new_entry.entity_ids.push_back(masked_entity_id.as<std::string>()); // add entity list
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
settings.entityCustomizations.push_back(new_entry); // save the new object
|
settings.entityCustomizations.push_back(new_entry); // save the new object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,7 +160,7 @@ void WebCustomizationService::reset_customization(AsyncWebServerRequest * reques
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// send back a short list devices used in the customization page
|
// send back a list of devices used to the customization web page
|
||||||
void WebCustomizationService::devices(AsyncWebServerRequest * request) {
|
void WebCustomizationService::devices(AsyncWebServerRequest * request) {
|
||||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_LARGE_DYN);
|
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_LARGE_DYN);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
@@ -167,14 +171,16 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) {
|
|||||||
JsonObject obj = devices.createNestedObject();
|
JsonObject obj = devices.createNestedObject();
|
||||||
obj["i"] = emsdevice->unique_id(); // a unique id
|
obj["i"] = emsdevice->unique_id(); // a unique id
|
||||||
|
|
||||||
// shortname - we prefix the count to make it unique
|
/*
|
||||||
uint8_t device_index = EMSESP::device_index(emsdevice->device_type(), emsdevice->unique_id());
|
uint8_t device_index = EMSESP::device_index(emsdevice->device_type(), emsdevice->unique_id());
|
||||||
if (device_index) {
|
if (device_index) {
|
||||||
char s[10];
|
char s[10];
|
||||||
obj["s"] = emsdevice->device_type_name() + Helpers::smallitoa(s, device_index);
|
obj["s"] = emsdevice->device_type_name() + Helpers::smallitoa(s, device_index) + " (" + emsdevice->name() + ")"; // shortname - we prefix the count to make it unique
|
||||||
} else {
|
} else {
|
||||||
obj["s"] = emsdevice->device_type_name();
|
obj["s"] = emsdevice->device_type_name() + " (" + emsdevice->name() + ")";
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
obj["s"] = emsdevice->device_type_name() + " (" + emsdevice->name() + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,10 +188,10 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) {
|
|||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// send back list device entities
|
// send back list of device entities
|
||||||
void WebCustomizationService::device_entities(AsyncWebServerRequest * request, JsonVariant & json) {
|
void WebCustomizationService::device_entities(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||||
if (json.is<JsonObject>()) {
|
if (json.is<JsonObject>()) {
|
||||||
auto * response = new MsgpackAsyncJsonResponse(true, EMSESP_JSON_SIZE_XXLARGE_DYN);
|
auto * response = new MsgpackAsyncJsonResponse(true, EMSESP_JSON_SIZE_XXXLARGE_DYN);
|
||||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||||
if (emsdevice->unique_id() == json["id"]) {
|
if (emsdevice->unique_id() == json["id"]) {
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
@@ -204,52 +210,53 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request, J
|
|||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// takes a list of excluded ids send from the webUI
|
// takes a list of updated entities with new masks from the web UI
|
||||||
// saves it in the customization service
|
// saves it in the customization service
|
||||||
// and updates the entity list real-time
|
// and updates the entity list real-time
|
||||||
void WebCustomizationService::exclude_entities(AsyncWebServerRequest * request, JsonVariant & json) {
|
void WebCustomizationService::masked_entities(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||||
if (json.is<JsonObject>()) {
|
if (json.is<JsonObject>()) {
|
||||||
// find the device using the unique_id
|
// find the device using the unique_id
|
||||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||||
if (emsdevice) {
|
if (emsdevice) {
|
||||||
uint8_t unique_device_id = json["id"];
|
uint8_t unique_device_id = json["id"];
|
||||||
if (emsdevice->unique_id() == unique_device_id) {
|
if (emsdevice->unique_id() == unique_device_id) {
|
||||||
// first reset all the entity ids
|
|
||||||
emsdevice->reset_exclude_entities();
|
|
||||||
|
|
||||||
// build a list of entities to exclude and then set the flag to non-visible
|
|
||||||
JsonArray entity_ids_json = json["entity_ids"];
|
|
||||||
std::vector<uint8_t> entity_ids;
|
|
||||||
for (JsonVariant id : entity_ids_json) {
|
|
||||||
uint8_t entity_id = id.as<int>();
|
|
||||||
emsdevice->exclude_entity(entity_id); // this will have immediate affect
|
|
||||||
entity_ids.push_back(entity_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the list to the customization file
|
|
||||||
uint8_t product_id = emsdevice->product_id();
|
uint8_t product_id = emsdevice->product_id();
|
||||||
uint8_t device_id = emsdevice->device_id();
|
uint8_t device_id = emsdevice->device_id();
|
||||||
|
|
||||||
|
// and set the mask immediately for the changed entities
|
||||||
|
JsonArray entity_ids_json = json["entity_ids"];
|
||||||
|
for (const JsonVariant id : entity_ids_json) {
|
||||||
|
emsdevice->mask_entity(id.as<std::string>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the list to the customization file
|
||||||
EMSESP::webCustomizationService.update(
|
EMSESP::webCustomizationService.update(
|
||||||
[&](WebCustomization & settings) {
|
[&](WebCustomization & settings) {
|
||||||
// if it exists (productid and deviceid match) overwrite it
|
// see if we already have a mask list for this device, if so remove it
|
||||||
for (auto & entityCustomization : settings.entityCustomizations) {
|
for (auto it = settings.entityCustomizations.begin(); it != settings.entityCustomizations.end();) {
|
||||||
if ((entityCustomization.product_id == product_id) && (entityCustomization.device_id == device_id)) {
|
if ((*it).product_id == product_id && (*it).device_id == device_id) {
|
||||||
// already exists, clear the list and add the new values
|
it = settings.entityCustomizations.erase(it);
|
||||||
entityCustomization.entity_ids.clear();
|
break;
|
||||||
for (uint8_t i = 0; i < entity_ids.size(); i++) {
|
} else {
|
||||||
entityCustomization.entity_ids.push_back(entity_ids[i]);
|
++it;
|
||||||
}
|
|
||||||
return StateUpdateResult::CHANGED;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// create a new entry in the list
|
|
||||||
|
if (!entity_ids_json.size()) {
|
||||||
|
return StateUpdateResult::UNCHANGED; // nothing to add
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new entry for this device if there are values
|
||||||
EntityCustomization new_entry;
|
EntityCustomization new_entry;
|
||||||
new_entry.product_id = product_id;
|
new_entry.product_id = product_id;
|
||||||
new_entry.device_id = device_id;
|
new_entry.device_id = device_id;
|
||||||
for (uint8_t i = 0; i < entity_ids.size(); i++) {
|
|
||||||
new_entry.entity_ids.push_back(entity_ids[i]);
|
// get list of entities that have masks
|
||||||
}
|
std::vector<std::string> entity_ids;
|
||||||
|
emsdevice->getMaskedEntities(entity_ids);
|
||||||
|
new_entry.entity_ids = entity_ids;
|
||||||
|
|
||||||
|
// add the record and save
|
||||||
settings.entityCustomizations.push_back(new_entry);
|
settings.entityCustomizations.push_back(new_entry);
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
// POST
|
// POST
|
||||||
#define DEVICE_ENTITIES_PATH "/rest/deviceEntities"
|
#define DEVICE_ENTITIES_PATH "/rest/deviceEntities"
|
||||||
#define EXCLUDE_ENTITIES_PATH "/rest/excludeEntities"
|
#define MASKED_ENTITIES_PATH "/rest/maskedEntities"
|
||||||
#define RESET_CUSTOMIZATION_SERVICE_PATH "/rest/resetCustomizations"
|
#define RESET_CUSTOMIZATION_SERVICE_PATH "/rest/resetCustomizations"
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
@@ -63,15 +63,14 @@ class EntityCustomization {
|
|||||||
public:
|
public:
|
||||||
uint8_t product_id; // device's product id
|
uint8_t product_id; // device's product id
|
||||||
uint8_t device_id; // device's device id
|
uint8_t device_id; // device's device id
|
||||||
std::vector<uint8_t> entity_ids; // array of entity ids to exclude
|
std::vector<std::string> entity_ids; // array of entity ids with masks
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebCustomization {
|
class WebCustomization {
|
||||||
public:
|
public:
|
||||||
std::list<SensorCustomization> sensorCustomizations; // for sensor names and offsets
|
std::list<SensorCustomization> sensorCustomizations; // for sensor names and offsets
|
||||||
std::list<AnalogCustomization> analogCustomizations; // for analog sensors
|
std::list<AnalogCustomization> analogCustomizations; // for analog sensors
|
||||||
std::list<EntityCustomization> entityCustomizations; // for a list of entities that should be excluded from the device list
|
std::list<EntityCustomization> entityCustomizations; // for a list of entities that have a special mask set
|
||||||
|
|
||||||
static void read(WebCustomization & settings, JsonObject & root);
|
static void read(WebCustomization & settings, JsonObject & root);
|
||||||
static StateUpdateResult update(JsonObject & root, WebCustomization & settings);
|
static StateUpdateResult update(JsonObject & root, WebCustomization & settings);
|
||||||
};
|
};
|
||||||
@@ -94,11 +93,11 @@ class WebCustomizationService : public StatefulService<WebCustomization> {
|
|||||||
void devices(AsyncWebServerRequest * request);
|
void devices(AsyncWebServerRequest * request);
|
||||||
|
|
||||||
// POST
|
// POST
|
||||||
void exclude_entities(AsyncWebServerRequest * request, JsonVariant & json);
|
void masked_entities(AsyncWebServerRequest * request, JsonVariant & json);
|
||||||
void device_entities(AsyncWebServerRequest * request, JsonVariant & json);
|
void device_entities(AsyncWebServerRequest * request, JsonVariant & json);
|
||||||
void reset_customization(AsyncWebServerRequest * request);
|
void reset_customization(AsyncWebServerRequest * request);
|
||||||
|
|
||||||
AsyncCallbackJsonWebHandler _exclude_entities_handler, _device_entities_handler;
|
AsyncCallbackJsonWebHandler _masked_entities_handler, _device_entities_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
|
|||||||
// Ignore Contoller
|
// Ignore Contoller
|
||||||
JsonArray devices = root.createNestedArray("devices");
|
JsonArray devices = root.createNestedArray("devices");
|
||||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||||
if (emsdevice && emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER) {
|
if (emsdevice && (emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER || emsdevice->count_entities() > 0)) {
|
||||||
JsonObject obj = devices.createNestedObject();
|
JsonObject obj = devices.createNestedObject();
|
||||||
obj["i"] = emsdevice->unique_id(); // a unique id
|
obj["i"] = emsdevice->unique_id(); // a unique id
|
||||||
obj["t"] = emsdevice->device_type_name(); // type
|
obj["t"] = emsdevice->device_type_name(); // type
|
||||||
|
|||||||
Reference in New Issue
Block a user