mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
MQTT Formatting payload (nested vs single) is a pull-down option
This commit is contained in:
@@ -1,11 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
- Mock API to simulate an ESP, for testing web
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
- Icon for Network
|
||||||
|
- 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
|
||||||
|
|
||||||
## Removed
|
## Removed
|
||||||
|
|||||||
@@ -1,22 +1,31 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import { TextValidator, ValidatorForm, SelectValidator } from 'react-material-ui-form-validator';
|
import {
|
||||||
|
TextValidator,
|
||||||
|
ValidatorForm,
|
||||||
|
SelectValidator,
|
||||||
|
} from "react-material-ui-form-validator";
|
||||||
|
|
||||||
import { Checkbox, TextField, Typography } from '@material-ui/core';
|
import { Checkbox, TextField, Typography } from "@material-ui/core";
|
||||||
import SaveIcon from '@material-ui/icons/Save';
|
import SaveIcon from "@material-ui/icons/Save";
|
||||||
import MenuItem from '@material-ui/core/MenuItem';
|
import MenuItem from "@material-ui/core/MenuItem";
|
||||||
|
|
||||||
import { RestFormProps, FormActions, FormButton, BlockFormControlLabel, PasswordValidator } from '../components';
|
import {
|
||||||
import { isIP, isHostname, or, isPath } from '../validators';
|
RestFormProps,
|
||||||
|
FormActions,
|
||||||
|
FormButton,
|
||||||
|
BlockFormControlLabel,
|
||||||
|
PasswordValidator,
|
||||||
|
} from "../components";
|
||||||
|
import { isIP, isHostname, or, isPath } from "../validators";
|
||||||
|
|
||||||
import { MqttSettings } from './types';
|
import { MqttSettings } from "./types";
|
||||||
|
|
||||||
type MqttSettingsFormProps = RestFormProps<MqttSettings>;
|
type MqttSettingsFormProps = RestFormProps<MqttSettings>;
|
||||||
|
|
||||||
class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
|
class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
ValidatorForm.addValidationRule('isIPOrHostname', or(isIP, isHostname));
|
ValidatorForm.addValidationRule("isIPOrHostname", or(isIP, isHostname));
|
||||||
ValidatorForm.addValidationRule('isPath', isPath);
|
ValidatorForm.addValidationRule("isPath", isPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -27,44 +36,57 @@ class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
|
|||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={data.enabled}
|
checked={data.enabled}
|
||||||
onChange={handleValueChange('enabled')}
|
onChange={handleValueChange("enabled")}
|
||||||
value="enabled"
|
value="enabled"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label="Enable MQTT"
|
label="Enable MQTT"
|
||||||
/>
|
/>
|
||||||
<TextValidator
|
<TextValidator
|
||||||
validators={['required', 'isIPOrHostname']}
|
validators={["required", "isIPOrHostname"]}
|
||||||
errorMessages={['Host is required', "Not a valid IP address or hostname"]}
|
errorMessages={[
|
||||||
|
"Host is required",
|
||||||
|
"Not a valid IP address or hostname",
|
||||||
|
]}
|
||||||
name="host"
|
name="host"
|
||||||
label="Host"
|
label="Host"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.host}
|
value={data.host}
|
||||||
onChange={handleValueChange('host')}
|
onChange={handleValueChange("host")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<TextValidator
|
<TextValidator
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
|
validators={[
|
||||||
errorMessages={['Port is required', "Must be a number", "Must be greater than 0 ", "Max value is 65535"]}
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:65535",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"Port is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be greater than 0 ",
|
||||||
|
"Max value is 65535",
|
||||||
|
]}
|
||||||
name="port"
|
name="port"
|
||||||
label="Port"
|
label="Port"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.port}
|
value={data.port}
|
||||||
type="number"
|
type="number"
|
||||||
onChange={handleValueChange('port')}
|
onChange={handleValueChange("port")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<TextValidator
|
<TextValidator
|
||||||
validators={['required', 'isPath']}
|
validators={["required", "isPath"]}
|
||||||
errorMessages={['Base is required', "Not a valid Path"]}
|
errorMessages={["Base is required", "Not a valid Path"]}
|
||||||
name="base"
|
name="base"
|
||||||
label="Base"
|
label="Base"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.base}
|
value={data.base}
|
||||||
onChange={handleValueChange('base')}
|
onChange={handleValueChange("base")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
@@ -73,7 +95,7 @@ class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
|
|||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.username}
|
value={data.username}
|
||||||
onChange={handleValueChange('username')}
|
onChange={handleValueChange("username")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<PasswordValidator
|
<PasswordValidator
|
||||||
@@ -82,7 +104,7 @@ class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
|
|||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.password}
|
value={data.password}
|
||||||
onChange={handleValueChange('password')}
|
onChange={handleValueChange("password")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
@@ -91,28 +113,40 @@ class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
|
|||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.client_id}
|
value={data.client_id}
|
||||||
onChange={handleValueChange('client_id')}
|
onChange={handleValueChange("client_id")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<TextValidator
|
<TextValidator
|
||||||
validators={['required', 'isNumber', 'minNumber:1', 'maxNumber:65535']}
|
validators={[
|
||||||
errorMessages={['Keep alive is required', "Must be a number", "Must be greater than 0", "Max value is 65535"]}
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:1",
|
||||||
|
"maxNumber:65535",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"Keep alive is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be greater than 0",
|
||||||
|
"Max value is 65535",
|
||||||
|
]}
|
||||||
name="keep_alive"
|
name="keep_alive"
|
||||||
label="Keep Alive (seconds)"
|
label="Keep Alive (seconds)"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.keep_alive}
|
value={data.keep_alive}
|
||||||
type="number"
|
type="number"
|
||||||
onChange={handleValueChange('keep_alive')}
|
onChange={handleValueChange("keep_alive")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<SelectValidator name="mqtt_qos"
|
<SelectValidator
|
||||||
|
name="mqtt_qos"
|
||||||
label="QoS"
|
label="QoS"
|
||||||
value={data.mqtt_qos}
|
value={data.mqtt_qos}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={handleValueChange('mqtt_qos')}
|
onChange={handleValueChange("mqtt_qos")}
|
||||||
margin="normal">
|
margin="normal"
|
||||||
|
>
|
||||||
<MenuItem value={0}>0 (default)</MenuItem>
|
<MenuItem value={0}>0 (default)</MenuItem>
|
||||||
<MenuItem value={1}>1</MenuItem>
|
<MenuItem value={1}>1</MenuItem>
|
||||||
<MenuItem value={2}>2</MenuItem>
|
<MenuItem value={2}>2</MenuItem>
|
||||||
@@ -121,7 +155,7 @@ class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
|
|||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={data.clean_session}
|
checked={data.clean_session}
|
||||||
onChange={handleValueChange('clean_session')}
|
onChange={handleValueChange("clean_session")}
|
||||||
value="clean_session"
|
value="clean_session"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
@@ -131,55 +165,63 @@ class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
|
|||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={data.mqtt_retain}
|
checked={data.mqtt_retain}
|
||||||
onChange={handleValueChange('mqtt_retain')}
|
onChange={handleValueChange("mqtt_retain")}
|
||||||
value="mqtt_retain"
|
value="mqtt_retain"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label="Retain Flag"
|
label="Retain Flag"
|
||||||
/>
|
/>
|
||||||
<br></br>
|
<br></br>
|
||||||
<Typography variant="h6" color="primary" >
|
<Typography variant="h6" color="primary">
|
||||||
Formatting
|
Formatting
|
||||||
</Typography>
|
</Typography>
|
||||||
<BlockFormControlLabel
|
<SelectValidator
|
||||||
control={
|
name="nested_format"
|
||||||
<Checkbox
|
label="Topic/Payload Format"
|
||||||
checked={data.nested_format}
|
value={data.nested_format}
|
||||||
onChange={handleValueChange('nested_format')}
|
fullWidth
|
||||||
value="nested_format"
|
variant="outlined"
|
||||||
/>
|
onChange={handleValueChange("nested_format")}
|
||||||
}
|
margin="normal"
|
||||||
label="Nested format (Thermostat & Mixer only)"
|
>
|
||||||
/>
|
<MenuItem value={1}>nested on a single topic</MenuItem>
|
||||||
<SelectValidator name="dallas_format"
|
<MenuItem value={2}>as individual topics</MenuItem>
|
||||||
|
</SelectValidator>
|
||||||
|
<SelectValidator
|
||||||
|
name="dallas_format"
|
||||||
label="Dallas Sensor Payload Grouping"
|
label="Dallas Sensor Payload Grouping"
|
||||||
value={data.dallas_format}
|
value={data.dallas_format}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={handleValueChange('dallas_format')}
|
onChange={handleValueChange("dallas_format")}
|
||||||
margin="normal">
|
margin="normal"
|
||||||
|
>
|
||||||
<MenuItem value={1}>by Sensor ID</MenuItem>
|
<MenuItem value={1}>by Sensor ID</MenuItem>
|
||||||
<MenuItem value={2}>by Number</MenuItem>
|
<MenuItem value={2}>by Number</MenuItem>
|
||||||
</SelectValidator>
|
</SelectValidator>
|
||||||
<SelectValidator name="bool_format"
|
<SelectValidator
|
||||||
|
name="bool_format"
|
||||||
label="Boolean Format"
|
label="Boolean Format"
|
||||||
value={data.bool_format}
|
value={data.bool_format}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={handleValueChange('bool_format')}
|
onChange={handleValueChange("bool_format")}
|
||||||
margin="normal">
|
margin="normal"
|
||||||
|
>
|
||||||
<MenuItem value={1}>"on"/"off"</MenuItem>
|
<MenuItem value={1}>"on"/"off"</MenuItem>
|
||||||
<MenuItem value={2}>true/false</MenuItem>
|
<MenuItem value={2}>true/false</MenuItem>
|
||||||
<MenuItem value={3}>1/0</MenuItem>
|
<MenuItem value={3}>1/0</MenuItem>
|
||||||
<MenuItem value={4}>"ON"/"OFF"</MenuItem>
|
<MenuItem value={4}>"ON"/"OFF"</MenuItem>
|
||||||
</SelectValidator>
|
</SelectValidator>
|
||||||
<SelectValidator name="subscribe_format"
|
<SelectValidator
|
||||||
|
name="subscribe_format"
|
||||||
label="Subscribe Format"
|
label="Subscribe Format"
|
||||||
value={data.subscribe_format}
|
value={data.subscribe_format}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={handleValueChange('subscribe_format')}
|
onChange={handleValueChange("subscribe_format")}
|
||||||
margin="normal">
|
margin="normal"
|
||||||
|
>
|
||||||
<MenuItem value={0}>general device topic</MenuItem>
|
<MenuItem value={0}>general device topic</MenuItem>
|
||||||
<MenuItem value={1}>individual topics, main heating circuit</MenuItem>
|
<MenuItem value={1}>individual topics, main heating circuit</MenuItem>
|
||||||
<MenuItem value={2}>individual topics, all heating circuits</MenuItem>
|
<MenuItem value={2}>individual topics, all heating circuits</MenuItem>
|
||||||
@@ -188,103 +230,170 @@ class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
|
|||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={data.ha_enabled}
|
checked={data.ha_enabled}
|
||||||
onChange={handleValueChange('ha_enabled')}
|
onChange={handleValueChange("ha_enabled")}
|
||||||
value="ha_enabled"
|
value="ha_enabled"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label="Home Assistant MQTT Discovery"
|
label="Use Home Assistant MQTT Discovery"
|
||||||
/>
|
/>
|
||||||
{ data.ha_enabled &&
|
{data.ha_enabled && (
|
||||||
<SelectValidator name="ha_climate_format"
|
<SelectValidator
|
||||||
|
name="ha_climate_format"
|
||||||
label="Thermostat Room Temperature"
|
label="Thermostat Room Temperature"
|
||||||
value={data.ha_climate_format}
|
value={data.ha_climate_format}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={handleValueChange('ha_climate_format')}
|
onChange={handleValueChange("ha_climate_format")}
|
||||||
margin="normal">
|
margin="normal"
|
||||||
|
>
|
||||||
<MenuItem value={1}>use Current temperature (default)</MenuItem>
|
<MenuItem value={1}>use Current temperature (default)</MenuItem>
|
||||||
<MenuItem value={2}>use Setpoint temperature</MenuItem>
|
<MenuItem value={2}>use Setpoint temperature</MenuItem>
|
||||||
<MenuItem value={3}>Fix to 0</MenuItem>
|
<MenuItem value={3}>Fix to 0</MenuItem>
|
||||||
</SelectValidator>
|
</SelectValidator>
|
||||||
}
|
)}
|
||||||
<br></br>
|
<br></br>
|
||||||
<Typography variant="h6" color="primary" >
|
<Typography variant="h6" color="primary">
|
||||||
Publish Intervals
|
Publish Intervals
|
||||||
</Typography>
|
</Typography>
|
||||||
<TextValidator
|
<TextValidator
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
|
validators={[
|
||||||
errorMessages={['Publish time is required', "Must be a number", "Must be 0 or greater", "Max value is 65535"]}
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:65535",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"Publish time is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or greater",
|
||||||
|
"Max value is 65535",
|
||||||
|
]}
|
||||||
name="publish_time_boiler"
|
name="publish_time_boiler"
|
||||||
label="Boiler Publish Interval (seconds, 0=on change)"
|
label="Boiler Publish Interval (seconds, 0=on change)"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.publish_time_boiler}
|
value={data.publish_time_boiler}
|
||||||
type="number"
|
type="number"
|
||||||
onChange={handleValueChange('publish_time_boiler')}
|
onChange={handleValueChange("publish_time_boiler")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<TextValidator
|
<TextValidator
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
|
validators={[
|
||||||
errorMessages={['Publish time is required', "Must be a number", "Must be 0 or greater", "Max value is 65535"]}
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:65535",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"Publish time is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or greater",
|
||||||
|
"Max value is 65535",
|
||||||
|
]}
|
||||||
name="publish_time_thermostat"
|
name="publish_time_thermostat"
|
||||||
label="Thermostat Publish Interval (seconds, 0=on change)"
|
label="Thermostat Publish Interval (seconds, 0=on change)"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.publish_time_thermostat}
|
value={data.publish_time_thermostat}
|
||||||
type="number"
|
type="number"
|
||||||
onChange={handleValueChange('publish_time_thermostat')}
|
onChange={handleValueChange("publish_time_thermostat")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<TextValidator
|
<TextValidator
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
|
validators={[
|
||||||
errorMessages={['Publish time is required', "Must be a number", "Must be 0 or greater", "Max value is 65535"]}
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:65535",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"Publish time is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or greater",
|
||||||
|
"Max value is 65535",
|
||||||
|
]}
|
||||||
name="publish_time_solar"
|
name="publish_time_solar"
|
||||||
label="Solar Publish Interval (seconds, 0=on change)"
|
label="Solar Publish Interval (seconds, 0=on change)"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.publish_time_solar}
|
value={data.publish_time_solar}
|
||||||
type="number"
|
type="number"
|
||||||
onChange={handleValueChange('publish_time_solar')}
|
onChange={handleValueChange("publish_time_solar")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<TextValidator
|
<TextValidator
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
|
validators={[
|
||||||
errorMessages={['Publish time is required', "Must be a number", "Must be 0 or greater", "Max value is 65535"]}
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:65535",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"Publish time is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or greater",
|
||||||
|
"Max value is 65535",
|
||||||
|
]}
|
||||||
name="publish_time_mixer"
|
name="publish_time_mixer"
|
||||||
label="Mixer Publish Interval (seconds, 0=on change)"
|
label="Mixer Publish Interval (seconds, 0=on change)"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.publish_time_mixer}
|
value={data.publish_time_mixer}
|
||||||
type="number"
|
type="number"
|
||||||
onChange={handleValueChange('publish_time_mixer')}
|
onChange={handleValueChange("publish_time_mixer")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<TextValidator
|
<TextValidator
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
|
validators={[
|
||||||
errorMessages={['Publish time is required', "Must be a number", "Must be 0 or greater", "Max value is 65535"]}
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:65535",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"Publish time is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or greater",
|
||||||
|
"Max value is 65535",
|
||||||
|
]}
|
||||||
name="publish_time_sensor"
|
name="publish_time_sensor"
|
||||||
label="Sensors Publish Interval (seconds, 0=on change)"
|
label="Sensors Publish Interval (seconds, 0=on change)"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.publish_time_sensor}
|
value={data.publish_time_sensor}
|
||||||
type="number"
|
type="number"
|
||||||
onChange={handleValueChange('publish_time_sensor')}
|
onChange={handleValueChange("publish_time_sensor")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<TextValidator
|
<TextValidator
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
|
validators={[
|
||||||
errorMessages={['Publish time is required', "Must be a number", "Must be 0 or greater", "Max value is 65535"]}
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:65535",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"Publish time is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or greater",
|
||||||
|
"Max value is 65535",
|
||||||
|
]}
|
||||||
name="publish_time_other"
|
name="publish_time_other"
|
||||||
label="All other Modules Publish Interval (seconds, 0=on change)"
|
label="All other Modules Publish Interval (seconds, 0=on change)"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.publish_time_other}
|
value={data.publish_time_other}
|
||||||
type="number"
|
type="number"
|
||||||
onChange={handleValueChange('publish_time_other')}
|
onChange={handleValueChange("publish_time_other")}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<FormActions>
|
<FormActions>
|
||||||
<FormButton startIcon={<SaveIcon />} variant="contained" color="primary" type="submit">
|
<FormButton
|
||||||
|
startIcon={<SaveIcon />}
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
Save
|
Save
|
||||||
</FormButton>
|
</FormButton>
|
||||||
</FormActions>
|
</FormActions>
|
||||||
|
|||||||
@@ -40,6 +40,6 @@ export interface MqttSettings {
|
|||||||
mqtt_retain: boolean;
|
mqtt_retain: boolean;
|
||||||
ha_enabled: boolean;
|
ha_enabled: boolean;
|
||||||
ha_climate_format: number;
|
ha_climate_format: number;
|
||||||
nested_format: boolean;
|
nested_format: number;
|
||||||
subscribe_format: number;
|
subscribe_format: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,417 +1,577 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import { ValidatorForm, TextValidator, SelectValidator } from 'react-material-ui-form-validator';
|
import {
|
||||||
|
ValidatorForm,
|
||||||
|
TextValidator,
|
||||||
|
SelectValidator,
|
||||||
|
} from "react-material-ui-form-validator";
|
||||||
|
|
||||||
import { Checkbox, Typography, Box, Link, withWidth, WithWidthProps } from '@material-ui/core';
|
import {
|
||||||
import SaveIcon from '@material-ui/icons/Save';
|
Checkbox,
|
||||||
import MenuItem from '@material-ui/core/MenuItem';
|
Typography,
|
||||||
|
Box,
|
||||||
|
Link,
|
||||||
|
withWidth,
|
||||||
|
WithWidthProps,
|
||||||
|
} from "@material-ui/core";
|
||||||
|
import SaveIcon from "@material-ui/icons/Save";
|
||||||
|
import MenuItem from "@material-ui/core/MenuItem";
|
||||||
|
|
||||||
import Grid from '@material-ui/core/Grid';
|
import Grid from "@material-ui/core/Grid";
|
||||||
|
|
||||||
import { redirectingAuthorizedFetch, withAuthenticatedContext, AuthenticatedContextProps } from "../authentication";
|
import {
|
||||||
|
redirectingAuthorizedFetch,
|
||||||
|
withAuthenticatedContext,
|
||||||
|
AuthenticatedContextProps,
|
||||||
|
} from "../authentication";
|
||||||
|
|
||||||
import { RestFormProps, FormActions, FormButton, BlockFormControlLabel } from '../components';
|
import {
|
||||||
|
RestFormProps,
|
||||||
|
FormActions,
|
||||||
|
FormButton,
|
||||||
|
BlockFormControlLabel,
|
||||||
|
} from "../components";
|
||||||
|
|
||||||
import { isIP, optional } from '../validators';
|
import { isIP, optional } from "../validators";
|
||||||
|
|
||||||
import { EMSESPSettings } from './EMSESPtypes';
|
import { EMSESPSettings } from "./EMSESPtypes";
|
||||||
|
|
||||||
import { boardProfileSelectItems } from './EMSESPBoardProfiles';
|
import { boardProfileSelectItems } from "./EMSESPBoardProfiles";
|
||||||
|
|
||||||
import { ENDPOINT_ROOT } from "../api";
|
import { ENDPOINT_ROOT } from "../api";
|
||||||
export const BOARD_PROFILE_ENDPOINT = ENDPOINT_ROOT + "boardProfile";
|
export const BOARD_PROFILE_ENDPOINT = ENDPOINT_ROOT + "boardProfile";
|
||||||
|
|
||||||
type EMSESPSettingsFormProps = RestFormProps<EMSESPSettings> & AuthenticatedContextProps & WithWidthProps;
|
type EMSESPSettingsFormProps = RestFormProps<EMSESPSettings> &
|
||||||
|
AuthenticatedContextProps &
|
||||||
|
WithWidthProps;
|
||||||
|
|
||||||
interface EMSESPSettingsFormState {
|
interface EMSESPSettingsFormState {
|
||||||
processing: boolean;
|
processing: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
class EMSESPSettingsForm extends React.Component<EMSESPSettingsFormProps> {
|
class EMSESPSettingsForm extends React.Component<EMSESPSettingsFormProps> {
|
||||||
|
state: EMSESPSettingsFormState = {
|
||||||
|
processing: false,
|
||||||
|
};
|
||||||
|
|
||||||
state: EMSESPSettingsFormState = {
|
componentDidMount() {
|
||||||
processing: false
|
ValidatorForm.addValidationRule("isOptionalIP", optional(isIP));
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
changeBoardProfile = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
ValidatorForm.addValidationRule('isOptionalIP', optional(isIP));
|
const { data, setData } = this.props;
|
||||||
}
|
setData({
|
||||||
|
...data,
|
||||||
|
board_profile: event.target.value,
|
||||||
|
});
|
||||||
|
|
||||||
changeBoardProfile = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
if (event.target.value === "CUSTOM") return;
|
||||||
const { data, setData } = this.props;
|
|
||||||
|
this.setState({ processing: true });
|
||||||
|
redirectingAuthorizedFetch(BOARD_PROFILE_ENDPOINT, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({ code: event.target.value }),
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
throw Error("Unexpected response code: " + response.status);
|
||||||
|
})
|
||||||
|
.then((json) => {
|
||||||
|
this.props.enqueueSnackbar("Profile loaded", { variant: "success" });
|
||||||
setData({
|
setData({
|
||||||
...data,
|
...data,
|
||||||
board_profile: event.target.value
|
led_gpio: json.led_gpio,
|
||||||
|
dallas_gpio: json.dallas_gpio,
|
||||||
|
rx_gpio: json.rx_gpio,
|
||||||
|
tx_gpio: json.tx_gpio,
|
||||||
|
pbutton_gpio: json.pbutton_gpio,
|
||||||
|
board_profile: event.target.value,
|
||||||
});
|
});
|
||||||
|
this.setState({ processing: false });
|
||||||
if (event.target.value === "CUSTOM")
|
})
|
||||||
return;
|
.catch((error) => {
|
||||||
|
this.props.enqueueSnackbar(
|
||||||
this.setState({ processing: true });
|
error.message || "Problem fetching board profile",
|
||||||
redirectingAuthorizedFetch(BOARD_PROFILE_ENDPOINT, {
|
{ variant: "warning" }
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({ code: event.target.value }),
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
throw Error("Unexpected response code: " + response.status);
|
|
||||||
})
|
|
||||||
.then((json) => {
|
|
||||||
this.props.enqueueSnackbar("Profile loaded", { variant: 'success' });
|
|
||||||
setData({
|
|
||||||
...data,
|
|
||||||
led_gpio: json.led_gpio,
|
|
||||||
dallas_gpio: json.dallas_gpio,
|
|
||||||
rx_gpio: json.rx_gpio,
|
|
||||||
tx_gpio: json.tx_gpio,
|
|
||||||
pbutton_gpio: json.pbutton_gpio,
|
|
||||||
board_profile: event.target.value
|
|
||||||
});
|
|
||||||
this.setState({ processing: false });
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this.props.enqueueSnackbar(
|
|
||||||
error.message || "Problem fetching board profile",
|
|
||||||
{ variant: "warning" }
|
|
||||||
);
|
|
||||||
this.setState({ processing: false });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { data, saveData, handleValueChange } = this.props;
|
|
||||||
return (
|
|
||||||
<ValidatorForm onSubmit={saveData}>
|
|
||||||
<Box bgcolor="info.main" p={2} mt={2} mb={2}>
|
|
||||||
<Typography variant="body1">
|
|
||||||
Modify any of the EMS-ESP settings here. For help refer to the <Link target="_blank" href="https://emsesp.github.io/docs/#/Configure-firmware32?id=ems-esp-settings" color="primary">{'online documentation'}</Link>.
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<br></br>
|
|
||||||
<Typography variant="h6" color="primary" >
|
|
||||||
EMS Bus
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Grid container spacing={1} direction="row" justify="flex-start" alignItems="flex-start">
|
|
||||||
<Grid item xs={5}>
|
|
||||||
<SelectValidator name="tx_mode"
|
|
||||||
label="Tx Mode"
|
|
||||||
value={data.tx_mode}
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
onChange={handleValueChange('tx_mode')}
|
|
||||||
margin="normal">
|
|
||||||
<MenuItem value={0}>Off</MenuItem>
|
|
||||||
<MenuItem value={1}>EMS</MenuItem>
|
|
||||||
<MenuItem value={2}>EMS+</MenuItem>
|
|
||||||
<MenuItem value={3}>HT3</MenuItem>
|
|
||||||
<MenuItem value={4}>Hardware</MenuItem>
|
|
||||||
</SelectValidator>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<SelectValidator name="ems_bus_id"
|
|
||||||
label="Bus ID"
|
|
||||||
value={data.ems_bus_id}
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
onChange={handleValueChange('ems_bus_id')}
|
|
||||||
margin="normal">
|
|
||||||
<MenuItem value={0x0B}>Service Key (0x0B)</MenuItem>
|
|
||||||
<MenuItem value={0x0D}>Modem (0x0D)</MenuItem>
|
|
||||||
<MenuItem value={0x0A}>Terminal (0x0A)</MenuItem>
|
|
||||||
<MenuItem value={0x0F}>Time Module (0x0F)</MenuItem>
|
|
||||||
<MenuItem value={0x12}>Alarm Module (0x12)</MenuItem>
|
|
||||||
</SelectValidator>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<TextValidator
|
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:120']}
|
|
||||||
errorMessages={['Tx delay is required', "Must be a number", "Must be 0 or higher", "Max value is 120"]}
|
|
||||||
name="tx_delay"
|
|
||||||
label="Tx start delay (seconds)"
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={data.tx_delay}
|
|
||||||
type="number"
|
|
||||||
onChange={handleValueChange('tx_delay')}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<br></br>
|
|
||||||
<Typography variant="h6" color="primary" >
|
|
||||||
Board Profile
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Box color="warning.main" p={0} mt={0} mb={0}>
|
|
||||||
<Typography variant="body2">
|
|
||||||
<i>Select a pre-configured board layout to automatically set the GPIO pins, or set your own custom configuration</i>
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<SelectValidator name="board_profile"
|
|
||||||
label="Board Profile"
|
|
||||||
value={data.board_profile}
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
onChange={this.changeBoardProfile}
|
|
||||||
margin="normal">
|
|
||||||
{boardProfileSelectItems()}
|
|
||||||
<MenuItem key={"CUSTOM"} value={"CUSTOM"}>Custom...</MenuItem>
|
|
||||||
</SelectValidator>
|
|
||||||
|
|
||||||
{ (data.board_profile === "CUSTOM") &&
|
|
||||||
<Grid container spacing={1} direction="row" justify="flex-start" alignItems="flex-start">
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<TextValidator
|
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40', 'matchRegexp:^((?!6|7|8|9|10|11|12|14|15|20|24|28|29|30|31)[0-9]*)$']}
|
|
||||||
errorMessages={['GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40", "Not a valid GPIO"]}
|
|
||||||
name="rx_gpio"
|
|
||||||
label="Rx GPIO"
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={data.rx_gpio}
|
|
||||||
type="number"
|
|
||||||
onChange={handleValueChange('rx_gpio')}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<TextValidator
|
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40', 'matchRegexp:^((?!6|7|8|9|10|11|12|14|15|20|24|28|29|30|31)[0-9]*)$']}
|
|
||||||
errorMessages={['GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40", "Not a valid GPIO"]}
|
|
||||||
name="tx_gpio"
|
|
||||||
label="Tx GPIO"
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={data.tx_gpio}
|
|
||||||
type="number"
|
|
||||||
onChange={handleValueChange('tx_gpio')}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<TextValidator
|
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40', 'matchRegexp:^((?!6|7|8|9|10|11|12|14|15|20|24|28|29|30|31)[0-9]*)$']}
|
|
||||||
errorMessages={['GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40", "Not a valid GPIO"]}
|
|
||||||
name="pbutton_gpio"
|
|
||||||
label="Button GPIO"
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={data.pbutton_gpio}
|
|
||||||
type="number"
|
|
||||||
onChange={handleValueChange('pbutton_gpio')}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<TextValidator
|
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40', 'matchRegexp:^((?!6|7|8|9|10|11|12|14|15|20|24|28|29|30|31)[0-9]*)$']}
|
|
||||||
errorMessages={['GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40", "Not a valid GPIO"]}
|
|
||||||
name="dallas_gpio"
|
|
||||||
label="Dallas GPIO (0=none)"
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={data.dallas_gpio}
|
|
||||||
type="number"
|
|
||||||
onChange={handleValueChange('dallas_gpio')}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<TextValidator
|
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40', 'matchRegexp:^((?!6|7|8|9|10|11|12|14|15|20|24|28|29|30|31)[0-9]*)$']}
|
|
||||||
errorMessages={['GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40", "Not a valid GPIO"]}
|
|
||||||
name="led_gpio"
|
|
||||||
label="LED GPIO (0=none)"
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={data.led_gpio}
|
|
||||||
type="number"
|
|
||||||
onChange={handleValueChange('led_gpio')}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
}
|
|
||||||
|
|
||||||
<br></br>
|
|
||||||
<Typography variant="h6" color="primary" >
|
|
||||||
Options
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
{ data.dallas_gpio !== 0 &&
|
|
||||||
<BlockFormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={data.dallas_parasite}
|
|
||||||
onChange={handleValueChange('dallas_parasite')}
|
|
||||||
value="dallas_parasite"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label="Enable Dallas parasite mode"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
{ data.led_gpio !== 0 &&
|
|
||||||
<BlockFormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={data.hide_led}
|
|
||||||
onChange={handleValueChange('hide_led')}
|
|
||||||
value="hide_led"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label = "Hide LED"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
|
|
||||||
<Grid container spacing={0} direction="row" justify="flex-start" alignItems="flex-start">
|
|
||||||
|
|
||||||
<BlockFormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={data.shower_timer}
|
|
||||||
onChange={handleValueChange('shower_timer')}
|
|
||||||
value="shower_timer"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label="Shower Timer"
|
|
||||||
/>
|
|
||||||
{/* <BlockFormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={data.shower_alert}
|
|
||||||
onChange={handleValueChange('shower_alert')}
|
|
||||||
value="shower_alert"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label="Shower Alert"
|
|
||||||
/> */}
|
|
||||||
</Grid>
|
|
||||||
<BlockFormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={data.api_enabled}
|
|
||||||
onChange={handleValueChange('api_enabled')}
|
|
||||||
value="api_enabled"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label="Enable API write commands"
|
|
||||||
/>
|
|
||||||
<BlockFormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={data.analog_enabled}
|
|
||||||
onChange={handleValueChange('analog_enabled')}
|
|
||||||
value="analog_enabled"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label="Enable ADC"
|
|
||||||
/>
|
|
||||||
<br></br>
|
|
||||||
<Typography variant="h6" color="primary" >
|
|
||||||
Syslog
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<BlockFormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={data.syslog_enabled}
|
|
||||||
onChange={handleValueChange('syslog_enabled')}
|
|
||||||
value="syslog_enabled"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label="Enable Syslog"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{ data.syslog_enabled &&
|
|
||||||
<Grid container spacing={1} direction="row" justify="flex-start" alignItems="flex-start">
|
|
||||||
<Grid item xs={5}>
|
|
||||||
<TextValidator
|
|
||||||
validators={['isOptionalIP']}
|
|
||||||
errorMessages={["Not a valid IP address"]}
|
|
||||||
name="syslog_host"
|
|
||||||
label="IP"
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={data.syslog_host}
|
|
||||||
onChange={handleValueChange('syslog_host')}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<TextValidator
|
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
|
|
||||||
errorMessages={['Port is required', "Must be a number", "Must be greater than 0 ", "Max value is 65535"]}
|
|
||||||
name="syslog_port"
|
|
||||||
label="Port"
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={data.syslog_port}
|
|
||||||
type="number"
|
|
||||||
onChange={handleValueChange('syslog_port')}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={5}>
|
|
||||||
<SelectValidator name="syslog_level"
|
|
||||||
label="Log Level"
|
|
||||||
value={data.syslog_level}
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
onChange={handleValueChange('syslog_level')}
|
|
||||||
margin="normal">
|
|
||||||
<MenuItem value={-1}>OFF</MenuItem>
|
|
||||||
<MenuItem value={3}>ERR</MenuItem>
|
|
||||||
<MenuItem value={5}>NOTICE</MenuItem>
|
|
||||||
<MenuItem value={6}>INFO</MenuItem>
|
|
||||||
<MenuItem value={7}>DEBUG</MenuItem>
|
|
||||||
<MenuItem value={8}>ALL</MenuItem>
|
|
||||||
</SelectValidator>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<TextValidator
|
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
|
|
||||||
errorMessages={['Syslog Mark is required', "Must be a number", "Must be 0 or higher", "Max value is 10"]}
|
|
||||||
name="syslog_mark_interval"
|
|
||||||
label="Mark Interval seconds (0=off)"
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={data.syslog_mark_interval}
|
|
||||||
type="number"
|
|
||||||
onChange={handleValueChange('syslog_mark_interval')}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<BlockFormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={data.trace_raw}
|
|
||||||
onChange={handleValueChange('trace_raw')}
|
|
||||||
value="trace_raw"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label="Output EMS telegrams in raw format"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
}
|
|
||||||
|
|
||||||
<br></br>
|
|
||||||
<FormActions>
|
|
||||||
<FormButton startIcon={<SaveIcon />} variant="contained" color="primary" type="submit">
|
|
||||||
Save
|
|
||||||
</FormButton>
|
|
||||||
</FormActions>
|
|
||||||
</ValidatorForm >
|
|
||||||
);
|
);
|
||||||
}
|
this.setState({ processing: false });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { data, saveData, handleValueChange } = this.props;
|
||||||
|
return (
|
||||||
|
<ValidatorForm onSubmit={saveData}>
|
||||||
|
<Box bgcolor="info.main" p={2} mt={2} mb={2}>
|
||||||
|
<Typography variant="body1">
|
||||||
|
Modify any of the EMS-ESP settings here. For help refer to the{" "}
|
||||||
|
<Link
|
||||||
|
target="_blank"
|
||||||
|
href="https://emsesp.github.io/docs/#/Configure-firmware32?id=ems-esp-settings"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
{"online documentation"}
|
||||||
|
</Link>
|
||||||
|
.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<br></br>
|
||||||
|
<Typography variant="h6" color="primary">
|
||||||
|
EMS Bus
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
spacing={1}
|
||||||
|
direction="row"
|
||||||
|
justify="flex-start"
|
||||||
|
alignItems="flex-start"
|
||||||
|
>
|
||||||
|
<Grid item xs={5}>
|
||||||
|
<SelectValidator
|
||||||
|
name="tx_mode"
|
||||||
|
label="Tx Mode"
|
||||||
|
value={data.tx_mode}
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
onChange={handleValueChange("tx_mode")}
|
||||||
|
margin="normal"
|
||||||
|
>
|
||||||
|
<MenuItem value={0}>Off</MenuItem>
|
||||||
|
<MenuItem value={1}>EMS</MenuItem>
|
||||||
|
<MenuItem value={2}>EMS+</MenuItem>
|
||||||
|
<MenuItem value={3}>HT3</MenuItem>
|
||||||
|
<MenuItem value={4}>Hardware</MenuItem>
|
||||||
|
</SelectValidator>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<SelectValidator
|
||||||
|
name="ems_bus_id"
|
||||||
|
label="Bus ID"
|
||||||
|
value={data.ems_bus_id}
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
onChange={handleValueChange("ems_bus_id")}
|
||||||
|
margin="normal"
|
||||||
|
>
|
||||||
|
<MenuItem value={0x0b}>Service Key (0x0B)</MenuItem>
|
||||||
|
<MenuItem value={0x0d}>Modem (0x0D)</MenuItem>
|
||||||
|
<MenuItem value={0x0a}>Terminal (0x0A)</MenuItem>
|
||||||
|
<MenuItem value={0x0f}>Time Module (0x0F)</MenuItem>
|
||||||
|
<MenuItem value={0x12}>Alarm Module (0x12)</MenuItem>
|
||||||
|
</SelectValidator>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<TextValidator
|
||||||
|
validators={[
|
||||||
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:120",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"Tx delay is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or higher",
|
||||||
|
"Max value is 120",
|
||||||
|
]}
|
||||||
|
name="tx_delay"
|
||||||
|
label="Tx start delay (seconds)"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={data.tx_delay}
|
||||||
|
type="number"
|
||||||
|
onChange={handleValueChange("tx_delay")}
|
||||||
|
margin="normal"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<br></br>
|
||||||
|
<Typography variant="h6" color="primary">
|
||||||
|
Board Profile
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Box color="warning.main" p={0} mt={0} mb={0}>
|
||||||
|
<Typography variant="body2">
|
||||||
|
<i>
|
||||||
|
Select a pre-configured board layout to automatically set the GPIO
|
||||||
|
pins, or set your own custom configuration
|
||||||
|
</i>
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<SelectValidator
|
||||||
|
name="board_profile"
|
||||||
|
label="Board Profile"
|
||||||
|
value={data.board_profile}
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
onChange={this.changeBoardProfile}
|
||||||
|
margin="normal"
|
||||||
|
>
|
||||||
|
{boardProfileSelectItems()}
|
||||||
|
<MenuItem key={"CUSTOM"} value={"CUSTOM"}>
|
||||||
|
Custom...
|
||||||
|
</MenuItem>
|
||||||
|
</SelectValidator>
|
||||||
|
|
||||||
|
{data.board_profile === "CUSTOM" && (
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
spacing={1}
|
||||||
|
direction="row"
|
||||||
|
justify="flex-start"
|
||||||
|
alignItems="flex-start"
|
||||||
|
>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextValidator
|
||||||
|
validators={[
|
||||||
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:40",
|
||||||
|
"matchRegexp:^((?!6|7|8|9|10|11|12|14|15|20|24|28|29|30|31)[0-9]*)$",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"GPIO is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or higher",
|
||||||
|
"Max value is 40",
|
||||||
|
"Not a valid GPIO",
|
||||||
|
]}
|
||||||
|
name="rx_gpio"
|
||||||
|
label="Rx GPIO"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={data.rx_gpio}
|
||||||
|
type="number"
|
||||||
|
onChange={handleValueChange("rx_gpio")}
|
||||||
|
margin="normal"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextValidator
|
||||||
|
validators={[
|
||||||
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:40",
|
||||||
|
"matchRegexp:^((?!6|7|8|9|10|11|12|14|15|20|24|28|29|30|31)[0-9]*)$",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"GPIO is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or higher",
|
||||||
|
"Max value is 40",
|
||||||
|
"Not a valid GPIO",
|
||||||
|
]}
|
||||||
|
name="tx_gpio"
|
||||||
|
label="Tx GPIO"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={data.tx_gpio}
|
||||||
|
type="number"
|
||||||
|
onChange={handleValueChange("tx_gpio")}
|
||||||
|
margin="normal"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextValidator
|
||||||
|
validators={[
|
||||||
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:40",
|
||||||
|
"matchRegexp:^((?!6|7|8|9|10|11|12|14|15|20|24|28|29|30|31)[0-9]*)$",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"GPIO is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or higher",
|
||||||
|
"Max value is 40",
|
||||||
|
"Not a valid GPIO",
|
||||||
|
]}
|
||||||
|
name="pbutton_gpio"
|
||||||
|
label="Button GPIO"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={data.pbutton_gpio}
|
||||||
|
type="number"
|
||||||
|
onChange={handleValueChange("pbutton_gpio")}
|
||||||
|
margin="normal"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextValidator
|
||||||
|
validators={[
|
||||||
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:40",
|
||||||
|
"matchRegexp:^((?!6|7|8|9|10|11|12|14|15|20|24|28|29|30|31)[0-9]*)$",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"GPIO is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or higher",
|
||||||
|
"Max value is 40",
|
||||||
|
"Not a valid GPIO",
|
||||||
|
]}
|
||||||
|
name="dallas_gpio"
|
||||||
|
label="Dallas GPIO (0=none)"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={data.dallas_gpio}
|
||||||
|
type="number"
|
||||||
|
onChange={handleValueChange("dallas_gpio")}
|
||||||
|
margin="normal"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextValidator
|
||||||
|
validators={[
|
||||||
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:40",
|
||||||
|
"matchRegexp:^((?!6|7|8|9|10|11|12|14|15|20|24|28|29|30|31)[0-9]*)$",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"GPIO is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or higher",
|
||||||
|
"Max value is 40",
|
||||||
|
"Not a valid GPIO",
|
||||||
|
]}
|
||||||
|
name="led_gpio"
|
||||||
|
label="LED GPIO (0=none)"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={data.led_gpio}
|
||||||
|
type="number"
|
||||||
|
onChange={handleValueChange("led_gpio")}
|
||||||
|
margin="normal"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<br></br>
|
||||||
|
<Typography variant="h6" color="primary">
|
||||||
|
Options
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{data.led_gpio !== 0 && (
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={data.hide_led}
|
||||||
|
onChange={handleValueChange("hide_led")}
|
||||||
|
value="hide_led"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Hide LED"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{data.dallas_gpio !== 0 && (
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={data.dallas_parasite}
|
||||||
|
onChange={handleValueChange("dallas_parasite")}
|
||||||
|
value="dallas_parasite"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Enable Dallas parasite mode"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={data.api_enabled}
|
||||||
|
onChange={handleValueChange("api_enabled")}
|
||||||
|
value="api_enabled"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Enable API write commands"
|
||||||
|
/>
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={data.analog_enabled}
|
||||||
|
onChange={handleValueChange("analog_enabled")}
|
||||||
|
value="analog_enabled"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Enable ADC"
|
||||||
|
/>
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
spacing={0}
|
||||||
|
direction="row"
|
||||||
|
justify="flex-start"
|
||||||
|
alignItems="flex-start"
|
||||||
|
>
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={data.shower_timer}
|
||||||
|
onChange={handleValueChange("shower_timer")}
|
||||||
|
value="shower_timer"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Enable Shower Timer"
|
||||||
|
/>
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={data.shower_alert}
|
||||||
|
onChange={handleValueChange("shower_alert")}
|
||||||
|
value="shower_alert"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Enable Shower Alert"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<br></br>
|
||||||
|
<Typography variant="h6" color="primary">
|
||||||
|
Syslog
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={data.syslog_enabled}
|
||||||
|
onChange={handleValueChange("syslog_enabled")}
|
||||||
|
value="syslog_enabled"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Enable Syslog"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{data.syslog_enabled && (
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
spacing={1}
|
||||||
|
direction="row"
|
||||||
|
justify="flex-start"
|
||||||
|
alignItems="flex-start"
|
||||||
|
>
|
||||||
|
<Grid item xs={5}>
|
||||||
|
<TextValidator
|
||||||
|
validators={["isOptionalIP"]}
|
||||||
|
errorMessages={["Not a valid IP address"]}
|
||||||
|
name="syslog_host"
|
||||||
|
label="IP"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={data.syslog_host}
|
||||||
|
onChange={handleValueChange("syslog_host")}
|
||||||
|
margin="normal"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<TextValidator
|
||||||
|
validators={[
|
||||||
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:65535",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"Port is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be greater than 0 ",
|
||||||
|
"Max value is 65535",
|
||||||
|
]}
|
||||||
|
name="syslog_port"
|
||||||
|
label="Port"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={data.syslog_port}
|
||||||
|
type="number"
|
||||||
|
onChange={handleValueChange("syslog_port")}
|
||||||
|
margin="normal"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={5}>
|
||||||
|
<SelectValidator
|
||||||
|
name="syslog_level"
|
||||||
|
label="Log Level"
|
||||||
|
value={data.syslog_level}
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
onChange={handleValueChange("syslog_level")}
|
||||||
|
margin="normal"
|
||||||
|
>
|
||||||
|
<MenuItem value={-1}>OFF</MenuItem>
|
||||||
|
<MenuItem value={3}>ERR</MenuItem>
|
||||||
|
<MenuItem value={5}>NOTICE</MenuItem>
|
||||||
|
<MenuItem value={6}>INFO</MenuItem>
|
||||||
|
<MenuItem value={7}>DEBUG</MenuItem>
|
||||||
|
<MenuItem value={8}>ALL</MenuItem>
|
||||||
|
</SelectValidator>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<TextValidator
|
||||||
|
validators={[
|
||||||
|
"required",
|
||||||
|
"isNumber",
|
||||||
|
"minNumber:0",
|
||||||
|
"maxNumber:65535",
|
||||||
|
]}
|
||||||
|
errorMessages={[
|
||||||
|
"Syslog Mark is required",
|
||||||
|
"Must be a number",
|
||||||
|
"Must be 0 or higher",
|
||||||
|
"Max value is 10",
|
||||||
|
]}
|
||||||
|
name="syslog_mark_interval"
|
||||||
|
label="Mark Interval seconds (0=off)"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={data.syslog_mark_interval}
|
||||||
|
type="number"
|
||||||
|
onChange={handleValueChange("syslog_mark_interval")}
|
||||||
|
margin="normal"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={data.trace_raw}
|
||||||
|
onChange={handleValueChange("trace_raw")}
|
||||||
|
value="trace_raw"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Output EMS telegrams in raw format"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<br></br>
|
||||||
|
<FormActions>
|
||||||
|
<FormButton
|
||||||
|
startIcon={<SaveIcon />}
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</FormButton>
|
||||||
|
</FormActions>
|
||||||
|
</ValidatorForm>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withAuthenticatedContext(withWidth()(EMSESPSettingsForm));
|
export default withAuthenticatedContext(withWidth()(EMSESPSettingsForm));
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class MqttSettings {
|
|||||||
uint8_t bool_format;
|
uint8_t bool_format;
|
||||||
uint8_t ha_climate_format;
|
uint8_t ha_climate_format;
|
||||||
bool ha_enabled;
|
bool ha_enabled;
|
||||||
bool nested_format;
|
uint8_t nested_format;
|
||||||
uint8_t subscribe_format;
|
uint8_t subscribe_format;
|
||||||
|
|
||||||
static void read(MqttSettings & settings, JsonObject & root);
|
static void read(MqttSettings & settings, JsonObject & root);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class DummySettings {
|
|||||||
bool mqtt_retain = false;
|
bool mqtt_retain = false;
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
uint8_t dallas_format = 1;
|
uint8_t dallas_format = 1;
|
||||||
bool nested_format = true;
|
uint8_t nested_format = 1;
|
||||||
uint8_t ha_climate_format = 1;
|
uint8_t ha_climate_format = 1;
|
||||||
bool ha_enabled = true;
|
bool ha_enabled = true;
|
||||||
String base = "ems-esp";
|
String base = "ems-esp";
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ const mqtt_settings = {
|
|||||||
"client_id": "ems-esp32", "keep_alive": 60, "clean_session": true, "max_topic_length": 128,
|
"client_id": "ems-esp32", "keep_alive": 60, "clean_session": true, "max_topic_length": 128,
|
||||||
"publish_time_boiler": 10, "publish_time_thermostat": 10, "publish_time_solar": 10, "publish_time_mixer": 10,
|
"publish_time_boiler": 10, "publish_time_thermostat": 10, "publish_time_solar": 10, "publish_time_mixer": 10,
|
||||||
"publish_time_other": 10, "publish_time_sensor": 10, "mqtt_qos": 0, "mqtt_retain": false, "dallas_format": 1,
|
"publish_time_other": 10, "publish_time_sensor": 10, "mqtt_qos": 0, "mqtt_retain": false, "dallas_format": 1,
|
||||||
"bool_format": 1, "ha_climate_format": 1, "ha_enabled": true, "nested_format": true, "subscribe_format": 0
|
"bool_format": 1, "ha_climate_format": 1, "ha_enabled": true, "nested_format": 1, "subscribe_format": 0
|
||||||
};
|
};
|
||||||
const mqtt_status = {
|
const mqtt_status = {
|
||||||
"enabled": true, "connected": true, "client_id": "ems-esp32", "disconnect_reason": 0, "mqtt_fails": 0
|
"enabled": true, "connected": true, "client_id": "ems-esp32", "disconnect_reason": 0, "mqtt_fails": 0
|
||||||
|
|||||||
@@ -145,7 +145,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EMSESP_DEFAULT_NESTED_FORMAT
|
#ifndef EMSESP_DEFAULT_NESTED_FORMAT
|
||||||
#define EMSESP_DEFAULT_NESTED_FORMAT true
|
#define EMSESP_DEFAULT_NESTED_FORMAT 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EMSESP_DEFAULT_SUBSCRIBE_FORMAT
|
#ifndef EMSESP_DEFAULT_SUBSCRIBE_FORMAT
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ void Thermostat::register_mqtt_ha_config_hc(uint8_t hc_num) {
|
|||||||
doc["~"] = Mqtt::base(); // ems-esp
|
doc["~"] = Mqtt::base(); // ems-esp
|
||||||
|
|
||||||
char topic_t[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic_t[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
if (Mqtt::nested_format()) {
|
if (Mqtt::nested_format() == 1) {
|
||||||
snprintf_P(topic_t, sizeof(topic_t), PSTR("~/%s"), Mqtt::tag_to_topic(EMSdevice::DeviceType::THERMOSTAT, DeviceValueTAG::TAG_NONE).c_str());
|
snprintf_P(topic_t, sizeof(topic_t), PSTR("~/%s"), Mqtt::tag_to_topic(EMSdevice::DeviceType::THERMOSTAT, DeviceValueTAG::TAG_NONE).c_str());
|
||||||
|
|
||||||
char mode_str_tpl[40];
|
char mode_str_tpl[40];
|
||||||
@@ -1148,7 +1148,7 @@ bool Thermostat::set_building(const char * value, const int8_t id) {
|
|||||||
if ((model() == EMS_DEVICE_FLAG_RC300) || (model() == EMS_DEVICE_FLAG_RC100)) {
|
if ((model() == EMS_DEVICE_FLAG_RC300) || (model() == EMS_DEVICE_FLAG_RC100)) {
|
||||||
if (Helpers::value2enum(value, bd, FL_(enum_ibaBuildingType))) {
|
if (Helpers::value2enum(value, bd, FL_(enum_ibaBuildingType))) {
|
||||||
LOG_INFO(F("Setting building to %s"), value);
|
LOG_INFO(F("Setting building to %s"), value);
|
||||||
write_command(0x240, 9, bd , 0x240);
|
write_command(0x240, 9, bd, 0x240);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -435,7 +435,7 @@ void EMSESP::publish_device_values(uint8_t device_type) {
|
|||||||
JsonObject json = doc.to<JsonObject>();
|
JsonObject json = doc.to<JsonObject>();
|
||||||
bool need_publish = false;
|
bool need_publish = false;
|
||||||
|
|
||||||
bool nested = Mqtt::nested_format();
|
uint8_t nested = Mqtt::nested_format();
|
||||||
|
|
||||||
// group by device type
|
// group by device type
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ uint8_t Mqtt::dallas_format_;
|
|||||||
uint8_t Mqtt::bool_format_;
|
uint8_t Mqtt::bool_format_;
|
||||||
uint8_t Mqtt::ha_climate_format_;
|
uint8_t Mqtt::ha_climate_format_;
|
||||||
bool Mqtt::ha_enabled_;
|
bool Mqtt::ha_enabled_;
|
||||||
bool Mqtt::nested_format_;
|
uint8_t Mqtt::nested_format_;
|
||||||
uint8_t Mqtt::subscribe_format_;
|
uint8_t Mqtt::subscribe_format_;
|
||||||
|
|
||||||
std::deque<Mqtt::QueuedMqttMessage> Mqtt::mqtt_messages_;
|
std::deque<Mqtt::QueuedMqttMessage> Mqtt::mqtt_messages_;
|
||||||
@@ -898,7 +898,7 @@ void Mqtt::publish_mqtt_ha_sensor(uint8_t type, // EMSdevice
|
|||||||
DynamicJsonDocument doc(EMSESP_JSON_SIZE_HA_CONFIG);
|
DynamicJsonDocument doc(EMSESP_JSON_SIZE_HA_CONFIG);
|
||||||
|
|
||||||
bool have_tag = !EMSdevice::tag_to_string(tag).empty() && (device_type != EMSdevice::DeviceType::BOILER); // ignore boiler
|
bool have_tag = !EMSdevice::tag_to_string(tag).empty() && (device_type != EMSdevice::DeviceType::BOILER); // ignore boiler
|
||||||
bool is_nested = nested_format_ || (device_type == EMSdevice::DeviceType::BOILER); // boiler never uses nested
|
bool is_nested = (nested_format_ == 1) || (device_type == EMSdevice::DeviceType::BOILER); // boiler never uses nested
|
||||||
|
|
||||||
// create entity by add the tag if present, seperating with a .
|
// create entity by add the tag if present, seperating with a .
|
||||||
char new_entity[50];
|
char new_entity[50];
|
||||||
@@ -1005,7 +1005,7 @@ const std::string Mqtt::tag_to_topic(uint8_t device_type, uint8_t tag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if there is a tag add it
|
// if there is a tag add it
|
||||||
if ((EMSdevice::tag_to_mqtt(tag).empty()) || (nested_format_ && (device_type != EMSdevice::DeviceType::BOILER))) {
|
if ((EMSdevice::tag_to_mqtt(tag).empty()) || ((nested_format_ == 1) && (device_type != EMSdevice::DeviceType::BOILER))) {
|
||||||
return EMSdevice::device_type_2_device_name(device_type) + "_data";
|
return EMSdevice::device_type_2_device_name(device_type) + "_data";
|
||||||
} else {
|
} else {
|
||||||
return EMSdevice::device_type_2_device_name(device_type) + "_data_" + EMSdevice::tag_to_mqtt(tag);
|
return EMSdevice::device_type_2_device_name(device_type) + "_data_" + EMSdevice::tag_to_mqtt(tag);
|
||||||
|
|||||||
@@ -158,11 +158,11 @@ class Mqtt {
|
|||||||
return bool_format_;
|
return bool_format_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool nested_format() {
|
static uint8_t nested_format() {
|
||||||
return nested_format_;
|
return nested_format_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nested_format(bool nested_format) {
|
static void nested_format(uint8_t nested_format) {
|
||||||
nested_format_ = nested_format;
|
nested_format_ = nested_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +274,7 @@ class Mqtt {
|
|||||||
static uint8_t bool_format_;
|
static uint8_t bool_format_;
|
||||||
static uint8_t ha_climate_format_;
|
static uint8_t ha_climate_format_;
|
||||||
static bool ha_enabled_;
|
static bool ha_enabled_;
|
||||||
static bool nested_format_;
|
static uint8_t nested_format_;
|
||||||
static uint8_t subscribe_format_;
|
static uint8_t subscribe_format_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd) {
|
|||||||
if (command == "boiler") {
|
if (command == "boiler") {
|
||||||
shell.printfln(F("Testing boiler..."));
|
shell.printfln(F("Testing boiler..."));
|
||||||
Mqtt::ha_enabled(false);
|
Mqtt::ha_enabled(false);
|
||||||
Mqtt::nested_format(true);
|
Mqtt::nested_format(1);
|
||||||
|
|
||||||
run_test("boiler");
|
run_test("boiler");
|
||||||
shell.invoke_command("show devices");
|
shell.invoke_command("show devices");
|
||||||
@@ -414,8 +414,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd) {
|
|||||||
if (command == "ha") {
|
if (command == "ha") {
|
||||||
shell.printfln(F("Testing HA discovery"));
|
shell.printfln(F("Testing HA discovery"));
|
||||||
Mqtt::ha_enabled(true);
|
Mqtt::ha_enabled(true);
|
||||||
// Mqtt::nested_format(true);
|
// Mqtt::nested_format(1);
|
||||||
Mqtt::nested_format(false);
|
Mqtt::nested_format(2);
|
||||||
|
|
||||||
// run_test("boiler");
|
// run_test("boiler");
|
||||||
run_test("thermostat");
|
run_test("thermostat");
|
||||||
@@ -436,11 +436,11 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd) {
|
|||||||
run_test("mixer");
|
run_test("mixer");
|
||||||
|
|
||||||
// first with nested
|
// first with nested
|
||||||
Mqtt::nested_format(true);
|
Mqtt::nested_format(1);
|
||||||
shell.invoke_command("call system publish");
|
shell.invoke_command("call system publish");
|
||||||
|
|
||||||
// then without nested
|
// then without nested
|
||||||
Mqtt::nested_format(false);
|
Mqtt::nested_format(2);
|
||||||
shell.invoke_command("call system publish");
|
shell.invoke_command("call system publish");
|
||||||
shell.invoke_command("show mqtt");
|
shell.invoke_command("show mqtt");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user