Merge pull request #1277 from proddy/dev

minor changes
This commit is contained in:
Proddy
2023-09-02 11:14:30 +02:00
committed by GitHub
34 changed files with 200 additions and 178 deletions

View File

@@ -1,9 +1,11 @@
# Changelog # Changelog
# [3.7.0] # [3.6.1]
## **IMPORTANT! BREAKING CHANGES** ## **IMPORTANT! BREAKING CHANGES**
- shower_data MQTT topic shows duration is seconds (was previously an English string)
## Added ## Added
- rssi in Network Status Page - rssi in Network Status Page
@@ -15,3 +17,4 @@
## Changed ## Changed
- mqtt free mem check 60k - mqtt free mem check 60k
- small cosmetic changes to Searching in Customization web page

View File

@@ -28,7 +28,7 @@
"@prefresh/vite": "^2.4.1", "@prefresh/vite": "^2.4.1",
"@table-library/react-table-library": "4.1.7", "@table-library/react-table-library": "4.1.7",
"@types/lodash-es": "^4.17.9", "@types/lodash-es": "^4.17.9",
"@types/node": "^20.5.7", "@types/node": "^20.5.8",
"@types/react": "^18.2.21", "@types/react": "^18.2.21",
"@types/react-dom": "^18.2.7", "@types/react-dom": "^18.2.7",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",

View File

