diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 4478bab35..bce2d5ed6 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -6,13 +6,21 @@ - System Log in Web UI will show current time if the NTP Service is enabled (#82) - Network settings for Tx-power, WiFi-bandwidth, WiFi-sleepmode (#83) - optional low clockrate (160 MHz) (#83) +- selectbox for enumerated values in web +- settings for water hysteresis on/off ## Fixed +- set mode allow numbers +- Junkers thermostat shows mode as selected by set_mode +- HA thermostat mode if bool-format: numbers is selected + ## Changed - removed Rx echo failures counting as incomplete telegrams. Bad telegrams show as Warning and not Errors. [#80](https://github.com/emsesp/EMS-ESP32/issues/80) - add upload_sec to `api/system/info` and removed # from some names to keep consistent with MQTT heartbeat - added debug target to PlatformIO build to help hunt down system crashes +- enumerated values always start at zero +- maintenance settings for time/date as extra setting ## Removed diff --git a/interface/src/project/EMSESPDevicesForm.tsx b/interface/src/project/EMSESPDevicesForm.tsx index 98630dae2..b9bcb422b 100644 --- a/interface/src/project/EMSESPDevicesForm.tsx +++ b/interface/src/project/EMSESPDevicesForm.tsx @@ -125,6 +125,7 @@ function formatValue(value: any, uom: number) { case DeviceValueUOM.MINUTES: return value ? formatDuration(value) : '0 minutes'; case DeviceValueUOM.NONE: + case DeviceValueUOM.LIST: return value; case DeviceValueUOM.NUM: return new Intl.NumberFormat().format(value); diff --git a/interface/src/project/EMSESPtypes.ts b/interface/src/project/EMSESPtypes.ts index 2294b384a..98527fe75 100644 --- a/interface/src/project/EMSESPtypes.ts +++ b/interface/src/project/EMSESPtypes.ts @@ -64,6 +64,7 @@ export interface DeviceValue { u: number; n: string; c: string; + l: string[]; } export interface EMSESPDeviceData { @@ -88,7 +89,8 @@ export enum DeviceValueUOM { SECONDS, DBM, NUM, - BOOLEAN + BOOLEAN, + LIST } export const DeviceValueUOM_s = [ @@ -108,5 +110,6 @@ export const DeviceValueUOM_s = [ 'seconds', 'dBm', 'number', - 'on/off' + 'on/off', + '' ]; diff --git a/interface/src/project/ValueForm.tsx b/interface/src/project/ValueForm.tsx index 3200a543b..e648a0fe9 100644 --- a/interface/src/project/ValueForm.tsx +++ b/interface/src/project/ValueForm.tsx @@ -51,24 +51,40 @@ class ValueForm extends React.Component { > Change Value - {devicevalue.u !== DeviceValueUOM.BOOLEAN && ( - - {DeviceValueUOM_s[devicevalue.u]} - - } - aria-describedby="outlined-value-helper-text" - inputProps={{ - 'aria-label': 'value' - }} - /> + variant="outlined" + > + {devicevalue.l.map((val) => ( + {val} + ))} + )} + {devicevalue.u !== DeviceValueUOM.BOOLEAN && + devicevalue.u !== DeviceValueUOM.LIST && ( + + {DeviceValueUOM_s[devicevalue.u]} + + } + aria-describedby="outlined-value-helper-text" + inputProps={{ + 'aria-label': 'value' + }} + /> + )} {devicevalue.u === DeviceValueUOM.BOOLEAN && ( mode, DeviceValueType::ENUM, FL_(enum_mode), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode)); - register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype), FL_(modetype), DeviceValueUOM::NONE); + register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode), FL_(mode), DeviceValueUOM::LIST, MAKE_CF_CB(set_mode)); + register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype), FL_(modetype), DeviceValueUOM::LIST); register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), FL_(ecotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_ecotemp)); register_device_value(tag, &hc->manualtemp, DeviceValueType::UINT, FL_(div2), FL_(manualtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_manualtemp)); register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), FL_(comforttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_comforttemp)); @@ -2333,34 +2333,34 @@ void Thermostat::register_device_values_hc(std::shared_ptrroominfluence, DeviceValueType::UINT, nullptr, FL_(roominfluence), DeviceValueUOM::NONE, MAKE_CF_CB(set_roominfluence)); register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, FL_(nofrosttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nofrosttemp)); register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, FL_(targetflowtemp), DeviceValueUOM::DEGREES); - register_device_value(tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), FL_(heatingtype), DeviceValueUOM::NONE); + register_device_value(tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), FL_(heatingtype), DeviceValueUOM::LIST); register_device_value( - tag, &hc->summer_setmode, DeviceValueType::ENUM, FL_(enum_summermode), FL_(summersetmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_summermode)); + tag, &hc->summer_setmode, DeviceValueType::ENUM, FL_(enum_summermode), FL_(summersetmode), DeviceValueUOM::LIST, MAKE_CF_CB(set_summermode)); register_device_value(tag, &hc->summermode, DeviceValueType::BOOL, nullptr, FL_(summermode), DeviceValueUOM::BOOLEAN); register_device_value( - tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode), FL_(controlmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_controlmode)); + tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode), FL_(controlmode), DeviceValueUOM::LIST, MAKE_CF_CB(set_controlmode)); register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program)); register_device_value(tag, &hc->tempautotemp, DeviceValueType::UINT, FL_(div2), FL_(tempautotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_tempautotemp)); break; case EMS_DEVICE_FLAG_CRF: - register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode5), FL_(mode), DeviceValueUOM::NONE); - register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype5), FL_(modetype), DeviceValueUOM::NONE); + register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode5), FL_(mode), DeviceValueUOM::LIST); + register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype5), FL_(modetype), DeviceValueUOM::LIST); register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, FL_(targetflowtemp), DeviceValueUOM::DEGREES); break; case EMS_DEVICE_FLAG_RC20: - register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode)); + register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::LIST, MAKE_CF_CB(set_mode)); break; case EMS_DEVICE_FLAG_RC20_N: - register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode)); - register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype2), FL_(modetype), DeviceValueUOM::NONE); + register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::LIST, MAKE_CF_CB(set_mode)); + register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype2), FL_(modetype), DeviceValueUOM::LIST); register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), FL_(daytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daytemp)); register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), FL_(nighttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nighttemp)); register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program)); break; case EMS_DEVICE_FLAG_RC30_N: case EMS_DEVICE_FLAG_RC35: - register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode3), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode)); - register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype3), FL_(modetype), DeviceValueUOM::NONE); + register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode3), FL_(mode), DeviceValueUOM::LIST, MAKE_CF_CB(set_mode)); + register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype3), FL_(modetype), DeviceValueUOM::LIST); register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), FL_(daytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daytemp)); register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), FL_(nighttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nighttemp)); register_device_value(tag, &hc->designtemp, DeviceValueType::UINT, nullptr, FL_(designtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_designtemp)); @@ -2375,22 +2375,22 @@ void Thermostat::register_device_values_hc(std::shared_ptrminflowtemp, DeviceValueType::UINT, nullptr, FL_(minflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_minflowtemp)); register_device_value(tag, &hc->maxflowtemp, DeviceValueType::UINT, nullptr, FL_(maxflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_maxflowtemp)); register_device_value(tag, &hc->flowtempoffset, DeviceValueType::UINT, nullptr, FL_(flowtempoffset), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flowtempoffset)); - register_device_value(tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), FL_(heatingtype), DeviceValueUOM::NONE); - register_device_value(tag, &hc->reducemode, DeviceValueType::ENUM, FL_(enum_reducemode), FL_(reducemode), DeviceValueUOM::NONE, MAKE_CF_CB(set_reducemode)); + register_device_value(tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), FL_(heatingtype), DeviceValueUOM::LIST); + register_device_value(tag, &hc->reducemode, DeviceValueType::ENUM, FL_(enum_reducemode), FL_(reducemode), DeviceValueUOM::LIST, MAKE_CF_CB(set_reducemode)); register_device_value( - tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode2), FL_(controlmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_controlmode)); - register_device_value(tag, &hc->control, DeviceValueType::ENUM, FL_(enum_control), FL_(control), DeviceValueUOM::NONE, MAKE_CF_CB(set_control)); + tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode2), FL_(controlmode), DeviceValueUOM::LIST, MAKE_CF_CB(set_controlmode)); + register_device_value(tag, &hc->control, DeviceValueType::ENUM, FL_(enum_control), FL_(control), DeviceValueUOM::LIST, MAKE_CF_CB(set_control)); register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program)); register_device_value(tag, &hc->pause, DeviceValueType::UINT, nullptr, FL_(pause), DeviceValueUOM::HOURS, MAKE_CF_CB(set_pause)); register_device_value(tag, &hc->party, DeviceValueType::UINT, nullptr, FL_(party), DeviceValueUOM::HOURS, MAKE_CF_CB(set_party)); register_device_value(tag, &hc->tempautotemp, DeviceValueType::UINT, FL_(div2), FL_(tempautotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_tempautotemp)); register_device_value(tag, &hc->noreducetemp, DeviceValueType::INT, nullptr, FL_(noreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_noreducetemp)); register_device_value(tag, &hc->remotetemp, DeviceValueType::SHORT, FL_(div10), FL_(remotetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_remotetemp)); - register_device_value(tag, &dummychar_, DeviceValueType::TEXT, nullptr, FL_(switchtime), DeviceValueUOM::NONE, MAKE_CF_CB(set_switchtime)); + register_device_value(tag, &dummy_, DeviceValueType::CMD, nullptr, FL_(switchtime), DeviceValueUOM::NONE, MAKE_CF_CB(set_switchtime)); break; case EMS_DEVICE_FLAG_JUNKERS: - register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode4), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode)); - register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype4), FL_(modetype), DeviceValueUOM::NONE); + register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode4), FL_(mode), DeviceValueUOM::LIST, MAKE_CF_CB(set_mode)); + register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype4), FL_(modetype), DeviceValueUOM::LIST); register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), FL_(heattemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_heattemp)); register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), FL_(ecotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_ecotemp)); register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, FL_(div2), FL_(nofrosttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nofrosttemp)); diff --git a/src/devices/thermostat.h b/src/devices/thermostat.h index 9a76726cc..edf994582 100644 --- a/src/devices/thermostat.h +++ b/src/devices/thermostat.h @@ -146,7 +146,7 @@ class Thermostat : public EMSdevice { char errorCode_[15]; // code from 0xA2 as string i.e. "A22(816)" uint16_t errorNumber_; // used internally to build error code char lastCode_[30]; // error log - char dummychar_[5]; // for commands with no output + uint8_t dummy_; // for commands with no output // Installation parameters uint8_t ibaMainDisplay_; // display on Thermostat: 0 int temp, 1 int setpoint, 2 ext temp, 3 burner temp, 4 ww temp, 5 functioning mode, 6 time, 7 data, 9 smoke temp diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index dd7d5a2bb..dc59a3399 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -40,7 +40,8 @@ static const __FlashStringHelper * DeviceValueUOM_s[] __attribute__((__aligned__ F_(seconds), F_(dbm), F_(num), - F_(bool) + F_(bool), + F_(blank) }; @@ -580,6 +581,12 @@ void EMSdevice::generate_values_json_web(JsonObject & json) { } } + // handle commands without value + else if(dv.type == DeviceValueType::CMD) { + obj = data.createNestedObject(); + obj["v"] = ""; + } + else { // handle Integers and Floats // If a divider is specified, do the division to 2 decimals places and send back as double/float @@ -634,6 +641,16 @@ void EMSdevice::generate_values_json_web(JsonObject & json) { } else { obj["c"] = ""; } + + // add enum and text option settings + if ((dv.uom == DeviceValueUOM::LIST) && dv.has_cmd) { + JsonArray l = obj.createNestedArray("l"); + for (uint8_t i = 0; i < dv.options_size; i++) { + if (!uuid::read_flash_string(dv.options[i]).empty()) { + l.add(uuid::read_flash_string(dv.options[i])); + } + } + } } } } diff --git a/src/emsdevice.h b/src/emsdevice.h index bd414aa0d..ef19c7494 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -39,7 +39,8 @@ enum DeviceValueType : uint8_t { ULONG, TIME, // same as ULONG (32 bits) ENUM, - TEXT + TEXT, + CMD }; @@ -64,7 +65,8 @@ enum DeviceValueUOM : uint8_t { SECONDS, // 13 DBM, // 14 NUM, // 15 - BOOLEAN // 16 + BOOLEAN, // 16 + LIST // 17 }; diff --git a/src/locale_EN.h b/src/locale_EN.h index 64a5bb607..592f74cbe 100644 --- a/src/locale_EN.h +++ b/src/locale_EN.h @@ -175,6 +175,7 @@ MAKE_PSTR(seconds, "seconds") MAKE_PSTR(dbm, "dBm") MAKE_PSTR(num, " ") // this is hack so HA renders numbers correctly MAKE_PSTR(bool, " ") // this is hack so HA renders numbers correctly +MAKE_PSTR(blank, " ") // this is hack so HA renders numbers correctly // TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp // use empty string if want to suppress showing tags @@ -467,8 +468,9 @@ MAKE_PSTR_LIST(wWHystOn, F("wwhyston"), F("ww hysteresis on temperature")) MAKE_PSTR_LIST(wWHystOff, F("wwhystoff"), F("ww hysteresis off temperature")) // thermostat +// extra commands +MAKE_PSTR_LIST(switchtime, F("switchtime"), F("single program switchtime")) // extra commands, with no long name so they don't show up in WebUI -MAKE_PSTR_LIST(switchtime, F("switchtime")) MAKE_PSTR_LIST(temp, F("temp")) MAKE_PSTR_LIST(hatemp, F("hatemp")) MAKE_PSTR_LIST(hamode, F("hamode"))