Merge remote-tracking branch 'origin/ft_webcallcmd' into dev

This commit is contained in:
proddy
2021-04-17 13:08:04 +02:00
40 changed files with 5130 additions and 6604 deletions

View File

@@ -1,13 +1,20 @@
# Changelog # Changelog
## Added ## Added
- Mock API to simulate an ESP, for testing web - Mock API to simulate an ESP, for testing web
- Able to write values from the Web UI
## Fixed ## Fixed
- Don't create Home Assistant MQTT discovery entries for device values that don't exists (#756 on EMS-ESP repo)
- Update shower MQTT when a shower start is detected
## Changed ## Changed
- Icon for Network - Icon for Network
- MQTT Formatting payload (nested vs single) is a pull-down option - MQTT Formatting payload (nested vs single) is a pull-down option
- moved mqtt-topics and texts to local_EN, all topics lower case - moved mqtt-topics and texts to local_EN, all topics lower case
- Re-enabled Shower Alert (still experimental) - Re-enabled Shower Alert (still experimental)
- lowercased Flow temp in commands
## Removed ## Removed

View File

@@ -2,7 +2,13 @@
**EMS-ESP** is an open-source firmware for the Espressif ESP8266 and ESP32 microcontroller that communicates with **EMS** (Energy Management System) based equipment from manufacturers like Bosch, Buderus, Nefit, Junkers, Worcester and Sieger. **EMS-ESP** is an open-source firmware for the Espressif ESP8266 and ESP32 microcontroller that communicates with **EMS** (Energy Management System) based equipment from manufacturers like Bosch, Buderus, Nefit, Junkers, Worcester and Sieger.
This is the firmware for the ESP32. This is the firmware for the ESP32. Compared to version 2 on the ESP8266, this version has
- Ethernet Support
- Pre-configured board layouts
- Writing values directly from the Web UI
- Mock API server for faster offline development
- Expose to more commands, via MQTT
- Improvements to Dallas sensors, Shower service
[![version](https://img.shields.io/github/release/emsesp/EMS-ESP32.svg?label=Latest%20Release)](https://github.com/emsesp/EMS-ESP32/blob/main/CHANGELOG.md) [![version](https://img.shields.io/github/release/emsesp/EMS-ESP32.svg?label=Latest%20Release)](https://github.com/emsesp/EMS-ESP32/blob/main/CHANGELOG.md)
[![release-date](https://img.shields.io/github/release-date/emsesp/EMS-ESP32.svg?label=Released)](https://github.com/emsesp/EMS-ESP32/commits/main) [![release-date](https://img.shields.io/github/release-date/emsesp/EMS-ESP32.svg?label=Released)](https://github.com/emsesp/EMS-ESP32/commits/main)

View File

@@ -9,7 +9,7 @@ const fs = require('fs');
module.exports = function override(config, env) { module.exports = function override(config, env) {
if (env === "production") { if (env === "production") {
// rename the ouput file, we need it's path to be short, for SPIFFS // rename the output file, we need it's path to be short for LittleFS
config.output.filename = 'js/[id].[chunkhash:4].js'; config.output.filename = 'js/[id].[chunkhash:4].js';
config.output.chunkFilename = 'js/[id].[chunkhash:4].js'; config.output.chunkFilename = 'js/[id].[chunkhash:4].js';

File diff suppressed because it is too large Load Diff

View File

@@ -6,29 +6,29 @@
"@material-ui/core": "^4.11.3", "@material-ui/core": "^4.11.3",
"@material-ui/icons": "^4.11.2", "@material-ui/icons": "^4.11.2",
"@types/lodash": "^4.14.168", "@types/lodash": "^4.14.168",
"@types/node": "^12.20.4", "@types/node": "^14.14.37",
"@types/react": "^17.0.3", "@types/react": "^17.0.3",
"@types/react-dom": "^17.0.1", "@types/react-dom": "^17.0.3",
"@types/react-material-ui-form-validator": "^2.1.0", "@types/react-material-ui-form-validator": "^2.1.0",
"@types/react-router": "^5.1.12", "@types/react-router": "^5.1.13",
"@types/react-router-dom": "^5.1.6", "@types/react-router-dom": "^5.1.7",
"compression-webpack-plugin": "^4.0.0", "compression-webpack-plugin": "^5.0.2",
"express": "^4.17.1", "express": "^4.17.1",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mime-types": "^2.1.29", "mime-types": "^2.1.30",
"notistack": "^1.0.5", "notistack": "^1.0.5",
"parse-ms": "^2.1.0", "parse-ms": "^3.0.0",
"react": "^17.0.1", "react": "^17.0.2",
"react-dom": "^17.0.1", "react-dom": "^17.0.2",
"react-dropzone": "^11.3.1", "react-dropzone": "^11.3.2",
"react-form-validator-core": "^1.1.1", "react-form-validator-core": "^1.1.1",
"react-material-ui-form-validator": "^2.1.4", "react-material-ui-form-validator": "^2.1.4",
"react-router": "^5.2.0", "react-router": "^5.2.0",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-scripts": "4.0.1", "react-scripts": "4.0.3",
"sockette": "^2.0.6", "sockette": "^2.0.6",
"typescript": "4.0.5", "typescript": "4.2.4",
"zlib": "^1.0.5" "zlib": "^1.0.5"
}, },
"scripts": { "scripts": {
@@ -54,9 +54,9 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"concurrently": "^6.0.0", "concurrently": "^6.0.1",
"http-proxy-middleware": "^0.19.1", "http-proxy-middleware": "^1.1.1",
"nodemon": "^2.0.4", "nodemon": "^2.0.7",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"react-app-rewired": "^2.1.8" "react-app-rewired": "^2.1.8"
} }

View File

@@ -5,10 +5,8 @@ import { withSnackbar, WithSnackbarProps } from 'notistack';
import * as Authentication from './Authentication'; import * as Authentication from './Authentication';
import { withAuthenticationContext, AuthenticationContextProps, AuthenticatedContext, AuthenticatedContextValue } from './AuthenticationContext'; import { withAuthenticationContext, AuthenticationContextProps, AuthenticatedContext, AuthenticatedContextValue } from './AuthenticationContext';
type ChildComponent = React.ComponentType<RouteComponentProps<any>> | React.ComponentType<any>;
interface AuthenticatedRouteProps extends RouteProps, WithSnackbarProps, AuthenticationContextProps { interface AuthenticatedRouteProps extends RouteProps, WithSnackbarProps, AuthenticationContextProps {
component: ChildComponent; component: React.ComponentType<RouteComponentProps<any>> | React.ComponentType<any>;
} }
type RenderComponent = (props: RouteComponentProps<any>) => React.ReactNode; type RenderComponent = (props: RouteComponentProps<any>) => React.ReactNode;
@@ -27,7 +25,7 @@ export class AuthenticatedRoute extends React.Component<AuthenticatedRouteProps>
); );
} }
Authentication.storeLoginRedirect(location); Authentication.storeLoginRedirect(location);
enqueueSnackbar("Please sign in to continue.", { variant: 'info' }); enqueueSnackbar("Please sign in to continue", { variant: 'info' });
return ( return (
<Redirect to='/' /> <Redirect to='/' />
); );

View File

@@ -101,7 +101,7 @@ class AuthenticationWrapper extends React.Component<AuthenticationWrapperProps,
me: undefined me: undefined
} }
}); });
this.props.enqueueSnackbar("You have signed out.", { variant: 'success', }); this.props.enqueueSnackbar("You have signed out", { variant: 'success', });
history.push('/'); history.push('/');
} }

View File

@@ -19,8 +19,10 @@ class UnauthenticatedRoute extends Route<UnauthenticatedRouteProps> {
if (authenticationContext.me) { if (authenticationContext.me) {
return (<Redirect to={Authentication.fetchLoginRedirect(features)} />); return (<Redirect to={Authentication.fetchLoginRedirect(features)} />);
} }
if (Component) {
return (<Component {...props} />); return (<Component {...props} />);
} }
}
return ( return (
<Route {...rest} render={renderComponent} /> <Route {...rest} render={renderComponent} />
); );

View File