@@ -86,7 +86,7 @@ const SettingsCustomization: FC = () => {
const entities_theme = useTheme({ const entities_theme = useTheme({
Table: ` Table: `
--data-table-library_grid-template-columns: 150px repeat(1, minmax(80px, 1fr)) 45px minmax(45px, auto) minmax(120px, auto); --data-table-library_grid-template-columns: 156px repeat(1, minmax(80px, 1fr)) 45px minmax(45px, auto) minmax(120px, auto);
`, `,
BaseRow: ` BaseRow: `
font-size: 14px; font-size: 14px;
@@ -192,17 +192,9 @@ const SettingsCustomization: FC = () => {
return value; return value;
} }
function formatName(de: DeviceEntity) { const formatName = (de: DeviceEntity, withShortname: boolean) =>
return ( (de.n && de.n[0] === '!' ? LL.COMMAND(1) + ': ' + de.n.slice(1) : de.cn && de.cn !== '' ? de.cn : de.n) +
<> (withShortname ? ' ' + de.id : '');
{de.n && (de.n[0] === '!' ? LL.COMMAND(1) + ': ' + de.n.slice(1) : de.cn && de.cn !== '' ? de.cn : de.n) + ' '}(
<Link target="_blank" href={APIURL + devices?.devices[selectedDevice].tn + '/' + de.id}>
{de.id}
</Link>
)
</>
);
}
const getMaskNumber = (newMask: string[]) => { const getMaskNumber = (newMask: string[]) => {
let new_mask = 0; let new_mask = 0;
@@ -232,10 +224,13 @@ const SettingsCustomization: FC = () => {
return new_masks; return new_masks;
}; };
const filter_entity = (de: DeviceEntity) =>
(de.m & selectedFilters || !selectedFilters) && formatName(de, true).includes(search.toLocaleLowerCase());
const maskDisabled = (set: boolean) => { const maskDisabled = (set: boolean) => {
setDeviceEntities( setDeviceEntities(
deviceEntities.map(function (de) { deviceEntities.map(function (de) {
if ((de.m & selectedFilters || !selectedFilters) && de.id.toLowerCase().includes(search.toLowerCase())) { if (filter_entity(de)) {
return { return {
...de, ...de,
m: set m: set
@@ -353,7 +348,7 @@ const SettingsCustomization: FC = () => {
margin="normal" margin="normal"
select select
> >
<MenuItem disabled key={0} value={-1}> <MenuItem disabled key={-1} value={-1}>
{LL.SELECT_DEVICE()}... {LL.SELECT_DEVICE()}...
</MenuItem> </MenuItem>
{devices.devices.map((device: DeviceShort, index) => ( {devices.devices.map((device: DeviceShort, index) => (
@@ -370,9 +365,7 @@ const SettingsCustomization: FC = () => {
return; return;
} }
const shown_data = deviceEntities.filter( const shown_data = deviceEntities.filter((de) => filter_entity(de));
(de) => (de.m & selectedFilters || !selectedFilters) && de.id.toLowerCase().includes(search.toLowerCase())
);
return ( return (
<> <>
@@ -470,7 +463,13 @@ const SettingsCustomization: FC = () => {
<Cell stiff> <Cell stiff>
<EntityMaskToggle onUpdate={updateDeviceEntity} de={de} /> <EntityMaskToggle onUpdate={updateDeviceEntity} de={de} />
</Cell> </Cell>
<Cell>{formatName(de)}</Cell> <Cell>
{formatName(de, false)}&nbsp;(
<Link target="_blank" href={APIURL + devices?.devices[selectedDevice].tn + '/' + de.id}>
{de.id}
</Link>
)
</Cell>
<Cell>{!(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.mi)}</Cell> <Cell>{!(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.mi)}</Cell>
<Cell>{!(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.ma)}</Cell> <Cell>{!(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.ma)}</Cell>
<Cell>{formatValue(de.v)}</Cell> <Cell>{formatValue(de.v)}</Cell>

View File

@@ -1,4 +1,5 @@
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import CloseIcon from '@mui/icons-material/Close';
import DoneIcon from '@mui/icons-material/Done'; import DoneIcon from '@mui/icons-material/Done';
import { import {
@@ -67,15 +68,34 @@ const SettingsCustomizationDialog = ({ open, onClose, onSave, selectedItem }: Se
<Dialog sx={dialogStyle} open={open} onClose={close}> <Dialog sx={dialogStyle} open={open} onClose={close}>
<DialogTitle>{LL.EDIT() + ' ' + LL.ENTITY()}</DialogTitle> <DialogTitle>{LL.EDIT() + ' ' + LL.ENTITY()}</DialogTitle>
<DialogContent dividers> <DialogContent dividers>
<Box color="warning.main"> <Grid container direction="row">
<Typography variant="body2">{editItem.id}</Typography> <Typography variant="body2" color="warning.main">
</Box> {LL.ENTITY() + ' ID'}:&nbsp;
<Box color="warning.main" mt={1} mb={2}>
<Typography variant="body2">
{LL.DEFAULT(1) + ' ' + LL.ENTITY_NAME(1)}:&nbsp;{editItem.n}
</Typography> </Typography>
</Box> <Typography variant="body2">{editItem.id}</Typography>
<Box mb={3}> </Grid>
<Grid container direction="row">
<Typography variant="body2" color="warning.main">
{LL.DEFAULT(1) + ' ' + LL.ENTITY_NAME(1)}:&nbsp;
</Typography>
<Typography variant="body2">{editItem.n}</Typography>
</Grid>
<Grid container direction="row">
<Typography variant="body2" color="warning.main">
{LL.WRITEABLE()}:&nbsp;
</Typography>
<Typography variant="body2">
{editItem.w ? (
<DoneIcon color="success" sx={{ fontSize: 16 }} />
) : (
<CloseIcon color="error" sx={{ fontSize: 16 }} />
)}
</Typography>
</Grid>
<Box mt={1} mb={2}>
<EntityMaskToggle onUpdate={updateDeviceEntity} de={editItem} /> <EntityMaskToggle onUpdate={updateDeviceEntity} de={editItem} />
</Box> </Box>
<Grid container spacing={1}> <Grid container spacing={1}>

View File

@@ -1,6 +1,6 @@
import AddIcon from '@mui/icons-material/Add'; import AddIcon from '@mui/icons-material/Add';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import CircleIcon from '@mui/icons-material/Circle';
import WarningIcon from '@mui/icons-material/Warning'; import WarningIcon from '@mui/icons-material/Warning';
import { Box, Typography, Divider, Stack, Button } from '@mui/material'; import { Box, Typography, Divider, Stack, Button } from '@mui/material';
@@ -216,7 +216,11 @@ const SettingsScheduler: FC = () => {
{tableList.map((si: ScheduleItem) => ( {tableList.map((si: ScheduleItem) => (
<Row key={si.id} item={si} onClick={() => editScheduleItem(si)}> <Row key={si.id} item={si} onClick={() => editScheduleItem(si)}>
<Cell stiff> <Cell stiff>
{si.active && <CheckCircleIcon sx={{ color: '#79D200', fontSize: 16, verticalAlign: 'middle' }} />} {si.active ? (
<CircleIcon color="success" sx={{ fontSize: 16, verticalAlign: 'middle' }} />
) : (
<CircleIcon color="error" sx={{ fontSize: 16, verticalAlign: 'middle' }} />
)}
</Cell> </Cell>
<Cell stiff> <Cell stiff>
<Stack spacing={1} direction="row"> <Stack spacing={1} direction="row">

View File

@@ -1,6 +1,5 @@
import AddIcon from '@mui/icons-material/Add'; import AddIcon from '@mui/icons-material/Add';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
import DoneIcon from '@mui/icons-material/Done'; import DoneIcon from '@mui/icons-material/Done';
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline'; import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
@@ -184,11 +183,6 @@ const SettingsSchedulerDialog = ({
control={<Checkbox checked={editItem.active} onChange={updateFormValue} name="active" />} control={<Checkbox checked={editItem.active} onChange={updateFormValue} name="active" />}
label={LL.ACTIVE()} label={LL.ACTIVE()}
/> />
{editItem.active && (
<Grid item sx={{ mt: 1 }}>
<CheckCircleIcon sx={{ color: '#79D200', fontSize: 16, verticalAlign: 'middle' }} />
</Grid>
)}
</Grid> </Grid>
<Grid container> <Grid container>
<TextField <TextField

View File

@@ -1355,10 +1355,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/node@npm:^20.5.7": "@types/node@npm:^20.5.8":
version: 20.5.7 version: 20.5.8
resolution: "@types/node@npm:20.5.7" resolution: "@types/node@npm:20.5.8"
checksum: e5bce3d38478f2a135e254e910f40f844d379dbc8d5576ec6532122297c435f9c05e01f585c38fb9a83e21bde2652cc266b6aa98e45c8b5e51cc5b11a4f64cf0 checksum: 5d4af299b4499c4658d5fed3475ad1039828c5a8a44cd15494d45d8d1097965b59246f140af43a9e94277007082e8d04bc4f7771a4b97a8292ffd7442240cffd
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1587,7 +1587,7 @@ __metadata:
"@table-library/react-table-library": 4.1.7 "@table-library/react-table-library": 4.1.7
"@types/babel__core": ^7 "@types/babel__core": ^7
"@types/lodash-es": ^4.17.9 "@types/lodash-es": ^4.17.9
"@types/node": ^20.5.7 "@types/node": ^20.5.8
"@types/react": ^18.2.21 "@types/react": ^18.2.21
"@types/react-dom": ^18.2.7 "@types/react-dom": ^18.2.7
"@types/react-router-dom": ^5.3.3 "@types/react-router-dom": ^5.3.3

View File

@@ -260,7 +260,7 @@ void AnalogSensor::measure() {
for (auto & sensor : sensors_) { for (auto & sensor : sensors_) {
if (sensor.type() == AnalogType::DIGITAL_IN || sensor.type() == AnalogType::COUNTER || sensor.type() == AnalogType::TIMER if (sensor.type() == AnalogType::DIGITAL_IN || sensor.type() == AnalogType::COUNTER || sensor.type() == AnalogType::TIMER
|| sensor.type() == AnalogType::RATE) { || sensor.type() == AnalogType::RATE) {
auto old_value = sensor.value(); // remember current value before reading auto old_value = sensor.value(); // remember current value before reading
auto current_reading = digitalRead(sensor.gpio()); auto current_reading = digitalRead(sensor.gpio());
if (sensor.poll_ != current_reading) { // check for pinchange if (sensor.poll_ != current_reading) { // check for pinchange
sensor.polltime_ = uuid::get_uptime(); // remember time of pinchange sensor.polltime_ = uuid::get_uptime(); // remember time of pinchange
@@ -274,7 +274,7 @@ void AnalogSensor::measure() {
} else if (!sensor.poll_) { // falling edge } else if (!sensor.poll_) { // falling edge
if (sensor.type() == AnalogType::COUNTER) { if (sensor.type() == AnalogType::COUNTER) {
sensor.set_value(old_value + sensor.factor()); sensor.set_value(old_value + sensor.factor());
} else if (sensor.type() == AnalogType::RATE) { // dafault uom: Hz (1/sec) with factor 1 } else if (sensor.type() == AnalogType::RATE) { // dafault uom: Hz (1/sec) with factor 1
sensor.set_value(sensor.factor() * 1000 / (sensor.polltime_ - sensor.last_polltime_)); sensor.set_value(sensor.factor() * 1000 / (sensor.polltime_ - sensor.last_polltime_));
} else if (sensor.type() == AnalogType::TIMER) { // default seconds with factor 1 } else if (sensor.type() == AnalogType::TIMER) { // default seconds with factor 1
sensor.set_value(sensor.factor() * (sensor.polltime_ - sensor.last_polltime_) / 1000); sensor.set_value(sensor.factor() * (sensor.polltime_ - sensor.last_polltime_) / 1000);
@@ -685,7 +685,7 @@ bool AnalogSensor::command_info(const char * value, const int8_t id, JsonObject
dataSensor["value"] = sensor.value(); dataSensor["value"] = sensor.value();
} else if (id == 0) { // output values command } else if (id == 0) { // output values command
output[sensor.name()] = sensor.value(); output[sensor.name()] = sensor.value();
} else { // if someone wants gpio numbers } else { // if someone wants gpio numbers
char gpio_str[9]; char gpio_str[9];
snprintf(gpio_str, sizeof(gpio_str), "gpio_%02d", sensor.gpio()); snprintf(gpio_str, sizeof(gpio_str), "gpio_%02d", sensor.gpio());
output[gpio_str] = sensor.value(); output[gpio_str] = sensor.value();

View File

@@ -56,7 +56,7 @@ class Command {
struct CmdFunction { struct CmdFunction {
uint8_t device_type_; // DeviceType:: uint8_t device_type_; // DeviceType::
uint8_t device_id_; uint8_t device_id_;
uint8_t flags_; // mqtt flags for command subscriptions uint8_t flags_; // mqtt flags for command subscriptions
const char * cmd_; const char * cmd_;
cmd_function_p cmdfunction_; cmd_function_p cmdfunction_;
cmd_json_function_p cmdfunction_json_; cmd_json_function_p cmdfunction_json_;

View File

@@ -87,9 +87,9 @@ class Boiler : public EMSdevice {
uint32_t wwWorkM_; // DHW minutes uint32_t wwWorkM_; // DHW minutes
int8_t wwHystOn_; int8_t wwHystOn_;
int8_t wwHystOff_; int8_t wwHystOff_;
uint8_t wwTapActivated_; // maintenance-mode to switch DHW off uint8_t wwTapActivated_; // maintenance-mode to switch DHW off
uint16_t wwMixerTemp_; // mixing temperature uint16_t wwMixerTemp_; // mixing temperature
uint16_t wwCylMiddleTemp_; // Cyl middle temperature (TS3) uint16_t wwCylMiddleTemp_; // Cyl middle temperature (TS3)
uint16_t wwSolarTemp_; uint16_t wwSolarTemp_;
uint8_t wwAlternatingOper_; // alternating operation on/off uint8_t wwAlternatingOper_; // alternating operation on/off
uint8_t wwAltOpPrioHeat_; // alternating operation, prioritize heat time uint8_t wwAltOpPrioHeat_; // alternating operation, prioritize heat time

View File

@@ -170,7 +170,7 @@ void Mixer::process_MMPLUSStatusMessage_HC(std::shared_ptr<const Telegram> teleg
void Mixer::process_MMPLUSStatusMessage_WWC(std::shared_ptr<const Telegram> telegram) { void Mixer::process_MMPLUSStatusMessage_WWC(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, flowTempHc_, 0); // is * 10 has_update(telegram, flowTempHc_, 0); // is * 10
has_bitupdate(telegram, pumpStatus_, 2, 0); has_bitupdate(telegram, pumpStatus_, 2, 0);
has_update(telegram, status_, 11); // temp status has_update(telegram, status_, 11); // temp status
} }
// Mixer IPM - 0x010C // Mixer IPM - 0x010C
@@ -220,7 +220,7 @@ void Mixer::process_MMStatusMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, flowTempHc_, 1); // is * 10 has_update(telegram, flowTempHc_, 1); // is * 10
has_bitupdate(telegram, pumpStatus_, 3, 2); // is 0 or 0x64 (100%), check only bit 2 has_bitupdate(telegram, pumpStatus_, 3, 2); // is 0 or 0x64 (100%), check only bit 2
has_update(telegram, flowSetTemp_, 0); has_update(telegram, flowSetTemp_, 0);
has_update(telegram, status_, 4); // valve status -100 to 100 has_update(telegram, status_, 4); // valve status -100 to 100
} }
/* /*

View File

@@ -685,9 +685,9 @@ void Solar::process_SM100Monitor(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, cylBottomTemp2_, 16); // is *10 - TS5: Temperature sensor 2 cylinder, bottom, or swimming pool has_update(telegram, cylBottomTemp2_, 16); // is *10 - TS5: Temperature sensor 2 cylinder, bottom, or swimming pool
has_update(telegram, heatExchangerTemp_, 20); // is *10 - TS6: Heat exchanger temperature sensor has_update(telegram, heatExchangerTemp_, 20); // is *10 - TS6: Heat exchanger temperature sensor
has_update(telegram, collector2Temp_, 6); // is *10 - TS7: Temperature sensor for collector array 2 has_update(telegram, collector2Temp_, 6); // is *10 - TS7: Temperature sensor for collector array 2
has_update(telegram, cylMiddleTemp_, 8); // is *10 - TS14: cylinder middle temperature has_update(telegram, cylMiddleTemp_, 8); // is *10 - TS14: cylinder middle temperature
has_update(telegram, retHeatAssist_, 10); // is *10 - TS15: return temperature heating assistance has_update(telegram, retHeatAssist_, 10); // is *10 - TS15: return temperature heating assistance
} }
// SM100wwTemperature - 0x07D6 // SM100wwTemperature - 0x07D6
@@ -749,8 +749,8 @@ void Solar::process_SM100Monitor2(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(heatCntFlowTemp_, 0)); // is *10 has_update(telegram->read_value(heatCntFlowTemp_, 0)); // is *10
has_update(telegram->read_value(heatCntRetTemp_, 2)); // is *10 has_update(telegram->read_value(heatCntRetTemp_, 2)); // is *10
has_update(telegram->read_value(heatCnt_, 12)); has_update(telegram->read_value(heatCnt_, 12));
has_update(telegram->read_value(swapRetTemp_, 6)); // is *10 has_update(telegram->read_value(swapRetTemp_, 6)); // is *10
has_update(telegram->read_value(swapFlowTemp_, 8)); // is *10 has_update(telegram->read_value(swapFlowTemp_, 8)); // is *10
} }
#pragma GCC diagnostic push #pragma GCC diagnostic push
@@ -879,7 +879,7 @@ void Solar::process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram)
has_update(telegram, collectorTemp_, 4); // Collector Temperature has_update(telegram, collectorTemp_, 4); // Collector Temperature
has_update(telegram, cylBottomTemp_, 6); // Temperature Bottom of Solar Boiler cyl has_update(telegram, cylBottomTemp_, 6); // Temperature Bottom of Solar Boiler cyl
uint16_t Wh = energyLastHour_ / 10; uint16_t Wh = energyLastHour_ / 10;
telegram->read_value(Wh, 2); // Solar Energy produced in last hour only ushort, is not * 10 telegram->read_value(Wh, 2); // Solar Energy produced in last hour only ushort, is not * 10
if (energyLastHour_ != Wh * 10) { if (energyLastHour_ != Wh * 10) {
energyLastHour_ = Wh * 10; energyLastHour_ = Wh * 10;
has_update(&energyLastHour_); has_update(&energyLastHour_);

View File

@@ -58,9 +58,9 @@ class Solar : public EMSdevice {
uint32_t energyLastHour_; uint32_t energyLastHour_;
uint32_t energyToday_; uint32_t energyToday_;
uint32_t energyTotal_; uint32_t energyTotal_;
uint32_t pumpWorkTime_; // Total solar pump operating time uint32_t pumpWorkTime_; // Total solar pump operating time
uint32_t pump2WorkTime_; // Total solar pump 2 operating time uint32_t pump2WorkTime_; // Total solar pump 2 operating time
uint32_t m1WorkTime_; // differential control work time uint32_t m1WorkTime_; // differential control work time
uint8_t cylHeated_; uint8_t cylHeated_;
uint8_t collectorShutdown_; // Collector shutdown on/off uint8_t collectorShutdown_; // Collector shutdown on/off

View File

@@ -661,8 +661,8 @@ void Thermostat::process_RC20Set_2(std::shared_ptr<const Telegram> telegram) {
return; return;
} }
has_update(telegram, hc->heatingtype, 0); has_update(telegram, hc->heatingtype, 0);
has_update(telegram, hc->nighttemp, 1); // is * 2, has_update(telegram, hc->nighttemp, 1); // is * 2,
has_update(telegram, hc->daytemp, 2); // is * 2, has_update(telegram, hc->daytemp, 2); // is * 2,
has_update(telegram, hc->mode, 3); has_update(telegram, hc->mode, 3);
has_enumupdate(telegram, hc->program, 11, 1); // 1 .. 9 predefined programs has_enumupdate(telegram, hc->program, 11, 1); // 1 .. 9 predefined programs
has_update(telegram, hc->tempautotemp, 13); has_update(telegram, hc->tempautotemp, 13);
@@ -798,8 +798,8 @@ void Thermostat::process_RC35wwSettings(std::shared_ptr<const Telegram> telegram
has_update(telegram, wwDisinfecting_, 4); // 0-off, 0xFF on has_update(telegram, wwDisinfecting_, 4); // 0-off, 0xFF on
has_update(telegram, wwDisinfectDay_, 5); // 0-6 Day of week, 7 every day has_update(telegram, wwDisinfectDay_, 5); // 0-6 Day of week, 7 every day
has_update(telegram, wwDisinfectHour_, 6); has_update(telegram, wwDisinfectHour_, 6);
has_update(telegram, wwMaxTemp_, 8); // Limiter 60 degrees has_update(telegram, wwMaxTemp_, 8); // Limiter 60 degrees
has_update(telegram, wwOneTimeKey_, 9); // 0-off, 0xFF on has_update(telegram, wwOneTimeKey_, 9); // 0-off, 0xFF on
} }
// Settings WW 0x3A - RC30 // Settings WW 0x3A - RC30
@@ -951,7 +951,7 @@ void Thermostat::process_RC300Monitor(std::shared_ptr<const Telegram> telegram)
return; return;
} }
has_update(telegram, hc->roomTemp, 0); // is * 10 has_update(telegram, hc->roomTemp, 0); // is * 10
has_bitupdate(telegram, hc->modetype, 10, 1); has_bitupdate(telegram, hc->modetype, 10, 1);
has_bitupdate(telegram, hc->mode, 10, 0); // bit 1, mode (auto=1 or manual=0) has_bitupdate(telegram, hc->mode, 10, 0); // bit 1, mode (auto=1 or manual=0)
@@ -1013,8 +1013,8 @@ void Thermostat::process_RC300Set(std::shared_ptr<const Telegram> telegram) {
} }
has_update(hc->tempautotemp, tat); has_update(hc->tempautotemp, tat);
has_update(telegram, hc->manualtemp, 10); // is * 2 has_update(telegram, hc->manualtemp, 10); // is * 2
has_enumupdate(telegram, hc->program, 11, 1); // timer program 1 or 2 has_enumupdate(telegram, hc->program, 11, 1); // timer program 1 or 2
has_enumupdate(telegram, hc->reducemode, 5, 1); // 1-outdoor temp threshold, 2-room temp threshold, 3-reduced mode has_enumupdate(telegram, hc->reducemode, 5, 1); // 1-outdoor temp threshold, 2-room temp threshold, 3-reduced mode
has_update(telegram, hc->reducetemp, 9); has_update(telegram, hc->reducetemp, 9);
@@ -1097,7 +1097,7 @@ void Thermostat::process_RC300WWtemp(std::shared_ptr<const Telegram> telegram) {
// RC300WWmode(0x2F5), data: 01 FF 04 00 00 00 08 05 00 08 04 00 00 00 00 00 00 00 00 00 01 // RC300WWmode(0x2F5), data: 01 FF 04 00 00 00 08 05 00 08 04 00 00 00 00 00 00 00 00 00 01
void Thermostat::process_RC300WWmode(std::shared_ptr<const Telegram> telegram) { void Thermostat::process_RC300WWmode(std::shared_ptr<const Telegram> telegram) {
// circulation pump see: https://github.com/Th3M3/buderus_ems-wiki/blob/master/Einstellungen%20der%20Bedieneinheit%20RC310.md // circulation pump see: https://github.com/Th3M3/buderus_ems-wiki/blob/master/Einstellungen%20der%20Bedieneinheit%20RC310.md
has_update(telegram, wwCircPump_, 1); // FF=off, 0=on ? has_update(telegram, wwCircPump_, 1); // FF=off, 0=on ?
has_update(telegram, wwMode_, 2); // 0=off, 1=low, 2=high, 3=auto, 4=own prog has_update(telegram, wwMode_, 2); // 0=off, 1=low, 2=high, 3=auto, 4=own prog
has_update(telegram, wwCircMode_, 3); // 0=off, 1=on, 2=auto, 4=own? has_update(telegram, wwCircMode_, 3); // 0=off, 1=on, 2=auto, 4=own?
@@ -1207,11 +1207,11 @@ void Thermostat::process_RC30Set(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, mixingvalves_, 17); // Number of Mixing Valves: (0x00=0, 0x01=1, 0x02=2) has_update(telegram, mixingvalves_, 17); // Number of Mixing Valves: (0x00=0, 0x01=1, 0x02=2)
has_update(telegram, brightness_, 18); // Screen brightness 0F=dark F1=light has_update(telegram, brightness_, 18); // Screen brightness 0F=dark F1=light
has_update(telegram, hc->mode, 23); has_update(telegram, hc->mode, 23);
has_update(telegram, hc->nofrosttemp, 24); // Set Temperature when mode is Off / 10 (e.g.: 0x0F = 7.5 degrees Celsius) has_update(telegram, hc->nofrosttemp, 24); // Set Temperature when mode is Off / 10 (e.g.: 0x0F = 7.5 degrees Celsius)
has_update(telegram, heatingpid_, 25); // PID setting 00=1 01=2 02=3 has_update(telegram, heatingpid_, 25); // PID setting 00=1 01=2 02=3
has_update(telegram, preheating_, 26); // Preheating in the clock program: (0x00 = off, 0xFF = on) has_update(telegram, preheating_, 26); // Preheating in the clock program: (0x00 = off, 0xFF = on)
has_update(telegram, hc->tempautotemp, 28); // is * 2 has_update(telegram, hc->tempautotemp, 28); // is * 2
has_update(telegram, hc->manualtemp, 29); // manualtemp is * 2 has_update(telegram, hc->manualtemp, 29); // manualtemp is * 2
} }
// type 0x40 (HC1) - for reading the operating mode from the RC30 thermostat (0x10) // type 0x40 (HC1) - for reading the operating mode from the RC30 thermostat (0x10)
@@ -1274,13 +1274,13 @@ void Thermostat::process_RC35Set(std::shared_ptr<const Telegram> telegram) {
return; return;
} }
has_update(telegram, hc->heatingtype, 0); // 0- off, 1-radiator, 2-convector, 3-floor has_update(telegram, hc->heatingtype, 0); // 0- off, 1-radiator, 2-convector, 3-floor
has_update(telegram, hc->nighttemp, 1); // is * 2 has_update(telegram, hc->nighttemp, 1); // is * 2
has_update(telegram, hc->daytemp, 2); // is * 2 has_update(telegram, hc->daytemp, 2); // is * 2
has_update(telegram, hc->holidaytemp, 3); // is * 2 has_update(telegram, hc->holidaytemp, 3); // is * 2
has_update(telegram, hc->roominfluence, 4); // is * 1 has_update(telegram, hc->roominfluence, 4); // is * 1
has_update(telegram, hc->offsettemp, 6); // is * 2 has_update(telegram, hc->offsettemp, 6); // is * 2
has_update(telegram, hc->mode, 7); // night, day, auto has_update(telegram, hc->mode, 7); // night, day, auto
has_update(telegram, hc->wwprio, 21); // 0xFF for on has_update(telegram, hc->wwprio, 21); // 0xFF for on
has_update(telegram, hc->summertemp, 22); // is * 1 has_update(telegram, hc->summertemp, 22); // is * 1
@@ -1291,10 +1291,10 @@ void Thermostat::process_RC35Set(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, hc->control, 26); // 0-off, 1-RC20 (remote), 2-RC35 has_update(telegram, hc->control, 26); // 0-off, 1-RC20 (remote), 2-RC35
has_update(telegram, hc->controlmode, 33); // 0-outdoortemp, 1-roomtemp has_update(telegram, hc->controlmode, 33); // 0-outdoortemp, 1-roomtemp
has_update(telegram, hc->tempautotemp, 37); has_update(telegram, hc->tempautotemp, 37);
has_update(telegram, hc->noreducetemp, 38); // outdoor temperature for no reduce has_update(telegram, hc->noreducetemp, 38); // outdoor temperature for no reduce
has_update(telegram, hc->reducetemp, 39); // temperature for off/reduce has_update(telegram, hc->reducetemp, 39); // temperature for off/reduce
has_update(telegram, hc->vacreducetemp, 40); // temperature for off/reduce in vacations has_update(telegram, hc->vacreducetemp, 40); // temperature for off/reduce in vacations
has_update(telegram, hc->vacreducemode, 41); // vacations reduce mode has_update(telegram, hc->vacreducemode, 41); // vacations reduce mode
has_update(telegram, hc->minflowtemp, 16); has_update(telegram, hc->minflowtemp, 16);
// RC35 stores values for floorheating in different position // RC35 stores values for floorheating in different position
@@ -1416,7 +1416,7 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
bool ivtclock = (telegram->message_data[0] & 0x80) == 0x80; // dont sync ivt-clock, #439 bool ivtclock = (telegram->message_data[0] & 0x80) == 0x80; // dont sync ivt-clock, #439
bool junkersclock = model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS; bool junkersclock = model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS;
time_t ttime = mktime(tm_); // thermostat time time_t ttime = mktime(tm_); // thermostat time
// correct thermostat clock if we have valid ntp time, and could write the command // correct thermostat clock if we have valid ntp time, and could write the command
if (!ivtclock && !junkersclock && tset_ && EMSESP::system_.ntp_connected() && !EMSESP::system_.readonly_mode() && has_command(&dateTime_)) { if (!ivtclock && !junkersclock && tset_ && EMSESP::system_.ntp_connected() && !EMSESP::system_.readonly_mode() && has_command(&dateTime_)) {
double difference = difftime(now, ttime); double difference = difftime(now, ttime);
@@ -1426,7 +1426,7 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
} }
} }
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
if (!tset_ && tm_->tm_year > 110) { // emsesp clock not set, but thermostat clock if (!tset_ && tm_->tm_year > 110) { // emsesp clock not set, but thermostat clock
if (ivtclock) { if (ivtclock) {
tm_->tm_isdst = -1; // determine dst tm_->tm_isdst = -1; // determine dst
ttime = mktime(tm_); // thermostat time ttime = mktime(tm_); // thermostat time
@@ -2302,7 +2302,7 @@ bool Thermostat::set_datetime(const char * value, const int8_t id) {
data[6] = (tm_->tm_wday + 6) % 7; // Bosch counts from Mo, time from Su data[6] = (tm_->tm_wday + 6) % 7; // Bosch counts from Mo, time from Su
data[7] = tm_->tm_isdst + 2; // set DST and flag for ext. clock data[7] = tm_->tm_isdst + 2; // set DST and flag for ext. clock
if (model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) { if (model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
data[6]++; // Junkers use 1-7; data[6]++; // Junkers use 1-7;
data[7] = 0; data[7] = 0;
} }
} else if (dt.length() == 23) { } else if (dt.length() == 23) {
@@ -2500,7 +2500,7 @@ bool Thermostat::set_mode_n(const uint8_t mode, const uint8_t hc_num) {
if (mode == HeatingCircuit::Mode::AUTO) { if (mode == HeatingCircuit::Mode::AUTO) {
set_mode_value = 0xFF; // special value for auto set_mode_value = 0xFF; // special value for auto
} else { } else {
set_mode_value = 0; // everything else, like manual/day etc.. set_mode_value = 0; // everything else, like manual/day etc..
} }
break; break;
case EMSdevice::EMS_DEVICE_FLAG_JUNKERS: case EMSdevice::EMS_DEVICE_FLAG_JUNKERS:
@@ -3121,7 +3121,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
offset = 0x0A; // manual offset offset = 0x0A; // manual offset
break; break;
case HeatingCircuit::Mode::TEMPAUTO: case HeatingCircuit::Mode::TEMPAUTO:
offset = 0x08; // auto offset offset = 0x08; // auto offset
if (temperature == -1) { if (temperature == -1) {
factor = 1; // to write 0xFF factor = 1; // to write 0xFF
} }

View File

@@ -256,9 +256,9 @@ class Thermostat : public EMSdevice {
static constexpr uint16_t EMS_TYPE_RCOutdoorTemp = 0xA3; // is an automatic thermostat broadcast, outdoor external temp static constexpr uint16_t EMS_TYPE_RCOutdoorTemp = 0xA3; // is an automatic thermostat broadcast, outdoor external temp
// Type offsets // Type offsets
static constexpr uint8_t EMS_OFFSET_RC10StatusMessage_setpoint = 1; // setpoint temp static constexpr uint8_t EMS_OFFSET_RC10StatusMessage_setpoint = 1; // setpoint temp
static constexpr uint8_t EMS_OFFSET_RC10StatusMessage_curr = 2; // current temp static constexpr uint8_t EMS_OFFSET_RC10StatusMessage_curr = 2; // current temp
static constexpr uint8_t EMS_OFFSET_RC10Set_temp = 4; // position of thermostat setpoint temperature static constexpr uint8_t EMS_OFFSET_RC10Set_temp = 4; // position of thermostat setpoint temperature
static constexpr uint8_t EMS_OFFSET_RC20StatusMessage_setpoint = 1; // setpoint temp static constexpr uint8_t EMS_OFFSET_RC20StatusMessage_setpoint = 1; // setpoint temp
static constexpr uint8_t EMS_OFFSET_RC20StatusMessage_curr = 2; // current temp static constexpr uint8_t EMS_OFFSET_RC20StatusMessage_curr = 2; // current temp
@@ -267,9 +267,9 @@ class Thermostat : public EMSdevice {
static constexpr uint8_t EMS_OFFSET_RC20Set_temp_auto = 28; // position of thermostat setpoint temperature static constexpr uint8_t EMS_OFFSET_RC20Set_temp_auto = 28; // position of thermostat setpoint temperature
static constexpr uint8_t EMS_OFFSET_RC20Set_temp_manual = 29; // position of thermostat setpoint temperature static constexpr uint8_t EMS_OFFSET_RC20Set_temp_manual = 29; // position of thermostat setpoint temperature
static constexpr uint8_t EMS_OFFSET_RC20_2_Set_mode = 3; // ES72 - see https://github.com/emsesp/EMS-ESP/issues/334 static constexpr uint8_t EMS_OFFSET_RC20_2_Set_mode = 3; // ES72 - see https://github.com/emsesp/EMS-ESP/issues/334
static constexpr uint8_t EMS_OFFSET_RC20_2_Set_temp_night = 1; // ES72 static constexpr uint8_t EMS_OFFSET_RC20_2_Set_temp_night = 1; // ES72
static constexpr uint8_t EMS_OFFSET_RC20_2_Set_temp_day = 2; // ES72 static constexpr uint8_t EMS_OFFSET_RC20_2_Set_temp_day = 2; // ES72
static constexpr uint8_t EMS_OFFSET_RC30StatusMessage_setpoint = 1; // setpoint temp static constexpr uint8_t EMS_OFFSET_RC30StatusMessage_setpoint = 1; // setpoint temp
static constexpr uint8_t EMS_OFFSET_RC30StatusMessage_curr = 2; // current temp static constexpr uint8_t EMS_OFFSET_RC30StatusMessage_curr = 2; // current temp
@@ -308,8 +308,8 @@ class Thermostat : public EMSdevice {
static constexpr uint8_t EMS_OFFSET_RC35Set_temp_summer = 22; static constexpr uint8_t EMS_OFFSET_RC35Set_temp_summer = 22;
static constexpr uint8_t EMS_OFFSET_RC35Set_temp_nofrost = 23; static constexpr uint8_t EMS_OFFSET_RC35Set_temp_nofrost = 23;
static constexpr uint8_t EMS_OFFSET_EasyStatusMessage_setpoint = 10; // setpoint temp static constexpr uint8_t EMS_OFFSET_EasyStatusMessage_setpoint = 10; // setpoint temp
static constexpr uint8_t EMS_OFFSET_EasyStatusMessage_curr = 8; // current temp static constexpr uint8_t EMS_OFFSET_EasyStatusMessage_curr = 8; // current temp
static constexpr uint8_t EMS_OFFSET_RCPLUSStatusMessage_mode = 10; // thermostat mode (auto, manual) static constexpr uint8_t EMS_OFFSET_RCPLUSStatusMessage_mode = 10; // thermostat mode (auto, manual)
static constexpr uint8_t EMS_OFFSET_RCPLUSStatusMessage_setpoint = 3; // setpoint temp static constexpr uint8_t EMS_OFFSET_RCPLUSStatusMessage_setpoint = 3; // setpoint temp

View File

@@ -520,7 +520,7 @@ void EMSdevice::add_device_value(uint8_t tag, // to b
// get fullname, getting translation if it exists // get fullname, getting translation if it exists
const char * const * fullname; const char * const * fullname;
if (Helpers::count_items(name) == 1) { if (Helpers::count_items(name) == 1) {
fullname = nullptr; // no translations available, use empty fullname = nullptr; // no translations available, use empty
} else { } else {
fullname = &name[1]; // translations start at index 1 fullname = &name[1]; // translations start at index 1
} }
@@ -1311,7 +1311,7 @@ void EMSdevice::dump_value_info() {
if (dv.type == DeviceValueType::BOOL) { if (dv.type == DeviceValueType::BOOL) {
snprintf(entityid, sizeof(entityid), "binary_sensor.%s", entity_with_tag); // binary sensor (for booleans) snprintf(entityid, sizeof(entityid), "binary_sensor.%s", entity_with_tag); // binary sensor (for booleans)
} else { } else {
snprintf(entityid, sizeof(entityid), "sensor.%s", entity_with_tag); // normal HA sensor snprintf(entityid, sizeof(entityid), "sensor.%s", entity_with_tag); // normal HA sensor
} }
} }

View File

@@ -459,7 +459,7 @@ class EMSdevice {
std::vector<TelegramFunction> telegram_functions_; // each EMS device has its own set of registered telegram types std::vector<TelegramFunction> telegram_functions_; // each EMS device has its own set of registered telegram types
std::vector<DeviceValue> devicevalues_; // all the device values std::vector<DeviceValue> devicevalues_; // all the device values
std::vector<uint16_t> handlers_ignored_; std::vector<uint16_t> handlers_ignored_;
}; };

View File

@@ -145,12 +145,12 @@ class DeviceValue {
DV_NUMOP_MUL15 = -15 DV_NUMOP_MUL15 = -15
}; };
uint8_t device_type; // EMSdevice::DeviceType uint8_t device_type; // EMSdevice::DeviceType
uint8_t tag; // DeviceValueTAG::* uint8_t tag; // DeviceValueTAG::*
void * value_p; // pointer to variable of any type void * value_p; // pointer to variable of any type
uint8_t type; // DeviceValueType::* uint8_t type; // DeviceValueType::*
const char * const ** options; // options as a flash char array const char * const ** options; // options as a flash char array
const char * const * options_single; // options are not translated const char * const * options_single; // options are not translated
int8_t numeric_operator; int8_t numeric_operator;
uint8_t options_size; // number of options in the char array, calculated uint8_t options_size; // number of options in the char array, calculated
const char * const short_name; // used in MQTT and API const char * const short_name; // used in MQTT and API

View File

@@ -163,7 +163,7 @@ class EMSESP {
} }
static void watch(uint8_t watch) { static void watch(uint8_t watch) {
watch_ = watch; // 0=off, 1=on, 2=raw watch_ = watch; // 0=off, 1=on, 2=raw
if (watch == WATCH_OFF) { if (watch == WATCH_OFF) {
watch_id_ = 0; // reset watch id if watch is disabled watch_id_ = 0; // reset watch id if watch is disabled
} }

View File

@@ -385,7 +385,7 @@ std::string Helpers::data_to_hex(const uint8_t * data, const uint8_t length) {
*p++ = buffer[1]; *p++ = buffer[1];
*p++ = ' '; // space *p++ = ' '; // space
} }
*--p = '\0'; // null terminate just in case, loosing the trailing space *--p = '\0'; // null terminate just in case, loosing the trailing space
return std::string(str); return std::string(str);
} }

View File

@@ -592,7 +592,8 @@ bool Mqtt::queue_message(const uint8_t operation, const std::string & topic, con
if (!mqtt_enabled_ || topic.empty()) { if (!mqtt_enabled_ || topic.empty()) {
return false; // quit, not using MQTT return false; // quit, not using MQTT
} }
// check free mem // check free mem
#ifndef EMSESP_STANDALONE
if (ESP.getFreeHeap() < 60 * 1204) { if (ESP.getFreeHeap() < 60 * 1204) {
if (operation == Operation::PUBLISH) { if (operation == Operation::PUBLISH) {
mqtt_message_id_++; mqtt_message_id_++;
@@ -601,6 +602,7 @@ bool Mqtt::queue_message(const uint8_t operation, const std::string & topic, con
LOG_DEBUG("%s failed: low memory", operation == Operation::PUBLISH ? "Publish" : operation == Operation::SUBSCRIBE ? "Subscribe" : "Unsubscribe"); LOG_DEBUG("%s failed: low memory", operation == Operation::PUBLISH ? "Publish" : operation == Operation::SUBSCRIBE ? "Subscribe" : "Unsubscribe");
return false; // quit return false; // quit
} }
#endif
uint16_t packet_id = 0; uint16_t packet_id = 0;
char fulltopic[MQTT_TOPIC_MAX_SIZE]; char fulltopic[MQTT_TOPIC_MAX_SIZE];

View File

@@ -847,7 +847,7 @@ void System::led_monitor() {
} }
if (led_on_) { if (led_on_) {
digitalWrite(led_gpio_, LED_ON); // LED off digitalWrite(led_gpio_, LED_ON); // LED off
} }
#endif #endif
} else { } else {
@@ -1432,27 +1432,27 @@ bool System::command_test(const char * value, const int8_t id) {
// 3 = RMII clock output from GPIO17, for 50hz inverted clock // 3 = RMII clock output from GPIO17, for 50hz inverted clock
bool System::load_board_profile(std::vector<int8_t> & data, const std::string & board_profile) { bool System::load_board_profile(std::vector<int8_t> & data, const std::string & board_profile) {
if (board_profile == "S32") { if (board_profile == "S32") {
data = {2, 18, 23, 5, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // BBQKees Gateway S32 data = {2, 18, 23, 5, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // BBQKees Gateway S32
} else if (board_profile == "E32") { } else if (board_profile == "E32") {
data = {2, 4, 5, 17, 33, PHY_type::PHY_TYPE_LAN8720, 16, 1, 0}; // BBQKees Gateway E32 data = {2, 4, 5, 17, 33, PHY_type::PHY_TYPE_LAN8720, 16, 1, 0}; // BBQKees Gateway E32
} else if (board_profile == "MH-ET") { } else if (board_profile == "MH-ET") {
data = {2, 18, 23, 5, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // MH-ET Live D1 Mini data = {2, 18, 23, 5, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // MH-ET Live D1 Mini
} else if (board_profile == "NODEMCU") { } else if (board_profile == "NODEMCU") {
data = {2, 18, 23, 5, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // NodeMCU 32S data = {2, 18, 23, 5, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // NodeMCU 32S
} else if (board_profile == "LOLIN") { } else if (board_profile == "LOLIN") {
data = {2, 18, 17, 16, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin D32 data = {2, 18, 17, 16, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin D32
} else if (board_profile == "OLIMEX") { } else if (board_profile == "OLIMEX") {
data = {0, 0, 36, 4, 34, PHY_type::PHY_TYPE_LAN8720, -1, 0, 0}; // Olimex ESP32-EVB (uses U1TXD/U1RXD/BUTTON, no LED or Temperature sensor) data = {0, 0, 36, 4, 34, PHY_type::PHY_TYPE_LAN8720, -1, 0, 0}; // Olimex ESP32-EVB (uses U1TXD/U1RXD/BUTTON, no LED or Temperature sensor)
} else if (board_profile == "OLIMEXPOE") { } else if (board_profile == "OLIMEXPOE") {
data = {0, 0, 36, 4, 34, PHY_type::PHY_TYPE_LAN8720, 12, 0, 3}; // Olimex ESP32-POE data = {0, 0, 36, 4, 34, PHY_type::PHY_TYPE_LAN8720, 12, 0, 3}; // Olimex ESP32-POE
} else if (board_profile == "C3MINI") { } else if (board_profile == "C3MINI") {
data = {7, 1, 4, 5, 9, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin C3 Mini data = {7, 1, 4, 5, 9, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin C3 Mini
} else if (board_profile == "S2MINI") { } else if (board_profile == "S2MINI") {
data = {15, 7, 11, 12, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin S2 Mini data = {15, 7, 11, 12, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin S2 Mini
} else if (board_profile == "S3MINI") { } else if (board_profile == "S3MINI") {
data = {17, 18, 8, 5, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Liligo S3 data = {17, 18, 8, 5, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Liligo S3
} else if (board_profile == "S32S3") { } else if (board_profile == "S32S3") {
data = {2, 18, 5, 17, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // BBQKees Gateway S3 data = {2, 18, 5, 17, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // BBQKees Gateway S3
} else if (board_profile == "CUSTOM") { } else if (board_profile == "CUSTOM") {
// send back current values // send back current values
data = {(int8_t)EMSESP::system_.led_gpio_, data = {(int8_t)EMSESP::system_.led_gpio_,

View File

@@ -148,11 +148,11 @@ void RxService::add(uint8_t * data, uint8_t length) {
// validate the CRC. if it fails then increment the number of corrupt/incomplete telegrams and only report to console/syslog // validate the CRC. if it fails then increment the number of corrupt/incomplete telegrams and only report to console/syslog
uint8_t crc = calculate_crc(data, length - 1); uint8_t crc = calculate_crc(data, length - 1);
if (data[length - 1] != crc) { if (data[length - 1] != crc) {
if ((data[0] & 0x7F) != ems_bus_id()) { // do not count echos as errors if ((data[0] & 0x7F) != ems_bus_id()) { // do not count echos as errors
telegram_error_count_++; telegram_error_count_++;
LOG_WARNING("Incomplete Rx: %s", Helpers::data_to_hex(data, length - 1).c_str()); // exclude CRC LOG_WARNING("Incomplete Rx: %s", Helpers::data_to_hex(data, length - 1).c_str()); // exclude CRC
} else { } else {
LOG_TRACE("Incomplete Rx: %s", Helpers::data_to_hex(data, length - 1).c_str()); // exclude CRC LOG_TRACE("Incomplete Rx: %s", Helpers::data_to_hex(data, length - 1).c_str()); // exclude CRC
} }
return; return;
} }
@@ -347,7 +347,7 @@ void TxService::send_telegram(const QueuedTxTelegram & tx_telegram) {
telegram_raw[5] = (telegram->type_id >> 8) - 1; // type, 1st byte, high-byte, subtract 0x100 telegram_raw[5] = (telegram->type_id >> 8) - 1; // type, 1st byte, high-byte, subtract 0x100
telegram_raw[6] = telegram->type_id & 0xFF; // type, 2nd byte, low-byte telegram_raw[6] = telegram->type_id & 0xFF; // type, 2nd byte, low-byte
message_p = 7; message_p = 7;
copy_data = false; // there are no more data values after the type_id when reading on EMS+ copy_data = false; // there are no more data values after the type_id when reading on EMS+
} }
} else { } else {
// EMS 1.0 // EMS 1.0
@@ -396,11 +396,11 @@ void TxService::send_telegram(const QueuedTxTelegram & tx_telegram) {
if (status == EMS_TX_STATUS_ERR) { if (status == EMS_TX_STATUS_ERR) {
LOG_ERROR("Failed to transmit Tx via UART."); LOG_ERROR("Failed to transmit Tx via UART.");
if (telegram->operation == Telegram::Operation::TX_READ) { if (telegram->operation == Telegram::Operation::TX_READ) {
increment_telegram_read_fail_count(); // another Tx fail increment_telegram_read_fail_count(); // another Tx fail
} else { } else {
increment_telegram_write_fail_count(); // another Tx fail increment_telegram_write_fail_count(); // another Tx fail
} }
tx_state(Telegram::Operation::NONE); // nothing send, tx not in wait state tx_state(Telegram::Operation::NONE); // nothing send, tx not in wait state
return; return;
} }
@@ -456,7 +456,7 @@ void TxService::add(const uint8_t operation,
if (front) { if (front) {
tx_telegrams_.emplace_front(tx_telegram_id_++, std::move(telegram), false, validateid); // add to front of queue tx_telegrams_.emplace_front(tx_telegram_id_++, std::move(telegram), false, validateid); // add to front of queue
} else { } else {
tx_telegrams_.emplace_back(tx_telegram_id_++, std::move(telegram), false, validateid); // add to back of queue tx_telegrams_.emplace_back(tx_telegram_id_++, std::move(telegram), false, validateid); // add to back of queue
} }
if (validateid != 0) { if (validateid != 0) {
EMSESP::wait_validate(validateid); EMSESP::wait_validate(validateid);
@@ -595,14 +595,14 @@ bool TxService::send_raw(const char * telegram_data) {
void TxService::retry_tx(const uint8_t operation, const uint8_t * data, const uint8_t length) { void TxService::retry_tx(const uint8_t operation, const uint8_t * data, const uint8_t length) {
// have we reached the limit? if so, reset count and give up // have we reached the limit? if so, reset count and give up
if (++retry_count_ > MAXIMUM_TX_RETRIES) { if (++retry_count_ > MAXIMUM_TX_RETRIES) {
reset_retry_count(); // give up reset_retry_count(); // give up
EMSESP::wait_validate(0); // do not wait for validation EMSESP::wait_validate(0); // do not wait for validation
if (operation == Telegram::Operation::TX_READ) { if (operation == Telegram::Operation::TX_READ) {
if (telegram_last_->offset > 0) { // ignore errors for higher offsets if (telegram_last_->offset > 0) { // ignore errors for higher offsets
LOG_DEBUG("Last Tx Read operation failed after %d retries. Ignoring request: %s", MAXIMUM_TX_RETRIES, telegram_last_->to_string().c_str()); LOG_DEBUG("Last Tx Read operation failed after %d retries. Ignoring request: %s", MAXIMUM_TX_RETRIES, telegram_last_->to_string().c_str());
return; return;
} }
increment_telegram_read_fail_count(); // another Tx fail increment_telegram_read_fail_count(); // another Tx fail
} else { } else {
increment_telegram_write_fail_count(); // another Tx fail increment_telegram_write_fail_count(); // another Tx fail
} }

View File

@@ -48,8 +48,8 @@ static constexpr int16_t EMS_VALUE_SHORT_NOTSET = 0x7D00; // 32000: for 2-
static constexpr uint32_t EMS_VALUE_ULONG_NOTSET = 0x00FFFFFF; // for 3-byte longs static constexpr uint32_t EMS_VALUE_ULONG_NOTSET = 0x00FFFFFF; // for 3-byte longs
static constexpr uint32_t EMS_VALUE_ULLONG_NOTSET = 0xFFFFFFFF; // for 4-byte longs static constexpr uint32_t EMS_VALUE_ULLONG_NOTSET = 0xFFFFFFFF; // for 4-byte longs
static constexpr uint8_t EMS_MAX_TELEGRAM_LENGTH = 32; // max length of a complete EMS telegram static constexpr uint8_t EMS_MAX_TELEGRAM_LENGTH = 32; // max length of a complete EMS telegram
static constexpr uint8_t EMS_MAX_TELEGRAM_MESSAGE_LENGTH = 27; // max length of message block, assuming EMS1.0 static constexpr uint8_t EMS_MAX_TELEGRAM_MESSAGE_LENGTH = 27; // max length of message block, assuming EMS1.0
#define EMS_VALUE_DEFAULT_INT EMS_VALUE_INT_NOTSET #define EMS_VALUE_DEFAULT_INT EMS_VALUE_INT_NOTSET
#define EMS_VALUE_DEFAULT_UINT EMS_VALUE_UINT_NOTSET #define EMS_VALUE_DEFAULT_UINT EMS_VALUE_UINT_NOTSET
@@ -232,13 +232,13 @@ class EMSbus {
private: private:
static constexpr uint32_t EMS_BUS_TIMEOUT = 30000; // timeout in ms before recognizing the ems bus is offline (30 seconds) static constexpr uint32_t EMS_BUS_TIMEOUT = 30000; // timeout in ms before recognizing the ems bus is offline (30 seconds)
static uint32_t last_bus_activity_; // timestamp of last time a valid Rx came in static uint32_t last_bus_activity_; // timestamp of last time a valid Rx came in
static uint32_t bus_uptime_start_; // timestamp of first time we connected to the bus static uint32_t bus_uptime_start_; // timestamp of first time we connected to the bus
static bool bus_connected_; // start assuming the bus hasn't been connected static bool bus_connected_; // start assuming the bus hasn't been connected
static uint8_t ems_mask_; // unset=0xFF, buderus=0x00, junkers/ht3=0x80 static uint8_t ems_mask_; // unset=0xFF, buderus=0x00, junkers/ht3=0x80
static uint8_t ems_bus_id_; // the bus id, which configurable and stored in settings static uint8_t ems_bus_id_; // the bus id, which configurable and stored in settings
static uint8_t tx_mode_; // local copy of the tx mode static uint8_t tx_mode_; // local copy of the tx mode
static uint8_t tx_state_; // state of the Tx line (NONE or waiting on a TX_READ or TX_WRITE) static uint8_t tx_state_; // state of the Tx line (NONE or waiting on a TX_READ or TX_WRITE)
}; };
class RxService : public EMSbus { class RxService : public EMSbus {
@@ -433,17 +433,17 @@ class TxService : public EMSbus {
private: private:
std::deque<QueuedTxTelegram> tx_telegrams_; // the Tx queue std::deque<QueuedTxTelegram> tx_telegrams_; // the Tx queue
uint32_t telegram_read_count_ = 0; // # Tx successful reads uint32_t telegram_read_count_ = 0; // # Tx successful reads
uint32_t telegram_write_count_ = 0; // # Tx successful writes uint32_t telegram_write_count_ = 0; // # Tx successful writes
uint32_t telegram_read_fail_count_ = 0; // # Tx unsuccessful transmits uint32_t telegram_read_fail_count_ = 0; // # Tx unsuccessful transmits
uint32_t telegram_write_fail_count_ = 0; // # Tx unsuccessful transmits uint32_t telegram_write_fail_count_ = 0; // # Tx unsuccessful transmits
std::shared_ptr<Telegram> telegram_last_; std::shared_ptr<Telegram> telegram_last_;
uint16_t telegram_last_post_send_query_; // which type ID to query after a successful send, to read back the values just written uint16_t telegram_last_post_send_query_; // which type ID to query after a successful send, to read back the values just written
uint8_t retry_count_ = 0; // count for # Tx retries uint8_t retry_count_ = 0; // count for # Tx retries
uint32_t delayed_send_ = 0; // manage delay for post send query uint32_t delayed_send_ = 0; // manage delay for post send query
uint8_t tx_telegram_id_ = 0; // queue counter uint8_t tx_telegram_id_ = 0; // queue counter
void send_telegram(const QueuedTxTelegram & tx_telegram); void send_telegram(const QueuedTxTelegram & tx_telegram);
}; };

View File

@@ -214,7 +214,7 @@ void TemperatureSensor::loop() {
// LOG_DEBUG("Adding %d sensor(s) from first scan", firstscan_); // LOG_DEBUG("Adding %d sensor(s) from first scan", firstscan_);
} else if ((scancnt_ <= 0) && (firstscan_ != sensors_.size())) { // check 2 times for no change of sensor # } else if ((scancnt_ <= 0) && (firstscan_ != sensors_.size())) { // check 2 times for no change of sensor #
scancnt_ = SCAN_START; scancnt_ = SCAN_START;
sensors_.clear(); // restart scanning and clear to get correct numbering sensors_.clear(); // restart scanning and clear to get correct numbering
} }
state_ = State::IDLE; state_ = State::IDLE;
} }
@@ -576,7 +576,7 @@ TemperatureSensor::Sensor::Sensor(const uint8_t addr[])
(unsigned int)(internal_id_ >> 48) & 0xFF, (unsigned int)(internal_id_ >> 48) & 0xFF,
(unsigned int)(internal_id_ >> 32) & 0xFFFF, (unsigned int)(internal_id_ >> 32) & 0xFFFF,
(unsigned int)(internal_id_ >> 16) & 0xFFFF, (unsigned int)(internal_id_ >> 16) & 0xFFFF,
(unsigned int)(internal_id_)&0xFFFF); (unsigned int)(internal_id_) & 0xFFFF);
id_ = std::string(id_s); id_ = std::string(id_s);
name_ = std::string{}; // name (alias) is empty name_ = std::string{}; // name (alias) is empty
offset_ = 0; // 0 degrees offset offset_ = 0; // 0 degrees offset

View File

@@ -132,7 +132,7 @@ class TemperatureSensor {
static constexpr uint8_t TYPE_DS18B20 = 0x28; static constexpr uint8_t TYPE_DS18B20 = 0x28;
static constexpr uint8_t TYPE_DS18S20 = 0x10; static constexpr uint8_t TYPE_DS18S20 = 0x10;
static constexpr uint8_t TYPE_DS1822 = 0x22; static constexpr uint8_t TYPE_DS1822 = 0x22;
static constexpr uint8_t TYPE_DS1825 = 0x3B; // also DS1826 static constexpr uint8_t TYPE_DS1825 = 0x3B; // also DS1826
static constexpr uint32_t READ_INTERVAL_MS = 5000; // 5 seconds static constexpr uint32_t READ_INTERVAL_MS = 5000; // 5 seconds
static constexpr uint32_t CONVERSION_MS = 1000; // 1 seconds static constexpr uint32_t CONVERSION_MS = 1000; // 1 seconds

View File

@@ -86,7 +86,7 @@ void EMSuart::start(const uint8_t tx_mode, const uint8_t rx_gpio, const uint8_t
uart_set_pin(EMSUART_NUM, tx_gpio, rx_gpio, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); uart_set_pin(EMSUART_NUM, tx_gpio, rx_gpio, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(EMSUART_NUM, 129, 0, (EMS_MAXBUFFERSIZE + 1) * 2, &uart_queue, 0); // buffer must be > fifo uart_driver_install(EMSUART_NUM, 129, 0, (EMS_MAXBUFFERSIZE + 1) * 2, &uart_queue, 0); // buffer must be > fifo
uart_set_rx_full_threshold(EMSUART_NUM, 1); uart_set_rx_full_threshold(EMSUART_NUM, 1);
uart_set_rx_timeout(EMSUART_NUM, 0); // disable uart_set_rx_timeout(EMSUART_NUM, 0); // disable
// note esp32s3 crashes with 2k stacksize, stack overflow here sometimes wipes settingsfiles. // note esp32s3 crashes with 2k stacksize, stack overflow here sometimes wipes settingsfiles.
xTaskCreate(uart_event_task, "uart_event_task", 2560, NULL, configMAX_PRIORITIES - 1, NULL); xTaskCreate(uart_event_task, "uart_event_task", 2560, NULL, configMAX_PRIORITIES - 1, NULL);

View File

@@ -24,7 +24,7 @@
#ifndef EMSESP_EMSUART_H #ifndef EMSESP_EMSUART_H
#define EMSESP_EMSUART_H #define EMSESP_EMSUART_H
#define EMS_MAXBUFFERSIZE 33 // max size of the buffer. EMS packets are max 32 bytes, plus extra for BRK #define EMS_MAXBUFFERSIZE 33 // max size of the buffer. EMS packets are max 32 bytes, plus extra for BRK
#define EMSUART_NUM UART_NUM_1 // on C3 and S2 there is no UART2, use UART1 for all #define EMSUART_NUM UART_NUM_1 // on C3 and S2 there is no UART2, use UART1 for all
#define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit #define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.7.0-dev.2" #define EMSESP_APP_VERSION "3.6.1-dev.0"

View File

@@ -156,7 +156,7 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) {
if (sensor.type() != AnalogSensor::AnalogType::NOTUSED) { if (sensor.type() != AnalogSensor::AnalogType::NOTUSED) {
obj["v"] = Helpers::transformNumFloat(sensor.value(), 0); // is optional and is a float obj["v"] = Helpers::transformNumFloat(sensor.value(), 0); // is optional and is a float
} else { } else {
obj["v"] = 0; // must have a value for web sorting to work obj["v"] = 0; // must have a value for web sorting to work
} }
} }
} }

View File

@@ -66,7 +66,7 @@ class WebLogService : public uuid::log::Handler {
void setValues(AsyncWebServerRequest * request, JsonVariant & json); void setValues(AsyncWebServerRequest * request, JsonVariant & json);
AsyncCallbackJsonWebHandler setValues_; // for POSTs AsyncCallbackJsonWebHandler setValues_; // for POSTs
uint64_t last_transmit_ = 0; // Last transmit time uint64_t last_transmit_ = 0; // Last transmit time
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; // Maximum number of log messages to buffer before they are output size_t maximum_log_messages_ = MAX_LOG_MESSAGES; // Maximum number of log messages to buffer before they are output

View File

@@ -86,7 +86,7 @@ StateUpdateResult WebScheduler::update(JsonObject & root, WebScheduler & webSche
// calculated elapsed minutes // calculated elapsed minutes
si.elapsed_min = Helpers::string2minutes(si.time); si.elapsed_min = Helpers::string2minutes(si.time);
si.retry_cnt = 0xFF; // no startup retries si.retry_cnt = 0xFF; // no startup retries
webScheduler.scheduleItems.push_back(si); // add to list webScheduler.scheduleItems.push_back(si); // add to list
if (!webScheduler.scheduleItems.back().name.empty()) { if (!webScheduler.scheduleItems.back().name.empty()) {

View File

@@ -22,8 +22,8 @@
#define EMSESP_SCHEDULER_FILE "/config/emsespScheduler.json" #define EMSESP_SCHEDULER_FILE "/config/emsespScheduler.json"
#define EMSESP_SCHEDULER_SERVICE_PATH "/rest/schedule" // GET and POST #define EMSESP_SCHEDULER_SERVICE_PATH "/rest/schedule" // GET and POST
#define SCHEDULEFLAG_SCHEDULE_TIMER 0x80 // 7th bit for Timer #define SCHEDULEFLAG_SCHEDULE_TIMER 0x80 // 7th bit for Timer
#define MAX_STARTUP_RETRIES 3 // retry the start-up commands x times #define MAX_STARTUP_RETRIES 3 // retry the start-up commands x times
namespace emsesp { namespace emsesp {

View File

@@ -228,61 +228,61 @@ void WebStatusService::mDNS_start() const {
const char * WebStatusService::disconnectReason(uint8_t code) { const char * WebStatusService::disconnectReason(uint8_t code) {
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
switch (code) { switch (code) {
case WIFI_REASON_UNSPECIFIED: // = 1, case WIFI_REASON_UNSPECIFIED: // = 1,
return "unspecified"; return "unspecified";
case WIFI_REASON_AUTH_EXPIRE: // = 2, case WIFI_REASON_AUTH_EXPIRE: // = 2,
return "auth expire"; return "auth expire";
case WIFI_REASON_AUTH_LEAVE: // = 3, case WIFI_REASON_AUTH_LEAVE: // = 3,
return "auth leave"; return "auth leave";
case WIFI_REASON_ASSOC_EXPIRE: // = 4, case WIFI_REASON_ASSOC_EXPIRE: // = 4,
return "assoc expired"; return "assoc expired";
case WIFI_REASON_ASSOC_TOOMANY: // = 5, case WIFI_REASON_ASSOC_TOOMANY: // = 5,
return "assoc too many"; return "assoc too many";
case WIFI_REASON_NOT_AUTHED: // = 6, case WIFI_REASON_NOT_AUTHED: // = 6,
return "not authenticated"; return "not authenticated";
case WIFI_REASON_NOT_ASSOCED: // = 7, case WIFI_REASON_NOT_ASSOCED: // = 7,
return "not assoc"; return "not assoc";
case WIFI_REASON_ASSOC_LEAVE: // = 8, case WIFI_REASON_ASSOC_LEAVE: // = 8,
return "assoc leave"; return "assoc leave";
case WIFI_REASON_ASSOC_NOT_AUTHED: // = 9, case WIFI_REASON_ASSOC_NOT_AUTHED: // = 9,
return "assoc not authed"; return "assoc not authed";
case WIFI_REASON_DISASSOC_PWRCAP_BAD: // = 10, case WIFI_REASON_DISASSOC_PWRCAP_BAD: // = 10,
return "disassoc powerCAP bad"; return "disassoc powerCAP bad";
case WIFI_REASON_DISASSOC_SUPCHAN_BAD: // = 11, case WIFI_REASON_DISASSOC_SUPCHAN_BAD: // = 11,
return "disassoc supchan bad"; return "disassoc supchan bad";
case WIFI_REASON_IE_INVALID: // = 13, case WIFI_REASON_IE_INVALID: // = 13,
return "IE invalid"; return "IE invalid";
case WIFI_REASON_MIC_FAILURE: // = 14, case WIFI_REASON_MIC_FAILURE: // = 14,
return "MIC failure"; return "MIC failure";
case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: // = 15, case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: // = 15,
return "4way handshake timeout"; return "4way handshake timeout";
case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT: // = 16, case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT: // = 16,
return "group key-update timeout"; return "group key-update timeout";
case WIFI_REASON_IE_IN_4WAY_DIFFERS: // = 17, case WIFI_REASON_IE_IN_4WAY_DIFFERS: // = 17,
return "IE in 4way differs"; return "IE in 4way differs";
case WIFI_REASON_GROUP_CIPHER_INVALID: // = 18, case WIFI_REASON_GROUP_CIPHER_INVALID: // = 18,
return "group cipher invalid"; return "group cipher invalid";
case WIFI_REASON_PAIRWISE_CIPHER_INVALID: // = 19, case WIFI_REASON_PAIRWISE_CIPHER_INVALID: // = 19,
return "pairwise cipher invalid"; return "pairwise cipher invalid";
case WIFI_REASON_AKMP_INVALID: // = 20, case WIFI_REASON_AKMP_INVALID: // = 20,
return "AKMP invalid"; return "AKMP invalid";
case WIFI_REASON_UNSUPP_RSN_IE_VERSION: // = 21, case WIFI_REASON_UNSUPP_RSN_IE_VERSION: // = 21,
return "unsupported RSN_IE version"; return "unsupported RSN_IE version";
case WIFI_REASON_INVALID_RSN_IE_CAP: // = 22, case WIFI_REASON_INVALID_RSN_IE_CAP: // = 22,
return "invalid RSN_IE_CAP"; return "invalid RSN_IE_CAP";
case WIFI_REASON_802_1X_AUTH_FAILED: // = 23, case WIFI_REASON_802_1X_AUTH_FAILED: // = 23,
return "802 X1 auth failed"; return "802 X1 auth failed";
case WIFI_REASON_CIPHER_SUITE_REJECTED: // = 24, case WIFI_REASON_CIPHER_SUITE_REJECTED: // = 24,
return "cipher suite rejected"; return "cipher suite rejected";
case WIFI_REASON_BEACON_TIMEOUT: // = 200, case WIFI_REASON_BEACON_TIMEOUT: // = 200,
return "beacon timeout"; return "beacon timeout";
case WIFI_REASON_NO_AP_FOUND: // = 201, case WIFI_REASON_NO_AP_FOUND: // = 201,
return "no AP found"; return "no AP found";
case WIFI_REASON_AUTH_FAIL: // = 202, case WIFI_REASON_AUTH_FAIL: // = 202,
return "auth fail"; return "auth fail";
case WIFI_REASON_ASSOC_FAIL: // = 203, case WIFI_REASON_ASSOC_FAIL: // = 203,
return "assoc fail"; return "assoc fail";
case WIFI_REASON_HANDSHAKE_TIMEOUT: // = 204, case WIFI_REASON_HANDSHAKE_TIMEOUT: // = 204,
return "handshake timeout"; return "handshake timeout";
default: default:
return "unknown"; return "unknown";