@@ -8,15 +8,21 @@ import {
import RefreshIcon from "@material-ui/icons/Refresh"; import RefreshIcon from "@material-ui/icons/Refresh";
import ListIcon from "@material-ui/icons/List"; import ListIcon from "@material-ui/icons/List";
import IconButton from '@material-ui/core/IconButton';
import EditIcon from '@material-ui/icons/Edit';
import { redirectingAuthorizedFetch, withAuthenticatedContext, AuthenticatedContextProps } from "../authentication"; import { redirectingAuthorizedFetch, withAuthenticatedContext, AuthenticatedContextProps } from "../authentication";
import { RestFormProps, FormButton } from "../components"; import { RestFormProps, FormButton, extractEventValue } from "../components";
import { EMSESPDevices, EMSESPDeviceData, Device } from "./EMSESPtypes"; import { EMSESPDevices, EMSESPDeviceData, Device, DeviceValue } from "./EMSESPtypes";
import ValueForm from './ValueForm';
import { ENDPOINT_ROOT } from "../api"; import { ENDPOINT_ROOT } from "../api";
export const SCANDEVICES_ENDPOINT = ENDPOINT_ROOT + "scanDevices"; export const SCANDEVICES_ENDPOINT = ENDPOINT_ROOT + "scanDevices";
export const DEVICE_DATA_ENDPOINT = ENDPOINT_ROOT + "deviceData"; export const DEVICE_DATA_ENDPOINT = ENDPOINT_ROOT + "deviceData";
export const WRITE_VALUE_ENDPOINT = ENDPOINT_ROOT + "writeValue";
const StyledTableCell = withStyles((theme: Theme) => const StyledTableCell = withStyles((theme: Theme) =>
createStyles({ createStyles({
@@ -30,6 +36,16 @@ const StyledTableCell = withStyles((theme: Theme) =>
}) })
)(TableCell); )(TableCell);
const CustomTooltip = withStyles((theme: Theme) => ({
tooltip: {
backgroundColor: theme.palette.secondary.main,
color: 'white',
boxShadow: theme.shadows[1],
fontSize: 11,
border: '1px solid #dadde9',
},
}))(Tooltip);
function compareDevices(a: Device, b: Device) { function compareDevices(a: Device, b: Device) {
if (a.type < b.type) { if (a.type < b.type) {
return -1; return -1;
@@ -44,11 +60,11 @@ interface EMSESPDevicesFormState {
confirmScanDevices: boolean; confirmScanDevices: boolean;
processing: boolean; processing: boolean;
deviceData?: EMSESPDeviceData; deviceData?: EMSESPDeviceData;
selectedDevice?: number;
devicevalue?: DeviceValue;
} }
type EMSESPDevicesFormProps = RestFormProps<EMSESPDevices> & type EMSESPDevicesFormProps = RestFormProps<EMSESPDevices> & AuthenticatedContextProps & WithWidthProps;
AuthenticatedContextProps &
WithWidthProps;
function formatTemp(t: string) { function formatTemp(t: string) {
if (t == null) { if (t == null) {
@@ -67,9 +83,66 @@ function formatUnit(u: string) {
class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesFormState> { class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesFormState> {
state: EMSESPDevicesFormState = { state: EMSESPDevicesFormState = {
confirmScanDevices: false, confirmScanDevices: false,
processing: false, processing: false
}; };
handleValueChange = (name: keyof DeviceValue) => (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ devicevalue: { ...this.state.devicevalue!, [name]: extractEventValue(event) } });
};
cancelEditingValue = () => {
this.setState({
devicevalue: undefined
});
}
doneEditingValue = () => {
const { devicevalue } = this.state;
redirectingAuthorizedFetch(WRITE_VALUE_ENDPOINT, {
method: "POST",
body: JSON.stringify({ devicevalue: devicevalue }),
headers: {
"Content-Type": "application/json",
},
})
.then((response) => {
if (response.status === 200) {
this.props.enqueueSnackbar("Write command sent to device", { variant: "success" });
} else if (response.status === 204) {
this.props.enqueueSnackbar("Write command failed", { variant: "error" });
} else if (response.status === 403) {
this.props.enqueueSnackbar("Write access denied", { variant: "error" });
} else {
throw Error("Unexpected response code: " + response.status);
}
})
.catch((error) => {
this.props.enqueueSnackbar(
error.message || "Problem writing value", { variant: "error" }
);
});
if (devicevalue) {
this.setState({
devicevalue: undefined
});
}
};
sendCommand = (i: any) => {
this.setState({
devicevalue: {
id: this.state.selectedDevice!,
data: this.state.deviceData?.data[i]!,
uom: this.state.deviceData?.data[i + 1]!,
name: this.state.deviceData?.data[i + 2]!,
cmd: this.state.deviceData?.data[i + 3]!,
}
});
}
noDevices = () => { noDevices = () => {
return this.props.data.devices.length === 0; return this.props.data.devices.length === 0;
}; };
@@ -95,50 +168,20 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
size="small" size="small"
padding={isWidthDown("xs", width!) ? "none" : "default"} padding={isWidthDown("xs", width!) ? "none" : "default"}
> >
<TableHead>
<TableRow>
<StyledTableCell>Type</StyledTableCell>
<StyledTableCell align="center">Brand</StyledTableCell>
<StyledTableCell align="center">Model</StyledTableCell>
<StyledTableCell align="center">Device ID</StyledTableCell>
<StyledTableCell align="center">Product ID</StyledTableCell>
<StyledTableCell align="center">Version</StyledTableCell>
<StyledTableCell></StyledTableCell>
</TableRow>
</TableHead>
<TableBody> <TableBody>
{data.devices.sort(compareDevices).map((device) => ( {data.devices.sort(compareDevices).map((device) => (
<TableRow <TableRow hover key={device.id} onClick={() => this.handleRowClick(device)}>
hover <TableCell>
key={device.id} <CustomTooltip
onClick={() => this.handleRowClick(device.id)} title={"DeviceID:0x" + ("00" + device.deviceid.toString(16).toUpperCase()).slice(-2) + " ProductID:" + device.productid + " Version:" + device.version}
>
<TableCell component="th" scope="row">
<Tooltip
title="click for details..."
arrow
placement="right-end" placement="right-end"
> >
<Button <Button startIcon={<ListIcon />} size="small" variant="outlined">
startIcon={<ListIcon />}
size="small"
variant="outlined"
>
{device.type} {device.type}
</Button> </Button>
</Tooltip> </CustomTooltip>
</TableCell> </TableCell>
<TableCell align="center">{device.brand}</TableCell> <TableCell align="right">{device.brand + " " + device.name} </TableCell>
<TableCell align="center">{device.name}</TableCell>
<TableCell align="center">
0x
{("00" + device.deviceid.toString(16).toUpperCase()).slice(
-2
)}
</TableCell>
<TableCell align="center">{device.productid}</TableCell>
<TableCell align="center">{device.version}</TableCell>
<TableCell></TableCell>
</TableRow> </TableRow>
))} ))}
</TableBody> </TableBody>
@@ -148,13 +191,10 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
<Box <Box
bgcolor="error.main" bgcolor="error.main"
color="error.contrastText" color="error.contrastText"
p={2} p={2} mt={2} mb={2}
mt={2}
mb={2}
> >
<Typography variant="body1"> <Typography variant="body1">
No EMS devices found. Check the connections and for possible Tx No EMS devices found. Check the connections and for possible Tx errors.
errors.
</Typography> </Typography>
</Box> </Box>
)} )}
@@ -213,25 +253,14 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
> >
<DialogTitle>Confirm Scan Devices</DialogTitle> <DialogTitle>Confirm Scan Devices</DialogTitle>
<DialogContent dividers> <DialogContent dividers>
Are you sure you want to initiate a scan on the EMS bus for all new Are you sure you want to initiate a scan on the EMS bus for all new devices?
devices?
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button <Button variant="contained" onClick={this.onScanDevicesRejected} color="secondary">
variant="contained"
onClick={this.onScanDevicesRejected}
color="secondary"
>
Cancel Cancel
</Button> </Button>
<Button <Button
startIcon={<RefreshIcon />} startIcon={<RefreshIcon />} variant="contained" onClick={this.onScanDevicesConfirmed} disabled={this.state.processing} color="primary" autoFocus>
variant="contained"
onClick={this.onScanDevicesConfirmed}
disabled={this.state.processing}
color="primary"
autoFocus
>
Start Scan Start Scan
</Button> </Button>
</DialogActions> </DialogActions>
@@ -268,11 +297,11 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
}); });
}; };
handleRowClick = (id: any) => { handleRowClick = (device: any) => {
this.setState({ deviceData: undefined }); this.setState({ selectedDevice: device.id, deviceData: undefined });
redirectingAuthorizedFetch(DEVICE_DATA_ENDPOINT, { redirectingAuthorizedFetch(DEVICE_DATA_ENDPOINT, {
method: "POST", method: "POST",
body: JSON.stringify({ id: id }), body: JSON.stringify({ id: device.id }),
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
@@ -298,6 +327,7 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
renderDeviceData() { renderDeviceData() {
const { deviceData } = this.state; const { deviceData } = this.state;
const { width } = this.props; const { width } = this.props;
const me = this.props.authenticatedContext.me;
if (this.noDevices()) { if (this.noDevices()) {
return; return;
@@ -321,16 +351,28 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
size="small" size="small"
padding={isWidthDown("xs", width!) ? "none" : "default"} padding={isWidthDown("xs", width!) ? "none" : "default"}
> >
<TableHead></TableHead> <TableHead>
</TableHead>
<TableBody> <TableBody>
{deviceData.data.map((item, i) => { {deviceData.data.map((item, i) => {
if (i % 3) { if (i % 4) {
return null; return null;
} else { } else {
return ( return (
<TableRow key={i}> <TableRow hover key={i}>
<TableCell component="th" scope="row">{deviceData.data[i + 2]}</TableCell> <TableCell padding="checkbox" style={{ width: 18 }} >
<TableCell align="right">{deviceData.data[i]}{formatUnit(deviceData.data[i + 1])}</TableCell> {deviceData.data[i + 3] && me.admin && (
<CustomTooltip title="change value" placement="left-end"
>
<IconButton edge="start" size="small" aria-label="Edit"
onClick={() => this.sendCommand(i)}>
<EditIcon color="primary" fontSize="small" />
</IconButton>
</CustomTooltip>
)}
</TableCell>
<TableCell padding="none" component="th" scope="row">{deviceData.data[i + 2]}</TableCell>
<TableCell padding="none" align="right">{deviceData.data[i]}{formatUnit(deviceData.data[i + 1])}</TableCell>
</TableRow> </TableRow>
); );
} }
@@ -351,6 +393,7 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
} }
render() { render() {
const { devicevalue } = this.state;
return ( return (
<Fragment> <Fragment>
<br></br> <br></br>
@@ -360,27 +403,26 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
<br></br> <br></br>
<Box display="flex" flexWrap="wrap"> <Box display="flex" flexWrap="wrap">
<Box flexGrow={1} padding={1}> <Box flexGrow={1} padding={1}>
<FormButton <FormButton startIcon={<RefreshIcon />} variant="contained" color="secondary" onClick={this.props.loadData} >
startIcon={<RefreshIcon />}
variant="contained"
color="secondary"
onClick={this.props.loadData}
>
Refresh Refresh
</FormButton> </FormButton>
</Box> </Box>
<Box flexWrap="none" padding={1} whiteSpace="nowrap"> <Box flexWrap="none" padding={1} whiteSpace="nowrap">
<FormButton <FormButton startIcon={<RefreshIcon />} variant="contained" onClick={this.onScanDevices} >
startIcon={<RefreshIcon />}
variant="contained"
color="primary"
onClick={this.onScanDevices}
>
Scan Devices Scan Devices
</FormButton> </FormButton>
</Box> </Box>
</Box> </Box>
{this.renderScanDevicesDialog()} {this.renderScanDevicesDialog()}
{
devicevalue &&
<ValueForm
devicevalue={devicevalue}
onDoneEditing={this.doneEditingValue}
onCancelEditing={this.cancelEditingValue}
handleValueChange={this.handleValueChange}
/>
}
</Fragment> </Fragment>
); );
} }

View File

@@ -108,7 +108,7 @@ class EMSESPSettingsForm extends React.Component<EMSESPSettingsFormProps> {
<ValidatorForm onSubmit={saveData}> <ValidatorForm onSubmit={saveData}>
<Box bgcolor="info.main" p={2} mt={2} mb={2}> <Box bgcolor="info.main" p={2} mt={2} mb={2}>
<Typography variant="body1"> <Typography variant="body1">
Modify any of the EMS-ESP settings here. For help refer to the{" "} Adjust any of the EMS-ESP settings here. For help refer to the{" "}
<Link <Link
target="_blank" target="_blank"
href="https://emsesp.github.io/docs/#/Configure-firmware32?id=ems-esp-settings" href="https://emsesp.github.io/docs/#/Configure-firmware32?id=ems-esp-settings"

View File

@@ -62,3 +62,11 @@ export interface EMSESPDeviceData {
name: string; name: string;
data: string[]; data: string[];
} }
export interface DeviceValue {
id: number;
data: string,
uom: string,
name: string,
cmd: string
}

View File

@@ -0,0 +1,64 @@
import React, { RefObject } from 'react';
import { TextValidator, ValidatorForm } from 'react-material-ui-form-validator';
import { Dialog, DialogTitle, DialogContent, DialogActions, Box, Typography } from '@material-ui/core';
import { FormButton } from '../components';
import { DeviceValue } from './EMSESPtypes';
interface ValueFormProps {
devicevalue: DeviceValue;
onDoneEditing: () => void;
onCancelEditing: () => void;
handleValueChange: (data: keyof DeviceValue) => (event: React.ChangeEvent<HTMLInputElement>) => void;
}
class ValueForm extends React.Component<ValueFormProps> {
formRef: RefObject<any> = React.createRef();
submit = () => {
this.formRef.current.submit();
}
buildLabel = (devicevalue: DeviceValue) => {
if ((devicevalue.uom === "") || (!devicevalue.uom)) {
return "New value";
}
return "New value (" + devicevalue.uom + ")";
}
render() {
const { devicevalue, handleValueChange, onDoneEditing, onCancelEditing } = this.props;
return (
<ValidatorForm onSubmit={onDoneEditing} ref={this.formRef}>
<Dialog maxWidth="xs" onClose={onCancelEditing} aria-labelledby="user-form-dialog-title" open>
<DialogTitle id="user-form-dialog-title">Change the {devicevalue.name}</DialogTitle>
<DialogContent dividers>
<TextValidator
validators={['required']}
errorMessages={['is required']}
name="data"
label={this.buildLabel(devicevalue)}
fullWidth
variant="outlined"
value={devicevalue.data}
margin="normal"
onChange={handleValueChange('data')}
/>
<Box color="warning.main" p={1} pl={0} pr={0} mt={0} mb={0}>
<Typography variant="body2">
<i>Note: it may take a few seconds before the change is visible. If nothing happens check the logs.</i>
</Typography>
</Box>
</DialogContent>
<DialogActions>
<FormButton variant="contained" color="secondary" onClick={onCancelEditing}>Cancel</FormButton>
<FormButton variant="contained" color="primary" type="submit" onClick={this.submit}>Done</FormButton>
</DialogActions>
</Dialog>
</ValidatorForm>
);
}
}
export default ValueForm;

View File

@@ -122,9 +122,7 @@ class ManageUsersForm extends React.Component<ManageUsersFormProps, ManageUsersF
{user.username} {user.username}
</TableCell> </TableCell>
<TableCell align="center"> <TableCell align="center">
{ {user.admin ? <CheckIcon /> : <CloseIcon />}
user.admin ? <CheckIcon /> : <CloseIcon />
}
</TableCell> </TableCell>
<TableCell align="center"> <TableCell align="center">
<IconButton size="small" aria-label="Delete" onClick={() => this.removeUser(user)}> <IconButton size="small" aria-label="Delete" onClick={() => this.removeUser(user)}>

View File

@@ -1,4 +1,4 @@
const createProxyMiddleware = require('http-proxy-middleware'); const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) { module.exports = function (app) {
app.use( app.use(
@@ -6,10 +6,7 @@ module.exports = function (app) {
createProxyMiddleware({ createProxyMiddleware({
target: 'http://localhost:3080', target: 'http://localhost:3080',
secure: false, secure: false,
changeOrigin: true, changeOrigin: true
// pathRewrite: {
// '^/api/settings': '/api/app/settings'
// },
}) })
); );
}; };

View File

@@ -17,7 +17,7 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "react", "jsx": "react-jsx",
"noFallthroughCasesInSwitch": true "noFallthroughCasesInSwitch": true
}, },
"include": [ "include": [

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
{ {
"name": "api", "name": "api",
"version": "1.0.0", "version": "1.0.0",
"private": "true",
"description": "mock api for EMS-ESP", "description": "mock api for EMS-ESP",
"main": "server.js", "main": "server.js",
"scripts": { "scripts": {
@@ -11,6 +12,6 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"express": "^4.17.1", "express": "^4.17.1",
"nodemon": "^2.0.4" "nodemon": "^2.0.7"
} }
} }

View File

@@ -110,6 +110,7 @@ const EMSESP_SCANDEVICES_ENDPOINT = ENDPOINT_ROOT + "scanDevices";
const EMSESP_DEVICEDATA_ENDPOINT = ENDPOINT_ROOT + "deviceData"; const EMSESP_DEVICEDATA_ENDPOINT = ENDPOINT_ROOT + "deviceData";
const EMSESP_STATUS_ENDPOINT = ENDPOINT_ROOT + "emsespStatus"; const EMSESP_STATUS_ENDPOINT = ENDPOINT_ROOT + "emsespStatus";
const EMSESP_BOARDPROFILE_ENDPOINT = ENDPOINT_ROOT + "boardProfile"; const EMSESP_BOARDPROFILE_ENDPOINT = ENDPOINT_ROOT + "boardProfile";
const WRITE_VALUE_ENDPOINT = ENDPOINT_ROOT + "writeValue";
const emsesp_settings = { const emsesp_settings = {
"tx_mode": 1, "tx_delay": 0, "ems_bus_id": 11, "syslog_enabled": false, "syslog_level": 3, "tx_mode": 1, "tx_delay": 0, "ems_bus_id": 11, "syslog_enabled": false, "syslog_level": 3,
"trace_raw": false, "syslog_mark_interval": 0, "syslog_host": "192.168.1.4", "syslog_port": 514, "trace_raw": false, "syslog_mark_interval": 0, "syslog_host": "192.168.1.4", "syslog_port": 514,
@@ -119,13 +120,13 @@ const emsesp_settings = {
}; };
const emsesp_alldevices = { const emsesp_alldevices = {
"devices": [{ "devices": [{
"id": 1, "type": "Thermostat", "brand": "---", "name": "RC20/Moduline 300", "id": 1, "type": "Thermostat", "brand": "", "name": "RC20/Moduline 300",
"deviceid": 23, "productid": 77, "version": "03.03" "deviceid": 23, "productid": 77, "version": "03.03"
}, { }, {
"id": 2, "type": "Boiler", "brand": "Nefit", "name": "GBx72/Trendline/Cerapur/Greenstar Si/27i", "id": 2, "type": "Boiler", "brand": "Nefit", "name": "GBx72/Trendline/Cerapur/Greenstar Si/27i",
"deviceid": 8, "productid": 123, "version": "06.01" "deviceid": 8, "productid": 123, "version": "06.01"
}, { }, {
"id": 3, "type": "Controller", "brand": "---", "name": "BC10", "id": 3, "type": "Controller", "brand": "", "name": "BC10",
"deviceid": 9, "productid": 190, "version": "01.03" "deviceid": 9, "productid": 190, "version": "01.03"
}], }],
"sensors": [] "sensors": []
@@ -134,33 +135,78 @@ const emsesp_status = {
"status": 0, "rx_received": 344, "tx_sent": 104, "rx_quality": 100, "tx_quality": 100 "status": 0, "rx_received": 344, "tx_sent": 104, "rx_quality": 100, "tx_quality": 100
}; };
const emsesp_devicedata_1 = { const emsesp_devicedata_1 = {
"name": "Thermostat: RC20/Moduline 300", "data": ["16:28:21 01/04/2021", "", "date/time", "name": "Thermostat: RC20/Moduline 300",
"(0)", "", "error code", 15, "°C", "(hc1) setpoint room temperature", 20.5, "°C", "data": [
"(hc1) current room temperature", "auto", "", "(hc1) mode"] "16:28:21 01/04/2021", "", "date/time", "datetime",
"(0)", "", "error code", "",
15, "°C", "(hc1) setpoint room temperature", "temp",
20.5, "°C", "(hc1) current room temperature", "",
"auto", "", "(hc1) mode", "mode"
]
}; };
const emsesp_devicedata_2 = { const emsesp_devicedata_2 = {
"name": "Boiler: Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i", "data": ["off", "", "heating active", "off", "", "name": "Boiler: Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i",
"warm water active", 5, "°C", "selected flow temperature", 0, "%", "burner selected max power", 0, "%", "data": [
"heating pump modulation", 42.7, "°C", "current flow temperature", 39, "°C", "return temperature", 1.2, "off", "", "heating active", "",
"bar", "system pressure", 45.3, "°C", "max boiler temperature", "off", "", "gas", 0, "uA", "flame current", "off", "", "warm water active", "",
"off", "", "heating pump", "off", "", "fan", "off", "", "ignition", "on", "", "heating activated", 75, "°C", 5, "°C", "selected flow temperature", "selflowtemp",
"heating temperature", 90, "%", "burner pump max power", 55, "%", "burner pump min power", 1, null, "pump delay", 0, "%", "burner selected max power", "",
10, null, "burner min period", 0, "%", "burner min power", 75, "%", "burner max power", -6, "°C", "hysteresis on temperature", 6, 0, "%", "heating pump modulation", "",
"°C", "hysteresis off temperature", 0, "%", "burner current power", 295740, "", "burner # starts", "344 days 2 hours 8 minutes", 42.7, "°C", "current flow temperature", "",
null, "total burner operating time", "279 days 11 hours 55 minutes", null, "total heat operating time", 39, "°C", "return temperature", "",
"2946 days 19 hours 8 minutes", null, "total UBA operating time", "1C(210) 06.06.2020 12:07", "", 1.2, "bar", "system pressure", "",
"last error code", "0H", "", "service code", 203, "", "service code number", "01.01.2012", "", 45.3, "°C", "max boiler temperature", "",
"maintenance set date", "off", "", "maintenance scheduled", 6000, "hours", "maintenance set time", 60, "°C", "off", "", "gas", "",
"(warm water) selected temperature", 62, "°C", "(warm water) set temperature", "flow", "", "(warm water) type", "hot", 0, "uA", "flame current", "",
"", "(warm water) comfort", 40, "", "(warm water) flow temperature offset", 100, "%", "(warm water) max power", "off", "off", "", "heating pump", "",
"", "(warm water) circulation pump available", "3-way valve", "", "(warm water) charging type", 70, "°C", "off", "", "fan", "",
"(warm water) disinfection temperature", "off", "", "(warm water) circulation pump freq", "off", "", "off", "", "ignition", "",
"(warm water) circulation active", 34.7, "°C", "(warm water) current intern temperature", 0, "l/min", "on", "", "heating activated", "",
"(warm water) current tap water flow", 34.6, "°C", "(warm water) storage intern temperature", "on", "", 75, "°C", "heating temperature", "",
"(warm water) activated", "off", "", "(warm water) one time charging", "off", "", 90, "%", "burner pump max power", "",
"(warm water) disinfecting", "off", "", "(warm water) charging", "off", "", "(warm water) recharging", "on", "", 55, "%", "burner pump min power", "",
"(warm water) temperature ok", "off", "", "(warm water) active", "on", "", "(warm water) heating", 262387, "", 1, null, "pump delay", "",
"(warm water) # starts", "64 days 14 hours 13 minutes", null, "(warm water) active time"] 10, null, "burner min period", "",
0, "%", "burner min power", "",
75, "%", "burner max power", "",
-6, "°C", "hysteresis on temperature", "",
6, "°C", "hysteresis off temperature", "",
0, "%", "burner current power", "",
295740, "", "burner # starts", "",
"344 days 2 hours 8 minutes", null, "total burner operating time", "",
"279 days 11 hours 55 minutes", null, "total heat operating time", "",
"2946 days 19 hours 8 minutes", null, "total UBA operating time", "",
"1C(210) 06.06.2020 12:07", "", "last error code", "",
"0H", "", "service code", "",
203, "", "service code number", "",
"01.01.2012", "", "maintenance set date", "",
"off", "", "maintenance scheduled", "",
6000, "hours", "maintenance set time", "",
60, "°C", "(warm water) selected temperature", "",
62, "°C", "(warm water) set temperature", "",
"flow", "", "(warm water) type", "",
"hot", "", "(warm water) comfort", "",
40, "", "(warm water) flow temperature offset", "",
100, "%", "(warm water) max power", "",
"off", "", "(warm water) circulation pump available", "",
"3-way valve", "", "(warm water) charging type", "",
70, "°C", "(warm water) disinfection temperature", "",
"off", "", "(warm water) circulation pump freq", "",
"off", "", "(warm water) circulation active", "",
34.7, "°C", "(warm water) current intern temperature", "",
0, "l/min", "(warm water) current tap water flow", "",
34.6, "°C", "(warm water) storage intern temperature", "",
"on", "", "(warm water) activated", "",
"off", "", "(warm water) one time charging", "",
"off", "", "(warm water) disinfecting", "",
"off", "", "(warm water) charging", "",
"off", "", "(warm water) recharging", "",
"on", "", "(warm water) temperature ok", "",
"off", "", "(warm water) active", "",
"on", "", "(warm water) heating", "",
262387, "", "(warm water) # starts", "",
"64 days 14 hours 13 minutes", null, "(warm water) active time", ""
]
}; };
@@ -206,6 +252,7 @@ app.post(SIGN_IN_ENDPOINT, (req, res) => { res.json(signin); });
app.get(EMSESP_SETTINGS_ENDPOINT, (req, res) => { res.json(emsesp_settings); }); app.get(EMSESP_SETTINGS_ENDPOINT, (req, res) => { res.json(emsesp_settings); });
app.post(EMSESP_SETTINGS_ENDPOINT, (req, res) => { res.json(emsesp_settings); }); app.post(EMSESP_SETTINGS_ENDPOINT, (req, res) => { res.json(emsesp_settings); });
app.get(EMSESP_ALLDEVICES_ENDPOINT, (req, res) => { res.json(emsesp_alldevices); }); app.get(EMSESP_ALLDEVICES_ENDPOINT, (req, res) => { res.json(emsesp_alldevices); });
app.post(EMSESP_SCANDEVICES_ENDPOINT, (req, res) => { res.sendStatus(200); });
app.get(EMSESP_STATUS_ENDPOINT, (req, res) => { res.json(emsesp_status); }); app.get(EMSESP_STATUS_ENDPOINT, (req, res) => { res.json(emsesp_status); });
app.post(EMSESP_DEVICEDATA_ENDPOINT, (req, res) => { app.post(EMSESP_DEVICEDATA_ENDPOINT, (req, res) => {
const id = req.body.id; const id = req.body.id;
@@ -216,6 +263,15 @@ app.post(EMSESP_DEVICEDATA_ENDPOINT, (req, res) => {
res.json(emsesp_devicedata_2); res.json(emsesp_devicedata_2);
} }
}); });
app.post(WRITE_VALUE_ENDPOINT, (req, res) => {
const devicevalue = req.body.devicevalue;
console.log(devicevalue);
res.sendStatus(200);
});
app.post(EMSESP_BOARDPROFILE_ENDPOINT, (req, res) => { app.post(EMSESP_BOARDPROFILE_ENDPOINT, (req, res) => {
const board_profile = req.body.code; const board_profile = req.body.code;

View File

@@ -28,10 +28,6 @@ WebAPIService::WebAPIService(AsyncWebServer * server) {
// e.g. http://ems-esp/api?device=boiler&cmd=wwtemp&data=20&id=1 // e.g. http://ems-esp/api?device=boiler&cmd=wwtemp&data=20&id=1
void WebAPIService::webAPIService(AsyncWebServerRequest * request) { void WebAPIService::webAPIService(AsyncWebServerRequest * request) {
// see if the API is enabled
bool api_enabled;
EMSESP::webSettingsService.read([&](WebSettings & settings) { api_enabled = settings.api_enabled; });
// must have device and cmd parameters // must have device and cmd parameters
if ((!request->hasParam(F_(device))) || (!request->hasParam(F_(cmd)))) { if ((!request->hasParam(F_(device))) || (!request->hasParam(F_(cmd)))) {
request->send(400, "text/plain", F("Invalid syntax")); request->send(400, "text/plain", F("Invalid syntax"));
@@ -77,8 +73,10 @@ void WebAPIService::webAPIService(AsyncWebServerRequest * request) {
if (data.isEmpty()) { if (data.isEmpty()) {
ok = Command::call(device_type, cmd.c_str(), nullptr, id.toInt(), json); // command only ok = Command::call(device_type, cmd.c_str(), nullptr, id.toInt(), json); // command only
} else { } else {
if (api_enabled) {
// we only allow commands with parameters if the API is enabled // we only allow commands with parameters if the API is enabled
bool api_enabled;
EMSESP::webSettingsService.read([&](WebSettings & settings) { api_enabled = settings.api_enabled; });
if (api_enabled) {
ok = Command::call(device_type, cmd.c_str(), data.c_str(), id.toInt(), json); // has cmd, data and id ok = Command::call(device_type, cmd.c_str(), data.c_str(), id.toInt(), json); // has cmd, data and id
} else { } else {
request->send(401, "text/plain", F("Unauthorized")); request->send(401, "text/plain", F("Unauthorized"));

View File

@@ -23,14 +23,18 @@ namespace emsesp {
using namespace std::placeholders; // for `_1` etc using namespace std::placeholders; // for `_1` etc
WebDevicesService::WebDevicesService(AsyncWebServer * server, SecurityManager * securityManager) WebDevicesService::WebDevicesService(AsyncWebServer * server, SecurityManager * securityManager)
: _device_dataHandler(DEVICE_DATA_SERVICE_PATH, securityManager->wrapCallback(std::bind(&WebDevicesService::device_data, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED)) { : _device_dataHandler(DEVICE_DATA_SERVICE_PATH, securityManager->wrapCallback(std::bind(&WebDevicesService::device_data, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED))
, _writevalue_dataHandler(WRITE_VALUE_SERVICE_PATH, securityManager->wrapCallback(std::bind(&WebDevicesService::write_value, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED)) {
server->on(EMSESP_DEVICES_SERVICE_PATH, HTTP_GET, securityManager->wrapRequest(std::bind(&WebDevicesService::all_devices, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); server->on(EMSESP_DEVICES_SERVICE_PATH, HTTP_GET, securityManager->wrapRequest(std::bind(&WebDevicesService::all_devices, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
server->on(SCAN_DEVICES_SERVICE_PATH, HTTP_GET, securityManager->wrapRequest(std::bind(&WebDevicesService::scan_devices, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); server->on(SCAN_DEVICES_SERVICE_PATH, HTTP_GET, securityManager->wrapRequest(std::bind(&WebDevicesService::scan_devices, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
_device_dataHandler.setMethod(HTTP_POST); _device_dataHandler.setMethod(HTTP_POST);
_device_dataHandler.setMaxContentLength(256); _device_dataHandler.setMaxContentLength(256);
server->addHandler(&_device_dataHandler); server->addHandler(&_device_dataHandler);
_writevalue_dataHandler.setMethod(HTTP_POST);
_writevalue_dataHandler.setMaxContentLength(256);
server->addHandler(&_writevalue_dataHandler);
} }
void WebDevicesService::scan_devices(AsyncWebServerRequest * request) { void WebDevicesService::scan_devices(AsyncWebServerRequest * request) {
@@ -96,4 +100,49 @@ void WebDevicesService::device_data(AsyncWebServerRequest * request, JsonVariant
request->send(response); request->send(response);
} }
// takes a command and its data value from a specific Device, from the Web
void WebDevicesService::write_value(AsyncWebServerRequest * request, JsonVariant & json) {
// only issue commands if the API is enabled
EMSESP::webSettingsService.read([&](WebSettings & settings) {
if (!settings.api_enabled) {
request->send(403); // forbidden error
return;
}
});
if (json.is<JsonObject>()) {
JsonObject dv = json["devicevalue"];
// using the unique ID from the web find the real device type
for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice) {
if (emsdevice->unique_id() == dv["id"].as<int>()) {
const char * cmd = dv["cmd"];
uint8_t device_type = emsdevice->device_type();
bool ok = false;
char s[10];
// the data could be in any format, but we need string
JsonVariant data = dv["data"];
if (data.is<char *>()) {
ok = Command::call(device_type, cmd, data.as<const char *>());
} else if (data.is<int>()) {
ok = Command::call(device_type, cmd, Helpers::render_value(s, data.as<int16_t>(), 0));
} else if (data.is<float>()) {
ok = Command::call(device_type, cmd, Helpers::render_value(s, (float)data.as<float>(), 1));
} else if (data.is<bool>()) {
ok = Command::call(device_type, cmd, data.as<bool>() ? "true" : "false");
}
if (ok) {
request->send(200);
}
return; // found device, quit
}
}
}
request->send(204); // no content error
}
}
} // namespace emsesp } // namespace emsesp

View File

@@ -27,6 +27,8 @@
#define EMSESP_DEVICES_SERVICE_PATH "/rest/allDevices" #define EMSESP_DEVICES_SERVICE_PATH "/rest/allDevices"
#define SCAN_DEVICES_SERVICE_PATH "/rest/scanDevices" #define SCAN_DEVICES_SERVICE_PATH "/rest/scanDevices"
#define DEVICE_DATA_SERVICE_PATH "/rest/deviceData" #define DEVICE_DATA_SERVICE_PATH "/rest/deviceData"
#define WRITE_VALUE_SERVICE_PATH "/rest/writeValue"
namespace emsesp { namespace emsesp {
@@ -35,11 +37,15 @@ class WebDevicesService {
WebDevicesService(AsyncWebServer * server, SecurityManager * securityManager); WebDevicesService(AsyncWebServer * server, SecurityManager * securityManager);
private: private:
// GET
void all_devices(AsyncWebServerRequest * request); void all_devices(AsyncWebServerRequest * request);
void scan_devices(AsyncWebServerRequest * request); void scan_devices(AsyncWebServerRequest * request);
void device_data(AsyncWebServerRequest * request, JsonVariant & json);
AsyncCallbackJsonWebHandler _device_dataHandler; // POST
void device_data(AsyncWebServerRequest * request, JsonVariant & json);
void write_value(AsyncWebServerRequest * request, JsonVariant & json);
AsyncCallbackJsonWebHandler _device_dataHandler, _writevalue_dataHandler;
}; };
} // namespace emsesp } // namespace emsesp

View File

@@ -30,14 +30,15 @@ std::vector<Command::CmdFunction> Command::cmdfunctions_;
// id may be used to represent a heating circuit for example, it's optional // id may be used to represent a heating circuit for example, it's optional
// returns false if error or not found // returns false if error or not found
bool Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id) { bool Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id) {
std::string dname = EMSdevice::device_type_2_device_name(device_type);
auto cf = find_command(device_type, cmd); auto cf = find_command(device_type, cmd);
if ((cf == nullptr) || (cf->cmdfunction_json_)) { if ((cf == nullptr) || (cf->cmdfunction_json_)) {
LOG_WARNING(F("Command %s not found"), cmd); LOG_WARNING(F("Command %s on %s not found"), cmd, dname.c_str());
return false; // command not found, or requires a json return false; // command not found, or requires a json
} }
#ifdef EMSESP_DEBUG #ifdef EMSESP_DEBUG
std::string dname = EMSdevice::device_type_2_device_name(device_type);
if (value == nullptr) { if (value == nullptr) {
LOG_DEBUG(F("[DEBUG] Calling %s command %s"), dname.c_str(), cmd); LOG_DEBUG(F("[DEBUG] Calling %s command %s"), dname.c_str(), cmd);
} else if (id == -1) { } else if (id == -1) {
@@ -54,14 +55,15 @@ bool Command::call(const uint8_t device_type, const char * cmd, const char * val
// id may be used to represent a heating circuit for example // id may be used to represent a heating circuit for example
// returns false if error or not found // returns false if error or not found
bool Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id, JsonObject & json) { bool Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id, JsonObject & json) {
std::string dname = EMSdevice::device_type_2_device_name(device_type);
auto cf = find_command(device_type, cmd); auto cf = find_command(device_type, cmd);
if (cf == nullptr) { if (cf == nullptr) {
LOG_WARNING(F("Command %s not found"), cmd); LOG_WARNING(F("Command %s on %s not found"), cmd, dname.c_str());
return false; // command not found or not json return false; // command not found or not json
} }
#ifdef EMSESP_DEBUG #ifdef EMSESP_DEBUG
std::string dname = EMSdevice::device_type_2_device_name(device_type);
if (value == nullptr) { if (value == nullptr) {
LOG_DEBUG(F("[DEBUG] Calling %s command %s"), dname.c_str(), cmd); LOG_DEBUG(F("[DEBUG] Calling %s command %s"), dname.c_str(), cmd);
} else if (id == -1) { } else if (id == -1) {
@@ -110,6 +112,7 @@ void Command::add_with_json(const uint8_t device_type, const __FlashStringHelper
} }
// see if a command exists for that device type // see if a command exists for that device type
// is not case sensitive
Command::CmdFunction * Command::find_command(const uint8_t device_type, const char * cmd) { Command::CmdFunction * Command::find_command(const uint8_t device_type, const char * cmd) {
if ((cmd == nullptr) || (strlen(cmd) == 0) || (cmdfunctions_.empty())) { if ((cmd == nullptr) || (strlen(cmd) == 0) || (cmdfunctions_.empty())) {
return nullptr; return nullptr;

View File

@@ -41,7 +41,7 @@ class Command {
public: public:
struct CmdFunction { struct CmdFunction {
uint8_t device_type_; // DeviceType:: uint8_t device_type_; // DeviceType::
uint8_t flag_; uint8_t flag_; // mqtt flags for command subscriptions
const __FlashStringHelper * cmd_; const __FlashStringHelper * cmd_;
cmdfunction_p cmdfunction_; cmdfunction_p cmdfunction_;
cmdfunction_json_p cmdfunction_json_; cmdfunction_json_p cmdfunction_json_;

View File

@@ -25,7 +25,7 @@
// Boilers - 0x08 // Boilers - 0x08
{ 64, DeviceType::BOILER, F("BK13/BK15/Smartline/GB1x2"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, { 64, DeviceType::BOILER, F("BK13/BK15/Smartline/GB1x2"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{ 72, DeviceType::BOILER, F("GB125/MC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, { 72, DeviceType::BOILER, F("GB125/MC10"), DeviceFlags::EMS_DEVICE_FLAG_EMS},
{ 84, DeviceType::BOILER, F("Logamax Plus GB022"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, { 84, DeviceType::BOILER, F("Logamax Plus GB022"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{ 95, DeviceType::BOILER, F("Condens 2500/Logamax/Logomatic/Cerapur Top/Greenstar/Generic HT3"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, { 95, DeviceType::BOILER, F("Condens 2500/Logamax/Logomatic/Cerapur Top/Greenstar/Generic HT3"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{115, DeviceType::BOILER, F("Topline/GB162"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, {115, DeviceType::BOILER, F("Topline/GB162"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
@@ -68,13 +68,13 @@
{203, DeviceType::THERMOSTAT, F("EasyControl CT200"), DeviceFlags::EMS_DEVICE_FLAG_EASY | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18, cannot write {203, DeviceType::THERMOSTAT, F("EasyControl CT200"), DeviceFlags::EMS_DEVICE_FLAG_EASY | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18, cannot write
// Thermostat - Buderus/Nefit/Bosch specific - 0x17 / 0x10 / 0x18 / 0x19 / 0x38 // Thermostat - Buderus/Nefit/Bosch specific - 0x17 / 0x10 / 0x18 / 0x19 / 0x38
{ 67, DeviceType::THERMOSTAT, F("RC30"), DeviceFlags::EMS_DEVICE_FLAG_RC30_1},// 0x10 - based on RC35 { 67, DeviceType::THERMOSTAT, F("RC30"), DeviceFlags::EMS_DEVICE_FLAG_RC30_N},// 0x10 - based on RC35
{ 77, DeviceType::THERMOSTAT, F("RC20/Moduline 300"), DeviceFlags::EMS_DEVICE_FLAG_RC20},// 0x17 { 77, DeviceType::THERMOSTAT, F("RC20/Moduline 300"), DeviceFlags::EMS_DEVICE_FLAG_RC20},// 0x17
{ 78, DeviceType::THERMOSTAT, F("Moduline 400"), DeviceFlags::EMS_DEVICE_FLAG_RC30}, // 0x10 { 78, DeviceType::THERMOSTAT, F("Moduline 400"), DeviceFlags::EMS_DEVICE_FLAG_RC30}, // 0x10
{ 79, DeviceType::THERMOSTAT, F("RC10/Moduline 100"), DeviceFlags::EMS_DEVICE_FLAG_RC10},// 0x17 { 79, DeviceType::THERMOSTAT, F("RC10/Moduline 100"), DeviceFlags::EMS_DEVICE_FLAG_RC10},// 0x17
{ 80, DeviceType::THERMOSTAT, F("Moduline 200"), DeviceFlags::EMS_DEVICE_FLAG_RC10}, // 0x17 { 80, DeviceType::THERMOSTAT, F("Moduline 200"), DeviceFlags::EMS_DEVICE_FLAG_RC10}, // 0x17
{ 86, DeviceType::THERMOSTAT, F("RC35"), DeviceFlags::EMS_DEVICE_FLAG_RC35}, // 0x10 { 86, DeviceType::THERMOSTAT, F("RC35"), DeviceFlags::EMS_DEVICE_FLAG_RC35}, // 0x10
{ 90, DeviceType::THERMOSTAT, F("RC10/Moduline 100"), DeviceFlags::EMS_DEVICE_FLAG_RC20_2}, // 0x17 { 90, DeviceType::THERMOSTAT, F("RC10/Moduline 100"), DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17
{ 93, DeviceType::THERMOSTAT, F("RC20RF"), DeviceFlags::EMS_DEVICE_FLAG_RC20}, // 0x19 { 93, DeviceType::THERMOSTAT, F("RC20RF"), DeviceFlags::EMS_DEVICE_FLAG_RC20}, // 0x19
{ 94, DeviceType::THERMOSTAT, F("RFM20 Remote"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x18 { 94, DeviceType::THERMOSTAT, F("RFM20 Remote"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x18
{157, DeviceType::THERMOSTAT, F("RC200/CW100"), DeviceFlags::EMS_DEVICE_FLAG_RC100}, // 0x18 {157, DeviceType::THERMOSTAT, F("RC200/CW100"), DeviceFlags::EMS_DEVICE_FLAG_RC100}, // 0x18
@@ -82,9 +82,9 @@
{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
// Thermostat - Sieger - 0x10 / 0x17 // Thermostat - Sieger - 0x10 / 0x17
{ 66, DeviceType::THERMOSTAT, F("ES72/RC20"), DeviceFlags::EMS_DEVICE_FLAG_RC20_2}, // 0x17 or remote { 66, DeviceType::THERMOSTAT, F("ES72/RC20"), DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17 or remote
{ 76, DeviceType::THERMOSTAT, F("ES73"), DeviceFlags::EMS_DEVICE_FLAG_RC35}, // 0x10 { 76, DeviceType::THERMOSTAT, F("ES73"), DeviceFlags::EMS_DEVICE_FLAG_RC35}, // 0x10
{113, DeviceType::THERMOSTAT, F("ES72/RC20"), DeviceFlags::EMS_DEVICE_FLAG_RC20_2}, // 0x17 {113, DeviceType::THERMOSTAT, F("ES72/RC20"), DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17
// Thermostat - Junkers - 0x10 // Thermostat - Junkers - 0x10
{105, DeviceType::THERMOSTAT, F("FW100"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS}, {105, DeviceType::THERMOSTAT, F("FW100"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},

View File

@@ -48,64 +48,50 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
reserve_telgram_functions(25); // reserve some space for the telegram registries, to avoid memory fragmentation reserve_telgram_functions(25); // reserve some space for the telegram registries, to avoid memory fragmentation
// the telegram handlers... // the telegram handlers...
// common for all boilers
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(0x14, F("UBATotalUptime"), true, MAKE_PF_CB(process_UBATotalUptime)); register_telegram_type(0x14, F("UBATotalUptime"), true, MAKE_PF_CB(process_UBATotalUptime));
register_telegram_type(0x15, F("UBAMaintenanceData"), false, MAKE_PF_CB(process_UBAMaintenanceData)); register_telegram_type(0x15, F("UBAMaintenanceData"), false, MAKE_PF_CB(process_UBAMaintenanceData));
register_telegram_type(0x16, F("UBAParameters"), true, MAKE_PF_CB(process_UBAParameters)); register_telegram_type(0x1C, F("UBAMaintenanceStatus"), false, MAKE_PF_CB(process_UBAMaintenanceStatus));
// EMS1.0 and maybe EMS+?
register_telegram_type(0x18, F("UBAMonitorFast"), false, MAKE_PF_CB(process_UBAMonitorFast)); register_telegram_type(0x18, F("UBAMonitorFast"), false, MAKE_PF_CB(process_UBAMonitorFast));
register_telegram_type(0x19, F("UBAMonitorSlow"), true, MAKE_PF_CB(process_UBAMonitorSlow)); register_telegram_type(0x19, F("UBAMonitorSlow"), true, MAKE_PF_CB(process_UBAMonitorSlow));
register_telegram_type(0x1A, F("UBASetPoints"), false, MAKE_PF_CB(process_UBASetPoints)); register_telegram_type(0x35, F("UBAFlags"), false, MAKE_PF_CB(process_UBAFlags));
register_telegram_type(0x1C, F("UBAMaintenanceStatus"), false, MAKE_PF_CB(process_UBAMaintenanceStatus)); // only EMS 1.0
register_telegram_type(0x26, F("UBASettingsWW"), true, MAKE_PF_CB(process_UBASettingsWW)); register_telegram_type(0x16, F("UBAParameters"), true, MAKE_PF_CB(process_UBAParameters));
register_telegram_type(0x2A, F("MC10Status"), false, MAKE_PF_CB(process_MC10Status));
register_telegram_type(0x33, F("UBAParameterWW"), true, MAKE_PF_CB(process_UBAParameterWW)); register_telegram_type(0x33, F("UBAParameterWW"), true, MAKE_PF_CB(process_UBAParameterWW));
register_telegram_type(0x34, F("UBAMonitorWW"), false, MAKE_PF_CB(process_UBAMonitorWW)); register_telegram_type(0x34, F("UBAMonitorWW"), false, MAKE_PF_CB(process_UBAMonitorWW));
register_telegram_type(0x35, F("UBAFlags"), false, MAKE_PF_CB(process_UBAFlags)); // only EMS+
if ((flags & 0x0F) != EMSdevice::EMS_DEVICE_FLAG_EMS) {
register_telegram_type(0x1A, F("UBASetPoints"), false, MAKE_PF_CB(process_UBASetPoints));
register_telegram_type(0x26, F("UBASettingsWW"), true, MAKE_PF_CB(process_UBASettingsWW));
register_telegram_type(0x2A, F("MC110Status"), false, MAKE_PF_CB(process_MC110Status));
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("UBAMonitorSlowPlus"), false, MAKE_PF_CB(process_UBAMonitorSlowPlus2)); register_telegram_type(0xE3, F("UBAMonitorSlowPlus"), 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));
register_telegram_type(0xE5, F("UBAMonitorSlowPlus"), false, MAKE_PF_CB(process_UBAMonitorSlowPlus)); register_telegram_type(0xE5, F("UBAMonitorSlowPlus"), false, MAKE_PF_CB(process_UBAMonitorSlowPlus));
register_telegram_type(0xE6, F("UBAParametersPlus"), true, MAKE_PF_CB(process_UBAParametersPlus)); register_telegram_type(0xE6, F("UBAParametersPlus"), true, MAKE_PF_CB(process_UBAParametersPlus));
register_telegram_type(0xE9, F("UBADHWStatus"), false, MAKE_PF_CB(process_UBADHWStatus)); register_telegram_type(0xE9, F("UBAMonitorWWPlus"), false, MAKE_PF_CB(process_UBAMonitorWWPlus));
register_telegram_type(0xEA, F("UBAParameterWWPlus"), true, MAKE_PF_CB(process_UBAParameterWWPlus)); register_telegram_type(0xEA, F("UBAParameterWWPlus"), true, MAKE_PF_CB(process_UBAParameterWWPlus));
register_telegram_type(0x494, F("UBAEnergySupplied"), false, MAKE_PF_CB(process_UBAEnergySupplied)); register_telegram_type(0x494, F("UBAEnergySupplied"), false, MAKE_PF_CB(process_UBAEnergySupplied));
register_telegram_type(0x495, F("UBAInformation"), false, MAKE_PF_CB(process_UBAInformation)); register_telegram_type(0x495, F("UBAInformation"), false, MAKE_PF_CB(process_UBAInformation));
}
// MQTT commands for boiler topic // MQTT commands for boiler topic
register_mqtt_cmd(MQTT_TOPIC(wWComfort), MAKE_CF_CB(set_warmwater_mode)); register_cmd(MQTT_TOPIC(wwtapactivated), MAKE_CF_CB(set_tapwarmwater_activated));
register_mqtt_cmd(MQTT_TOPIC(wWActivated), MAKE_CF_CB(set_warmwater_activated)); register_cmd(MQTT_TOPIC(reset), MAKE_CF_CB(set_reset));
register_mqtt_cmd(F_(wwtapactivated), MAKE_CF_CB(set_tapwarmwater_activated));
register_mqtt_cmd(MQTT_TOPIC(wWFlowTempOffset), MAKE_CF_CB(set_wWFlowTempOffset));
register_mqtt_cmd(MQTT_TOPIC(wWMaxPower), MAKE_CF_CB(set_warmwater_maxpower));
register_mqtt_cmd(MQTT_TOPIC(wWOneTime), MAKE_CF_CB(set_warmwater_onetime));
register_mqtt_cmd(MQTT_TOPIC(wWCircPump), MAKE_CF_CB(set_warmwater_circulation_pump));
register_mqtt_cmd(MQTT_TOPIC(wWCirc), MAKE_CF_CB(set_warmwater_circulation));
register_mqtt_cmd(MQTT_TOPIC(wWCircMode), MAKE_CF_CB(set_warmwater_circulation_mode));
register_mqtt_cmd(MQTT_TOPIC(selFlowTemp), MAKE_CF_CB(set_flow_temp));
register_mqtt_cmd(MQTT_TOPIC(wWSetTemp), MAKE_CF_CB(set_warmwater_temp));
register_mqtt_cmd(MQTT_TOPIC(heatingActivated), MAKE_CF_CB(set_heating_activated));
register_mqtt_cmd(MQTT_TOPIC(heatingTemp), MAKE_CF_CB(set_heating_temp));
register_mqtt_cmd(MQTT_TOPIC(burnMaxPower), MAKE_CF_CB(set_max_power));
register_mqtt_cmd(MQTT_TOPIC(burnMinPower), MAKE_CF_CB(set_min_power));
register_mqtt_cmd(MQTT_TOPIC(boilHystOn), MAKE_CF_CB(set_hyst_on));
register_mqtt_cmd(MQTT_TOPIC(boilHystOff), MAKE_CF_CB(set_hyst_off));
register_mqtt_cmd(MQTT_TOPIC(burnPeriod), MAKE_CF_CB(set_burn_period));
register_mqtt_cmd(MQTT_TOPIC(pumpDelay), MAKE_CF_CB(set_pump_delay));
register_mqtt_cmd(F_(maintenance), MAKE_CF_CB(set_maintenance));
register_mqtt_cmd(MQTT_TOPIC(pumpModMax), MAKE_CF_CB(set_max_pump));
register_mqtt_cmd(MQTT_TOPIC(pumpModMin), MAKE_CF_CB(set_min_pump));
register_mqtt_cmd(F_(reset), MAKE_CF_CB(set_reset));
// add values // add values
reserve_device_values(50); reserve_device_values(50);
// main - boiler_data topic // main - boiler_data topic
register_device_value(TAG_BOILER_DATA, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr); // empty full name to prevent being shown in web or console register_device_value(TAG_BOILER_DATA, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr, DeviceValueUOM::NONE); // empty full name to prevent being shown in web or console
id_ = product_id; id_ = product_id;
register_device_value(TAG_BOILER_DATA, &heatingActive_, DeviceValueType::BOOL, nullptr, FL_(heatingActive)); register_device_value(TAG_BOILER_DATA, &heatingActive_, DeviceValueType::BOOL, nullptr, FL_(heatingActive), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &tapwaterActive_, DeviceValueType::BOOL, nullptr, FL_(tapwaterActive)); register_device_value(TAG_BOILER_DATA, &tapwaterActive_, DeviceValueType::BOOL, nullptr, FL_(tapwaterActive), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &selFlowTemp_, DeviceValueType::UINT, nullptr, FL_(selFlowTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &selFlowTemp_, DeviceValueType::UINT, nullptr, FL_(selFlowTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flow_temp));
register_device_value(TAG_BOILER_DATA, &selBurnPow_, DeviceValueType::UINT, nullptr, FL_(selBurnPow), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA, &selBurnPow_, DeviceValueType::UINT, nullptr, FL_(selBurnPow), DeviceValueUOM::PERCENT);
register_device_value(TAG_BOILER_DATA, &heatingPumpMod_, DeviceValueType::UINT, nullptr, FL_(heatingPumpMod), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA, &heatingPumpMod_, DeviceValueType::UINT, nullptr, FL_(heatingPumpMod), DeviceValueUOM::PERCENT);
register_device_value(TAG_BOILER_DATA, &heatingPump2Mod_, DeviceValueType::UINT, nullptr, FL_(heatingPump2Mod), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA, &heatingPump2Mod_, DeviceValueType::UINT, nullptr, FL_(heatingPump2Mod), DeviceValueUOM::PERCENT);
@@ -116,85 +102,85 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_device_value(TAG_BOILER_DATA, &sysPress_, DeviceValueType::UINT, FL_(div10), FL_(sysPress), DeviceValueUOM::BAR); register_device_value(TAG_BOILER_DATA, &sysPress_, DeviceValueType::UINT, FL_(div10), FL_(sysPress), DeviceValueUOM::BAR);
register_device_value(TAG_BOILER_DATA, &boilTemp_, DeviceValueType::USHORT, FL_(div10), FL_(boilTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &boilTemp_, DeviceValueType::USHORT, FL_(div10), FL_(boilTemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA, &exhaustTemp_, DeviceValueType::USHORT, FL_(div10), FL_(exhaustTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &exhaustTemp_, DeviceValueType::USHORT, FL_(div10), FL_(exhaustTemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA, &burnGas_, DeviceValueType::BOOL, nullptr, FL_(burnGas)); register_device_value(TAG_BOILER_DATA, &burnGas_, DeviceValueType::BOOL, nullptr, FL_(burnGas), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &flameCurr_, DeviceValueType::USHORT, FL_(div10), FL_(flameCurr), DeviceValueUOM::UA); register_device_value(TAG_BOILER_DATA, &flameCurr_, DeviceValueType::USHORT, FL_(div10), FL_(flameCurr), DeviceValueUOM::UA);
register_device_value(TAG_BOILER_DATA, &heatingPump_, DeviceValueType::BOOL, nullptr, FL_(heatingPump), DeviceValueUOM::PUMP); register_device_value(TAG_BOILER_DATA, &heatingPump_, DeviceValueType::BOOL, nullptr, FL_(heatingPump), DeviceValueUOM::PUMP);
register_device_value(TAG_BOILER_DATA, &fanWork_, DeviceValueType::BOOL, nullptr, FL_(fanWork)); register_device_value(TAG_BOILER_DATA, &fanWork_, DeviceValueType::BOOL, nullptr, FL_(fanWork), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &ignWork_, DeviceValueType::BOOL, nullptr, FL_(ignWork)); register_device_value(TAG_BOILER_DATA, &ignWork_, DeviceValueType::BOOL, nullptr, FL_(ignWork), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &heatingActivated_, DeviceValueType::BOOL, nullptr, FL_(heatingActivated)); register_device_value(TAG_BOILER_DATA, &heatingActivated_, DeviceValueType::BOOL, nullptr, FL_(heatingActivated), DeviceValueUOM::NONE, MAKE_CF_CB(set_heating_activated));
register_device_value(TAG_BOILER_DATA, &heatingTemp_, DeviceValueType::UINT, nullptr, FL_(heatingTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &heatingTemp_, DeviceValueType::UINT, nullptr, FL_(heatingTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_heating_temp));
register_device_value(TAG_BOILER_DATA, &pumpModMax_, DeviceValueType::UINT, nullptr, FL_(pumpModMax), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA, &pumpModMax_, DeviceValueType::UINT, nullptr, FL_(pumpModMax), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_max_pump));
register_device_value(TAG_BOILER_DATA, &pumpModMin_, DeviceValueType::UINT, nullptr, FL_(pumpModMin), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA, &pumpModMin_, DeviceValueType::UINT, nullptr, FL_(pumpModMin), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_min_pump));
register_device_value(TAG_BOILER_DATA, &pumpDelay_, DeviceValueType::UINT, nullptr, FL_(pumpDelay), DeviceValueUOM::MINUTES); register_device_value(TAG_BOILER_DATA, &pumpDelay_, DeviceValueType::UINT, nullptr, FL_(pumpDelay), DeviceValueUOM::MINUTES, MAKE_CF_CB(set_pump_delay));
register_device_value(TAG_BOILER_DATA, &burnMinPeriod_, DeviceValueType::UINT, nullptr, FL_(burnMinPeriod), DeviceValueUOM::MINUTES); register_device_value(TAG_BOILER_DATA, &burnMinPeriod_, DeviceValueType::UINT, nullptr, FL_(burnMinPeriod), DeviceValueUOM::MINUTES, MAKE_CF_CB(set_burn_period));
register_device_value(TAG_BOILER_DATA, &burnMinPower_, DeviceValueType::UINT, nullptr, FL_(burnMinPower), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA, &burnMinPower_, DeviceValueType::UINT, nullptr, FL_(burnMinPower), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_min_power));
register_device_value(TAG_BOILER_DATA, &burnMaxPower_, DeviceValueType::UINT, nullptr, FL_(burnMaxPower), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA, &burnMaxPower_, DeviceValueType::UINT, nullptr, FL_(burnMaxPower), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_max_power));
register_device_value(TAG_BOILER_DATA, &boilHystOn_, DeviceValueType::INT, nullptr, FL_(boilHystOn), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &boilHystOn_, DeviceValueType::INT, nullptr, FL_(boilHystOn), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_hyst_on));
register_device_value(TAG_BOILER_DATA, &boilHystOff_, DeviceValueType::INT, nullptr, FL_(boilHystOff), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &boilHystOff_, DeviceValueType::INT, nullptr, FL_(boilHystOff), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_hyst_off));
register_device_value(TAG_BOILER_DATA, &setFlowTemp_, DeviceValueType::UINT, nullptr, FL_(setFlowTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &setFlowTemp_, DeviceValueType::UINT, nullptr, FL_(setFlowTemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA, &setBurnPow_, DeviceValueType::UINT, nullptr, FL_(setBurnPow), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA, &setBurnPow_, DeviceValueType::UINT, nullptr, FL_(setBurnPow), DeviceValueUOM::PERCENT);
register_device_value(TAG_BOILER_DATA, &curBurnPow_, DeviceValueType::UINT, nullptr, FL_(curBurnPow), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA, &curBurnPow_, DeviceValueType::UINT, nullptr, FL_(curBurnPow), DeviceValueUOM::PERCENT);
register_device_value(TAG_BOILER_DATA, &burnStarts_, DeviceValueType::ULONG, nullptr, FL_(burnStarts)); register_device_value(TAG_BOILER_DATA, &burnStarts_, DeviceValueType::ULONG, nullptr, FL_(burnStarts), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &burnWorkMin_, DeviceValueType::TIME, nullptr, FL_(burnWorkMin), DeviceValueUOM::MINUTES); register_device_value(TAG_BOILER_DATA, &burnWorkMin_, DeviceValueType::TIME, nullptr, FL_(burnWorkMin), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA, &heatWorkMin_, DeviceValueType::TIME, nullptr, FL_(heatWorkMin), DeviceValueUOM::MINUTES); register_device_value(TAG_BOILER_DATA, &heatWorkMin_, DeviceValueType::TIME, nullptr, FL_(heatWorkMin), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA, &UBAuptime_, DeviceValueType::TIME, nullptr, FL_(UBAuptime), DeviceValueUOM::MINUTES); register_device_value(TAG_BOILER_DATA, &UBAuptime_, DeviceValueType::TIME, nullptr, FL_(UBAuptime), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA, &lastCode_, DeviceValueType::TEXT, nullptr, FL_(lastCode)); register_device_value(TAG_BOILER_DATA, &lastCode_, DeviceValueType::TEXT, nullptr, FL_(lastCode), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &serviceCode_, DeviceValueType::TEXT, nullptr, FL_(serviceCode)); register_device_value(TAG_BOILER_DATA, &serviceCode_, DeviceValueType::TEXT, nullptr, FL_(serviceCode), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &serviceCodeNumber_, DeviceValueType::USHORT, nullptr, FL_(serviceCodeNumber)); register_device_value(TAG_BOILER_DATA, &serviceCodeNumber_, DeviceValueType::USHORT, nullptr, FL_(serviceCodeNumber), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &upTimeControl_, DeviceValueType::TIME, FL_(div60), FL_(upTimeControl), DeviceValueUOM::MINUTES); register_device_value(TAG_BOILER_DATA, &upTimeControl_, DeviceValueType::TIME, FL_(div60), FL_(upTimeControl), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA, &upTimeCompHeating_, DeviceValueType::TIME, FL_(div60), FL_(upTimeCompHeating), DeviceValueUOM::MINUTES); register_device_value(TAG_BOILER_DATA, &upTimeCompHeating_, DeviceValueType::TIME, FL_(div60), FL_(upTimeCompHeating), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA, &upTimeCompCooling_, DeviceValueType::TIME, FL_(div60), FL_(upTimeCompCooling), DeviceValueUOM::MINUTES); register_device_value(TAG_BOILER_DATA, &upTimeCompCooling_, DeviceValueType::TIME, FL_(div60), FL_(upTimeCompCooling), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA, &upTimeCompWw_, DeviceValueType::TIME, FL_(div60), FL_(upTimeCompWw), DeviceValueUOM::MINUTES); register_device_value(TAG_BOILER_DATA, &upTimeCompWw_, DeviceValueType::TIME, FL_(div60), FL_(upTimeCompWw), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA, &heatingStarts_, DeviceValueType::ULONG, nullptr, FL_(heatingStarts)); register_device_value(TAG_BOILER_DATA, &heatingStarts_, DeviceValueType::ULONG, nullptr, FL_(heatingStarts), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &coolingStarts_, DeviceValueType::ULONG, nullptr, FL_(coolingStarts)); register_device_value(TAG_BOILER_DATA, &coolingStarts_, DeviceValueType::ULONG, nullptr, FL_(coolingStarts), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &nrgConsTotal_, DeviceValueType::ULONG, nullptr, FL_(nrgConsTotal)); register_device_value(TAG_BOILER_DATA, &nrgConsTotal_, DeviceValueType::ULONG, nullptr, FL_(nrgConsTotal), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &nrgConsCompTotal_, DeviceValueType::ULONG, nullptr, FL_(nrgConsCompTotal)); register_device_value(TAG_BOILER_DATA, &nrgConsCompTotal_, DeviceValueType::ULONG, nullptr, FL_(nrgConsCompTotal), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &nrgConsCompHeating_, DeviceValueType::ULONG, nullptr, FL_(nrgConsCompHeating)); register_device_value(TAG_BOILER_DATA, &nrgConsCompHeating_, DeviceValueType::ULONG, nullptr, FL_(nrgConsCompHeating), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &nrgConsCompWw_, DeviceValueType::ULONG, nullptr, FL_(nrgConsCompWw)); register_device_value(TAG_BOILER_DATA, &nrgConsCompWw_, DeviceValueType::ULONG, nullptr, FL_(nrgConsCompWw), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &nrgConsCompCooling_, DeviceValueType::ULONG, nullptr, FL_(nrgConsCompCooling)); register_device_value(TAG_BOILER_DATA, &nrgConsCompCooling_, DeviceValueType::ULONG, nullptr, FL_(nrgConsCompCooling), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &nrgSuppTotal_, DeviceValueType::ULONG, nullptr, FL_(nrgSuppTotal)); register_device_value(TAG_BOILER_DATA, &nrgSuppTotal_, DeviceValueType::ULONG, nullptr, FL_(nrgSuppTotal), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &nrgSuppHeating_, DeviceValueType::ULONG, nullptr, FL_(nrgSuppHeating)); register_device_value(TAG_BOILER_DATA, &nrgSuppHeating_, DeviceValueType::ULONG, nullptr, FL_(nrgSuppHeating), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &nrgSuppWw_, DeviceValueType::ULONG, nullptr, FL_(nrgSuppWw)); register_device_value(TAG_BOILER_DATA, &nrgSuppWw_, DeviceValueType::ULONG, nullptr, FL_(nrgSuppWw), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &nrgSuppCooling_, DeviceValueType::ULONG, nullptr, FL_(nrgSuppCooling)); register_device_value(TAG_BOILER_DATA, &nrgSuppCooling_, DeviceValueType::ULONG, nullptr, FL_(nrgSuppCooling), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &auxElecHeatNrgConsTotal_, DeviceValueType::ULONG, nullptr, FL_(auxElecHeatNrgConsTotal)); register_device_value(TAG_BOILER_DATA, &auxElecHeatNrgConsTotal_, DeviceValueType::ULONG, nullptr, FL_(auxElecHeatNrgConsTotal), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &auxElecHeatNrgConsHeating_, DeviceValueType::ULONG, nullptr, FL_(auxElecHeatNrgConsHeating)); register_device_value(TAG_BOILER_DATA, &auxElecHeatNrgConsHeating_, DeviceValueType::ULONG, nullptr, FL_(auxElecHeatNrgConsHeating), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &auxElecHeatNrgConsDHW_, DeviceValueType::ULONG, nullptr, FL_(auxElecHeatNrgConsDHW)); register_device_value(TAG_BOILER_DATA, &auxElecHeatNrgConsDHW_, DeviceValueType::ULONG, nullptr, FL_(auxElecHeatNrgConsDHW), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &maintenanceMessage_, DeviceValueType::TEXT, nullptr, FL_(maintenanceMessage)); register_device_value(TAG_BOILER_DATA, &maintenanceMessage_, DeviceValueType::TEXT, nullptr, FL_(maintenanceMessage), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &maintenanceDate_, DeviceValueType::TEXT, nullptr, FL_(maintenanceDate)); register_device_value(TAG_BOILER_DATA, &maintenanceDate_, DeviceValueType::TEXT, nullptr, FL_(maintenanceDate), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA, &maintenanceType_, DeviceValueType::ENUM, FL_(enum_off_time_date), FL_(maintenanceType)); register_device_value(TAG_BOILER_DATA, &maintenanceType_, DeviceValueType::ENUM, FL_(enum_off_time_date), FL_(maintenance), DeviceValueUOM::NONE, MAKE_CF_CB(set_maintenance));
register_device_value(TAG_BOILER_DATA, &maintenanceTime_, DeviceValueType::USHORT, nullptr, FL_(maintenanceTime), DeviceValueUOM::HOURS); register_device_value(TAG_BOILER_DATA, &maintenanceTime_, DeviceValueType::USHORT, nullptr, FL_(maintenanceTime), DeviceValueUOM::HOURS);
// warm water - boiler_data_ww topic // warm water - boiler_data_ww topic
register_device_value(TAG_BOILER_DATA_WW, &wWSelTemp_, DeviceValueType::UINT, nullptr, FL_(wWSelTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA_WW, &wWSelTemp_, DeviceValueType::UINT, nullptr, FL_(wWSelTemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA_WW, &wWSetTemp_, DeviceValueType::UINT, nullptr, FL_(wWSetTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA_WW, &wWSetTemp_, DeviceValueType::UINT, nullptr, FL_(wWSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_warmwater_temp));
register_device_value(TAG_BOILER_DATA_WW, &wWType_, DeviceValueType::ENUM, FL_(enum_flow), FL_(wWType)); register_device_value(TAG_BOILER_DATA_WW, &wWType_, DeviceValueType::ENUM, FL_(enum_flow), FL_(wWType), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA_WW, &wWComfort_, DeviceValueType::ENUM, FL_(enum_comfort), FL_(wWComfort)); register_device_value(TAG_BOILER_DATA_WW, &wWComfort_, DeviceValueType::ENUM, FL_(enum_comfort), FL_(wWComfort), DeviceValueUOM::NONE, MAKE_CF_CB(set_warmwater_mode));
register_device_value(TAG_BOILER_DATA_WW, &wWFlowTempOffset_, DeviceValueType::UINT, nullptr, FL_(wWFlowTempOffset)); register_device_value(TAG_BOILER_DATA_WW, &wWFlowTempOffset_, DeviceValueType::UINT, nullptr, FL_(wWFlowTempOffset), DeviceValueUOM::NONE, MAKE_CF_CB(set_wWFlowTempOffset));
register_device_value(TAG_BOILER_DATA_WW, &wWMaxPower_, DeviceValueType::UINT, nullptr, FL_(wWMaxPower), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA_WW, &wWMaxPower_, DeviceValueType::UINT, nullptr, FL_(wWMaxPower), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_warmwater_maxpower));
register_device_value(TAG_BOILER_DATA_WW, &wWCircPump_, DeviceValueType::BOOL, nullptr, FL_(wWCircPump)); register_device_value(TAG_BOILER_DATA_WW, &wWCircPump_, DeviceValueType::BOOL, nullptr, FL_(wWCircPump), DeviceValueUOM::NONE, MAKE_CF_CB(set_warmwater_circulation_pump));
register_device_value(TAG_BOILER_DATA_WW, &wWChargeType_, DeviceValueType::BOOL, FL_(enum_charge), FL_(wWChargeType)); register_device_value(TAG_BOILER_DATA_WW, &wWChargeType_, DeviceValueType::BOOL, FL_(enum_charge), FL_(wWChargeType), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA_WW, &wWDisinfectionTemp_, DeviceValueType::UINT, nullptr, FL_(wWDisinfectionTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA_WW, &wWDisinfectionTemp_, DeviceValueType::UINT, nullptr, FL_(wWDisinfectionTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_disinfect_temp));
register_device_value(TAG_BOILER_DATA_WW, &wWCircMode_, DeviceValueType::ENUM, FL_(enum_freq), FL_(wWCircMode)); register_device_value(TAG_BOILER_DATA_WW, &wWCircMode_, DeviceValueType::ENUM, FL_(enum_freq), FL_(wWCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_warmwater_circulation_mode));
register_device_value(TAG_BOILER_DATA_WW, &wWCirc_, DeviceValueType::BOOL, nullptr, FL_(wWCirc)); register_device_value(TAG_BOILER_DATA_WW, &wWCirc_, DeviceValueType::BOOL, nullptr, FL_(wWCirc), DeviceValueUOM::NONE, MAKE_CF_CB(set_warmwater_circulation));
register_device_value(TAG_BOILER_DATA_WW, &wWCurTemp_, DeviceValueType::USHORT, FL_(div10), FL_(wWCurTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA_WW, &wWCurTemp_, DeviceValueType::USHORT, FL_(div10), FL_(wWCurTemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA_WW, &wWCurTemp2_, DeviceValueType::USHORT, FL_(div10), FL_(wWCurTemp2), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA_WW, &wWCurTemp2_, DeviceValueType::USHORT, FL_(div10), FL_(wWCurTemp2), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA_WW, &wWCurFlow_, DeviceValueType::UINT, FL_(div10), FL_(wWCurFlow), DeviceValueUOM::LMIN); register_device_value(TAG_BOILER_DATA_WW, &wWCurFlow_, DeviceValueType::UINT, FL_(div10), FL_(wWCurFlow), DeviceValueUOM::LMIN);
register_device_value(TAG_BOILER_DATA_WW, &wWStorageTemp1_, DeviceValueType::USHORT, FL_(div10), FL_(wWStorageTemp1), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA_WW, &wWStorageTemp1_, DeviceValueType::USHORT, FL_(div10), FL_(wWStorageTemp1), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA_WW, &wWStorageTemp2_, DeviceValueType::USHORT, FL_(div10), FL_(wWStorageTemp2), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA_WW, &wWStorageTemp2_, DeviceValueType::USHORT, FL_(div10), FL_(wWStorageTemp2), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA_WW, &wWActivated_, DeviceValueType::BOOL, nullptr, FL_(wWActivated)); register_device_value(TAG_BOILER_DATA_WW, &wWActivated_, DeviceValueType::BOOL, nullptr, FL_(wWActivated), DeviceValueUOM::NONE, MAKE_CF_CB(set_warmwater_activated));
register_device_value(TAG_BOILER_DATA_WW, &wWOneTime_, DeviceValueType::BOOL, nullptr, FL_(wWOneTime)); register_device_value(TAG_BOILER_DATA_WW, &wWOneTime_, DeviceValueType::BOOL, nullptr, FL_(wWOneTime), DeviceValueUOM::NONE, MAKE_CF_CB(set_warmwater_onetime));
register_device_value(TAG_BOILER_DATA_WW, &wWDisinfecting_, DeviceValueType::BOOL, nullptr, FL_(wWDisinfecting)); register_device_value(TAG_BOILER_DATA_WW, &wWDisinfecting_, DeviceValueType::BOOL, nullptr, FL_(wWDisinfecting), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA_WW, &wWCharging_, DeviceValueType::BOOL, nullptr, FL_(wWCharging)); register_device_value(TAG_BOILER_DATA_WW, &wWCharging_, DeviceValueType::BOOL, nullptr, FL_(wWCharging), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA_WW, &wWRecharging_, DeviceValueType::BOOL, nullptr, FL_(wWRecharging)); register_device_value(TAG_BOILER_DATA_WW, &wWRecharging_, DeviceValueType::BOOL, nullptr, FL_(wWRecharging), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA_WW, &wWTempOK_, DeviceValueType::BOOL, nullptr, FL_(wWTempOK)); register_device_value(TAG_BOILER_DATA_WW, &wWTempOK_, DeviceValueType::BOOL, nullptr, FL_(wWTempOK), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA_WW, &wWActive_, DeviceValueType::BOOL, nullptr, FL_(wWActive)); register_device_value(TAG_BOILER_DATA_WW, &wWActive_, DeviceValueType::BOOL, nullptr, FL_(wWActive), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA_WW, &wWHeat_, DeviceValueType::BOOL, nullptr, FL_(wWHeat)); register_device_value(TAG_BOILER_DATA_WW, &wWHeat_, DeviceValueType::BOOL, nullptr, FL_(wWHeat), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA_WW, &wWSetPumpPower_, DeviceValueType::UINT, nullptr, FL_(wWSetPumpPower), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA_WW, &wWSetPumpPower_, DeviceValueType::UINT, nullptr, FL_(wWSetPumpPower), DeviceValueUOM::PERCENT);
register_device_value(TAG_BOILER_DATA_WW, &mixerTemp_, DeviceValueType::USHORT, FL_(div10), FL_(mixerTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA_WW, &mixerTemp_, DeviceValueType::USHORT, FL_(div10), FL_(mixerTemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA_WW, &tankMiddleTemp_, DeviceValueType::USHORT, FL_(div10), FL_(tankMiddleTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA_WW, &tankMiddleTemp_, DeviceValueType::USHORT, FL_(div10), FL_(tankMiddleTemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA_WW, &wWStarts_, DeviceValueType::ULONG, nullptr, FL_(wWStarts)); register_device_value(TAG_BOILER_DATA_WW, &wWStarts_, DeviceValueType::ULONG, nullptr, FL_(wWStarts), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA_WW, &wWStarts2_, DeviceValueType::ULONG, nullptr, FL_(wWStarts2)); register_device_value(TAG_BOILER_DATA_WW, &wWStarts2_, DeviceValueType::ULONG, nullptr, FL_(wWStarts2), DeviceValueUOM::NONE);
register_device_value(TAG_BOILER_DATA_WW, &wWWorkM_, DeviceValueType::TIME, nullptr, FL_(wWWorkM), DeviceValueUOM::MINUTES); register_device_value(TAG_BOILER_DATA_WW, &wWWorkM_, DeviceValueType::TIME, nullptr, FL_(wWWorkM), DeviceValueUOM::MINUTES);
// fetch some initial data // fetch some initial data
@@ -514,9 +500,9 @@ void Boiler::process_UBAParameterWWPlus(std::shared_ptr<const Telegram> telegram
// has_update(telegram->read_value(wWSelTemp_, 6)); // settings, status in E9 // has_update(telegram->read_value(wWSelTemp_, 6)); // settings, status in E9
} }
// 0xE9 - DHW Status // 0xE9 - WW monitor ems+
// e.g. 08 00 E9 00 37 01 F6 01 ED 00 00 00 00 41 3C 00 00 00 00 00 00 00 00 00 00 00 00 37 00 00 00 (CRC=77) #data=27 // e.g. 08 00 E9 00 37 01 F6 01 ED 00 00 00 00 41 3C 00 00 00 00 00 00 00 00 00 00 00 00 37 00 00 00 (CRC=77) #data=27
void Boiler::process_UBADHWStatus(std::shared_ptr<const Telegram> telegram) { void Boiler::process_UBAMonitorWWPlus(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(wWSetTemp_, 0)); has_update(telegram->read_value(wWSetTemp_, 0));
has_update(telegram->read_value(wWCurTemp_, 1)); has_update(telegram->read_value(wWCurTemp_, 1));
has_update(telegram->read_value(wWCurTemp2_, 3)); has_update(telegram->read_value(wWCurTemp2_, 3));
@@ -581,10 +567,10 @@ void Boiler::process_UBAEnergySupplied(std::shared_ptr<const Telegram> telegram)
has_update(telegram->read_value(nrgSuppCooling_, 16)); has_update(telegram->read_value(nrgSuppCooling_, 16));
} }
// 0x2A - MC10Status // 0x2A - MC110Status
// e.g. 88 00 2A 00 00 00 00 00 00 00 00 00 D2 00 00 80 00 00 01 08 80 00 02 47 00 // e.g. 88 00 2A 00 00 00 00 00 00 00 00 00 D2 00 00 80 00 00 01 08 80 00 02 47 00
// see https://github.com/emsesp/EMS-ESP/issues/397 // see https://github.com/emsesp/EMS-ESP/issues/397
void Boiler::process_MC10Status(std::shared_ptr<const Telegram> telegram) { void Boiler::process_MC110Status(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(mixerTemp_, 14)); has_update(telegram->read_value(mixerTemp_, 14));
has_update(telegram->read_value(tankMiddleTemp_, 18)); has_update(telegram->read_value(tankMiddleTemp_, 18));
} }
@@ -598,8 +584,7 @@ void Boiler::process_UBAOutdoorTemp(std::shared_ptr<const Telegram> telegram) {
// UBASetPoint 0x1A // UBASetPoint 0x1A
void Boiler::process_UBASetPoints(std::shared_ptr<const Telegram> telegram) { void Boiler::process_UBASetPoints(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(setFlowTemp_, has_update(telegram->read_value(setFlowTemp_, 0)); // boiler set temp from thermostat
0)); // boiler set temp from thermostat
has_update(telegram->read_value(setBurnPow_, 1)); // max json power in % has_update(telegram->read_value(setBurnPow_, 1)); // max json power in %
has_update(telegram->read_value(wWSetPumpPower_, 2)); // ww pump speed/power? has_update(telegram->read_value(wWSetPumpPower_, 2)); // ww pump speed/power?
} }
@@ -618,6 +603,7 @@ void Boiler::process_CascadeMessage(std::shared_ptr<const Telegram> telegram) {
// 0x35 - not yet implemented // 0x35 - not yet implemented
void Boiler::process_UBAFlags(std::shared_ptr<const Telegram> telegram) { void Boiler::process_UBAFlags(std::shared_ptr<const Telegram> telegram) {
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
// 0x1C // 0x1C
@@ -706,6 +692,23 @@ bool Boiler::set_warmwater_temp(const char * value, const int8_t id) {
return true; return true;
} }
// Set the warm water disinfection temperature
bool Boiler::set_disinfect_temp(const char * value, const int8_t id) {
int v = 0;
if (!Helpers::value2number(value, v)) {
LOG_WARNING(F("Set boiler warm water disinfect temperature: Invalid value"));
return false;
}
LOG_INFO(F("Setting boiler warm water disinfect temperature to %d C"), v);
if (get_toggle_fetch(EMS_TYPE_UBAParametersPlus)) {
write_command(EMS_TYPE_UBAParameterWWPlus, 12, v, EMS_TYPE_UBAParameterWWPlus);
} else {
write_command(EMS_TYPE_UBAParameterWW, 8, v, EMS_TYPE_UBAParameterWW);
}
return true;
}
// flow temp // flow temp
bool Boiler::set_flow_temp(const char * value, const int8_t id) { bool Boiler::set_flow_temp(const char * value, const int8_t id) {
int v = 0; int v = 0;

View File

@@ -161,11 +161,11 @@ class Boiler : public EMSdevice {
void process_UBAOutdoorTemp(std::shared_ptr<const Telegram> telegram); void process_UBAOutdoorTemp(std::shared_ptr<const Telegram> telegram);
void process_UBASetPoints(std::shared_ptr<const Telegram> telegram); void process_UBASetPoints(std::shared_ptr<const Telegram> telegram);
void process_UBAFlags(std::shared_ptr<const Telegram> telegram); void process_UBAFlags(std::shared_ptr<const Telegram> telegram);
void process_MC10Status(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_UBAErrorMessage(std::shared_ptr<const Telegram> telegram); void process_UBAErrorMessage(std::shared_ptr<const Telegram> telegram);
void process_UBADHWStatus(std::shared_ptr<const Telegram> telegram); void process_UBAMonitorWWPlus(std::shared_ptr<const Telegram> telegram);
void process_UBAInformation(std::shared_ptr<const Telegram> telegram); void process_UBAInformation(std::shared_ptr<const Telegram> telegram);
void process_UBAEnergySupplied(std::shared_ptr<const Telegram> telegram); void process_UBAEnergySupplied(std::shared_ptr<const Telegram> telegram);
void process_CascadeMessage(std::shared_ptr<const Telegram> telegram); void process_CascadeMessage(std::shared_ptr<const Telegram> telegram);
@@ -180,6 +180,7 @@ class Boiler : public EMSdevice {
bool set_warmwater_circulation_pump(const char * value, const int8_t id); bool set_warmwater_circulation_pump(const char * value, const int8_t id);
bool set_warmwater_circulation_mode(const char * value, const int8_t id); bool set_warmwater_circulation_mode(const char * value, const int8_t id);
bool set_warmwater_temp(const char * value, const int8_t id); bool set_warmwater_temp(const char * value, const int8_t id);
bool set_disinfect_temp(const char * value, const int8_t id);
bool set_warmwater_maxpower(const char * value, const int8_t id); bool set_warmwater_maxpower(const char * value, const int8_t id);
bool set_wWFlowTempOffset(const char * value, const int8_t id); bool set_wWFlowTempOffset(const char * value, const int8_t id);
bool set_flow_temp(const char * value, const int8_t id); bool set_flow_temp(const char * value, const int8_t id);

View File

@@ -33,7 +33,7 @@ Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, c
register_telegram_type(0x047B, F("HP2"), true, MAKE_PF_CB(process_HPMonitor2)); register_telegram_type(0x047B, F("HP2"), true, MAKE_PF_CB(process_HPMonitor2));
// device values // device values
register_device_value(TAG_NONE, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr); // empty full name to prevent being shown in web or console register_device_value(TAG_NONE, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr, DeviceValueUOM::NONE); // empty full name to prevent being shown in web or console
register_device_value(TAG_NONE, &airHumidity_, DeviceValueType::UINT, FL_(div2), FL_(airHumidity), DeviceValueUOM::PERCENT); register_device_value(TAG_NONE, &airHumidity_, DeviceValueType::UINT, FL_(div2), FL_(airHumidity), DeviceValueUOM::PERCENT);
register_device_value(TAG_NONE, &dewTemperature_, DeviceValueType::UINT, nullptr, FL_(dewTemperature), DeviceValueUOM::DEGREES); register_device_value(TAG_NONE, &dewTemperature_, DeviceValueType::UINT, nullptr, FL_(dewTemperature), DeviceValueUOM::DEGREES);

View File

@@ -57,7 +57,7 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
type_ = Type::HC; type_ = Type::HC;
hc_ = device_id - 0x20 + 1; hc_ = device_id - 0x20 + 1;
uint8_t tag = TAG_HC1 + hc_ - 1; uint8_t tag = TAG_HC1 + hc_ - 1;
register_device_value(tag, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr); // empty full name to prevent being shown in web or console register_device_value(tag, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr, DeviceValueUOM::NONE); // empty full name to prevent being shown in web or console
register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, nullptr, FL_(flowSetTemp), DeviceValueUOM::DEGREES); register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, nullptr, FL_(flowSetTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES); register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES);
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::PUMP); register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::PUMP);
@@ -67,10 +67,10 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
type_ = Type::WWC; type_ = Type::WWC;
hc_ = device_id - 0x28 + 1; hc_ = device_id - 0x28 + 1;
uint8_t tag = TAG_WWC1 + hc_ - 1; uint8_t tag = TAG_WWC1 + hc_ - 1;
register_device_value(tag, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr); // empty full name to prevent being shown in web or console register_device_value(tag, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr, DeviceValueUOM::NONE); // empty full name to prevent being shown in web or console
register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(wwTemp), DeviceValueUOM::DEGREES); register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(wwTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::PUMP); register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::PUMP);
register_device_value(tag, &status_, DeviceValueType::INT, nullptr, FL_(tempStatus)); register_device_value(tag, &status_, DeviceValueType::INT, nullptr, FL_(tempStatus), DeviceValueUOM::NONE);
} }
id_ = product_id; id_ = product_id;

View File

@@ -50,8 +50,6 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
register_telegram_type(0x0380, F("SM100CollectorConfig"), true, MAKE_PF_CB(process_SM100CollectorConfig)); register_telegram_type(0x0380, F("SM100CollectorConfig"), true, MAKE_PF_CB(process_SM100CollectorConfig));
register_telegram_type(0x038E, F("SM100Energy"), true, MAKE_PF_CB(process_SM100Energy)); register_telegram_type(0x038E, F("SM100Energy"), true, MAKE_PF_CB(process_SM100Energy));
register_telegram_type(0x0391, F("SM100Time"), true, MAKE_PF_CB(process_SM100Time)); register_telegram_type(0x0391, F("SM100Time"), true, MAKE_PF_CB(process_SM100Time));
register_mqtt_cmd(F("SM100TankBottomMaxTemp"), MAKE_CF_CB(set_SM100TankBottomMaxTemp));
} }
} }
@@ -64,11 +62,11 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
// special case for a 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(TAG_NONE, &type_, DeviceValueType::TEXT, nullptr, F("type"), F("type")); register_device_value(TAG_NONE, &type_, DeviceValueType::TEXT, nullptr, F("type"), F("type"), DeviceValueUOM::NONE);
strncpy(type_, "warm water circuit", sizeof(type_)); strncpy(type_, "warm water circuit", sizeof(type_));
} }
register_device_value(TAG_NONE, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr); // empty full name to prevent being shown in web or console register_device_value(TAG_NONE, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr, DeviceValueUOM::NONE); // empty full name to prevent being shown in web or console
id_ = product_id; id_ = product_id;
register_device_value(TAG_NONE, &collectorTemp_, DeviceValueType::SHORT, FL_(div10), FL_(collectorTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_NONE, &collectorTemp_, DeviceValueType::SHORT, FL_(div10), FL_(collectorTemp), DeviceValueUOM::DEGREES);
@@ -76,14 +74,14 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
register_device_value(TAG_NONE, &tankBottomTemp2_, DeviceValueType::SHORT, FL_(div10), FL_(tank2BottomTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_NONE, &tankBottomTemp2_, DeviceValueType::SHORT, FL_(div10), FL_(tank2BottomTemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_NONE, &heatExchangerTemp_, DeviceValueType::SHORT, FL_(div10), FL_(heatExchangerTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_NONE, &heatExchangerTemp_, DeviceValueType::SHORT, FL_(div10), FL_(heatExchangerTemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_NONE, &tankBottomMaxTemp_, DeviceValueType::UINT, nullptr, FL_(tankMaxTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_NONE, &tankBottomMaxTemp_, DeviceValueType::UINT, nullptr, FL_(tankMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_SM100TankBottomMaxTemp));
register_device_value(TAG_NONE, &solarPumpModulation_, DeviceValueType::UINT, nullptr, FL_(solarPumpModulation), DeviceValueUOM::PERCENT); register_device_value(TAG_NONE, &solarPumpModulation_, DeviceValueType::UINT, nullptr, FL_(solarPumpModulation), DeviceValueUOM::PERCENT);
register_device_value(TAG_NONE, &cylinderPumpModulation_, DeviceValueType::UINT, nullptr, FL_(cylinderPumpModulation), DeviceValueUOM::PERCENT); register_device_value(TAG_NONE, &cylinderPumpModulation_, DeviceValueType::UINT, nullptr, FL_(cylinderPumpModulation), DeviceValueUOM::PERCENT);
register_device_value(TAG_NONE, &solarPump_, DeviceValueType::BOOL, nullptr, FL_(solarPump), DeviceValueUOM::PUMP); register_device_value(TAG_NONE, &solarPump_, DeviceValueType::BOOL, nullptr, FL_(solarPump), DeviceValueUOM::PUMP);
register_device_value(TAG_NONE, &valveStatus_, DeviceValueType::BOOL, nullptr, FL_(valveStatus)); register_device_value(TAG_NONE, &valveStatus_, DeviceValueType::BOOL, nullptr, FL_(valveStatus), DeviceValueUOM::NONE);
register_device_value(TAG_NONE, &tankHeated_, DeviceValueType::BOOL, nullptr, FL_(tankHeated)); register_device_value(TAG_NONE, &tankHeated_, DeviceValueType::BOOL, nullptr, FL_(tankHeated), DeviceValueUOM::NONE);
register_device_value(TAG_NONE, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown)); register_device_value(TAG_NONE, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::NONE);
register_device_value(TAG_NONE, &pumpWorkTime_, DeviceValueType::TIME, nullptr, FL_(pumpWorkTime), DeviceValueUOM::MINUTES); register_device_value(TAG_NONE, &pumpWorkTime_, DeviceValueType::TIME, nullptr, FL_(pumpWorkTime), DeviceValueUOM::MINUTES);

View File

@@ -34,10 +34,10 @@ Switch::Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const
register_telegram_type(0x9D, F("WM10SetMessage"), false, MAKE_PF_CB(process_WM10SetMessage)); register_telegram_type(0x9D, F("WM10SetMessage"), false, MAKE_PF_CB(process_WM10SetMessage));
register_telegram_type(0x1E, F("WM10TempMessage"), false, MAKE_PF_CB(process_WM10TempMessage)); register_telegram_type(0x1E, F("WM10TempMessage"), false, MAKE_PF_CB(process_WM10TempMessage));
register_device_value(TAG_NONE, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr); // empty full name to prevent being shown in web or console register_device_value(TAG_NONE, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr, DeviceValueUOM::NONE); // empty full name to prevent being shown in web or console
register_device_value(TAG_NONE, &activated_, DeviceValueType::BOOL, nullptr, FL_(activated)); register_device_value(TAG_NONE, &activated_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::NONE);
register_device_value(TAG_NONE, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES); register_device_value(TAG_NONE, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES);
register_device_value(TAG_NONE, &status_, DeviceValueType::INT, nullptr, FL_(status)); register_device_value(TAG_NONE, &status_, DeviceValueType::INT, nullptr, FL_(status), DeviceValueUOM::NONE);
id_ = product_id; id_ = product_id;
} }

View File

@@ -59,7 +59,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
} }
// RC35 // RC35
} else if ((model == EMSdevice::EMS_DEVICE_FLAG_RC35) || (model == EMSdevice::EMS_DEVICE_FLAG_RC30_1)) { } else if ((model == EMSdevice::EMS_DEVICE_FLAG_RC35) || (model == EMSdevice::EMS_DEVICE_FLAG_RC30_N)) {
monitor_typeids = {0x3E, 0x48, 0x52, 0x5C}; monitor_typeids = {0x3E, 0x48, 0x52, 0x5C};
set_typeids = {0x3D, 0x47, 0x51, 0x5B}; set_typeids = {0x3D, 0x47, 0x51, 0x5B};
timer_typeids = {0x3F, 0x49, 0x53, 0x5D}; timer_typeids = {0x3F, 0x49, 0x53, 0x5D};
@@ -84,7 +84,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(0xAF, F("RC20Remote"), false, MAKE_PF_CB(process_RC20Remote)); register_telegram_type(0xAF, F("RC20Remote"), false, MAKE_PF_CB(process_RC20Remote));
} }
// RC20 newer // RC20 newer
} else if (model == EMSdevice::EMS_DEVICE_FLAG_RC20_2) { } else if (model == EMSdevice::EMS_DEVICE_FLAG_RC20_N) {
monitor_typeids = {0xAE}; monitor_typeids = {0xAE};
set_typeids = {0xAD}; set_typeids = {0xAD};
if (actual_master_thermostat == device_id) { if (actual_master_thermostat == device_id) {
@@ -167,8 +167,6 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
// register device values for common values (not heating circuit) // register device values for common values (not heating circuit)
register_device_values(); register_device_values();
add_commands();
// only for for the master-thermostat, go a query all the heating circuits. This is only done once. // only for for the master-thermostat, go a query all the heating circuits. This is only done once.
// The automatic fetch will from now on only update the active heating circuits // The automatic fetch will from now on only update the active heating circuits
for (uint8_t i = 0; i < monitor_typeids.size(); i++) { for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
@@ -513,7 +511,7 @@ uint8_t Thermostat::HeatingCircuit::get_mode_type() const {
} else if (modetype == 1) { } else if (modetype == 1) {
return HeatingCircuit::Mode::NOFROST; return HeatingCircuit::Mode::NOFROST;
} }
} else if ((model == EMS_DEVICE_FLAG_RC35) || (model == EMS_DEVICE_FLAG_RC30_1)) { } else if ((model == EMS_DEVICE_FLAG_RC35) || (model == EMS_DEVICE_FLAG_RC30_N)) {
if (modetype == 0) { if (modetype == 0) {
return HeatingCircuit::Mode::NIGHT; return HeatingCircuit::Mode::NIGHT;
} else if (modetype == 1) { } else if (modetype == 1) {
@@ -537,59 +535,65 @@ uint8_t Thermostat::HeatingCircuit::get_mode_type() const {
std::string Thermostat::mode_tostring(uint8_t mode) { std::string Thermostat::mode_tostring(uint8_t mode) {
switch (mode) { switch (mode) {
case HeatingCircuit::Mode::OFF: case HeatingCircuit::Mode::OFF:
return read_flash_string(F("off")); return read_flash_string(F_(off));
break; break;
case HeatingCircuit::Mode::MANUAL: case HeatingCircuit::Mode::MANUAL:
return read_flash_string(F("manual")); return read_flash_string(F_(manual));
break; break;
case HeatingCircuit::Mode::DAY: case HeatingCircuit::Mode::DAY:
return read_flash_string(F("day")); return read_flash_string(F_(day));
break; break;
case HeatingCircuit::Mode::NIGHT: case HeatingCircuit::Mode::NIGHT:
return read_flash_string(F("night")); return read_flash_string(F_(night));
break; break;
case HeatingCircuit::Mode::ECO: case HeatingCircuit::Mode::ECO:
return read_flash_string(F("eco")); return read_flash_string(F_(eco));
break; break;
case HeatingCircuit::Mode::COMFORT: case HeatingCircuit::Mode::COMFORT:
return read_flash_string(F("comfort")); return read_flash_string(F_(comfort));
break; break;
case HeatingCircuit::Mode::HEAT: case HeatingCircuit::Mode::HEAT:
return read_flash_string(F("heat")); return read_flash_string(F_(heat));
break; break;
case HeatingCircuit::Mode::HOLIDAY: case HeatingCircuit::Mode::HOLIDAY:
return read_flash_string(F("holiday")); return read_flash_string(F_(holiday));
break; break;
case HeatingCircuit::Mode::NOFROST: case HeatingCircuit::Mode::NOFROST:
return read_flash_string(F("nofrost")); return read_flash_string(F_(nofrost));
break; break;
case HeatingCircuit::Mode::AUTO: case HeatingCircuit::Mode::AUTO:
return read_flash_string(F("auto")); return read_flash_string(F_(auto));
break; break;
case HeatingCircuit::Mode::SUMMER: case HeatingCircuit::Mode::SUMMER:
return read_flash_string(F("summer")); return read_flash_string(F_(summer));
break; break;
case HeatingCircuit::Mode::OFFSET: case HeatingCircuit::Mode::OFFSET:
return read_flash_string(F("offset")); return read_flash_string(F_(offset));
break; break;
case HeatingCircuit::Mode::DESIGN: case HeatingCircuit::Mode::DESIGN:
return read_flash_string(F("design")); return read_flash_string(F_(design));
break; break;
case HeatingCircuit::Mode::MINFLOW: case HeatingCircuit::Mode::MINFLOW:
return read_flash_string(F("minflow")); return read_flash_string(F_(minflow));
break; break;
case HeatingCircuit::Mode::MAXFLOW: case HeatingCircuit::Mode::MAXFLOW:
return read_flash_string(F("maxflow")); return read_flash_string(F_(maxflow));
break; break;
case HeatingCircuit::Mode::ROOMINFLUENCE: case HeatingCircuit::Mode::ROOMINFLUENCE:
return read_flash_string(F("roominfluence")); return read_flash_string(F_(roominfluence[0]));
break; break;
case HeatingCircuit::Mode::FLOWOFFSET: case HeatingCircuit::Mode::FLOWOFFSET:
return read_flash_string(F("flowtempoffset")); return read_flash_string(F_(flowtempoffset[0]));
break;
case HeatingCircuit::Mode::TEMPAUTO:
return read_flash_string(F_(tempauto));
break;
case HeatingCircuit::Mode::NOREDUCE:
return read_flash_string(F_(noreduce));
break; break;
default: default:
case HeatingCircuit::Mode::UNKNOWN: case HeatingCircuit::Mode::UNKNOWN:
return read_flash_string(F("unknown")); return read_flash_string(F_(unknown));
break; break;
} }
} }
@@ -792,6 +796,7 @@ void Thermostat::process_RC300Set(std::shared_ptr<const Telegram> telegram) {
// has_update(telegram->read_value(hc->mode, 0); // Auto = xFF, Manual = x00 eg. 10 00 FF 08 01 B9 FF // has_update(telegram->read_value(hc->mode, 0); // Auto = xFF, Manual = x00 eg. 10 00 FF 08 01 B9 FF
has_update(telegram->read_value(hc->daytemp, 2)); // is * 2 has_update(telegram->read_value(hc->daytemp, 2)); // is * 2
has_update(telegram->read_value(hc->nighttemp, 4)); // is * 2 has_update(telegram->read_value(hc->nighttemp, 4)); // is * 2
has_update(telegram->read_value(hc->tempautotemp, 8));
has_update(telegram->read_value(hc->manualtemp, 10)); // is * 2 has_update(telegram->read_value(hc->manualtemp, 10)); // is * 2
has_update(telegram->read_value(hc->program, 11)); // timer program 1 or 2 has_update(telegram->read_value(hc->program, 11)); // timer program 1 or 2
} }
@@ -957,7 +962,8 @@ void Thermostat::process_RC35Set(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(hc->reducemode, 25)); // 0-nofrost, 1-reduce, 2-roomhold, 3-outdoorhold has_update(telegram->read_value(hc->reducemode, 25)); // 0-nofrost, 1-reduce, 2-roomhold, 3-outdoorhold
has_update(telegram->read_value(hc->control, 26)); // 0-off, 1-RC20 (remote), 2-RC35 has_update(telegram->read_value(hc->control, 26)); // 0-off, 1-RC20 (remote), 2-RC35
has_update(telegram->read_value(hc->controlmode, 33)); // 0-outdoortemp, 1-roomtemp has_update(telegram->read_value(hc->controlmode, 33)); // 0-outdoortemp, 1-roomtemp
// has_update(telegram->read_value(hc->noreducetemp, 38)); // outdoor temperature for no reduce has_update(telegram->read_value(hc->tempautotemp, 37)); // 0-outdoortemp, 1-roomtemp
has_update(telegram->read_value(hc->noreducetemp, 38)); // outdoor temperature for no reduce
has_update(telegram->read_value(hc->minflowtemp, 16)); has_update(telegram->read_value(hc->minflowtemp, 16));
if (hc->heatingtype == 3) { if (hc->heatingtype == 3) {
has_update(telegram->read_value(hc->designtemp, 36)); // is * 1 has_update(telegram->read_value(hc->designtemp, 36)); // is * 1
@@ -976,6 +982,8 @@ void Thermostat::process_RC35Timer(std::shared_ptr<const Telegram> telegram) {
} }
has_update(telegram->read_value(hc->program, 84)); // 0 .. 10, 0-userprogram 1, 10-userprogram 2 has_update(telegram->read_value(hc->program, 84)); // 0 .. 10, 0-userprogram 1, 10-userprogram 2
has_update(telegram->read_value(hc->pause, 85)); // time in hours
has_update(telegram->read_value(hc->party, 86)); // time in hours
} }
// process_RCTime - type 0x06 - date and time from a thermostat - 14 bytes long // process_RCTime - type 0x06 - date and time from a thermostat - 14 bytes long
@@ -1311,7 +1319,7 @@ bool Thermostat::set_holiday(const char * value, const int8_t id) {
LOG_INFO(F("Setting holiday at home for hc %d"), hc->hc_num()); LOG_INFO(F("Setting holiday at home for hc %d"), hc->hc_num());
write_command(timer_typeids[hc->hc_num() - 1], 93, data, 6, 0); write_command(timer_typeids[hc->hc_num() - 1], 93, data, 6, 0);
} else { } else {
LOG_WARNING(F("Set holiday: Invalid")); LOG_WARNING(F("Set holiday: Invalid value"));
return false; return false;
} }
@@ -1503,7 +1511,7 @@ bool Thermostat::set_mode_n(const uint8_t mode, const uint8_t hc_num) {
offset = EMS_OFFSET_RC20Set_mode; offset = EMS_OFFSET_RC20Set_mode;
validate_typeid = set_typeids[hc_p]; validate_typeid = set_typeids[hc_p];
break; break;
case EMSdevice::EMS_DEVICE_FLAG_RC20_2: // ES72 case EMSdevice::EMS_DEVICE_FLAG_RC20_N: // ES72
offset = EMS_OFFSET_RC20_2_Set_mode; offset = EMS_OFFSET_RC20_2_Set_mode;
validate_typeid = set_typeids[hc_p]; validate_typeid = set_typeids[hc_p];
break; break;
@@ -1512,7 +1520,7 @@ bool Thermostat::set_mode_n(const uint8_t mode, const uint8_t hc_num) {
validate_typeid = set_typeids[hc_p]; validate_typeid = set_typeids[hc_p];
break; break;
case EMSdevice::EMS_DEVICE_FLAG_RC35: case EMSdevice::EMS_DEVICE_FLAG_RC35:
case EMSdevice::EMS_DEVICE_FLAG_RC30_1: case EMSdevice::EMS_DEVICE_FLAG_RC30_N:
offset = EMS_OFFSET_RC35Set_mode; offset = EMS_OFFSET_RC35Set_mode;
validate_typeid = set_typeids[hc_p]; validate_typeid = set_typeids[hc_p];
break; break;
@@ -1608,7 +1616,7 @@ bool Thermostat::set_controlmode(const char * value, const int8_t id) {
write_command(curve_typeids[hc->hc_num() - 1], 0, set, curve_typeids[hc->hc_num() - 1]); write_command(curve_typeids[hc->hc_num() - 1], 0, set, curve_typeids[hc->hc_num() - 1]);
return true; return true;
} }
} else if (model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_1) { } else if (model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N) {
if (Helpers::value2enum(value, set, FL_(enum_controlmode2))) { if (Helpers::value2enum(value, set, FL_(enum_controlmode2))) {
LOG_INFO(F("Setting control mode to %d for heating circuit %d"), set, hc->hc_num()); LOG_INFO(F("Setting control mode to %d for heating circuit %d"), set, hc->hc_num());
write_command(set_typeids[hc->hc_num() - 1], 33, set, set_typeids[hc->hc_num() - 1]); write_command(set_typeids[hc->hc_num() - 1], 33, set, set_typeids[hc->hc_num() - 1]);
@@ -1658,7 +1666,7 @@ bool Thermostat::set_switchtime(const char * value, const int8_t id) {
return false; return false;
} }
if ((model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_1)) { if ((model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N)) {
write_command(timer_typeids[hc->hc_num() - 1], no * 2, (uint8_t *)&data, 2, timer_typeids[hc->hc_num() - 1]); write_command(timer_typeids[hc->hc_num() - 1], no * 2, (uint8_t *)&data, 2, timer_typeids[hc->hc_num() - 1]);
} else { } else {
LOG_WARNING(F("Setting switchtime: thermostat not supported")); LOG_WARNING(F("Setting switchtime: thermostat not supported"));
@@ -1687,9 +1695,9 @@ bool Thermostat::set_program(const char * value, const int8_t id) {
return false; return false;
} }
if (model() == EMS_DEVICE_FLAG_RC20_2 && set > 0 && set < 10) { if (model() == EMS_DEVICE_FLAG_RC20_N && set > 0 && set < 10) {
write_command(set_typeids[hc->hc_num() - 1], 11, set, set_typeids[hc->hc_num() - 1]); write_command(set_typeids[hc->hc_num() - 1], 11, set, set_typeids[hc->hc_num() - 1]);
} else if ((model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_1) && set < 11) { } else if ((model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N) && set < 11) {
write_command(timer_typeids[hc->hc_num() - 1], 84, set, timer_typeids[hc->hc_num() - 1]); write_command(timer_typeids[hc->hc_num() - 1], 84, set, timer_typeids[hc->hc_num() - 1]);
} else if ((model() == EMS_DEVICE_FLAG_RC300 || model() == EMS_DEVICE_FLAG_RC100) && (set == 1 || set == 2)) { } else if ((model() == EMS_DEVICE_FLAG_RC300 || model() == EMS_DEVICE_FLAG_RC100) && (set == 1 || set == 2)) {
write_command(set_typeids[hc->hc_num() - 1], 11, set, set_typeids[hc->hc_num() - 1]); write_command(set_typeids[hc->hc_num() - 1], 11, set, set_typeids[hc->hc_num() - 1]);
@@ -1738,6 +1746,12 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
case HeatingCircuit::Mode::MANUAL: case HeatingCircuit::Mode::MANUAL:
offset = 0x0A; // manual offset offset = 0x0A; // manual offset
break; break;
case HeatingCircuit::Mode::TEMPAUTO:
offset = 0x08; // manual offset
if (temperature == -1) {
factor = 0xFF; // use factor as value
}
break;
case HeatingCircuit::Mode::COMFORT: case HeatingCircuit::Mode::COMFORT:
offset = 0x02; // comfort offset level 2 offset = 0x02; // comfort offset level 2
break; break;
@@ -1804,7 +1818,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
break; break;
} }
} else if (model == EMS_DEVICE_FLAG_RC20_2) { } else if (model == EMS_DEVICE_FLAG_RC20_N) {
switch (mode) { switch (mode) {
case HeatingCircuit::Mode::NIGHT: // change the night temp case HeatingCircuit::Mode::NIGHT: // change the night temp
offset = EMS_OFFSET_RC20_2_Set_temp_night; offset = EMS_OFFSET_RC20_2_Set_temp_night;
@@ -1819,7 +1833,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
break; break;
} }
} else if ((model == EMS_DEVICE_FLAG_RC35) || (model == EMS_DEVICE_FLAG_RC30_1)) { } else if ((model == EMS_DEVICE_FLAG_RC35) || (model == EMS_DEVICE_FLAG_RC30_N)) {
validate_typeid = set_typeids[hc->hc_num() - 1]; validate_typeid = set_typeids[hc->hc_num() - 1];
switch (mode) { switch (mode) {
case HeatingCircuit::Mode::NIGHT: // change the night temp case HeatingCircuit::Mode::NIGHT: // change the night temp
@@ -1858,6 +1872,13 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
offset = 4; offset = 4;
factor = 1; factor = 1;
break; break;
case HeatingCircuit::Mode::NOREDUCE:
offset = EMS_OFFSET_RC35Set_noreducetemp;
factor = 1;
break;
case HeatingCircuit::Mode::TEMPAUTO:
offset = EMS_OFFSET_RC35Set_seltemp;
break;
case HeatingCircuit::Mode::MINFLOW: case HeatingCircuit::Mode::MINFLOW:
offset = 16; offset = 16;
factor = 1; factor = 1;
@@ -2026,6 +2047,14 @@ bool Thermostat::set_manualtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::MANUAL); return set_temperature_value(value, id, HeatingCircuit::Mode::MANUAL);
} }
bool Thermostat::set_tempautotemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::TEMPAUTO);
}
bool Thermostat::set_noreducetemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::NOREDUCE);
}
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); return set_temperature_value(value, id, HeatingCircuit::Mode::FLOWOFFSET);
} }
@@ -2042,133 +2071,66 @@ bool Thermostat::set_roominfluence(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::ROOMINFLUENCE); return set_temperature_value(value, id, HeatingCircuit::Mode::ROOMINFLUENCE);
} }
// API commands for MQTT and Console
void Thermostat::add_commands() {
// if this thermostat doesn't support write, don't add the commands
if (has_flags(EMS_DEVICE_FLAG_NO_WRITE)) {
return;
}
// common to all thermostats
register_mqtt_cmd(F_(temp), MAKE_CF_CB(set_temp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(mode), MAKE_CF_CB(set_mode), FLAG_HC);
if (model() == EMS_DEVICE_FLAG_RC35) { // section is together with RC30
register_mqtt_cmd(MQTT_TOPIC(dateTime), MAKE_CF_CB(set_datetime));
}
switch (model()) {
case EMS_DEVICE_FLAG_RC100:
case EMS_DEVICE_FLAG_RC300:
register_mqtt_cmd(MQTT_TOPIC(dateTime), MAKE_CF_CB(set_datetime));
register_mqtt_cmd(MQTT_TOPIC(manualtemp), MAKE_CF_CB(set_manualtemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(ecotemp), MAKE_CF_CB(set_ecotemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(comforttemp), MAKE_CF_CB(set_comforttemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(summermode), MAKE_CF_CB(set_summermode), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(summertemp), MAKE_CF_CB(set_summertemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(wwMode), MAKE_CF_CB(set_wwmode));
register_mqtt_cmd(MQTT_TOPIC(wwSetTemp), MAKE_CF_CB(set_wwtemp));
register_mqtt_cmd(MQTT_TOPIC(wwSetTempLow), MAKE_CF_CB(set_wwtemplow));
register_mqtt_cmd(MQTT_TOPIC(wWOneTime), MAKE_CF_CB(set_wwonetime));
register_mqtt_cmd(MQTT_TOPIC(wWCircMode), MAKE_CF_CB(set_wwcircmode));
register_mqtt_cmd(MQTT_TOPIC(ibaBuildingType), MAKE_CF_CB(set_building));
register_mqtt_cmd(MQTT_TOPIC(nofrosttemp), MAKE_CF_CB(set_nofrosttemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(designtemp), MAKE_CF_CB(set_designtemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(offsettemp), MAKE_CF_CB(set_offsettemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(minflowtemp), MAKE_CF_CB(set_minflowtemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(maxflowtemp), MAKE_CF_CB(set_maxflowtemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(ibaMinExtTemperature), MAKE_CF_CB(set_minexttemp));
register_mqtt_cmd(MQTT_TOPIC(roominfluence), MAKE_CF_CB(set_roominfluence), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(program), MAKE_CF_CB(set_program), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(controlmode), MAKE_CF_CB(set_controlmode), FLAG_HC);
break;
case EMS_DEVICE_FLAG_RC20_2:
register_mqtt_cmd(MQTT_TOPIC(nighttemp), MAKE_CF_CB(set_nighttemp));
register_mqtt_cmd(MQTT_TOPIC(daytemp), MAKE_CF_CB(set_daytemp));
register_mqtt_cmd(MQTT_TOPIC(program), MAKE_CF_CB(set_program));
break;
case EMS_DEVICE_FLAG_RC30_1: // only RC30_1
register_mqtt_cmd(MQTT_TOPIC(ibaClockOffset), MAKE_CF_CB(set_clockoffset));
register_mqtt_cmd(MQTT_TOPIC(ibaLanguage), MAKE_CF_CB(set_language));
register_mqtt_cmd(MQTT_TOPIC(ibaMainDisplay), MAKE_CF_CB(set_display));
case EMS_DEVICE_FLAG_RC35: // RC30 and RC35
register_mqtt_cmd(MQTT_TOPIC(nighttemp), MAKE_CF_CB(set_nighttemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(daytemp), MAKE_CF_CB(set_daytemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(nofrosttemp), MAKE_CF_CB(set_nofrosttemp), FLAG_HC);
register_mqtt_cmd(F_(remoteTemp), MAKE_CF_CB(set_remotetemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(ibaMinExtTemperature), MAKE_CF_CB(set_minexttemp));
register_mqtt_cmd(MQTT_TOPIC(ibaCalIntTemperature), MAKE_CF_CB(set_calinttemp));
register_mqtt_cmd(MQTT_TOPIC(ibaBuildingType), MAKE_CF_CB(set_building));
register_mqtt_cmd(MQTT_TOPIC(control), MAKE_CF_CB(set_control), FLAG_HC);
register_mqtt_cmd(F_(pause), MAKE_CF_CB(set_pause), FLAG_HC);
register_mqtt_cmd(F_(party), MAKE_CF_CB(set_party), FLAG_HC);
register_mqtt_cmd(F_(holiday), MAKE_CF_CB(set_holiday), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(summertemp), MAKE_CF_CB(set_summertemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(designtemp), MAKE_CF_CB(set_designtemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(offsettemp), MAKE_CF_CB(set_offsettemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(holidaytemp), MAKE_CF_CB(set_holidaytemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(wwMode), MAKE_CF_CB(set_wwmode));
register_mqtt_cmd(MQTT_TOPIC(wWCircMode), MAKE_CF_CB(set_wwcircmode));
register_mqtt_cmd(MQTT_TOPIC(roominfluence), MAKE_CF_CB(set_roominfluence), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(flowtempoffset), MAKE_CF_CB(set_flowtempoffset), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(minflowtemp), MAKE_CF_CB(set_minflowtemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(maxflowtemp), MAKE_CF_CB(set_maxflowtemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(reducemode), MAKE_CF_CB(set_reducemode), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(program), MAKE_CF_CB(set_program), FLAG_HC);
register_mqtt_cmd(F_(switchtime), MAKE_CF_CB(set_switchtime), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(controlmode), MAKE_CF_CB(set_controlmode), FLAG_HC);
break;
case EMS_DEVICE_FLAG_JUNKERS:
register_mqtt_cmd(MQTT_TOPIC(dateTime), MAKE_CF_CB(set_datetime));
register_mqtt_cmd(MQTT_TOPIC(nofrosttemp), MAKE_CF_CB(set_nofrosttemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(ecotemp), MAKE_CF_CB(set_ecotemp), FLAG_HC);
register_mqtt_cmd(MQTT_TOPIC(heattemp), MAKE_CF_CB(set_heattemp), FLAG_HC);
break;
default:
break;
}
}
// register main device values, top level for all thermostats (excluding heating circuits) // register main device values, top level for all thermostats (excluding heating circuits)
// as these are done in void Thermostat::register_device_values_hc()
void Thermostat::register_device_values() { void Thermostat::register_device_values() {
uint8_t model = this->model(); // extra commands
if (!has_flags(EMS_DEVICE_FLAG_NO_WRITE)) {
register_cmd(MQTT_TOPIC(temp), MAKE_CF_CB(set_temp), FLAG_HC); // for backwards compatibility
}
// Common for all thermostats // Common for all thermostats
register_device_value(TAG_THERMOSTAT_DATA, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr); // empty full name to prevent being shown in web or console register_device_value(TAG_THERMOSTAT_DATA, &id_, DeviceValueType::UINT, nullptr, F("id"), nullptr, DeviceValueUOM::NONE); // empty full name to prevent being shown in web or console
register_device_value(TAG_THERMOSTAT_DATA, &dateTime_, DeviceValueType::TEXT, nullptr, FL_(dateTime)); register_device_value(TAG_THERMOSTAT_DATA, &errorCode_, DeviceValueType::TEXT, nullptr, FL_(errorCode), DeviceValueUOM::NONE);
register_device_value(TAG_THERMOSTAT_DATA, &errorCode_, DeviceValueType::TEXT, nullptr, FL_(errorCode)); register_device_value(TAG_THERMOSTAT_DATA, &lastCode_, DeviceValueType::TEXT, nullptr, FL_(lastCode), DeviceValueUOM::NONE);
register_device_value(TAG_THERMOSTAT_DATA, &lastCode_, DeviceValueType::TEXT, nullptr, FL_(lastCode));
// RC30 only switch (this->model()) {
if (model == EMSdevice::EMS_DEVICE_FLAG_RC30_1) { case EMS_DEVICE_FLAG_RC100:
register_device_value(TAG_THERMOSTAT_DATA, &ibaMainDisplay_, DeviceValueType::ENUM, FL_(enum_ibaMainDisplay), FL_(ibaMainDisplay)); case EMS_DEVICE_FLAG_RC300:
register_device_value(TAG_THERMOSTAT_DATA, &ibaLanguage_, DeviceValueType::ENUM, FL_(enum_ibaLanguage), FL_(ibaLanguage)); register_device_value(TAG_THERMOSTAT_DATA, &dateTime_, DeviceValueType::TEXT, nullptr, FL_(dateTime), DeviceValueUOM::NONE, MAKE_CF_CB(set_datetime));
register_device_value(TAG_THERMOSTAT_DATA, &ibaClockOffset_, DeviceValueType::UINT, nullptr, FL_(ibaClockOffset)); // offset (in sec) to clock, 0xff=-1s, 0x02=2s register_device_value(TAG_THERMOSTAT_DATA, &floordrystatus_, DeviceValueType::ENUM, FL_(enum_floordrystatus), FL_(floordrystatus), DeviceValueUOM::NONE);
}
// RC300 and RC100
if (model == EMS_DEVICE_FLAG_RC300 || model == EMS_DEVICE_FLAG_RC100) {
register_device_value(TAG_THERMOSTAT_DATA, &floordrystatus_, DeviceValueType::ENUM, FL_(enum_floordrystatus), FL_(floordrystatus));
register_device_value(TAG_THERMOSTAT_DATA, &dampedoutdoortemp2_, DeviceValueType::SHORT, FL_(div10), FL_(dampedoutdoortemp), DeviceValueUOM::DEGREES); register_device_value(TAG_THERMOSTAT_DATA, &dampedoutdoortemp2_, DeviceValueType::SHORT, FL_(div10), FL_(dampedoutdoortemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_THERMOSTAT_DATA, &floordrytemp_, DeviceValueType::UINT, nullptr, FL_(floordrytemp), DeviceValueUOM::DEGREES); register_device_value(TAG_THERMOSTAT_DATA, &floordrytemp_, DeviceValueType::UINT, nullptr, FL_(floordrytemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_THERMOSTAT_DATA, &ibaBuildingType_, DeviceValueType::ENUM, FL_(enum_ibaBuildingType), FL_(ibaBuildingType)); register_device_value(TAG_THERMOSTAT_DATA, &ibaBuildingType_, DeviceValueType::ENUM, FL_(enum_ibaBuildingType), FL_(ibaBuildingType), DeviceValueUOM::NONE, MAKE_CF_CB(set_building));
register_device_value(TAG_THERMOSTAT_DATA, &wwSetTemp_, DeviceValueType::UINT, nullptr, FL_(wwSetTemp), DeviceValueUOM::DEGREES); register_device_value(TAG_THERMOSTAT_DATA, &wwSetTemp_, DeviceValueType::UINT, nullptr, FL_(wwSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwtemp));
register_device_value(TAG_THERMOSTAT_DATA, &wwMode_, DeviceValueType::ENUM, FL_(enum_wwMode), FL_(wwMode)); register_device_value(TAG_THERMOSTAT_DATA, &wwMode_, DeviceValueType::ENUM, FL_(enum_wwMode), FL_(wwMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwmode));
register_device_value(TAG_THERMOSTAT_DATA, &wwSetTempLow_, DeviceValueType::UINT, nullptr, FL_(wwSetTempLow), DeviceValueUOM::DEGREES); register_device_value(TAG_THERMOSTAT_DATA, &wwSetTempLow_, DeviceValueType::UINT, nullptr, FL_(wwSetTempLow), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwtemplow));
register_device_value(TAG_THERMOSTAT_DATA, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wWCircMode)); register_device_value(TAG_THERMOSTAT_DATA, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wWCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwcircmode));
register_device_value(TAG_THERMOSTAT_DATA, &wwExtra1_, DeviceValueType::UINT, nullptr, FL_(wwExtra1), DeviceValueUOM::DEGREES); register_device_value(TAG_THERMOSTAT_DATA, &wwExtra1_, DeviceValueType::UINT, nullptr, FL_(wwExtra1), DeviceValueUOM::DEGREES);
register_device_value(TAG_THERMOSTAT_DATA, &wwExtra2_, DeviceValueType::UINT, nullptr, FL_(wwExtra2), DeviceValueUOM::DEGREES); register_device_value(TAG_THERMOSTAT_DATA, &wwExtra2_, DeviceValueType::UINT, nullptr, FL_(wwExtra2), DeviceValueUOM::DEGREES);
} break;
case EMS_DEVICE_FLAG_RC20_N:
// RC30 and RC35 case EMS_DEVICE_FLAG_RC20:
if (model == EMS_DEVICE_FLAG_RC35 || model == EMS_DEVICE_FLAG_RC30_1) { register_device_value(TAG_THERMOSTAT_DATA, &dateTime_, DeviceValueType::TEXT, nullptr, FL_(dateTime), DeviceValueUOM::NONE); // can't set datetime
register_device_value(TAG_THERMOSTAT_DATA, &ibaCalIntTemperature_, DeviceValueType::INT, FL_(div2), FL_(ibaCalIntTemperature), DeviceValueUOM::DEGREES); break;
register_device_value(TAG_THERMOSTAT_DATA, &ibaMinExtTemperature_, DeviceValueType::INT, nullptr, FL_(ibaMinExtTemperature), DeviceValueUOM::DEGREES); case EMS_DEVICE_FLAG_RC30_N:
register_device_value(TAG_THERMOSTAT_DATA, &dateTime_, DeviceValueType::TEXT, nullptr, FL_(dateTime), DeviceValueUOM::NONE); // can't set datetime
register_device_value(TAG_THERMOSTAT_DATA, &ibaMainDisplay_, DeviceValueType::ENUM, FL_(enum_ibaMainDisplay), FL_(ibaMainDisplay), DeviceValueUOM::NONE);
register_device_value(TAG_THERMOSTAT_DATA, &ibaLanguage_, DeviceValueType::ENUM, FL_(enum_ibaLanguage), FL_(ibaLanguage), DeviceValueUOM::NONE);
register_device_value(TAG_THERMOSTAT_DATA, &ibaClockOffset_, DeviceValueType::UINT, nullptr, FL_(ibaClockOffset), DeviceValueUOM::NONE); // offset (in sec) to clock, 0xff=-1s, 0x02=2s
register_device_value(TAG_THERMOSTAT_DATA, &ibaCalIntTemperature_, DeviceValueType::INT, FL_(div2), FL_(ibaCalIntTemperature), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_calinttemp));
register_device_value(TAG_THERMOSTAT_DATA, &ibaMinExtTemperature_, DeviceValueType::INT, nullptr, FL_(ibaMinExtTemperature), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_minexttemp));
register_device_value(TAG_THERMOSTAT_DATA, &dampedoutdoortemp_, DeviceValueType::INT, nullptr, FL_(dampedoutdoortemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_THERMOSTAT_DATA, &ibaBuildingType_, DeviceValueType::ENUM, FL_(enum_ibaBuildingType2), FL_(ibaBuildingType), DeviceValueUOM::NONE, MAKE_CF_CB(set_building));
register_device_value(TAG_THERMOSTAT_DATA, &wwMode_, DeviceValueType::ENUM, FL_(enum_wwMode2), FL_(wwMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwmode));
register_device_value(TAG_THERMOSTAT_DATA, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode2), FL_(wWCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwcircmode));
break;
case EMS_DEVICE_FLAG_RC35:
register_device_value(TAG_THERMOSTAT_DATA, &dateTime_, DeviceValueType::TEXT, nullptr, FL_(dateTime), DeviceValueUOM::NONE, MAKE_CF_CB(set_datetime));
register_device_value(TAG_THERMOSTAT_DATA, &ibaCalIntTemperature_, DeviceValueType::INT, FL_(div2), FL_(ibaCalIntTemperature), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_calinttemp));
register_device_value(TAG_THERMOSTAT_DATA, &ibaMinExtTemperature_, DeviceValueType::INT, nullptr, FL_(ibaMinExtTemperature), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_minexttemp));
register_device_value(TAG_THERMOSTAT_DATA, &tempsensor1_, DeviceValueType::USHORT, FL_(div10), FL_(tempsensor1), DeviceValueUOM::DEGREES); register_device_value(TAG_THERMOSTAT_DATA, &tempsensor1_, DeviceValueType::USHORT, FL_(div10), FL_(tempsensor1), DeviceValueUOM::DEGREES);
register_device_value(TAG_THERMOSTAT_DATA, &tempsensor2_, DeviceValueType::USHORT, FL_(div10), FL_(tempsensor2), DeviceValueUOM::DEGREES); register_device_value(TAG_THERMOSTAT_DATA, &tempsensor2_, DeviceValueType::USHORT, FL_(div10), FL_(tempsensor2), DeviceValueUOM::DEGREES);
register_device_value(TAG_THERMOSTAT_DATA, &dampedoutdoortemp_, DeviceValueType::INT, nullptr, FL_(dampedoutdoortemp), DeviceValueUOM::DEGREES); register_device_value(TAG_THERMOSTAT_DATA, &dampedoutdoortemp_, DeviceValueType::INT, nullptr, FL_(dampedoutdoortemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_THERMOSTAT_DATA, &ibaBuildingType_, DeviceValueType::ENUM, FL_(enum_ibaBuildingType2), FL_(ibaBuildingType)); register_device_value(TAG_THERMOSTAT_DATA, &ibaBuildingType_, DeviceValueType::ENUM, FL_(enum_ibaBuildingType2), FL_(ibaBuildingType), DeviceValueUOM::NONE, MAKE_CF_CB(set_building));
register_device_value(TAG_THERMOSTAT_DATA, &wwMode_, DeviceValueType::ENUM, FL_(enum_wwMode2), FL_(wwMode)); register_device_value(TAG_THERMOSTAT_DATA, &wwMode_, DeviceValueType::ENUM, FL_(enum_wwMode2), FL_(wwMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwmode));
register_device_value(TAG_THERMOSTAT_DATA, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode2), FL_(wWCircMode)); register_device_value(TAG_THERMOSTAT_DATA, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode2), FL_(wWCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwcircmode));
break;
case EMS_DEVICE_FLAG_JUNKERS:
register_device_value(TAG_THERMOSTAT_DATA, &dateTime_, DeviceValueType::TEXT, nullptr, FL_(dateTime), DeviceValueUOM::NONE, MAKE_CF_CB(set_datetime));
break;
default:
break;
} }
} }
@@ -2193,7 +2155,11 @@ void Thermostat::register_device_values_hc(std::shared_ptr<emsesp::Thermostat::H
setpoint_temp_divider = FL_(div2); setpoint_temp_divider = FL_(div2);
curr_temp_divider = FL_(div10); curr_temp_divider = FL_(div10);
} }
if (has_flags(EMS_DEVICE_FLAG_NO_WRITE) || device_id() != EMSESP::actual_master_thermostat()) {
register_device_value(tag, &hc->setpoint_roomTemp, DeviceValueType::SHORT, setpoint_temp_divider, FL_(setpoint_roomTemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->setpoint_roomTemp, DeviceValueType::SHORT, setpoint_temp_divider, FL_(setpoint_roomTemp), DeviceValueUOM::DEGREES);
} else {
register_device_value(tag, &hc->setpoint_roomTemp, DeviceValueType::SHORT, setpoint_temp_divider, FL_(setpoint_roomTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_temp));
}
register_device_value(tag, &hc->curr_roomTemp, DeviceValueType::SHORT, curr_temp_divider, FL_(curr_roomTemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->curr_roomTemp, DeviceValueType::SHORT, curr_temp_divider, FL_(curr_roomTemp), DeviceValueUOM::DEGREES);
if (device_id() != EMSESP::actual_master_thermostat()) { if (device_id() != EMSESP::actual_master_thermostat()) {
@@ -2205,82 +2171,87 @@ void Thermostat::register_device_values_hc(std::shared_ptr<emsesp::Thermostat::H
if (Mqtt::ha_enabled()) { if (Mqtt::ha_enabled()) {
uint8_t option = Mqtt::ha_climate_format(); uint8_t option = Mqtt::ha_climate_format();
if (option == Mqtt::HA_Climate_Format::CURRENT) { if (option == Mqtt::HA_Climate_Format::CURRENT) {
register_device_value(tag, &hc->curr_roomTemp, DeviceValueType::SHORT, curr_temp_divider, F("hatemp"), nullptr); register_device_value(tag, &hc->curr_roomTemp, DeviceValueType::SHORT, curr_temp_divider, F("hatemp"), nullptr, DeviceValueUOM::NONE);
} else if (option == Mqtt::HA_Climate_Format::SETPOINT) { } else if (option == Mqtt::HA_Climate_Format::SETPOINT) {
register_device_value(tag, &hc->setpoint_roomTemp, DeviceValueType::SHORT, setpoint_temp_divider, F("hatemp"), nullptr); register_device_value(tag, &hc->setpoint_roomTemp, DeviceValueType::SHORT, setpoint_temp_divider, F("hatemp"), nullptr, DeviceValueUOM::NONE);
} else if (option == Mqtt::HA_Climate_Format::ZERO) { } else if (option == Mqtt::HA_Climate_Format::ZERO) {
register_device_value(tag, &zero_value_, DeviceValueType::UINT, nullptr, F("hatemp"), nullptr); register_device_value(tag, &zero_value_, DeviceValueType::UINT, nullptr, F("hatemp"), nullptr, DeviceValueUOM::NONE);
} }
// if we're sending to HA the only valid mode types are heat, auto and off // if we're sending to HA the only valid mode types are heat, auto and off
// manual & day = heat // manual & day = heat
// night & off = off // night & off = off
// everything else auto // everything else auto
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_hamode), F("hamode"), nullptr); register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_hamode), F("hamode"), nullptr, DeviceValueUOM::NONE);
} }
switch (model) {
if (model == EMSdevice::EMS_DEVICE_FLAG_RC300 || model == EMSdevice::EMS_DEVICE_FLAG_RC100) { case EMS_DEVICE_FLAG_RC100:
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode), FL_(mode)); case EMS_DEVICE_FLAG_RC300:
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype), FL_(modetype)); register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), FL_(ecotemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype), FL_(modetype), DeviceValueUOM::NONE);
register_device_value(tag, &hc->manualtemp, DeviceValueType::UINT, FL_(div2), FL_(manualtemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), FL_(ecotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_ecotemp));
register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), FL_(comforttemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->manualtemp, DeviceValueType::UINT, FL_(div2), FL_(manualtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_manualtemp));
register_device_value(tag, &hc->summertemp, DeviceValueType::UINT, nullptr, FL_(summertemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), FL_(comforttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_comforttemp));
register_device_value(tag, &hc->designtemp, DeviceValueType::UINT, nullptr, FL_(designtemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->summertemp, DeviceValueType::UINT, nullptr, FL_(summertemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_summertemp));
register_device_value(tag, &hc->offsettemp, DeviceValueType::INT, nullptr, FL_(offsettemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->designtemp, DeviceValueType::UINT, nullptr, FL_(designtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_designtemp));
register_device_value(tag, &hc->minflowtemp, DeviceValueType::UINT, nullptr, FL_(minflowtemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->offsettemp, DeviceValueType::INT, nullptr, FL_(offsettemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_offsettemp));
register_device_value(tag, &hc->maxflowtemp, DeviceValueType::UINT, nullptr, FL_(maxflowtemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->minflowtemp, DeviceValueType::UINT, nullptr, FL_(minflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_minflowtemp));
register_device_value(tag, &hc->roominfluence, DeviceValueType::UINT, nullptr, FL_(roominfluence)); register_device_value(tag, &hc->maxflowtemp, DeviceValueType::UINT, nullptr, FL_(maxflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_maxflowtemp));
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, FL_(nofrosttemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->roominfluence, DeviceValueType::UINT, nullptr, FL_(roominfluence), DeviceValueUOM::NONE, MAKE_CF_CB(set_roominfluence));
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, FL_(nofrosttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nofrosttemp));
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, FL_(targetflowtemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, FL_(targetflowtemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), FL_(heatingtype)); register_device_value(tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), FL_(heatingtype), DeviceValueUOM::NONE);
register_device_value(tag, &hc->summer_setmode, DeviceValueType::ENUM, FL_(enum_summermode), FL_(summermode)); register_device_value(tag, &hc->summer_setmode, DeviceValueType::ENUM, FL_(enum_summermode), FL_(summermode), DeviceValueUOM::NONE, MAKE_CF_CB(set_summermode));
register_device_value(tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode), FL_(controlmode)); register_device_value(tag, &hc->summermode, DeviceValueType::BOOL, nullptr, FL_(summermode), DeviceValueUOM::NONE);
register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, FL_(program)); register_device_value(tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode), FL_(controlmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_controlmode));
} register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program));
register_device_value(tag, &hc->tempautotemp, DeviceValueType::UINT, FL_(div2), FL_(tempautotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_tempautotemp));
if (model == EMS_DEVICE_FLAG_RC20) { break;
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode)); case EMS_DEVICE_FLAG_RC20:
} register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
break;
if (model == EMS_DEVICE_FLAG_RC20_2) { case EMS_DEVICE_FLAG_RC20_N:
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode)); register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype2), FL_(modetype)); register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype2), FL_(modetype), DeviceValueUOM::NONE);
register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), FL_(daytemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), FL_(daytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daytemp));
register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), FL_(nighttemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), FL_(nighttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nighttemp));
register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, FL_(program)); register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program));
} break;
case EMS_DEVICE_FLAG_RC30_N:
if (model == EMS_DEVICE_FLAG_RC35 || model == EMS_DEVICE_FLAG_RC30_1) { case EMS_DEVICE_FLAG_RC35:
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode3), FL_(mode)); register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode3), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype3), FL_(modetype)); register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype3), FL_(modetype), DeviceValueUOM::NONE);
register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), FL_(daytemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), FL_(daytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daytemp));
register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), FL_(nighttemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), FL_(nighttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nighttemp));
register_device_value(tag, &hc->designtemp, DeviceValueType::UINT, nullptr, FL_(designtemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->designtemp, DeviceValueType::UINT, nullptr, FL_(designtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_designtemp));
register_device_value(tag, &hc->offsettemp, DeviceValueType::INT, FL_(div2), FL_(offsettemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->offsettemp, DeviceValueType::INT, FL_(div2), FL_(offsettemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_offsettemp));
register_device_value(tag, &hc->holidaytemp, DeviceValueType::UINT, FL_(div2), FL_(holidaytemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->holidaytemp, DeviceValueType::UINT, FL_(div2), FL_(holidaytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_holidaytemp));
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, FL_(targetflowtemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, FL_(targetflowtemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->summertemp, DeviceValueType::UINT, nullptr, FL_(summertemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->summertemp, DeviceValueType::UINT, nullptr, FL_(summertemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_summertemp));
register_device_value(tag, &hc->summermode, DeviceValueType::BOOL, nullptr, FL_(summermode)); register_device_value(tag, &hc->summermode, DeviceValueType::BOOL, nullptr, FL_(summermode), DeviceValueUOM::NONE);
register_device_value(tag, &hc->holidaymode, DeviceValueType::BOOL, nullptr, FL_(holidaymode)); register_device_value(tag, &hc->holidaymode, DeviceValueType::BOOL, nullptr, FL_(holidaymode), DeviceValueUOM::NONE, MAKE_CF_CB(set_holiday));
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, FL_(nofrosttemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, FL_(nofrosttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nofrosttemp));
register_device_value(tag, &hc->roominfluence, DeviceValueType::UINT, nullptr, FL_(roominfluence)); register_device_value(tag, &hc->roominfluence, DeviceValueType::UINT, nullptr, FL_(roominfluence), DeviceValueUOM::NONE, MAKE_CF_CB(set_roominfluence));
register_device_value(tag, &hc->minflowtemp, DeviceValueType::UINT, nullptr, FL_(minflowtemp), DeviceValueUOM::DEGREES); 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); register_device_value(tag, &hc->maxflowtemp, DeviceValueType::UINT, nullptr, FL_(maxflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_maxflowtemp));
register_device_value(tag, &hc->flowtempoffset, DeviceValueType::UINT, nullptr, FL_(flowtempoffset), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->flowtempoffset, DeviceValueType::UINT, nullptr, FL_(flowtempoffset), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flowtempoffset));
register_device_value(tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), FL_(heatingtype)); register_device_value(tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), FL_(heatingtype), DeviceValueUOM::NONE);
register_device_value(tag, &hc->reducemode, DeviceValueType::ENUM, FL_(enum_reducemode), FL_(reducemode)); register_device_value(tag, &hc->reducemode, DeviceValueType::ENUM, FL_(enum_reducemode), FL_(reducemode), DeviceValueUOM::NONE, MAKE_CF_CB(set_reducemode));
register_device_value(tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode2), FL_(controlmode)); register_device_value(tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode2), FL_(controlmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_controlmode));
register_device_value(tag, &hc->control, DeviceValueType::ENUM, FL_(enum_control), FL_(control)); register_device_value(tag, &hc->control, DeviceValueType::ENUM, FL_(enum_control), FL_(control), DeviceValueUOM::NONE, MAKE_CF_CB(set_control));
register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, FL_(program)); register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program));
} register_device_value(tag, &hc->pause, DeviceValueType::UINT, nullptr, FL_(pause), DeviceValueUOM::HOURS, MAKE_CF_CB(set_pause));
register_device_value(tag, &hc->party, DeviceValueType::UINT, nullptr, FL_(party), DeviceValueUOM::HOURS, MAKE_CF_CB(set_party));
if (model == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) { register_device_value(tag, &hc->tempautotemp, DeviceValueType::UINT, FL_(div2), FL_(tempautotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_tempautotemp));
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode4), FL_(mode)); register_device_value(tag, &hc->noreducetemp, DeviceValueType::INT, nullptr, FL_(noreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_noreducetemp));
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype4), FL_(modetype)); break;
register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), FL_(heattemp), DeviceValueUOM::DEGREES); case EMS_DEVICE_FLAG_JUNKERS:
register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), FL_(ecotemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode4), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, FL_(div2), FL_(nofrosttemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype4), FL_(modetype), DeviceValueUOM::NONE);
register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), FL_(heattemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_heattemp));
register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), FL_(ecotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_ecotemp));
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, FL_(div2), FL_(nofrosttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nofrosttemp));
break;
} }
} }

View File

@@ -36,6 +36,7 @@ class Thermostat : public EMSdevice {
int16_t setpoint_roomTemp; int16_t setpoint_roomTemp;
int16_t curr_roomTemp; int16_t curr_roomTemp;
uint8_t tempautotemp;
uint8_t mode; uint8_t mode;
uint8_t modetype; uint8_t modetype;
uint8_t summermode; uint8_t summermode;
@@ -59,6 +60,9 @@ class Thermostat : public EMSdevice {
uint8_t program; uint8_t program;
uint8_t controlmode; uint8_t controlmode;
uint8_t control; uint8_t control;
uint8_t pause;
uint8_t party;
int8_t noreducetemp; // signed -20°C to +10°C
uint8_t hc_num() const { uint8_t hc_num() const {
return hc_num_; return hc_num_;
@@ -94,6 +98,8 @@ class Thermostat : public EMSdevice {
MINFLOW, MINFLOW,
MAXFLOW, MAXFLOW,
ROOMINFLUENCE, ROOMINFLUENCE,
TEMPAUTO,
NOREDUCE,
UNKNOWN UNKNOWN
}; };
@@ -115,8 +121,6 @@ class Thermostat : public EMSdevice {
private: private:
static uuid::log::Logger logger_; static uuid::log::Logger logger_;
void add_commands();
void register_device_values(); void register_device_values();
void register_device_values(uint8_t hc_num); void register_device_values(uint8_t hc_num);
@@ -201,6 +205,7 @@ class Thermostat : public EMSdevice {
static constexpr uint8_t EMS_OFFSET_RC35Set_heatingtype = 0; // e.g. floor heating = 3 static constexpr uint8_t EMS_OFFSET_RC35Set_heatingtype = 0; // e.g. floor heating = 3
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_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;
@@ -310,6 +315,8 @@ class Thermostat : public EMSdevice {
bool set_offsettemp(const char * value, const int8_t id); bool set_offsettemp(const char * value, const int8_t id);
bool set_holidaytemp(const char * value, const int8_t id); bool set_holidaytemp(const char * value, const int8_t id);
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_noreducetemp(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_flowtempoffset(const char * value, const int8_t id); bool set_flowtempoffset(const char * value, const int8_t id);

View File

@@ -149,7 +149,7 @@ std::string EMSdevice::brand_to_string() const {
break; break;
case EMSdevice::Brand::NO_BRAND: case EMSdevice::Brand::NO_BRAND:
default: default:
return read_flash_string(F("---")); return read_flash_string(F(""));
break; break;
} }
@@ -405,7 +405,7 @@ void EMSdevice::register_mqtt_topic(const std::string & topic, mqtt_subfunction_
} }
// add command to library // add command to library
void EMSdevice::register_mqtt_cmd(const __FlashStringHelper * cmd, cmdfunction_p f, uint8_t flag) { void EMSdevice::register_cmd(const __FlashStringHelper * cmd, cmdfunction_p f, uint8_t flag) {
Command::add(device_type_, cmd, f, flag); Command::add(device_type_, cmd, f, flag);
} }
@@ -423,7 +423,14 @@ void EMSdevice::register_telegram_type(const uint16_t telegram_type_id, const __
// short_name: used in Mqtt as keys // short_name: used in Mqtt as keys
// full name: used in Web and Console unless empty (nullptr) // full name: used in Web and Console unless empty (nullptr)
// uom: unit of measure from DeviceValueUOM // uom: unit of measure from DeviceValueUOM
void EMSdevice::register_device_value(uint8_t tag, void * value_p, uint8_t type, const __FlashStringHelper * const * options, const __FlashStringHelper * short_name, const __FlashStringHelper * full_name, uint8_t uom) { void EMSdevice::register_device_value(uint8_t tag,
void * value_p,
uint8_t type,
const __FlashStringHelper * const * options,
const __FlashStringHelper * short_name,
const __FlashStringHelper * full_name,
uint8_t uom,
bool has_cmd) {
// init the value depending on it's type // init the value depending on it's type
if (type == DeviceValueType::TEXT) { if (type == DeviceValueType::TEXT) {
*(char *)(value_p) = {'\0'}; *(char *)(value_p) = {'\0'};
@@ -448,11 +455,18 @@ void EMSdevice::register_device_value(uint8_t tag, void * value_p, uint8_t type,
}; };
} }
devicevalues_.emplace_back(device_type_, tag, value_p, type, options, options_size, short_name, full_name, uom); devicevalues_.emplace_back(device_type_, tag, value_p, type, options, options_size, short_name, full_name, uom, 0, has_cmd);
} }
void EMSdevice::register_device_value(uint8_t tag, void * value_p, uint8_t type, const __FlashStringHelper * const * options, const __FlashStringHelper * const * name, uint8_t uom) { void EMSdevice::register_device_value(uint8_t tag, void * value_p, uint8_t type, const __FlashStringHelper * const * options, const __FlashStringHelper * const * name, uint8_t uom, cmdfunction_p f) {
register_device_value(tag, value_p, type, options, name[0], name[1], uom); register_device_value(tag, value_p, type, options, name[0], name[1], uom, (f != nullptr));
if (f != nullptr) {
if (tag >= TAG_HC1 && tag <= TAG_HC4) {
Command::add(device_type_, name[0], f, FLAG_HC);
} else {
Command::add(device_type_, name[0], f, 0);
}
}
} }
// looks up the uom (suffix) for a given key from the device value table // looks up the uom (suffix) for a given key from the device value table
@@ -570,7 +584,7 @@ bool EMSdevice::generate_values_json_web(JsonObject & json) {
if (sz > num_elements) { if (sz > num_elements) {
// add the unit of measure (uom) // add the unit of measure (uom)
if (dv.uom == DeviceValueUOM::MINUTES) { if (dv.uom == DeviceValueUOM::MINUTES) {
data.add(nullptr); data.add(nullptr); // use null for time/date
} else { } else {
data.add(uom_to_string(dv.uom)); data.add(uom_to_string(dv.uom));
} }
@@ -583,7 +597,15 @@ bool EMSdevice::generate_values_json_web(JsonObject & json) {
snprintf_P(name, sizeof(name), "(%s) %s", tag_to_string(dv.tag).c_str(), uuid::read_flash_string(dv.full_name).c_str()); snprintf_P(name, sizeof(name), "(%s) %s", tag_to_string(dv.tag).c_str(), uuid::read_flash_string(dv.full_name).c_str());
data.add(name); data.add(name);
} }
num_elements = sz + 2;
// add the name of the Command function if it exists
if (dv.has_cmd) {
data.add(dv.short_name);
} else {
data.add("");
}
num_elements = sz + 3; // increase count by 3
} }
} }
} }
@@ -595,11 +617,12 @@ bool EMSdevice::generate_values_json_web(JsonObject & json) {
// return false if empty // return false if empty
// this is used to create both the MQTT payloads and Console messages (console = true) // this is used to create both the MQTT payloads and Console messages (console = true)
bool EMSdevice::generate_values_json(JsonObject & root, const uint8_t tag_filter, const bool nested, const bool console) { bool EMSdevice::generate_values_json(JsonObject & root, const uint8_t tag_filter, const bool nested, const bool console) {
bool has_value = false; // to see if we've added a value. it's faster than doing a json.size() at the end bool has_values = false; // to see if we've added a value. it's faster than doing a json.size() at the end
uint8_t old_tag = 255; // NAN uint8_t old_tag = 255; // NAN
JsonObject json = root; JsonObject json = root;
for (const auto & dv : devicevalues_) { for (auto & dv : devicevalues_) {
bool has_value = false;
// only show if tag is either empty (TAG_NONE) or matches a value // only show if tag is either empty (TAG_NONE) or matches a value
// and don't show if full_name is empty unless we're outputing for mqtt payloads // and don't show if full_name is empty unless we're outputing for mqtt payloads
// for nested we use all values // for nested we use all values
@@ -731,21 +754,34 @@ bool EMSdevice::generate_values_json(JsonObject & root, const uint8_t tag_filter
} }
} }
} }
dv.ha |= has_value ? DeviceValueHA::HA_VALUE : DeviceValueHA::HA_NONE;
has_values |= has_value;
} }
return has_value; return has_values;
} }
// create the Home Assistant configs for each value // create the Home Assistant configs for each value
// this is called when an MQTT publish is done via an EMS Device, and only done once // this is called when an MQTT publish is done via an EMS Device
void EMSdevice::publish_mqtt_ha_sensor() { void EMSdevice::publish_mqtt_ha_sensor() {
for (const auto & dv : devicevalues_) { for (auto & dv : devicevalues_) {
if (dv.ha == DeviceValueHA::HA_VALUE) {
Mqtt::publish_mqtt_ha_sensor(dv.type, dv.tag, dv.full_name, device_type_, dv.short_name, dv.uom); Mqtt::publish_mqtt_ha_sensor(dv.type, dv.tag, dv.full_name, device_type_, dv.short_name, dv.uom);
dv.ha |= DeviceValueHA::HA_DONE;
} }
}
if (!ha_config_done()) {
bool ok = publish_ha_config(); bool ok = publish_ha_config();
ha_config_done(ok); // see if it worked ha_config_done(ok); // see if it worked
} }
}
void EMSdevice::ha_config_clear() {
for (auto & dv : devicevalues_) {
dv.ha &= ~DeviceValueHA::HA_DONE;
}
ha_config_done(false);
}
// return the name of the telegram type // return the name of the telegram type
std::string EMSdevice::telegram_type_name(std::shared_ptr<const Telegram> telegram) { std::string EMSdevice::telegram_type_name(std::shared_ptr<const Telegram> telegram) {

View File

@@ -141,6 +141,9 @@ enum DeviceValueTAG : uint8_t {
// mqtt flags for command subscriptions // mqtt flags for command subscriptions
enum MqttSubFlag : uint8_t { FLAG_NORMAL = 0, FLAG_HC, FLAG_WWC, FLAG_NOSUB }; enum MqttSubFlag : uint8_t { FLAG_NORMAL = 0, FLAG_HC, FLAG_WWC, FLAG_NOSUB };
// mqtt-HA flags
enum DeviceValueHA : uint8_t { HA_NONE = 0, HA_VALUE, HA_DONE};
class EMSdevice { class EMSdevice {
public: public:
virtual ~EMSdevice() = default; // destructor of base class must always be virtual because it's a polymorphic class virtual ~EMSdevice() = default; // destructor of base class must always be virtual because it's a polymorphic class
@@ -269,16 +272,17 @@ class EMSdevice {
const __FlashStringHelper * const * options, const __FlashStringHelper * const * options,
const __FlashStringHelper * short_name, const __FlashStringHelper * short_name,
const __FlashStringHelper * full_name, const __FlashStringHelper * full_name,
uint8_t uom = DeviceValueUOM::NONE); uint8_t uom,
bool has_cmd = false);
void register_device_value(uint8_t tag, void * value_p, uint8_t type, const __FlashStringHelper * const * options, const __FlashStringHelper * const * name, uint8_t uom, cmdfunction_p f = nullptr);
void register_device_value(uint8_t tag, void * value_p, uint8_t type, const __FlashStringHelper * const * options, const __FlashStringHelper * const * name, uint8_t uom = DeviceValueUOM::NONE);
void write_command(const uint16_t type_id, const uint8_t offset, uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid); void write_command(const uint16_t type_id, const uint8_t offset, uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid);
void write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid); void write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid);
void write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value); void write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value);
void read_command(const uint16_t type_id, uint8_t offset = 0, uint8_t length = 0); void read_command(const uint16_t type_id, uint8_t offset = 0, uint8_t length = 0);
void register_mqtt_topic(const std::string & topic, mqtt_subfunction_p f); void register_mqtt_topic(const std::string & topic, mqtt_subfunction_p f);
void register_mqtt_cmd(const __FlashStringHelper * cmd, cmdfunction_p f, uint8_t flag = 0); void register_cmd(const __FlashStringHelper * cmd, cmdfunction_p f, uint8_t flag = 0);
void publish_mqtt_ha_sensor(); void publish_mqtt_ha_sensor();
@@ -296,6 +300,8 @@ class EMSdevice {
ha_config_done_ = v; ha_config_done_ = v;
} }
void ha_config_clear();
enum Brand : uint8_t { enum Brand : uint8_t {
NO_BRAND = 0, // 0 NO_BRAND = 0, // 0
BOSCH, // 1 BOSCH, // 1
@@ -353,8 +359,8 @@ class EMSdevice {
static constexpr uint8_t EMS_DEVICE_FLAG_EASY = 1; static constexpr uint8_t EMS_DEVICE_FLAG_EASY = 1;
static constexpr uint8_t EMS_DEVICE_FLAG_RC10 = 2; static constexpr uint8_t EMS_DEVICE_FLAG_RC10 = 2;
static constexpr uint8_t EMS_DEVICE_FLAG_RC20 = 3; static constexpr uint8_t EMS_DEVICE_FLAG_RC20 = 3;
static constexpr uint8_t EMS_DEVICE_FLAG_RC20_2 = 4; // Variation on RC20, Older, like ES72 static constexpr uint8_t EMS_DEVICE_FLAG_RC20_N = 4; // Variation on RC20, Older, like ES72
static constexpr uint8_t EMS_DEVICE_FLAG_RC30_1 = 5; // variation on RC30, Newer models static constexpr uint8_t EMS_DEVICE_FLAG_RC30_N = 5; // variation on RC30, Newer models
static constexpr uint8_t EMS_DEVICE_FLAG_RC30 = 6; static constexpr uint8_t EMS_DEVICE_FLAG_RC30 = 6;
static constexpr uint8_t EMS_DEVICE_FLAG_RC35 = 7; static constexpr uint8_t EMS_DEVICE_FLAG_RC35 = 7;
static constexpr uint8_t EMS_DEVICE_FLAG_RC300 = 8; static constexpr uint8_t EMS_DEVICE_FLAG_RC300 = 8;
@@ -406,6 +412,8 @@ class EMSdevice {
const __FlashStringHelper * short_name; // used in MQTT const __FlashStringHelper * short_name; // used in MQTT
const __FlashStringHelper * full_name; // used in Web and Console const __FlashStringHelper * full_name; // used in Web and Console
uint8_t uom; // DeviceValueUOM::* uint8_t uom; // DeviceValueUOM::*
uint8_t ha; // DevcieValueHA::
bool has_cmd; // true if there is a Console/MQTT command which matches the short_name
DeviceValue(uint8_t device_type, DeviceValue(uint8_t device_type,
uint8_t tag, uint8_t tag,
@@ -415,7 +423,9 @@ class EMSdevice {
uint8_t options_size, uint8_t options_size,
const __FlashStringHelper * short_name, const __FlashStringHelper * short_name,
const __FlashStringHelper * full_name, const __FlashStringHelper * full_name,
uint8_t uom) uint8_t uom,
uint8_t ha,
bool has_cmd)
: device_type(device_type) : device_type(device_type)
, tag(tag) , tag(tag)
, value_p(value_p) , value_p(value_p)
@@ -424,7 +434,9 @@ class EMSdevice {
, options_size(options_size) , options_size(options_size)
, short_name(short_name) , short_name(short_name)
, full_name(full_name) , full_name(full_name)
, uom(uom) { , uom(uom)
, ha(ha)
, has_cmd(has_cmd) {
} }
}; };
const std::vector<DeviceValue> devicevalues() const; const std::vector<DeviceValue> devicevalues() const;

View File

@@ -423,7 +423,7 @@ void EMSESP::reset_mqtt_ha() {
} }
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
emsdevice->ha_config_done(false); emsdevice->ha_config_clear();
} }
dallassensor_.reload(); dallassensor_.reload();
} }
@@ -440,8 +440,8 @@ void EMSESP::publish_device_values(uint8_t device_type) {
// group by device type // group by device type
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice && (emsdevice->device_type() == device_type)) { if (emsdevice && (emsdevice->device_type() == device_type)) {
// if we're using HA and it's not already done, send the config topics first. only do this once // if we're using HA, if done is checked for each sensor in devices
if (Mqtt::ha_enabled() && (!emsdevice->ha_config_done())) { if (Mqtt::ha_enabled()) {
emsdevice->publish_mqtt_ha_sensor(); // create the configs for each value as a sensor emsdevice->publish_mqtt_ha_sensor(); // create the configs for each value as a sensor
} }

View File

@@ -61,7 +61,7 @@
#define EMSESP_JSON_SIZE_MEDIUM_DYN 1024 // for large json docs, using DynamicJsonDocument #define EMSESP_JSON_SIZE_MEDIUM_DYN 1024 // for large json docs, using DynamicJsonDocument
#define EMSESP_JSON_SIZE_LARGE_DYN 2048 // for very large json docs, using DynamicJsonDocument #define EMSESP_JSON_SIZE_LARGE_DYN 2048 // for very large json docs, using DynamicJsonDocument
#define EMSESP_JSON_SIZE_XLARGE_DYN 4096 // for very very large json docs, using DynamicJsonDocument #define EMSESP_JSON_SIZE_XLARGE_DYN 4096 // for very very large json docs, using DynamicJsonDocument
#define EMSESP_JSON_SIZE_XXLARGE_DYN 5120 // for extra very very large json docs, using DynamicJsonDocument #define EMSESP_JSON_SIZE_XXLARGE_DYN 8192 // for extra very very large json docs, using DynamicJsonDocument
// helpers for callback functions // helpers for callback functions
#define MAKE_PF_CB(__f) [&](std::shared_ptr<const Telegram> t) { __f(t); } // for process function callbacks to register_telegram_type() #define MAKE_PF_CB(__f) [&](std::shared_ptr<const Telegram> t) { __f(t); } // for process function callbacks to register_telegram_type()

View File

@@ -184,10 +184,10 @@ MAKE_PSTR_WORD(heat)
MAKE_PSTR_WORD(hold) MAKE_PSTR_WORD(hold)
MAKE_PSTR_WORD(cool) MAKE_PSTR_WORD(cool)
MAKE_PSTR_WORD(end) MAKE_PSTR_WORD(end)
MAKE_PSTR_WORD(German) MAKE_PSTR_WORD(german)
MAKE_PSTR_WORD(Dutch) MAKE_PSTR_WORD(dutch)
MAKE_PSTR_WORD(French) MAKE_PSTR_WORD(french)
MAKE_PSTR_WORD(Italian) MAKE_PSTR_WORD(italian)
MAKE_PSTR_WORD(high) MAKE_PSTR_WORD(high)
MAKE_PSTR_WORD(low) MAKE_PSTR_WORD(low)
MAKE_PSTR_WORD(radiator) MAKE_PSTR_WORD(radiator)
@@ -196,7 +196,7 @@ MAKE_PSTR_WORD(floor)
MAKE_PSTR_WORD(summer) MAKE_PSTR_WORD(summer)
MAKE_PSTR_WORD(winter) MAKE_PSTR_WORD(winter)
MAKE_PSTR_WORD(outdoor) MAKE_PSTR_WORD(outdoor)
MAKE_PSTR_WORD(MPC) MAKE_PSTR_WORD(mpc)
MAKE_PSTR_WORD(room) MAKE_PSTR_WORD(room)
MAKE_PSTR_WORD(power) MAKE_PSTR_WORD(power)
MAKE_PSTR_WORD(constant) MAKE_PSTR_WORD(constant)
@@ -208,19 +208,27 @@ MAKE_PSTR_WORD(night)
MAKE_PSTR_WORD(day) MAKE_PSTR_WORD(day)
MAKE_PSTR_WORD(holiday) MAKE_PSTR_WORD(holiday)
MAKE_PSTR_WORD(reduce) MAKE_PSTR_WORD(reduce)
MAKE_PSTR_WORD(RC3x) MAKE_PSTR_WORD(noreduce)
MAKE_PSTR_WORD(RC20) MAKE_PSTR_WORD(offset)
MAKE_PSTR_WORD(design)
MAKE_PSTR_WORD(tempauto)
MAKE_PSTR_WORD(minflow)
MAKE_PSTR_WORD(maxflow)
MAKE_PSTR_WORD(rc3x)
MAKE_PSTR_WORD(rc20)
MAKE_PSTR_WORD(error)
MAKE_PSTR(internal_temperature, "internal temperature") MAKE_PSTR(internal_temperature, "internal temperature")
MAKE_PSTR(internal_setpoint, "internal setpoint") MAKE_PSTR(internal_setpoint, "internal setpoint")
MAKE_PSTR(external_temperature, "external temperature") MAKE_PSTR(external_temperature, "external temperature")
MAKE_PSTR(burner_temperature, "burner temperature") MAKE_PSTR(burner_temperature, "burner temperature")
MAKE_PSTR(WW_temperature, "WW temperature") MAKE_PSTR(ww_temperature, "ww temperature")
MAKE_PSTR(functioning_mode, "functioning mode") 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(enum_ibaMainDisplay, F_(internal_temperature), F_(internal_setpoint), F_(external_temperature), F_(burner_temperature), F_(WW_temperature), F_(functioning_mode), F_(time), F_(date), F_(smoke_temperature)) MAKE_PSTR_LIST(enum_ibaMainDisplay, F_(internal_temperature), F_(internal_setpoint), F_(external_temperature), F_(burner_temperature), F_(ww_temperature), F_(functioning_mode), F_(time), F_(date), 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_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_(blank), F_(light), F_(medium), F_(heavy)) // RC300 MAKE_PSTR_LIST(enum_ibaBuildingType, F_(blank), F_(light), F_(medium), F_(heavy)) // RC300
MAKE_PSTR_LIST(enum_wwMode, F_(off), F_(low), F_(high), F_(auto), F_(own_prog)) MAKE_PSTR_LIST(enum_wwMode, F_(off), F_(low), F_(high), F_(auto), F_(own_prog))
@@ -243,9 +251,9 @@ MAKE_PSTR_LIST(enum_modetype4, F_(blank), F_(nofrost), F_(eco), F_(heat))
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_controlmode, F_(off), F_(outdoor), F_(simple), F_(MPC), F_(room), F_(power), F_(constant)) MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(outdoor), 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))
MAKE_PSTR_LIST(enum_control, F_(off), F_(RC20), F_(RC3x)) MAKE_PSTR_LIST(enum_control, F_(off), F_(rc20), F_(rc3x))
MAKE_PSTR_LIST(enum_hamode, F_(off), F_(heat), F_(auto), F_(heat), F_(off), F_(heat), F_(auto), F_(auto), F_(auto), F_(auto)) MAKE_PSTR_LIST(enum_hamode, F_(off), F_(heat), F_(auto), F_(heat), F_(off), F_(heat), F_(auto), F_(auto), F_(auto), F_(auto))
@@ -255,16 +263,14 @@ MAKE_PSTR_LIST(enum_hamode, F_(off), F_(heat), F_(auto), F_(heat), F_(off), F_(h
// Boiler // Boiler
// extra commands // extra commands
MAKE_PSTR(wwtapactivated, "wwtapactivated") MAKE_PSTR_LIST(wwtapactivated, F("wwtapactivated"))
MAKE_PSTR(maintenance, "maintenance") MAKE_PSTR_LIST(reset, F("reset"))
MAKE_PSTR(error, "error")
MAKE_PSTR(reset, "reset")
// single mqtt topics // single mqtt topics
MAKE_PSTR(heating_active, "heating_active") MAKE_PSTR(heating_active, "heating_active")
MAKE_PSTR(tapwater_active, "tapwater_active") MAKE_PSTR(tapwater_active, "tapwater_active")
// mqtt, commands and text // mqtt, commands and text
// MAKE_PSTR_LIST(id, F("id"), F("id"))
MAKE_PSTR_LIST(burnPeriod, F("burnperiod"), F("min burner periode"))
MAKE_PSTR_LIST(heatingActive, F("heatingactive"), F("heating active")) MAKE_PSTR_LIST(heatingActive, F("heatingactive"), F("heating active"))
MAKE_PSTR_LIST(tapwaterActive, F("tapwateractive"), F("warm water active")) MAKE_PSTR_LIST(tapwaterActive, F("tapwateractive"), F("warm water active"))
MAKE_PSTR_LIST(selFlowTemp, F("selflowtemp"), F("selected flow temperature")) MAKE_PSTR_LIST(selFlowTemp, F("selflowtemp"), F("selected flow temperature"))
@@ -272,7 +278,7 @@ MAKE_PSTR_LIST(selBurnPow, F("selburnpow"), F("burner selected max power"))
MAKE_PSTR_LIST(heatingPumpMod, F("heatingpumpmod"), F("heating pump modulation")) MAKE_PSTR_LIST(heatingPumpMod, F("heatingpumpmod"), F("heating pump modulation"))
MAKE_PSTR_LIST(heatingPump2Mod, F("heatingpump2mod"), F("heating pump 2 modulation")) MAKE_PSTR_LIST(heatingPump2Mod, F("heatingpump2mod"), F("heating pump 2 modulation"))
MAKE_PSTR_LIST(outdoorTemp, F("outdoortemp"), F("outside temperature")) MAKE_PSTR_LIST(outdoorTemp, F("outdoortemp"), F("outside temperature"))
MAKE_PSTR_LIST(curFlowTemp, F("curFlowtemp"), F("current flow temperature")) MAKE_PSTR_LIST(curFlowTemp, F("curflowtemp"), F("current flow temperature"))
MAKE_PSTR_LIST(retTemp, F("rettemp"), F("return temperature")) MAKE_PSTR_LIST(retTemp, F("rettemp"), F("return temperature"))
MAKE_PSTR_LIST(switchTemp, F("switchtemp"), F("mixing switch temperature")) MAKE_PSTR_LIST(switchTemp, F("switchtemp"), F("mixing switch temperature"))
MAKE_PSTR_LIST(sysPress, F("syspress"), F("system pressure")) MAKE_PSTR_LIST(sysPress, F("syspress"), F("system pressure"))
@@ -324,15 +330,15 @@ MAKE_PSTR_LIST(auxElecHeatNrgConsHeating, F("auxelecheatnrgconsheating"), F("aux
MAKE_PSTR_LIST(auxElecHeatNrgConsDHW, F("auxelecheatnrgconsww"), F("auxiliary electrical heater energy consumption DHW")) MAKE_PSTR_LIST(auxElecHeatNrgConsDHW, F("auxelecheatnrgconsww"), F("auxiliary electrical heater energy consumption DHW"))
MAKE_PSTR_LIST(maintenanceMessage, F("maintenancemessage"), F("maintenance message")) MAKE_PSTR_LIST(maintenanceMessage, F("maintenancemessage"), F("maintenance message"))
MAKE_PSTR_LIST(maintenanceDate, F("maintenancedate"), F("maintenance set date")) MAKE_PSTR_LIST(maintenanceDate, F("maintenancedate"), F("maintenance set date"))
MAKE_PSTR_LIST(maintenanceType, F("maintenancetype"), F("maintenance scheduled")) MAKE_PSTR_LIST(maintenance, F("maintenance"), F("maintenance scheduled"))
MAKE_PSTR_LIST(maintenanceTime, F("maintenancetime"), F("maintenance set time")) MAKE_PSTR_LIST(maintenanceTime, F("maintenancetime"), F("maintenance set time"))
MAKE_PSTR_LIST(wWSelTemp, F("wwseltemp"), F("selected temperature")) MAKE_PSTR_LIST(wWSelTemp, F("wwseltemp"), F("selected temperature"))
MAKE_PSTR_LIST(wWSetTemp, F("wwsettemp"), F("set temperature")) MAKE_PSTR_LIST(wWSetTemp, F("wwsettemp"), F("set temperature"))
MAKE_PSTR_LIST(wWType, F("wwtype"), F("type")) MAKE_PSTR_LIST(wWType, F("wwtype"), F("type"))
MAKE_PSTR_LIST(wWComfort, F("wwcomfort"), F("comfort")) MAKE_PSTR_LIST(wWComfort, F("wwcomfort"), F("comfort"))
MAKE_PSTR_LIST(wWFlowTempOffset, F("wwFlowtempoffset"), F("flow temperature offset")) MAKE_PSTR_LIST(wWFlowTempOffset, F("wwflowtempoffset"), F("flow temperature offset"))
MAKE_PSTR_LIST(wWMaxPower, F("wwMaxpower"), F("max power")) MAKE_PSTR_LIST(wWMaxPower, F("wwmaxpower"), F("max power"))
MAKE_PSTR_LIST(wWCircPump, F("wwcircpump"), F("circulation pump available")) MAKE_PSTR_LIST(wWCircPump, F("wwcircpump"), F("circulation pump available"))
MAKE_PSTR_LIST(wWChargeType, F("wwchargetype"), F("charging type")) MAKE_PSTR_LIST(wWChargeType, F("wwchargetype"), F("charging type"))
MAKE_PSTR_LIST(wWDisinfectionTemp, F("wwdisinfectiontemp"), F("disinfection temperature")) MAKE_PSTR_LIST(wWDisinfectionTemp, F("wwdisinfectiontemp"), F("disinfection temperature"))
@@ -344,29 +350,27 @@ MAKE_PSTR_LIST(wWCurFlow, F("wwcurflow"), F("current tap water flow"))
MAKE_PSTR_LIST(wWStorageTemp1, F("wwstoragetemp1"), F("storage intern temperature")) MAKE_PSTR_LIST(wWStorageTemp1, F("wwstoragetemp1"), F("storage intern temperature"))
MAKE_PSTR_LIST(wWStorageTemp2, F("wwstoragetemp2"), F("storage extern temperature")) MAKE_PSTR_LIST(wWStorageTemp2, F("wwstoragetemp2"), F("storage extern temperature"))
MAKE_PSTR_LIST(wWActivated, F("wwactivated"), F("activated")) MAKE_PSTR_LIST(wWActivated, F("wwactivated"), F("activated"))
MAKE_PSTR_LIST(wWOneTime, F("wwOnetime"), F("one time charging")) MAKE_PSTR_LIST(wWOneTime, F("wwonetime"), F("one time charging"))
MAKE_PSTR_LIST(wWDisinfecting, F("wwdisinfecting"), F("disinfecting")) MAKE_PSTR_LIST(wWDisinfecting, F("wwdisinfecting"), F("disinfecting"))
MAKE_PSTR_LIST(wWCharging, F("wwcharging"), F("charging")) MAKE_PSTR_LIST(wWCharging, F("wwcharging"), F("charging"))
MAKE_PSTR_LIST(wWRecharging, F("wwrecharging"), F("recharging")) MAKE_PSTR_LIST(wWRecharging, F("wwrecharging"), F("recharging"))
MAKE_PSTR_LIST(wWTempOK, F("wwtempok"), F("temperature ok")) MAKE_PSTR_LIST(wWTempOK, F("wwtempok"), F("temperature ok"))
MAKE_PSTR_LIST(wWActive, F("wwactive"), F("active")) MAKE_PSTR_LIST(wWActive, F("wwactive"), F("active"))
MAKE_PSTR_LIST(wWHeat, F("wwHeat"), F("heating")) MAKE_PSTR_LIST(wWHeat, F("wwHeat"), F("heating"))
MAKE_PSTR_LIST(wWSetPumpPower, F("wWSetPumpPower"), F("pump set power")) MAKE_PSTR_LIST(wWSetPumpPower, F("wwsetpumppower"), F("pump set power"))
MAKE_PSTR_LIST(mixerTemp, F("mixerTemp"), F("mixer temperature")) MAKE_PSTR_LIST(mixerTemp, F("mixertemp"), F("mixer temperature"))
MAKE_PSTR_LIST(tankMiddleTemp, F("tankMiddleTemp"), F("tank middle temperature (TS3)")) MAKE_PSTR_LIST(tankMiddleTemp, F("tankmiddletemp"), F("tank 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 starts"))
MAKE_PSTR_LIST(wWWorkM, F("wwworkm"), F("active time")) MAKE_PSTR_LIST(wWWorkM, F("wwworkm"), F("active time"))
// thermostat // thermostat
// extra commands // extra commands, not published yet
MAKE_PSTR(remoteTemp, "remotetemp") MAKE_PSTR_LIST(remoteTemp, F("remotetemp"), F("remotetemp"))
MAKE_PSTR(pause, "pause") MAKE_PSTR_LIST(switchtime, F("switchtime"), F("switchtime"))
MAKE_PSTR(party, "party") MAKE_PSTR_LIST(temp, F("temp"), F("temporary set temperature"))
MAKE_PSTR(switchtime, "switchtime")
MAKE_PSTR(temp, "temp")
// mqtt values / commands
MAKE_PSTR_LIST(dateTime, F("datetime"), F("date/time")) MAKE_PSTR_LIST(dateTime, F("datetime"), F("date/time"))
MAKE_PSTR_LIST(errorCode, F("errorcode"), F("error code")) MAKE_PSTR_LIST(errorCode, F("errorcode"), F("error code"))
@@ -387,11 +391,10 @@ MAKE_PSTR_LIST(floordrytemp, F("floordrytemp"), F("floor drying temperature"))
MAKE_PSTR_LIST(wwMode, F("wwmode"), F("warm water mode")) MAKE_PSTR_LIST(wwMode, F("wwmode"), F("warm water mode"))
MAKE_PSTR_LIST(wwSetTemp, F("wwsettemp"), F("warm water set temperature")) MAKE_PSTR_LIST(wwSetTemp, F("wwsettemp"), F("warm water set temperature"))
MAKE_PSTR_LIST(wwSetTempLow, F("wwsettemplow"), F("warm water set temperature low")) MAKE_PSTR_LIST(wwSetTempLow, F("wwsettemplow"), F("warm water set temperature low"))
// MAKE_PSTR_LIST(wwCircMode, F("wwcircmode"), F("warm water circulation mode"))
MAKE_PSTR_LIST(wwExtra1, F("wwextra1"), F("warm water circuit 1 extra")) MAKE_PSTR_LIST(wwExtra1, F("wwextra1"), F("warm water circuit 1 extra"))
MAKE_PSTR_LIST(wwExtra2, F("wwextra2"), F("warm water circuit 2 extra")) MAKE_PSTR_LIST(wwExtra2, F("wwextra2"), F("warm water circuit 2 extra"))
MAKE_PSTR_LIST(setpoint_roomTemp, F("seltemp"), F("setpoint room temperature")) MAKE_PSTR_LIST(setpoint_roomTemp, F("seltemp"), F("selected room temperature"))
MAKE_PSTR_LIST(curr_roomTemp, F("currtemp"), F("current room temperature")) MAKE_PSTR_LIST(curr_roomTemp, F("currtemp"), F("current room temperature"))
MAKE_PSTR_LIST(mode, F("mode"), F("mode")) MAKE_PSTR_LIST(mode, F("mode"), F("mode"))
@@ -402,6 +405,7 @@ MAKE_PSTR_LIST(heattemp, F("heattemp"), F("heat temperature"))
MAKE_PSTR_LIST(nighttemp, F("nighttemp"), F("night temperature")) MAKE_PSTR_LIST(nighttemp, F("nighttemp"), F("night temperature"))
MAKE_PSTR_LIST(ecotemp, F("ecotemp"), F("eco temperature")) MAKE_PSTR_LIST(ecotemp, F("ecotemp"), F("eco temperature"))
MAKE_PSTR_LIST(manualtemp, F("manualtemp"), F("manual temperature")) MAKE_PSTR_LIST(manualtemp, F("manualtemp"), F("manual temperature"))
MAKE_PSTR_LIST(tempautotemp, F("tempautotemp"), F("temporary room temperature automode"))
MAKE_PSTR_LIST(comforttemp, F("comforttemp"), F("comfort temperature")) MAKE_PSTR_LIST(comforttemp, F("comforttemp"), F("comfort temperature"))
MAKE_PSTR_LIST(summertemp, F("summertemp"), F("summer temperature")) MAKE_PSTR_LIST(summertemp, F("summertemp"), F("summer temperature"))
MAKE_PSTR_LIST(designtemp, F("designtemp"), F("design temperature")) MAKE_PSTR_LIST(designtemp, F("designtemp"), F("design temperature"))
@@ -412,16 +416,19 @@ MAKE_PSTR_LIST(roominfluence, F("roominfluence"), F("room influence"))
MAKE_PSTR_LIST(nofrosttemp, F("nofrosttemp"), F("nofrost temperature")) MAKE_PSTR_LIST(nofrosttemp, F("nofrosttemp"), F("nofrost temperature"))
MAKE_PSTR_LIST(targetflowtemp, F("targetflowtemp"), F("target flow temperature")) MAKE_PSTR_LIST(targetflowtemp, F("targetflowtemp"), F("target flow temperature"))
MAKE_PSTR_LIST(heatingtype, F("heatingtype"), F("heating type")) MAKE_PSTR_LIST(heatingtype, F("heatingtype"), F("heating type"))
MAKE_PSTR_LIST(summer_setmode, F("summermode"), F("summer mode")) MAKE_PSTR_LIST(summersetmode, F("summersetmode"), F("summer set mode"))
MAKE_PSTR_LIST(controlmode, F("controlmode"), F("control mode")) MAKE_PSTR_LIST(controlmode, F("controlmode"), F("control mode"))
MAKE_PSTR_LIST(control, F("control"), F("control device")) MAKE_PSTR_LIST(control, F("control"), F("control device"))
MAKE_PSTR_LIST(program, F("program"), F("program")) MAKE_PSTR_LIST(program, F("program"), F("program"))
MAKE_PSTR_LIST(pause, F("pause"), F("pause time"))
MAKE_PSTR_LIST(party, F("party"), F("party time"))
MAKE_PSTR_LIST(holidaytemp, F("holidaytemp"), F("holiday temperature")) MAKE_PSTR_LIST(holidaytemp, F("holidaytemp"), F("holiday temperature"))
MAKE_PSTR_LIST(summermode, F("summermode"), F("summer mode")) MAKE_PSTR_LIST(summermode, F("summermode"), F("summer mode"))
MAKE_PSTR_LIST(holidaymode, F("holidaymode"), F("holiday mode")) MAKE_PSTR_LIST(holidaymode, F("holidaymode"), F("holiday mode"))
MAKE_PSTR_LIST(flowtempoffset, F("flowtempoffset"), F("flow temperature offset")) MAKE_PSTR_LIST(flowtempoffset, F("flowtempoffset"), F("flow temperature offset"))
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"))
// heatpump // heatpump
MAKE_PSTR_LIST(airHumidity, F("airhumidity"), F("relative air humidity")) MAKE_PSTR_LIST(airHumidity, F("airhumidity"), F("relative air humidity"))
@@ -436,30 +443,28 @@ MAKE_PSTR_LIST(flowTempVf, F("flowtempvf"), F("flow temperature in header (T0/Vf
MAKE_PSTR_LIST(tempStatus, F("tempstatus"), F("temperature switch in assigned hc (MC1)")) MAKE_PSTR_LIST(tempStatus, F("tempstatus"), F("temperature switch in assigned hc (MC1)"))
MAKE_PSTR_LIST(wwTemp, F("wwtemp"), F("current warm water temperature")) MAKE_PSTR_LIST(wwTemp, F("wwtemp"), F("current warm water temperature"))
// MAKE_PSTR_LIST(mixertype, F("type"), F("type"))
// solar // solar
MAKE_PSTR_LIST(collectorTemp, F("collectorTemp"), F("collector temperature (TS1)")) MAKE_PSTR_LIST(collectorTemp, F("collectortemp"), F("collector temperature (TS1)"))
MAKE_PSTR_LIST(tankBottomTemp, F("tankBottomTemp"), F("tank bottom temperature (TS2)")) MAKE_PSTR_LIST(tankBottomTemp, F("tankbottomtemp"), F("tank bottom temperature (TS2)"))
MAKE_PSTR_LIST(tank2BottomTemp, F("tank2BottomTemp"), F("second tank bottom temperature (TS5)")) MAKE_PSTR_LIST(tank2BottomTemp, F("tank2bottomtemp"), F("second tank bottom temperature (TS5)"))
MAKE_PSTR_LIST(heatExchangerTemp, F("heatExchangerTemp"), F("heat exchanger temperature (TS6)")) MAKE_PSTR_LIST(heatExchangerTemp, F("heatexchangertemp"), F("heat exchanger temperature (TS6)"))
MAKE_PSTR_LIST(tankMaxTemp, F("tankMaxTemp"), F("maximum tank temperature")) MAKE_PSTR_LIST(tankMaxTemp, F("tankmaxtemp"), F("maximum tank temperature"))
MAKE_PSTR_LIST(solarPumpModulation, F("solarPumpModulation"), F("pump modulation (PS1)")) MAKE_PSTR_LIST(solarPumpModulation, F("solarpumpmodulation"), F("pump modulation (PS1)"))
MAKE_PSTR_LIST(cylinderPumpModulation, F("cylinderPumpModulation"), F("cylinder pump modulation (PS5)")) MAKE_PSTR_LIST(cylinderPumpModulation, F("cylinderpumpmodulation"), F("cylinder pump modulation (PS5)"))
MAKE_PSTR_LIST(solarPump, F("solarPump"), F("pump (PS1)")) MAKE_PSTR_LIST(solarPump, F("solarpump"), F("pump (PS1)"))
MAKE_PSTR_LIST(valveStatus, F("valveStatus"), F("valve status")) MAKE_PSTR_LIST(valveStatus, F("valvestatus"), F("valve status"))
MAKE_PSTR_LIST(tankHeated, F("tankHeated"), F("tank heated")) MAKE_PSTR_LIST(tankHeated, F("tankheated"), F("tank heated"))
MAKE_PSTR_LIST(collectorShutdown, F("collectorShutdown"), F("collector shutdown")) MAKE_PSTR_LIST(collectorShutdown, F("collectorshutdown"), F("collector shutdown"))
MAKE_PSTR_LIST(pumpWorkTime, F("pumpWorkTime"), F("pump working time")) MAKE_PSTR_LIST(pumpWorkTime, F("pumpWorktime"), F("pump 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("energy total"))
MAKE_PSTR_LIST(energyToday, F("energyToday"), F("energy today")) MAKE_PSTR_LIST(energyToday, F("energytoday"), F("energy today"))
// switch // switch
MAKE_PSTR_LIST(activated, F("activated"), F("activated")) MAKE_PSTR_LIST(activated, F("activated"), F("activated"))
// MAKE_PSTR_LIST(flowTempHc, F("flowTempHc"), F("flow temperature in assigned hc (TC1)"))
MAKE_PSTR_LIST(status, F("status"), F("status")) MAKE_PSTR_LIST(status, F("status"), F("status"))

View File

@@ -56,6 +56,7 @@ void Shower::loop() {
if (!shower_on_ && (time_now - timer_start_) > SHOWER_MIN_DURATION) { if (!shower_on_ && (time_now - timer_start_) > SHOWER_MIN_DURATION) {
shower_on_ = true; shower_on_ = true;
send_mqtt_stat(true); send_mqtt_stat(true);
publish_values();
LOG_DEBUG(F("[Shower] hot water still running, starting shower timer")); LOG_DEBUG(F("[Shower] hot water still running, starting shower timer"));
} }
// check if the shower has been on too long // check if the shower has been on too long

View File

@@ -404,8 +404,6 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd) {
run_test("boiler"); run_test("boiler");
DynamicJsonDocument doc(EMSESP_JSON_SIZE_LARGE_DYN);
JsonObject json = doc.to<JsonObject>();
// device type, command, data // device type, command, data
Command::call(EMSdevice::DeviceType::BOILER, "wwtapactivated", "false"); Command::call(EMSdevice::DeviceType::BOILER, "wwtapactivated", "false");
} }

View File

@@ -1,2 +1,2 @@
#define EMSESP_APP_VERSION "3.0.2b1" #define EMSESP_APP_VERSION "3.0.3b1"
#define EMSESP_PLATFORM "ESP32" #define EMSESP_PLATFORM "ESP32"