Merge branch 'fb-632-refactorvalues' into refactor

This commit is contained in:
Proddy
2020-12-15 19:51:55 +01:00
committed by GitHub
18 changed files with 687 additions and 343 deletions

View File

@@ -487,11 +487,9 @@ void Console::load_standard_commands(unsigned int context) {
Test::run_test(shell, arguments.front()); Test::run_test(shell, arguments.front());
} }
}); });
#if defined(EMSESP_STANDALONE)
EMSESPShell::commands->add_command(context, CommandFlags::USER, flash_string_vector{F("t")}, [](Shell & shell, const std::vector<std::string> & arguments) { EMSESPShell::commands->add_command(context, CommandFlags::USER, flash_string_vector{F("t")}, [](Shell & shell, const std::vector<std::string> & arguments) {
Test::run_test(shell, "default"); Test::run_test(shell, "default");
}); });
#endif
#endif #endif
EMSESPShell::commands->add_command( EMSESPShell::commands->add_command(

View File

@@ -45,6 +45,7 @@ using uuid::log::Level;
#define LOG_ERROR(...) logger_.err(__VA_ARGS__) #define LOG_ERROR(...) logger_.err(__VA_ARGS__)
// clang-format off // clang-format off
// strings stored 32 bit aligned on ESP8266/ESP32
#define MAKE_PSTR(string_name, string_literal) static const char __pstr__##string_name[] __attribute__((__aligned__(sizeof(int)))) PROGMEM = string_literal; #define MAKE_PSTR(string_name, string_literal) static const char __pstr__##string_name[] __attribute__((__aligned__(sizeof(int)))) PROGMEM = string_literal;
#define MAKE_PSTR_WORD(string_name) MAKE_PSTR(string_name, #string_name) #define MAKE_PSTR_WORD(string_name) MAKE_PSTR(string_name, #string_name)
#define F_(string_name) FPSTR(__pstr__##string_name) #define F_(string_name) FPSTR(__pstr__##string_name)

View File

@@ -30,6 +30,8 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
LOG_DEBUG(F("Adding new Boiler with device ID 0x%02X"), device_id); LOG_DEBUG(F("Adding new Boiler with device ID 0x%02X"), device_id);
System::show_mem("starting boiler regs"); // TODO remove debug
// the telegram handlers... // the telegram handlers...
register_telegram_type(0x10, F("UBAErrorMessage1"), false, [&](std::shared_ptr<const Telegram> t) { process_UBAErrorMessage(t); }); register_telegram_type(0x10, F("UBAErrorMessage1"), false, [&](std::shared_ptr<const Telegram> t) { process_UBAErrorMessage(t); });
register_telegram_type(0x11, F("UBAErrorMessage2"), false, [&](std::shared_ptr<const Telegram> t) { process_UBAErrorMessage(t); }); register_telegram_type(0x11, F("UBAErrorMessage2"), false, [&](std::shared_ptr<const Telegram> t) { process_UBAErrorMessage(t); });
@@ -54,6 +56,12 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_telegram_type(0x494, F("UBAEnergySupplied"), false, [&](std::shared_ptr<const Telegram> t) { process_UBAEnergySupplied(t); }); register_telegram_type(0x494, F("UBAEnergySupplied"), false, [&](std::shared_ptr<const Telegram> t) { process_UBAEnergySupplied(t); });
register_telegram_type(0x495, F("UBAInformation"), false, [&](std::shared_ptr<const Telegram> t) { process_UBAInformation(t); }); register_telegram_type(0x495, F("UBAInformation"), false, [&](std::shared_ptr<const Telegram> t) { process_UBAInformation(t); });
EMSESP::send_read_request(0x10, device_id); // read last errorcode on start (only published on errors)
EMSESP::send_read_request(0x11, device_id); // read last errorcode on start (only published on errors)
EMSESP::send_read_request(0x15, device_id); // read maintenace data on start (only published on change)
System::show_mem("after telegram type reg"); // TODO remove debug
// MQTT commands for boiler topic // MQTT commands for boiler topic
register_mqtt_cmd(F("comfort"), [&](const char * value, const int8_t id) { return set_warmwater_mode(value, id); }); register_mqtt_cmd(F("comfort"), [&](const char * value, const int8_t id) { return set_warmwater_mode(value, id); });
register_mqtt_cmd(F("wwactivated"), [&](const char * value, const int8_t id) { return set_warmwater_activated(value, id); }); register_mqtt_cmd(F("wwactivated"), [&](const char * value, const int8_t id) { return set_warmwater_activated(value, id); });
@@ -73,252 +81,407 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_mqtt_cmd(F("burnperiod"), [&](const char * value, const int8_t id) { return set_burn_period(value, id); }); register_mqtt_cmd(F("burnperiod"), [&](const char * value, const int8_t id) { return set_burn_period(value, id); });
register_mqtt_cmd(F("pumpdelay"), [&](const char * value, const int8_t id) { return set_pump_delay(value, id); }); register_mqtt_cmd(F("pumpdelay"), [&](const char * value, const int8_t id) { return set_pump_delay(value, id); });
// register_mqtt_cmd(F("reset"), [&](const char * value, const int8_t id) { return set_reset(value, id); }); // register_mqtt_cmd(F("reset"), [&](const char * value, const int8_t id) { return set_reset(value, id); });
register_mqtt_cmd(F("maintenance"), [&](const char * value, const int8_t id) { return set_maintenance(value, id); }); register_mqtt_cmd(F("maintenance"), [&](const char * value, const int8_t id) { return set_maintenance(value, id); });
EMSESP::send_read_request(0x10, device_id); // read last errorcode on start (only published on errors) System::show_mem("after mqtt cmd reg"); // TODO remove debug
EMSESP::send_read_request(0x11, device_id); // read last errorcode on start (only published on errors)
EMSESP::send_read_request(0x15, device_id); // read maintenace data on start (only published on change)
// add values // add values
// tags
std::string boiler_data_ww = "boiler_data_ww";
std::string boiler_data = "boiler_data";
std::string boiler_data_info = "boiler_data_info";
// ww // init_devicevalues(30); // TODO reserve mem
register_device_value(boiler_data_ww, &wWSelTemp_, DeviceValueType::UINT, {}, F("wWSelTemp"), F("Warm Water selected temperature"), DeviceValueUOM::DEGREES);
register_device_value(boiler_data_ww, &wWSetTemp_, DeviceValueType::UINT, {}, F("wWSetTemp"), F("Warm water set temperature"), DeviceValueUOM::DEGREES);
register_device_value(boiler_data_ww,
&wWType_,
DeviceValueType::ENUM,
flash_string_vector{F("off"), F("flow"), F("buffered flow"), F("buffer"), F("layered buffer")},
F("wWType"),
F("Warm water type"),
DeviceValueUOM::NONE);
register_device_value(boiler_data_ww,
&wWComfort_,
DeviceValueType::ENUM,
flash_string_vector{F("hot"), F("eco"), F("intelligent")},
F("wWComfort"),
F("Warm water comfort"),
DeviceValueUOM::NONE);
register_device_value(boiler_data_ww, &wWCircPump_, DeviceValueType::BOOL, {}, F("wWCircPump"), F("Warm water circulation pump available"), DeviceValueUOM::NONE);
register_device_value(boiler_data_ww,
&wWChargeType_,
DeviceValueType::BOOL,
flash_string_vector{F("3-way valve"), F("charge pump")},
F("wWChargeType"),
F("Warm Water charging type"),
DeviceValueUOM::NONE);
register_device_value(boiler_data_ww,
&wWDisinfectionTemp_,
DeviceValueType::UINT,
{},
F("wWDisinfectionTemp"),
F("Warm Water disinfection temperature"),
DeviceValueUOM::DEGREES);
register_device_value(boiler_data_ww,
&wWCircPumpMode_,
DeviceValueType::ENUM,
flash_string_vector{F("off"), F("1x3min"), F("2x3min"), F("3x3min"), F("4x3min"), F("5x3min"), F("6x3min"), F("continuos")},
F("wWCircPumpMode"),
F("Warm water circulation pump freq"),
DeviceValueUOM::NONE);
register_device_value(boiler_data_ww, &wWCirc_, DeviceValueType::BOOL, {}, F("wWCirc"), F("Warm Water circulation active"), DeviceValueUOM::NONE);
register_device_value(
boiler_data_ww, &wWCurTemp_, DeviceValueType::USHORT, {F("10")}, F("wWCurTemp"), F("Warm Water current temperature (intern)"), DeviceValueUOM::DEGREES);
register_device_value(boiler_data_ww,
&wWCurTemp2_,
DeviceValueType::USHORT,
flash_string_vector{F("10")},
F("wWCurTemp2"),
F("Warm Water current temperature (extern)"),
DeviceValueUOM::DEGREES);
register_device_value(boiler_data_ww, &wWCurFlow_, DeviceValueType::UINT, {F("10")}, F("wWCurFlow"), F("Warm Water current tap water flow"), DeviceValueUOM::LMIN);
register_device_value(boiler_data_ww,
&wwStorageTemp1_,
DeviceValueType::USHORT,
flash_string_vector{F("10")},
F("wwStorageTemp1"),
F("Warm water storage temperature (intern)"),
DeviceValueUOM::DEGREES);
register_device_value(boiler_data_ww,
&wwStorageTemp2_,
DeviceValueType::USHORT,
flash_string_vector{F("10")},
F("wwStorageTemp2"),
F("Warm water storage temperature (extern)"),
DeviceValueUOM::DEGREES);
register_device_value(boiler_data_ww, &wWActivated_, DeviceValueType::BOOL, {}, F("wWActivated"), F("Warm Water activated"), DeviceValueUOM::NONE);
register_device_value(boiler_data_ww, &wWOneTime_, DeviceValueType::BOOL, {}, F("wWOneTime"), F("Warm Water one time charging"), DeviceValueUOM::NONE);
register_device_value(boiler_data_ww, &wWDisinfecting_, DeviceValueType::BOOL, {}, F("wWDisinfecting"), F("Warm Water disinfecting"), DeviceValueUOM::NONE);
register_device_value(boiler_data_ww, &wWCharging_, DeviceValueType::BOOL, {}, F("wWCharging"), F("Warm Water charging"), DeviceValueUOM::NONE);
register_device_value(boiler_data_ww, &wWRecharging_, DeviceValueType::BOOL, {}, F("wWRecharging"), F("Warm Water recharging"), DeviceValueUOM::NONE);
register_device_value(boiler_data_ww, &wWTempOK_, DeviceValueType::BOOL, {}, F("wWTempOK"), F("Warm Water temperature ok"), DeviceValueUOM::NONE);
register_device_value(boiler_data_ww, &wWActive_, DeviceValueType::BOOL, {}, F("wWActive"), F("Warm Water active"), DeviceValueUOM::NONE);
register_device_value(boiler_data_ww, &wWHeat_, DeviceValueType::BOOL, {}, F("wWHeat"), F("Warm Water heating"), DeviceValueUOM::NONE);
register_device_value(boiler_data_ww, &wWSetPumpPower_, DeviceValueType::UINT, {}, F("wWSetPumpPower"), F("Warm Water pump set power"), DeviceValueUOM::PERCENT);
register_device_value(
boiler_data_ww, &wwMixTemperature_, DeviceValueType::USHORT, {}, F("wwMixTemperature"), F("Warm Water mix temperature"), DeviceValueUOM::DEGREES);
register_device_value(boiler_data_ww,
&wwBufferTemperature_,
DeviceValueType::USHORT,
{},
F("wwBufferTemperature"),
F("Warm Water buffer boiler temperature"),
DeviceValueUOM::DEGREES);
register_device_value(boiler_data_ww, &wWStarts_, DeviceValueType::ULONG, {}, F("wWStarts"), F("Warm Water # starts"), DeviceValueUOM::NONE);
register_device_value(boiler_data_ww, &wWStarts2_, DeviceValueType::ULONG, {}, F("wWStarts2"), F("Warm Water # starts (control)"), DeviceValueUOM::NONE);
register_device_value(boiler_data_ww, &wWWorkM_, DeviceValueType::TIME, {}, F("wWWorkM"), F("Warm Water active time"), DeviceValueUOM::MINUTES);
// main // main - boiler_data topic
register_device_value(boiler_data, &heatingActive_, DeviceValueType::BOOL, {}, F("heatingActive"), F("Heating active"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &heatingActive_, DeviceValueType::BOOL, {}, F("heatingActive"), F("Heating active"), DeviceValueUOM::NONE);
register_device_value(boiler_data, &tapwaterActive_, DeviceValueType::BOOL, {}, F("tapwaterActive"), F("Warm water/DHW active"), DeviceValueUOM::NONE);
register_device_value(boiler_data, &selFlowTemp_, DeviceValueType::UINT, {}, F("selFlowTemp"), F("Selected flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(boiler_data, &selBurnPow_, DeviceValueType::UINT, {}, F("selBurnPow"), F("Burner selected max power"), DeviceValueUOM::PERCENT);
register_device_value(boiler_data, &pumpMod_, DeviceValueType::UINT, {}, F("pumpMod"), F("Pump modulation"), DeviceValueUOM::PERCENT);
register_device_value(boiler_data, &pumpMod2_, DeviceValueType::UINT, {}, F("pumpMod2"), F("Heat pump modulation"), DeviceValueUOM::PERCENT);
register_device_value( register_device_value(
boiler_data, &outdoorTemp_, DeviceValueType::SHORT, flash_string_vector{F("10")}, F("outdoorTemp"), F("Outside temperature"), DeviceValueUOM::DEGREES); DeviceValueTAG::TAG_BOILER_DATA, &tapwaterActive_, DeviceValueType::BOOL, {}, F("tapwaterActive"), F("Warm water/DHW active"), DeviceValueUOM::NONE);
register_device_value(boiler_data, register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &selFlowTemp_, DeviceValueType::UINT, {}, F("selFlowTemp"), F("Selected flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &selBurnPow_, DeviceValueType::UINT, {}, F("selBurnPow"), F("Burner selected max power"), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &pumpMod_, DeviceValueType::UINT, {}, F("pumpMod"), F("Pump modulation"), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &pumpMod2_, DeviceValueType::UINT, {}, F("pumpMod2"), F("Heat pump modulation"), DeviceValueUOM::PERCENT);
register_device_value(TAG_BOILER_DATA,
&outdoorTemp_,
DeviceValueType::SHORT,
flash_string_vector{F("10")},
F("outdoorTemp"),
F("Outside temperature"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA,
&curFlowTemp_, &curFlowTemp_,
DeviceValueType::USHORT, DeviceValueType::USHORT,
flash_string_vector{F("10")}, flash_string_vector{F("10")},
F("curFlowTemp"), F("curFlowTemp"),
F("Current flow temperature"), F("Current flow temperature"),
DeviceValueUOM::DEGREES); DeviceValueUOM::DEGREES);
register_device_value(boiler_data, &retTemp_, DeviceValueType::USHORT, flash_string_vector{F("10")}, F("retTemp"), F("Return temperature"), DeviceValueUOM::DEGREES); register_device_value(DeviceValueTAG::TAG_BOILER_DATA,
register_device_value(boiler_data, &retTemp_,
DeviceValueType::USHORT,
flash_string_vector{F("10")},
F("retTemp"),
F("Return temperature"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA,
&switchTemp_, &switchTemp_,
DeviceValueType::USHORT, DeviceValueType::USHORT,
flash_string_vector{F("10")}, flash_string_vector{F("10")},
F("switchTemp"), F("switchTemp"),
F("Mixing switch temperature"), F("Mixing switch temperature"),
DeviceValueUOM::DEGREES); DeviceValueUOM::DEGREES);
register_device_value(boiler_data, &sysPress_, DeviceValueType::UINT, flash_string_vector{F("10")}, F("sysPress"), F("System pressure"), DeviceValueUOM::BAR); register_device_value(DeviceValueTAG::TAG_BOILER_DATA,
register_device_value( &sysPress_,
boiler_data, &boilTemp_, DeviceValueType::USHORT, flash_string_vector{F("10")}, F("boilTemp"), F("Max boiler temperature"), DeviceValueUOM::DEGREES); DeviceValueType::UINT,
register_device_value( flash_string_vector{F("10")},
boiler_data, &exhaustTemp_, DeviceValueType::USHORT, flash_string_vector{F("10")}, F("exhaustTemp"), F("Exhaust temperature"), DeviceValueUOM::DEGREES); F("sysPress"),
register_device_value(boiler_data, &burnGas_, DeviceValueType::BOOL, {}, F("burnGas"), F("Gas"), DeviceValueUOM::NONE); F("System pressure"),
register_device_value(boiler_data, &flameCurr_, DeviceValueType::USHORT, {F("10")}, F("flameCurr"), F("Flame current"), DeviceValueUOM::UA); DeviceValueUOM::BAR);
register_device_value(boiler_data, &heatPump_, DeviceValueType::BOOL, {}, F("heatPump"), F("Heat pump"), DeviceValueUOM::NONE); register_device_value(TAG_BOILER_DATA,
register_device_value(boiler_data, &fanWork_, DeviceValueType::BOOL, {}, F("fanWork"), F("Fan"), DeviceValueUOM::NONE); &boilTemp_,
register_device_value(boiler_data, &ignWork_, DeviceValueType::BOOL, {}, F("ignWork"), F("Ignition"), DeviceValueUOM::NONE); DeviceValueType::USHORT,
register_device_value(boiler_data, &heatingActivated_, DeviceValueType::BOOL, {}, F("heatingActivated"), F("Heating activated"), DeviceValueUOM::NONE); flash_string_vector{F("10")},
register_device_value(boiler_data, &heatingTemp_, DeviceValueType::UINT, {}, F("heatingTemp"), F("Heating temperature"), DeviceValueUOM::DEGREES); F("boilTemp"),
register_device_value(boiler_data, &pumpModMax_, DeviceValueType::UINT, {}, F("pumpModMax"), F("Burner pump max power"), DeviceValueUOM::PERCENT); F("Max boiler temperature"),
register_device_value(boiler_data, &pumpModMin_, DeviceValueType::UINT, {}, F("pumpModMin"), F("Burner pump min power"), DeviceValueUOM::PERCENT); DeviceValueUOM::DEGREES);
register_device_value(boiler_data, &pumpDelay_, DeviceValueType::UINT, {}, F("pumpDelay"), F("Pump delay"), DeviceValueUOM::MINUTES); register_device_value(TAG_BOILER_DATA,
register_device_value(boiler_data, &burnMinPeriod_, DeviceValueType::UINT, {}, F("burnMinPeriod"), F("Burner min period"), DeviceValueUOM::MINUTES); &exhaustTemp_,
register_device_value(boiler_data, &burnMinPower_, DeviceValueType::UINT, {}, F("burnMinPower"), F("Burner min power"), DeviceValueUOM::PERCENT); DeviceValueType::USHORT,
register_device_value(boiler_data, &burnMaxPower_, DeviceValueType::UINT, {}, F("burnMaxPower"), F("Burner max power"), DeviceValueUOM::PERCENT); flash_string_vector{F("10")},
register_device_value(boiler_data, &boilHystOn_, DeviceValueType::INT, {}, F("boilHystOn"), F("Hysteresis on temperature"), DeviceValueUOM::DEGREES); F("exhaustTemp"),
register_device_value(boiler_data, &boilHystOff_, DeviceValueType::INT, {}, F("boilHystOff"), F("Hysteresis off temperature"), DeviceValueUOM::DEGREES); F("Exhaust temperature"),
register_device_value(boiler_data, &setFlowTemp_, DeviceValueType::UINT, {}, F("setFlowTemp"), F("Set flow temperature"), DeviceValueUOM::DEGREES); DeviceValueUOM::DEGREES);
register_device_value(boiler_data, &setBurnPow_, DeviceValueType::UINT, {}, F("setBurnPow"), F("Burner set power"), DeviceValueUOM::PERCENT);
register_device_value(boiler_data, &curBurnPow_, DeviceValueType::UINT, {}, F("curBurnPow"), F("Burner current power"), DeviceValueUOM::PERCENT);
register_device_value(boiler_data, &burnStarts_, DeviceValueType::ULONG, {}, F("burnStarts"), F("Burner # starts"), DeviceValueUOM::NONE);
register_device_value(boiler_data, &burnWorkMin_, DeviceValueType::TIME, {}, F("burnWorkMin"), F("Total burner operating time"), DeviceValueUOM::MINUTES);
register_device_value(boiler_data, &heatWorkMin_, DeviceValueType::TIME, {}, F("heatWorkMin"), F("Total heat operating time"), DeviceValueUOM::MINUTES);
register_device_value(boiler_data, &UBAuptime_, DeviceValueType::TIME, {}, F("UBAuptime"), F("Total UBA operating time"), DeviceValueUOM::MINUTES);
register_device_value(boiler_data, &lastCode_, DeviceValueType::TEXT, {}, F("lastCode"), F("Last error code"), DeviceValueUOM::NONE);
register_device_value(boiler_data, &serviceCode_, DeviceValueType::TEXT, {}, F("serviceCode"), F("Service code"), DeviceValueUOM::NONE);
register_device_value(boiler_data, &serviceCodeNumber_, DeviceValueType::USHORT, {}, F("serviceCodeNumber"), F("Service code number"), DeviceValueUOM::NONE);
// info register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &burnGas_, DeviceValueType::BOOL, {}, F("burnGas"), F("Gas"), DeviceValueUOM::NONE);
register_device_value(boiler_data_info, register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &flameCurr_, DeviceValueType::USHORT, {F("10")}, F("flameCurr"), F("Flame current"), DeviceValueUOM::UA);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &heatPump_, DeviceValueType::BOOL, {}, F("heatPump"), F("Heat pump"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &fanWork_, DeviceValueType::BOOL, {}, F("fanWork"), F("Fan"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &ignWork_, DeviceValueType::BOOL, {}, F("ignWork"), F("Ignition"), DeviceValueUOM::NONE);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &heatingActivated_, DeviceValueType::BOOL, {}, F("heatingActivated"), F("Heating activated"), DeviceValueUOM::NONE);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &heatingTemp_, DeviceValueType::UINT, {}, F("heatingTemp"), F("Heating temperature"), DeviceValueUOM::DEGREES);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &pumpModMax_, DeviceValueType::UINT, {}, F("pumpModMax"), F("Burner pump max power"), DeviceValueUOM::PERCENT);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &pumpModMin_, DeviceValueType::UINT, {}, F("pumpModMin"), F("Burner pump min power"), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &pumpDelay_, DeviceValueType::UINT, {}, F("pumpDelay"), F("Pump delay"), DeviceValueUOM::MINUTES);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &burnMinPeriod_, DeviceValueType::UINT, {}, F("burnMinPeriod"), F("Burner min period"), DeviceValueUOM::MINUTES);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &burnMinPower_, DeviceValueType::UINT, {}, F("burnMinPower"), F("Burner min power"), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &burnMaxPower_, DeviceValueType::UINT, {}, F("burnMaxPower"), F("Burner max power"), DeviceValueUOM::PERCENT);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &boilHystOn_, DeviceValueType::INT, {}, F("boilHystOn"), F("Hysteresis on temperature"), DeviceValueUOM::DEGREES);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &boilHystOff_, DeviceValueType::INT, {}, F("boilHystOff"), F("Hysteresis off temperature"), DeviceValueUOM::DEGREES);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &setFlowTemp_, DeviceValueType::UINT, {}, F("setFlowTemp"), F("Set flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &setBurnPow_, DeviceValueType::UINT, {}, F("setBurnPow"), F("Burner set power"), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &curBurnPow_, DeviceValueType::UINT, {}, F("curBurnPow"), F("Burner current power"), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &burnStarts_, DeviceValueType::ULONG, {}, F("burnStarts"), F("Burner # starts"), DeviceValueUOM::NONE);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &burnWorkMin_, DeviceValueType::TIME, {}, F("burnWorkMin"), F("Total burner operating time"), DeviceValueUOM::MINUTES);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &heatWorkMin_, DeviceValueType::TIME, {}, F("heatWorkMin"), F("Total heat operating time"), DeviceValueUOM::MINUTES);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA, &UBAuptime_, DeviceValueType::TIME, {}, F("UBAuptime"), F("Total UBA operating time"), DeviceValueUOM::MINUTES);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &lastCode_, DeviceValueType::TEXT, {}, F("lastCode"), F("Last error code"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &serviceCode_, DeviceValueType::TEXT, {}, F("serviceCode"), F("Service code"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA,
&serviceCodeNumber_,
DeviceValueType::USHORT,
{},
F("serviceCodeNumber"),
F("Service code number"),
DeviceValueUOM::NONE);
System::show_mem("after device value reg"); // TODO remove debug
#ifdef EMSESP_FORCE_SERIAL
return; // TODO remove early exit
#endif
// ww - boiler_data_ww topic
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wWSelTemp_,
DeviceValueType::UINT,
{},
F("wWSelTemp"),
F("Warm Water selected temperature"),
DeviceValueUOM::DEGREES);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA_WW, &wWSetTemp_, DeviceValueType::UINT, {}, F("wWSetTemp"), F("Warm water set temperature"), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wWType_,
DeviceValueType::ENUM,
flash_string_vector{F("off"), F("flow"), F("buffered flow"), F("buffer"), F("layered buffer")},
F("wWType"),
F("Warm water type"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wWComfort_,
DeviceValueType::ENUM,
flash_string_vector{F("hot"), F("eco"), F("intelligent")},
F("wWComfort"),
F("Warm water comfort"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wWCircPump_,
DeviceValueType::BOOL,
{},
F("wWCircPump"),
F("Warm water circulation pump available"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wWChargeType_,
DeviceValueType::BOOL,
flash_string_vector{F("3-way valve"), F("charge pump")},
F("wWChargeType"),
F("Warm Water charging type"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wWDisinfectionTemp_,
DeviceValueType::UINT,
{},
F("wWDisinfectionTemp"),
F("Warm Water disinfection temperature"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wWCircPumpMode_,
DeviceValueType::ENUM,
flash_string_vector{F("off"), F("1x3min"), F("2x3min"), F("3x3min"), F("4x3min"), F("5x3min"), F("6x3min"), F("continuos")},
F("wWCircPumpMode"),
F("Warm water circulation pump freq"),
DeviceValueUOM::NONE);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA_WW, &wWCirc_, DeviceValueType::BOOL, {}, F("wWCirc"), F("Warm Water circulation active"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wWCurTemp_,
DeviceValueType::USHORT,
{F("10")},
F("wWCurTemp"),
F("Warm Water current temperature (intern)"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wWCurTemp2_,
DeviceValueType::USHORT,
flash_string_vector{F("10")},
F("wWCurTemp2"),
F("Warm Water current temperature (extern)"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wWCurFlow_,
DeviceValueType::UINT,
{F("10")},
F("wWCurFlow"),
F("Warm Water current tap water flow"),
DeviceValueUOM::LMIN);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wwStorageTemp1_,
DeviceValueType::USHORT,
flash_string_vector{F("10")},
F("wwStorageTemp1"),
F("Warm water storage temperature (intern)"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wwStorageTemp2_,
DeviceValueType::USHORT,
flash_string_vector{F("10")},
F("wwStorageTemp2"),
F("Warm water storage temperature (extern)"),
DeviceValueUOM::DEGREES);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA_WW, &wWActivated_, DeviceValueType::BOOL, {}, F("wWActivated"), F("Warm Water activated"), DeviceValueUOM::NONE);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA_WW, &wWOneTime_, DeviceValueType::BOOL, {}, F("wWOneTime"), F("Warm Water one time charging"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wWDisinfecting_,
DeviceValueType::BOOL,
{},
F("wWDisinfecting"),
F("Warm Water disinfecting"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW, &wWCharging_, DeviceValueType::BOOL, {}, F("wWCharging"), F("Warm Water charging"), DeviceValueUOM::NONE);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA_WW, &wWRecharging_, DeviceValueType::BOOL, {}, F("wWRecharging"), F("Warm Water recharging"), DeviceValueUOM::NONE);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA_WW, &wWTempOK_, DeviceValueType::BOOL, {}, F("wWTempOK"), F("Warm Water temperature ok"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW, &wWActive_, DeviceValueType::BOOL, {}, F("wWActive"), F("Warm Water active"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW, &wWHeat_, DeviceValueType::BOOL, {}, F("wWHeat"), F("Warm Water heating"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wWSetPumpPower_,
DeviceValueType::UINT,
{},
F("wWSetPumpPower"),
F("Warm Water pump set power"),
DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wwMixTemperature_,
DeviceValueType::USHORT,
{},
F("wwMixTemperature"),
F("Warm Water mix temperature"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW,
&wwBufferTemperature_,
DeviceValueType::USHORT,
{},
F("wwBufferTemperature"),
F("Warm Water buffer boiler temperature"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW, &wWStarts_, DeviceValueType::ULONG, {}, F("wWStarts"), F("Warm Water # starts"), DeviceValueUOM::NONE);
register_device_value(
DeviceValueTAG::TAG_BOILER_DATA_WW, &wWStarts2_, DeviceValueType::ULONG, {}, F("wWStarts2"), F("Warm Water # starts (control)"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW, &wWWorkM_, DeviceValueType::TIME, {}, F("wWWorkM"), F("Warm Water active time"), DeviceValueUOM::MINUTES);
// info - boiler_data_info topic
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&upTimeControl_, &upTimeControl_,
DeviceValueType::TIME, DeviceValueType::TIME,
flash_string_vector{F("60")}, flash_string_vector{F("60")},
F("upTimeControl"), F("upTimeControl"),
F("Operating time total heat"), F("Operating time total heat"),
DeviceValueUOM::MINUTES); DeviceValueUOM::MINUTES);
register_device_value(boiler_data_info, register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&upTimeCompHeating_, &upTimeCompHeating_,
DeviceValueType::TIME, DeviceValueType::TIME,
flash_string_vector{F("60")}, flash_string_vector{F("60")},
F("upTimeCompHeating"), F("upTimeCompHeating"),
F("Operating time compressor heating"), F("Operating time compressor heating"),
DeviceValueUOM::MINUTES); DeviceValueUOM::MINUTES);
register_device_value(boiler_data, register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&upTimeCompCooling_, &upTimeCompCooling_,
DeviceValueType::TIME, DeviceValueType::TIME,
flash_string_vector{F("60")}, flash_string_vector{F("60")},
F("upTimeCompCooling"), F("upTimeCompCooling"),
F("Operating time compressor cooling"), F("Operating time compressor cooling"),
DeviceValueUOM::MINUTES); DeviceValueUOM::MINUTES);
register_device_value(boiler_data_info, register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&upTimeCompWw_, &upTimeCompWw_,
DeviceValueType::TIME, DeviceValueType::TIME,
flash_string_vector{F("60")}, flash_string_vector{F("60")},
F("upTimeCompWw"), F("upTimeCompWw"),
F("Operating time compressor warm water"), F("Operating time compressor warm water"),
DeviceValueUOM::MINUTES); DeviceValueUOM::MINUTES);
register_device_value(boiler_data_info, &heatingStarts_, DeviceValueType::ULONG, {}, F("heatingStarts"), F("# heating starts (control)"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
register_device_value(boiler_data_info, &coolingStarts_, DeviceValueType::ULONG, {}, F("coolingStarts"), F("# cooling starts (control)"), DeviceValueUOM::NONE); &heatingStarts_,
register_device_value(boiler_data_info, &nrgConsTotal_, DeviceValueType::ULONG, {}, F("nrgConsTotal"), F("Total energy consumption"), DeviceValueUOM::NONE); DeviceValueType::ULONG,
register_device_value(boiler_data_info, {},
F("heatingStarts"),
F("# heating starts (control)"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&coolingStarts_,
DeviceValueType::ULONG,
{},
F("coolingStarts"),
F("# cooling starts (control)"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&nrgConsTotal_,
DeviceValueType::ULONG,
{},
F("nrgConsTotal"),
F("Total energy consumption"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&nrgConsCompTotal_, &nrgConsCompTotal_,
DeviceValueType::ULONG, DeviceValueType::ULONG,
{}, {},
F("nrgConsCompTotal"), F("nrgConsCompTotal"),
F("Energy consumption compressor total"), F("Energy consumption compressor total"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(boiler_data_info, register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&nrgConsCompHeating_, &nrgConsCompHeating_,
DeviceValueType::ULONG, DeviceValueType::ULONG,
{}, {},
F("nrgConsCompHeating"), F("nrgConsCompHeating"),
F("Energy consumption compressor heating"), F("Energy consumption compressor heating"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value( register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
boiler_data_info, &nrgConsCompWw_, DeviceValueType::ULONG, {}, F("nrgConsCompWw"), F("Energy consumption compressor warm water"), DeviceValueUOM::NONE); &nrgConsCompWw_,
register_device_value(boiler_data_info, DeviceValueType::ULONG,
{},
F("nrgConsCompWw"),
F("Energy consumption compressor warm water"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&nrgConsCompCooling_, &nrgConsCompCooling_,
DeviceValueType::ULONG, DeviceValueType::ULONG,
{}, {},
F("nrgConsCompCooling"), F("nrgConsCompCooling"),
F("Energy consumption compressor cooling"), F("Energy consumption compressor cooling"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(boiler_data_info, &nrgSuppTotal_, DeviceValueType::ULONG, {}, F("nrgSuppTotal"), F("Total energy supplied"), DeviceValueUOM::NONE);
register_device_value( register_device_value(
boiler_data_info, &nrgSuppHeating_, DeviceValueType::ULONG, {}, F("nrgSuppHeating"), F("Total energy supplied heating"), DeviceValueUOM::NONE); DeviceValueTAG::TAG_BOILER_DATA_INFO, &nrgSuppTotal_, DeviceValueType::ULONG, {}, F("nrgSuppTotal"), F("Total energy supplied"), DeviceValueUOM::NONE);
register_device_value(boiler_data_info, &nrgSuppWw_, DeviceValueType::ULONG, {}, F("nrgSuppWw"), F("Total energy warm supplied warm water"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
register_device_value( &nrgSuppHeating_,
boiler_data_info, &nrgSuppCooling_, DeviceValueType::ULONG, {}, F("nrgSuppCooling"), F("Total energy supplied cooling"), DeviceValueUOM::NONE); DeviceValueType::ULONG,
register_device_value(boiler_data_info, {},
F("nrgSuppHeating"),
F("Total energy supplied heating"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&nrgSuppWw_,
DeviceValueType::ULONG,
{},
F("nrgSuppWw"),
F("Total energy warm supplied warm water"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&nrgSuppCooling_,
DeviceValueType::ULONG,
{},
F("nrgSuppCooling"),
F("Total energy supplied cooling"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&auxElecHeatNrgConsTotal_, &auxElecHeatNrgConsTotal_,
DeviceValueType::ULONG, DeviceValueType::ULONG,
{}, {},
F("auxElecHeatNrgConsTotal"), F("auxElecHeatNrgConsTotal"),
F("Auxiliary electrical heater energy consumption total"), F("Auxiliary electrical heater energy consumption total"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(boiler_data_info, register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&auxElecHeatNrgConsHeating_, &auxElecHeatNrgConsHeating_,
DeviceValueType::ULONG, DeviceValueType::ULONG,
{}, {},
F("auxElecHeatNrgConsHeating"), F("auxElecHeatNrgConsHeating"),
F("Auxiliary electrical heater energy consumption heating"), F("Auxiliary electrical heater energy consumption heating"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(boiler_data_info, register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&auxElecHeatNrgConsDHW_, &auxElecHeatNrgConsDHW_,
DeviceValueType::ULONG, DeviceValueType::ULONG,
{}, {},
F("auxElecHeatNrgConsDHW"), F("auxElecHeatNrgConsDHW"),
F("Auxiliary electrical heater energy consumption DHW"), F("Auxiliary electrical heater energy consumption DHW"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(boiler_data_info, &maintenanceMessage_, DeviceValueType::TEXT, {}, F("maintenanceMessage"), F("Maintenance message"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
register_device_value(boiler_data_info, &maintenanceDate_, DeviceValueType::TEXT, {}, F("maintenanceDate"), F("Maintenance set date"), DeviceValueUOM::NONE); &maintenanceMessage_,
register_device_value(boiler_data_info, DeviceValueType::TEXT,
{},
F("maintenanceMessage"),
F("Maintenance message"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&maintenanceDate_,
DeviceValueType::TEXT,
{},
F("maintenanceDate"),
F("Maintenance set date"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&maintenanceType_, &maintenanceType_,
DeviceValueType::ENUM, DeviceValueType::ENUM,
flash_string_vector{F("off"), F("time"), F("date")}, flash_string_vector{F("off"), F("time"), F("date")},
F("maintenanceType"), F("maintenanceType"),
F("Scheduled maintenance"), F("Scheduled maintenance"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(boiler_data_info, &maintenanceTime_, DeviceValueType::UINT, {}, F("maintenanceTime"), F("Maintenance set time"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_BOILER_DATA_INFO,
&maintenanceTime_,
DeviceValueType::UINT,
{},
F("maintenanceTime"),
F("Maintenance set time"),
DeviceValueUOM::NONE);
} }
// publish HA config // publish HA config

View File

@@ -32,9 +32,8 @@ Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, c
register_telegram_type(0x042B, F("HP1"), true, [&](std::shared_ptr<const Telegram> t) { process_HPMonitor1(t); }); register_telegram_type(0x042B, F("HP1"), true, [&](std::shared_ptr<const Telegram> t) { process_HPMonitor1(t); });
register_telegram_type(0x047B, F("HP2"), true, [&](std::shared_ptr<const Telegram> t) { process_HPMonitor2(t); }); register_telegram_type(0x047B, F("HP2"), true, [&](std::shared_ptr<const Telegram> t) { process_HPMonitor2(t); });
std::string empty(""); register_device_value(DeviceValueTAG::TAG_NONE, &airHumidity_, DeviceValueType::UINT, flash_string_vector{F("2")}, F("airHumidity"), F("Relative air humidity"), DeviceValueUOM::NONE);
register_device_value(empty, &airHumidity_, DeviceValueType::UINT, flash_string_vector{F("2")}, F("airHumidity"), F("Relative air humidity"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_NONE, &dewTemperature_, DeviceValueType::UINT, {}, F("dewTemperature"), F("Dew point temperature"), DeviceValueUOM::NONE);
register_device_value(empty, &dewTemperature_, DeviceValueType::UINT, {}, F("dewTemperature"), F("Dew point temperature"), DeviceValueUOM::NONE);
} }
// publish HA config // publish HA config

View File

@@ -66,14 +66,18 @@ void Mixer::register_values(const Type type, uint16_t hc) {
hc_ = hc + 1; hc_ = hc + 1;
type_ = type; type_ = type;
std::string prefix(10, '\0'); // with hc<n> or wwc<n>
snprintf_P(&prefix[0], sizeof(prefix), PSTR("%s%d"), (type_ == Type::HC) ? "hc" : "wwc", hc + 1); uint8_t tag = DeviceValueTAG::TAG_NONE;
if (type_ == Type::HC) {
tag = DeviceValueTAG::TAG_HC1 + hc - 1;
} else {
tag = DeviceValueTAG::TAG_WWC1 + hc - 1;
}
register_device_value( register_device_value(tag, &flowTemp_, DeviceValueType::USHORT, flash_string_vector{F("10")}, F("flowTemp"), F("Current flow temperature"), DeviceValueUOM::DEGREES);
prefix, &flowTemp_, DeviceValueType::USHORT, flash_string_vector{F("10")}, F("flowTemp"), F("Current flow temperature"), DeviceValueUOM::DEGREES); register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, {}, F("flowSetTemp"), F("Setpoint flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(prefix, &flowSetTemp_, DeviceValueType::UINT, {}, F("flowSetTemp"), F("Setpoint flow temperature"), DeviceValueUOM::DEGREES); register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, {}, F("pumpStatus"), F("Pump/Valve status"), DeviceValueUOM::NONE);
register_device_value(prefix, &pumpStatus_, DeviceValueType::BOOL, {}, F("pumpStatus"), F("Pump/Valve status"), DeviceValueUOM::NONE); register_device_value(tag, &status_, DeviceValueType::INT, {}, F("status"), F("Current status"), DeviceValueUOM::NONE);
register_device_value(prefix, &status_, DeviceValueType::INT, {}, F("status"), F("Current status"), DeviceValueUOM::NONE);
} }

View File

@@ -60,54 +60,81 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
register_telegram_type(0x0101, F("ISM1Set"), false, [&](std::shared_ptr<const Telegram> t) { process_ISM1Set(t); }); register_telegram_type(0x0101, F("ISM1Set"), false, [&](std::shared_ptr<const Telegram> t) { process_ISM1Set(t); });
} }
std::string empty("");
// special case for a device_id with 0x2A where it's not actual a solar module // special case for a device_id with 0x2A where it's not actual a solar module
if (device_id == 0x2A) { if (device_id == 0x2A) {
register_device_value(empty, &type_, DeviceValueType::TEXT, {}, F("type"), F("Type"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_NONE, &type_, DeviceValueType::TEXT, {}, F("type"), F("Type"), DeviceValueUOM::NONE);
strncpy(type_, "warm water circuit", sizeof(type_)); strncpy(type_, "warm water circuit", sizeof(type_));
} }
register_device_value(empty, register_device_value(DeviceValueTAG::TAG_NONE,
&collectorTemp_, &collectorTemp_,
DeviceValueType::SHORT, DeviceValueType::SHORT,
flash_string_vector{F("10")}, flash_string_vector{F("10")},
F("collectorTemp"), F("collectorTemp"),
F("Collector temperature (TS1)"), F("Collector temperature (TS1)"),
DeviceValueUOM::DEGREES); DeviceValueUOM::DEGREES);
register_device_value(empty, register_device_value(DeviceValueTAG::TAG_NONE,
&tankBottomTemp_, &tankBottomTemp_,
DeviceValueType::SHORT, DeviceValueType::SHORT,
flash_string_vector{F("10")}, flash_string_vector{F("10")},
F("tankBottomTemp"), F("tankBottomTemp"),
F("Bottom temperature (TS2)"), F("Bottom temperature (TS2)"),
DeviceValueUOM::DEGREES); DeviceValueUOM::DEGREES);
register_device_value(empty, register_device_value(DeviceValueTAG::TAG_NONE,
&tankBottomTemp2_, &tankBottomTemp2_,
DeviceValueType::SHORT, DeviceValueType::SHORT,
flash_string_vector{F("10")}, flash_string_vector{F("10")},
F("tankBottomTemp2"), F("tankBottomTemp2"),
F("Bottom temperature (TS5)"), F("Bottom temperature (TS5)"),
DeviceValueUOM::DEGREES); DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE,
&heatExchangerTemp_,
DeviceValueType::SHORT,
{F("10")},
F("heatExchangerTemp"),
F("Heat exchanger temperature (TS6)"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE,
&tank1MaxTempCurrent_,
DeviceValueType::UINT,
{},
F("tank1MaxTempCurrent"),
F("Maximum Tank temperature"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE,
&solarPumpModulation_,
DeviceValueType::UINT,
{},
F("solarPumpModulation"),
F("Solar pump modulation (PS1)"),
DeviceValueUOM::PERCENT);
register_device_value( register_device_value(
empty, &heatExchangerTemp_, DeviceValueType::SHORT, {F("10")}, F("heatExchangerTemp"), F("Heat exchanger temperature (TS6)"), DeviceValueUOM::DEGREES); DeviceValueTAG::TAG_NONE, &cylinderPumpModulation_, DeviceValueType::UINT, {}, F("cylinderPumpModulation"), F("Cylinder pump modulation (PS5)"), DeviceValueUOM::PERCENT);
register_device_value(empty, &tank1MaxTempCurrent_, DeviceValueType::UINT, {}, F("tank1MaxTempCurrent"), F("Maximum Tank temperature"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_NONE, &solarPump_, DeviceValueType::BOOL, {}, F("solarPump"), F("Solar pump (PS1) active"), DeviceValueUOM::NONE);
register_device_value(empty, &solarPumpModulation_, DeviceValueType::UINT, {}, F("solarPumpModulation"), F("Solar pump modulation (PS1)"), DeviceValueUOM::PERCENT); register_device_value(DeviceValueTAG::TAG_NONE, &valveStatus_, DeviceValueType::BOOL, {}, F("valveStatus"), F("Valve status"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE, &tankHeated_, DeviceValueType::BOOL, {}, F("tankHeated"), F("Tank heated"), DeviceValueUOM::NONE);
register_device_value( register_device_value(
empty, &cylinderPumpModulation_, DeviceValueType::UINT, {}, F("cylinderPumpModulation"), F("Cylinder pump modulation (PS5)"), DeviceValueUOM::PERCENT); DeviceValueTAG::TAG_NONE, &collectorShutdown_, DeviceValueType::BOOL, {}, F("collectorShutdown"), F("Collector shutdown"), DeviceValueUOM::NONE);
register_device_value(empty, &solarPump_, DeviceValueType::BOOL, {}, F("solarPump"), F("Solar pump (PS1) active"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_NONE, &pumpWorkMin_, DeviceValueType::TIME, {}, F("pumpWorkMin"), F("Pump working time"), DeviceValueUOM::MINUTES);
register_device_value(empty, &valveStatus_, DeviceValueType::BOOL, {}, F("valveStatus"), F("Valve status"), DeviceValueUOM::NONE);
register_device_value(empty, &tankHeated_, DeviceValueType::BOOL, {}, F("tankHeated"), F("Tank heated"), DeviceValueUOM::NONE);
register_device_value(empty, &collectorShutdown_, DeviceValueType::BOOL, {}, F("collectorShutdown"), F("Collector shutdown"), DeviceValueUOM::NONE);
register_device_value(empty, &pumpWorkMin_, DeviceValueType::TIME, {}, F("pumpWorkMin"), F("Pump working time"), DeviceValueUOM::MINUTES); register_device_value(DeviceValueTAG::TAG_NONE,
&energyLastHour_,
register_device_value( DeviceValueType::ULONG,
empty, &energyLastHour_, DeviceValueType::ULONG, flash_string_vector{F("10")}, F("energyLastHour"), F("Energy last hour"), DeviceValueUOM::WH); flash_string_vector{F("10")},
register_device_value(empty, &energyTotal_, DeviceValueType::ULONG, flash_string_vector{F("10")}, F("energyTotal"), F("Energy total"), DeviceValueUOM::KWH); F("energyLastHour"),
register_device_value(empty, &energyToday_, DeviceValueType::ULONG, {}, F("energyToday"), F("Energy today"), DeviceValueUOM::WH); F("Energy last hour"),
DeviceValueUOM::WH);
register_device_value(DeviceValueTAG::TAG_NONE,
&energyTotal_,
DeviceValueType::ULONG,
flash_string_vector{F("10")},
F("energyTotal"),
F("Energy total"),
DeviceValueUOM::KWH);
register_device_value(DeviceValueTAG::TAG_NONE, &energyToday_, DeviceValueType::ULONG, {}, F("energyToday"), F("Energy today"), DeviceValueUOM::WH);
} }
// publish HA config // publish HA config

View File

@@ -34,11 +34,15 @@ Switch::Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const
register_telegram_type(0x9D, F("WM10SetMessage"), false, [&](std::shared_ptr<const Telegram> t) { process_WM10SetMessage(t); }); register_telegram_type(0x9D, F("WM10SetMessage"), false, [&](std::shared_ptr<const Telegram> t) { process_WM10SetMessage(t); });
register_telegram_type(0x1E, F("WM10TempMessage"), false, [&](std::shared_ptr<const Telegram> t) { process_WM10TempMessage(t); }); register_telegram_type(0x1E, F("WM10TempMessage"), false, [&](std::shared_ptr<const Telegram> t) { process_WM10TempMessage(t); });
std::string empty(""); register_device_value(DeviceValueTAG::TAG_NONE, &activated_, DeviceValueType::BOOL, {}, F("activated"), F("Activated"), DeviceValueUOM::NONE);
register_device_value(empty, &activated_, DeviceValueType::BOOL, {}, F("activated"), F("Activated"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_NONE,
register_device_value( &flowTemp_,
empty, &flowTemp_, DeviceValueType::USHORT, flash_string_vector{F("10")}, F("flowTemp"), F("Current flow temperature"), DeviceValueUOM::DEGREES); DeviceValueType::USHORT,
register_device_value(empty, &status_, DeviceValueType::INT, {}, F("status"), F("Status"), DeviceValueUOM::NONE); flash_string_vector{F("10")},
F("flowTemp"),
F("Current flow temperature"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE, &status_, DeviceValueType::INT, {}, F("status"), F("Status"), DeviceValueUOM::NONE);
} }
// publish HA config // publish HA config

View File

@@ -2044,20 +2044,36 @@ void Thermostat::add_commands() {
void Thermostat::register_device_values() { void Thermostat::register_device_values() {
uint8_t model = this->model(); uint8_t model = this->model();
std::string empty("");
// Common for all thermostats // Common for all thermostats
register_device_value(empty, &dateTime_, DeviceValueType::TEXT, {}, F("dateTime"), F("Date/Time"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_NONE, &dateTime_, DeviceValueType::TEXT, {}, F("dateTime"), F("Date/Time"), DeviceValueUOM::NONE);
register_device_value(empty, &errorCode_, DeviceValueType::TEXT, {}, F("errorCode"), F("Error code"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_NONE, &errorCode_, DeviceValueType::TEXT, {}, F("errorCode"), F("Error code"), DeviceValueUOM::NONE);
register_device_value(empty, &lastCode_, DeviceValueType::TEXT, {}, F("lastCode"), F("Last error"), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_NONE, &lastCode_, DeviceValueType::TEXT, {}, F("lastCode"), F("Last error"), DeviceValueUOM::NONE);
register_device_value(empty, &wwTemp_, DeviceValueType::UINT, {}, F("wwTemp"), F("Warm water high temperature"), DeviceValueUOM::DEGREES); register_device_value(DeviceValueTAG::TAG_NONE, &wwTemp_, DeviceValueType::UINT, {}, F("wwTemp"), F("Warm water high temperature"), DeviceValueUOM::DEGREES);
register_device_value(empty, &wwTempLow_, DeviceValueType::UINT, {}, F("wwTempLow"), F("Warm water low temperature"), DeviceValueUOM::DEGREES); register_device_value(DeviceValueTAG::TAG_NONE, &wwTempLow_, DeviceValueType::UINT, {}, F("wwTempLow"), F("Warm water low temperature"), DeviceValueUOM::DEGREES);
register_device_value(empty, &wwExtra1_, DeviceValueType::UINT, {}, F("wwExtra1"), F("Warm water circuit 1 extra"), DeviceValueUOM::DEGREES); register_device_value(DeviceValueTAG::TAG_NONE, &wwExtra1_, DeviceValueType::UINT, {}, F("wwExtra1"), F("Warm water circuit 1 extra"), DeviceValueUOM::DEGREES);
register_device_value(empty, &wwExtra2_, DeviceValueType::UINT, {}, F("wwExtra2"), F("Warm water circuit 2 extra"), DeviceValueUOM::DEGREES); register_device_value(DeviceValueTAG::TAG_NONE, &wwExtra2_, DeviceValueType::UINT, {}, F("wwExtra2"), F("Warm water circuit 2 extra"), DeviceValueUOM::DEGREES);
register_device_value(empty, &tempsensor1_, DeviceValueType::USHORT, {F("10")}, F("inttemp1"), F("Temperature sensor 1"), DeviceValueUOM::DEGREES); register_device_value(DeviceValueTAG::TAG_NONE,
register_device_value(empty, &tempsensor2_, DeviceValueType::USHORT, {F("10")}, F("inttemp2"), F("Temperature sensor 2"), DeviceValueUOM::DEGREES); &tempsensor1_,
register_device_value(empty, &ibaCalIntTemperature_, DeviceValueType::INT, {F("2")}, F("intoffset"), F("Offset int. temperature"), DeviceValueUOM::DEGREES); DeviceValueType::USHORT,
register_device_value(empty, flash_string_vector{F("10")},
F("inttemp1"),
F("Temperature sensor 1"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE,
&tempsensor2_,
DeviceValueType::USHORT,
flash_string_vector{F("10")},
F("inttemp2"),
F("Temperature sensor 2"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE,
&ibaCalIntTemperature_,
DeviceValueType::INT,
flash_string_vector{F("2")},
F("intoffset"),
F("Offset int. temperature"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE,
&ibaMinExtTemperature_, &ibaMinExtTemperature_,
DeviceValueType::INT, DeviceValueType::INT,
{}, {},
@@ -2067,10 +2083,10 @@ void Thermostat::register_device_values() {
// RC30 only // RC30 only
if (model == EMSdevice::EMS_DEVICE_FLAG_RC30_1) { if (model == EMSdevice::EMS_DEVICE_FLAG_RC30_1) {
register_device_value(empty, register_device_value(DeviceValueTAG::TAG_NONE,
&ibaMainDisplay_, &ibaMainDisplay_,
DeviceValueType::ENUM, DeviceValueType::ENUM,
{F("internal temperature"), flash_string_vector{F("internal temperature"),
F("internal setpoint"), F("internal setpoint"),
F("external temperature"), F("external temperature"),
F("burner temperature"), F("burner temperature"),
@@ -2082,14 +2098,14 @@ void Thermostat::register_device_values() {
F("ibaMainDisplay"), F("ibaMainDisplay"),
F("Display"), F("Display"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(empty, register_device_value(DeviceValueTAG::TAG_NONE,
&ibaLanguage_, &ibaLanguage_,
DeviceValueType::ENUM, DeviceValueType::ENUM,
{F("German"), F("Dutch"), F("French"), F("Italian")}, flash_string_vector{F("German"), F("Dutch"), F("French"), F("Italian")},
F("ibaLanguage"), F("ibaLanguage"),
F("Language"), F("Language"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(empty, register_device_value(DeviceValueTAG::TAG_NONE,
&ibaClockOffset_, &ibaClockOffset_,
DeviceValueType::UINT, DeviceValueType::UINT,
{}, {},
@@ -2100,28 +2116,40 @@ void Thermostat::register_device_values() {
// RC300 and RC100 // RC300 and RC100
if (model == EMS_DEVICE_FLAG_RC300 || model == EMS_DEVICE_FLAG_RC100) { if (model == EMS_DEVICE_FLAG_RC300 || model == EMS_DEVICE_FLAG_RC100) {
register_device_value(empty, register_device_value(DeviceValueTAG::TAG_NONE,
&floordrystatus_, &floordrystatus_,
DeviceValueType::ENUM, DeviceValueType::ENUM,
{F("off"), F("start"), F("heat"), F("hold"), F("cool"), F("end")}, flash_string_vector{F("off"), F("start"), F("heat"), F("hold"), F("cool"), F("end")},
F("floordry"), F("floordry"),
F("Floor drying"), F("Floor drying"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(empty, &dampedoutdoortemp2_, DeviceValueType::SHORT, {F("10")}, F("dampedtemp"), F("Damped outdoor temperature"), DeviceValueUOM::DEGREES); register_device_value(DeviceValueTAG::TAG_NONE,
register_device_value(empty, &floordrytemp_, DeviceValueType::UINT, {}, F("floordrytemp"), F("Floor drying temperature"), DeviceValueUOM::DEGREES); &dampedoutdoortemp2_,
DeviceValueType::SHORT,
flash_string_vector{F("10")},
F("dampedtemp"),
F("Damped outdoor temperature"),
DeviceValueUOM::DEGREES);
register_device_value( register_device_value(
empty, &ibaBuildingType_, DeviceValueType::ENUM, {F(""), F("light"), F("medium"), F("heavy")}, F("building"), F("Building"), DeviceValueUOM::NONE); DeviceValueTAG::TAG_NONE, &floordrytemp_, DeviceValueType::UINT, {}, F("floordrytemp"), F("Floor drying temperature"), DeviceValueUOM::DEGREES);
register_device_value(empty, register_device_value(DeviceValueTAG::TAG_NONE,
&ibaBuildingType_,
DeviceValueType::ENUM,
flash_string_vector{F(""), F("light"), F("medium"), F("heavy")},
F("building"),
F("Building"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE,
&wwMode_, &wwMode_,
DeviceValueType::ENUM, DeviceValueType::ENUM,
{F("off"), F("low"), F("high"), F("auto"), F("own_prog")}, flash_string_vector{F("off"), F("low"), F("high"), F("auto"), F("own_prog")},
F("wwmode"), F("wwmode"),
F("Warm water mode"), F("Warm water mode"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(empty, register_device_value(DeviceValueTAG::TAG_NONE,
&wwCircMode_, &wwCircMode_,
DeviceValueType::ENUM, DeviceValueType::ENUM,
{F("off"), F("on"), F("auto"), F("own_prog")}, flash_string_vector{F("off"), F("on"), F("auto"), F("own_prog")},
F("wwcircmode"), F("wwcircmode"),
F("Warm water circulation mode"), F("Warm water circulation mode"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
@@ -2129,14 +2157,31 @@ void Thermostat::register_device_values() {
// RC30 and RC35 // RC30 and RC35
if (model == EMS_DEVICE_FLAG_RC35 || model == EMS_DEVICE_FLAG_RC30_1) { if (model == EMS_DEVICE_FLAG_RC35 || model == EMS_DEVICE_FLAG_RC30_1) {
register_device_value(empty, &dampedoutdoortemp_, DeviceValueType::SHORT, {}, F("dampedtemp"), F("Damped outdoor temperature"), DeviceValueUOM::DEGREES); register_device_value(DeviceValueTAG::TAG_NONE,
register_device_value( &dampedoutdoortemp_,
empty, &ibaBuildingType_, DeviceValueType::ENUM, {F("light"), F("medium"), F("heavy")}, F("building"), F("Building"), DeviceValueUOM::NONE); DeviceValueType::SHORT,
register_device_value(empty, &wwMode_, DeviceValueType::ENUM, {F("off"), F("on"), F("auto")}, F("wwmode"), F("Warm water mode"), DeviceValueUOM::NONE); {},
register_device_value(empty, F("dampedtemp"),
F("Damped outdoor temperature"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE,
&ibaBuildingType_,
DeviceValueType::ENUM,
flash_string_vector{F("light"), F("medium"), F("heavy")},
F("building"),
F("Building"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE,
&wwMode_,
DeviceValueType::ENUM,
flash_string_vector{F("off"), F("on"), F("auto")},
F("wwmode"),
F("Warm water mode"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE,
&wwCircMode_, &wwCircMode_,
DeviceValueType::ENUM, DeviceValueType::ENUM,
{F("off"), F("on"), F("auto")}, flash_string_vector{F("off"), F("on"), F("auto")},
F("wwcircmode"), F("wwcircmode"),
F("Warm water circulation mode"), F("Warm water circulation mode"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
@@ -2147,9 +2192,8 @@ void Thermostat::register_device_values() {
void Thermostat::register_device_values_hc(std::shared_ptr<emsesp::Thermostat::HeatingCircuit> hc) { void Thermostat::register_device_values_hc(std::shared_ptr<emsesp::Thermostat::HeatingCircuit> hc) {
uint8_t model = hc->get_model(); uint8_t model = hc->get_model();
// heatcontroller name // heating circuit
std::string hc_name(10, '\0'); // hc{1-4} uint8_t tag = DeviceValueTAG::TAG_HC1 + hc->hc_num() - 1;
snprintf_P(&hc_name[0], 10, PSTR("hc%d"), hc->hc_num());
// different logic on how temperature values are stored, depending on model // different logic on how temperature values are stored, depending on model
flash_string_vector setpoint_temp_divider, curr_temp_divider; flash_string_vector setpoint_temp_divider, curr_temp_divider;
@@ -2164,17 +2208,17 @@ void Thermostat::register_device_values_hc(std::shared_ptr<emsesp::Thermostat::H
curr_temp_divider = flash_string_vector{F("10")}; curr_temp_divider = flash_string_vector{F("10")};
} }
register_device_value( register_device_value(
hc_name, &hc->setpoint_roomTemp, DeviceValueType::SHORT, setpoint_temp_divider, F("seltemp"), F("Setpoint room temperature"), DeviceValueUOM::DEGREES); tag, &hc->setpoint_roomTemp, DeviceValueType::SHORT, setpoint_temp_divider, F("seltemp"), F("Setpoint room temperature"), DeviceValueUOM::DEGREES);
register_device_value(hc_name, &hc->curr_roomTemp, DeviceValueType::SHORT, curr_temp_divider, F("currtemp"), F("Current room temperature"), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->curr_roomTemp, DeviceValueType::SHORT, curr_temp_divider, F("currtemp"), F("Current room temperature"), DeviceValueUOM::DEGREES);
// special handling for Home Assistant // special handling for Home Assistant
// we create special values called hatemp and hamode, which have empty fullnames so not shown in the web or console // we create special values called hatemp and hamode, which have empty fullnames so not shown in the web or console
if (Mqtt::ha_enabled()) { if (Mqtt::ha_enabled()) {
uint8_t option = Mqtt::ha_climate_format(); uint8_t option = Mqtt::ha_climate_format();
if (option == Mqtt::HA_Climate_Format::CURRENT) { if (option == Mqtt::HA_Climate_Format::CURRENT) {
register_device_value(hc_name, &hc->curr_roomTemp, DeviceValueType::SHORT, curr_temp_divider, F("hatemp"), nullptr, DeviceValueUOM::DEGREES); register_device_value(tag, &hc->curr_roomTemp, DeviceValueType::SHORT, curr_temp_divider, F("hatemp"), nullptr, DeviceValueUOM::DEGREES);
} else if (option == Mqtt::HA_Climate_Format::SETPOINT) { } else if (option == Mqtt::HA_Climate_Format::SETPOINT) {
register_device_value(hc_name, register_device_value(tag,
&hc->setpoint_roomTemp, &hc->setpoint_roomTemp,
DeviceValueType::SHORT, DeviceValueType::SHORT,
setpoint_temp_divider, setpoint_temp_divider,
@@ -2182,17 +2226,17 @@ void Thermostat::register_device_values_hc(std::shared_ptr<emsesp::Thermostat::H
F("HA current room temperature"), F("HA current room temperature"),
DeviceValueUOM::DEGREES); DeviceValueUOM::DEGREES);
} else if (option == Mqtt::HA_Climate_Format::ZERO) { } else if (option == Mqtt::HA_Climate_Format::ZERO) {
register_device_value(hc_name, &zero_value_, DeviceValueType::UINT, {}, F("hatemp"), nullptr, DeviceValueUOM::DEGREES); register_device_value(tag, &zero_value_, DeviceValueType::UINT, {}, F("hatemp"), nullptr, DeviceValueUOM::DEGREES);
} }
// if we're sending to HA the only valid mode types are heat, auto and off // if we're sending to HA the only valid mode types are heat, auto and off
// manual & day = heat // manual & day = heat
// night & off = off // night & off = off
// everything else auto // everything else auto
register_device_value(hc_name, register_device_value(tag,
&hc->mode, &hc->mode,
DeviceValueType::ENUM, DeviceValueType::ENUM,
{F("off"), F("heat"), F("auto"), F("heat"), F("off"), F("heat"), F("auto"), F("auto"), F("auto"), F("auto")}, flash_string_vector{F("off"), F("heat"), F("auto"), F("heat"), F("off"), F("heat"), F("auto"), F("auto"), F("auto"), F("auto")},
F("hamode"), F("hamode"),
nullptr, nullptr,
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
@@ -2215,34 +2259,34 @@ void Thermostat::register_device_values_hc(std::shared_ptr<emsesp::Thermostat::H
register_device_value(hc_name, &hc->nofrosttemp, DeviceValueType::INT, {}, F("nofrosttemp"), F("Nofrost temperature"), DeviceValueUOM::DEGREES); register_device_value(hc_name, &hc->nofrosttemp, DeviceValueType::INT, {}, F("nofrosttemp"), F("Nofrost temperature"), DeviceValueUOM::DEGREES);
register_device_value(hc_name, &hc->targetflowtemp, DeviceValueType::UINT, {}, F("targetflowtemp"), F("Target flow temperature"), DeviceValueUOM::DEGREES); register_device_value(hc_name, &hc->targetflowtemp, DeviceValueType::UINT, {}, F("targetflowtemp"), F("Target flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(hc_name, &hc->heatingtype, DeviceValueType::ENUM, {F("off"), F("radiator"), F("convector"), F("floor")}, F("heatingtype"), F("Heating type"), DeviceValueUOM::NONE); register_device_value(hc_name, &hc->heatingtype, DeviceValueType::ENUM, {F("off"), F("radiator"), F("convector"), F("floor")}, F("heatingtype"), F("Heating type"), DeviceValueUOM::NONE);
register_device_value(hc_name, register_device_value(tag,
&hc->summer_setmode, &hc->summer_setmode,
DeviceValueType::ENUM, DeviceValueType::ENUM,
{F("summer"), F("auto"), F("winter")}, flash_string_vector{F("summer"), F("auto"), F("winter")},
F("summermode"), F("summermode"),
F("Summer mode"), F("Summer mode"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(hc_name, register_device_value(tag,
&hc->controlmode, &hc->controlmode,
DeviceValueType::ENUM, DeviceValueType::ENUM,
{F("off"), F("outdoor"), F("simple"), F("MPC"), F("room"), F("power"), F("const.")}, flash_string_vector{F("off"), F("outdoor"), F("simple"), F("MPC"), F("room"), F("power"), F("const.")},
F("controlmode"), F("controlmode"),
F("Control mode"), F("Control mode"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(hc_name, &hc->program, DeviceValueType::UINT, {}, F("program"), F("Program"), DeviceValueUOM::NONE); register_device_value(tag, &hc->program, DeviceValueType::UINT, {}, F("program"), F("Program"), DeviceValueUOM::NONE);
} }
if (model == EMS_DEVICE_FLAG_RC20) { if (model == EMS_DEVICE_FLAG_RC20) {
register_device_value(hc_name, &hc->mode, DeviceValueType::ENUM, {F("off"), F("manual"), F("auto")}, F("mode"), F("Mode"), DeviceValueUOM::NONE); register_device_value(tag, &hc->mode, DeviceValueType::ENUM, flash_string_vector{F("off"), F("manual"), F("auto")}, F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(hc_name, &hc->modetype, DeviceValueType::ENUM, {F("day")}, F("modetype"), F("Mode type"), DeviceValueUOM::NONE); register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, flash_string_vector{F("day")}, F("modetype"), F("Mode type"), DeviceValueUOM::NONE);
} }
if (model == EMS_DEVICE_FLAG_RC20_2) { if (model == EMS_DEVICE_FLAG_RC20_2) {
register_device_value(hc_name, &hc->mode, DeviceValueType::ENUM, {F("off"), F("manual"), F("auto")}, F("mode"), F("Mode"), DeviceValueUOM::NONE); register_device_value(tag, &hc->mode, DeviceValueType::ENUM, flash_string_vector{F("off"), F("manual"), F("auto")}, F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(hc_name, &hc->modetype, DeviceValueType::ENUM, {F("day")}, F("modetype"), F("Mode type"), DeviceValueUOM::NONE); register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, flash_string_vector{F("day")}, F("modetype"), F("Mode type"), DeviceValueUOM::NONE);
register_device_value(hc_name, &hc->daytemp, DeviceValueType::UINT, {F("2")}, F("daytemp"), F("Day temperature"), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, flash_string_vector{F("2")}, F("daytemp"), F("Day temperature"), DeviceValueUOM::DEGREES);
register_device_value(hc_name, &hc->nighttemp, DeviceValueType::UINT, {F("2")}, F("nighttemp"), F("Night temperature"), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, flash_string_vector{F("2")}, F("nighttemp"), F("Night temperature"), DeviceValueUOM::DEGREES);
register_device_value(hc_name, &hc->program, DeviceValueType::UINT, {}, F("program"), F("Program"), DeviceValueUOM::NONE); register_device_value(tag, &hc->program, DeviceValueType::UINT, {}, F("program"), F("Program"), DeviceValueUOM::NONE);
} }
if (model == EMS_DEVICE_FLAG_RC35 || model == EMS_DEVICE_FLAG_RC30_1) { if (model == EMS_DEVICE_FLAG_RC35 || model == EMS_DEVICE_FLAG_RC30_1) {
@@ -2266,20 +2310,34 @@ void Thermostat::register_device_values_hc(std::shared_ptr<emsesp::Thermostat::H
register_device_value(hc_name, register_device_value(hc_name,
&hc->reducemode, &hc->reducemode,
DeviceValueType::ENUM, DeviceValueType::ENUM,
{F("nofrost"), F("reduce"), F("room"), F("outdoor")}, flash_string_vector{F("nofrost"), F("reduce"), F("room"), F("outdoor")},
F("reducemode"), F("reducemode"),
F("Reduce mode"), F("Reduce mode"),
DeviceValueUOM::NONE); DeviceValueUOM::NONE);
register_device_value(hc_name, &hc->controlmode, DeviceValueType::ENUM, {F("outdoor"), F("room")}, F("controlmode"), F("Control mode"), DeviceValueUOM::NONE); register_device_value(tag,
register_device_value(hc_name, &hc->program, DeviceValueType::UINT, {}, F("program"), F("Program"), DeviceValueUOM::NONE); &hc->controlmode,
DeviceValueType::ENUM,
flash_string_vector{F("outdoor"), F("room")},
F("controlmode"),
F("Control mode"),
DeviceValueUOM::NONE);
register_device_value(tag, &hc->program, DeviceValueType::UINT, {}, F("program"), F("Program"), DeviceValueUOM::NONE);
} }
if (model == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) { if (model == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
register_device_value(hc_name, &hc->mode, DeviceValueType::ENUM, {F("manual"), F("auto"), F("holiday")}, F("mode"), F("Mode"), DeviceValueUOM::NONE); register_device_value(
register_device_value(hc_name, &hc->modetype, DeviceValueType::ENUM, {F("heat"), F("eco"), F("nofrost")}, F("modetype"), F("Mode type"), DeviceValueUOM::NONE); tag, &hc->mode, DeviceValueType::ENUM, flash_string_vector{F("manual"), F("auto"), F("holiday")}, F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(hc_name, &hc->daytemp, DeviceValueType::UINT, {F("2")}, F("heattemp"), F("Heat temperature"), DeviceValueUOM::DEGREES); register_device_value(tag,
register_device_value(hc_name, &hc->nighttemp, DeviceValueType::UINT, {F("2")}, F("ecotemp"), F("Eco temperature"), DeviceValueUOM::DEGREES); &hc->modetype,
register_device_value(hc_name, &hc->nofrosttemp, DeviceValueType::INT, {F("2")}, F("nofrosttemp"), F("Nofrost temperature"), DeviceValueUOM::DEGREES); DeviceValueType::ENUM,
flash_string_vector{F("heat"), F("eco"), F("nofrost")},
F("modetype"),
F("Mode type"),
DeviceValueUOM::NONE);
register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, flash_string_vector{F("2")}, F("heattemp"), F("Heat temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, flash_string_vector{F("2")}, F("ecotemp"), F("Eco temperature"), DeviceValueUOM::DEGREES);
register_device_value(
tag, &hc->nofrosttemp, DeviceValueType::INT, flash_string_vector{F("2")}, F("nofrosttemp"), F("Nofrost temperature"), DeviceValueUOM::DEGREES);
} }
} }

View File

@@ -21,8 +21,9 @@
namespace emsesp { namespace emsesp {
// mapping of UOM, to match order in DeviceValueUOM enum // mapping of UOM, to match order in DeviceValueUOM enum emsdevice.h
static const __FlashStringHelper * DeviceValueUOM_s[(uint8_t)10] __attribute__((__aligned__(sizeof(int)))) PROGMEM = { // must be an int of 4 bytes, 32bit aligned
static const __FlashStringHelper * DeviceValueUOM_s[] __attribute__((__aligned__(sizeof(int)))) PROGMEM = {
F_(degrees), F_(degrees),
F_(percent), F_(percent),
@@ -36,11 +37,36 @@ static const __FlashStringHelper * DeviceValueUOM_s[(uint8_t)10] __attribute__((
}; };
const __FlashStringHelper * EMSdevice::uom_to_string(uint8_t uom) { // mapping of TAGs, to match order in DeviceValueTAG enum in emsdevice.h
// must be an int of 4 bytes, 32bit aligned
static const __FlashStringHelper * const DeviceValueTAG_s[] PROGMEM = {
F_(tag_boiler_data),
F_(tag_boiler_data_ww),
F_(tag_boiler_data_info),
F_(tag_hc1),
F_(tag_hc2),
F_(tag_hc3),
F_(tag_hc4),
F_(tag_wwc1),
F_(tag_wwc2),
F_(tag_wwc3),
F_(tag_wwc4)
};
const std::string EMSdevice::uom_to_string(uint8_t uom) {
if (uom == DeviceValueUOM::NONE) { if (uom == DeviceValueUOM::NONE) {
return nullptr; return std::string{};
} }
return DeviceValueUOM_s[uom]; return uuid::read_flash_string(DeviceValueUOM_s[uom]);
}
const std::string EMSdevice::tag_to_string(uint8_t tag) {
if (tag == DeviceValueTAG::TAG_NONE) {
return std::string{};
}
return uuid::read_flash_string(DeviceValueTAG_s[tag - 1]); // offset by 1 to account for NONE
} }
const std::vector<EMSdevice::DeviceValue> EMSdevice::devicevalues() const { const std::vector<EMSdevice::DeviceValue> EMSdevice::devicevalues() const {
@@ -331,7 +357,7 @@ void EMSdevice::register_telegram_type(const uint16_t telegram_type_id, const __
// full name: used in Web and Console // full name: used in Web and Console
// uom: unit of measure from DeviceValueUOM // uom: unit of measure from DeviceValueUOM
// icon (optional): the HA mdi icon to use, from locale_*.h file // icon (optional): the HA mdi icon to use, from locale_*.h file
void EMSdevice::register_device_value(std::string & tag, void EMSdevice::register_device_value(uint8_t tag,
void * value_p, void * value_p,
uint8_t type, uint8_t type,
const flash_string_vector & options, const flash_string_vector & options,
@@ -378,12 +404,12 @@ std::string EMSdevice::get_value_uom(const char * key) {
if ((dv.uom == DeviceValueUOM::NONE) || (dv.uom == DeviceValueUOM::MINUTES)) { if ((dv.uom == DeviceValueUOM::NONE) || (dv.uom == DeviceValueUOM::MINUTES)) {
break; break;
} }
return uuid::read_flash_string(EMSdevice::uom_to_string(dv.uom)); return EMSdevice::uom_to_string(dv.uom);
} }
} }
} }
return {}; // not found return std::string{}; // not found
} }
// prepare array of device values, as 3 elements serialized (name, value, uom) in array to send to Web UI // prepare array of device values, as 3 elements serialized (name, value, uom) in array to send to Web UI
@@ -488,11 +514,11 @@ bool EMSdevice::generate_values_json_web(JsonObject & json) {
// add name, prefixing the tag if it exists // add name, prefixing the tag if it exists
// if we're a boiler, ignore the tag // if we're a boiler, ignore the tag
if (dv.tag.empty() || (device_type_ == DeviceType::BOILER)) { if ((dv.tag == DeviceValueTAG::TAG_NONE) || (device_type_ == DeviceType::BOILER)) {
data.add(dv.full_name); data.add(dv.full_name);
} else { } else {
char name[50]; char name[50];
snprintf_P(name, sizeof(name), "(%s) %s", dv.tag.c_str(), uuid::read_flash_string(dv.full_name).c_str()); snprintf_P(name, sizeof(name), "(%s) %s", tag_to_string(dv.tag).c_str(), uuid::read_flash_string(dv.full_name).c_str());
data.add(name); data.add(name);
} }
num_elements = sz + 2; num_elements = sz + 2;
@@ -505,20 +531,20 @@ bool EMSdevice::generate_values_json_web(JsonObject & json) {
// For each value in the device create the json object pair and add it to given json // For each value in the device create the json object pair and add it to given json
// return false if empty // return false if empty
bool EMSdevice::generate_values_json(JsonObject & root, const std::string & tag_filter, const bool verbose) { bool EMSdevice::generate_values_json(JsonObject & root, const uint8_t tag_filter, const bool verbose) {
bool has_value = false; // to see if we've added a value. it's faster than doing a json.size() at the end bool has_value = false; // to see if we've added a value. it's faster than doing a json.size() at the end
std::string old_tag(40, '\0'); uint8_t old_tag = 255;
JsonObject json = root; JsonObject json = root;
for (const auto & dv : devicevalues_) { for (const auto & dv : devicevalues_) {
// only show if tag is either empty or matches a value, and don't show if full_name is empty unless we're outputing for mqtt payloads // only show if tag is either empty or matches a value, and don't show if full_name is empty unless we're outputing for mqtt payloads
if (((tag_filter.empty()) || (tag_filter == dv.tag)) && (dv.full_name != nullptr || !verbose)) { if (((tag_filter == DeviceValueTAG::TAG_NONE) || (tag_filter == dv.tag)) && (dv.full_name != nullptr || !verbose)) {
bool have_tag = (!dv.tag.empty() && (dv.device_type != DeviceType::BOILER)); bool have_tag = ((dv.tag != DeviceValueTAG::TAG_NONE) && (dv.device_type != DeviceType::BOILER));
char name[80]; char name[80];
if (verbose) { if (verbose) {
// prefix the tag in brackets, unless it's Boiler because we're naughty and use tag for the MQTT topic // prefix the tag in brackets, unless it's Boiler because we're naughty and use tag for the MQTT topic
if (have_tag) { if (have_tag) {
snprintf_P(name, 80, "(%s) %s", dv.tag.c_str(), uuid::read_flash_string(dv.full_name).c_str()); snprintf_P(name, 80, "(%s) %s", tag_to_string(dv.tag).c_str(), uuid::read_flash_string(dv.full_name).c_str());
} else { } else {
strcpy(name, uuid::read_flash_string(dv.full_name).c_str()); // use full name strcpy(name, uuid::read_flash_string(dv.full_name).c_str()); // use full name
} }
@@ -528,7 +554,7 @@ bool EMSdevice::generate_values_json(JsonObject & root, const std::string & tag_
// if we have a tag, and its different to the last one create a nested object // if we have a tag, and its different to the last one create a nested object
if (have_tag && (dv.tag != old_tag)) { if (have_tag && (dv.tag != old_tag)) {
old_tag = dv.tag; old_tag = dv.tag;
json = root.createNestedObject(dv.tag); json = root.createNestedObject(tag_to_string(dv.tag));
} }
} }

View File

@@ -30,6 +30,14 @@
namespace emsesp { namespace emsesp {
// Home Assistant icons (https://materialdesignicons.com/)
MAKE_PSTR(icontemperature, "mdi:temperature-celsius")
MAKE_PSTR(iconpercent, "mdi:percent-outline")
MAKE_PSTR(iconfire, "mdi:fire")
MAKE_PSTR(iconfan, "mdi:fan")
MAKE_PSTR(iconflame, "mdi:flash")
MAKE_PSTR(iconvalve, "mdi:valve")
enum DeviceValueType : uint8_t { enum DeviceValueType : uint8_t {
BOOL, BOOL,
INT, INT,
@@ -37,13 +45,23 @@ enum DeviceValueType : uint8_t {
SHORT, SHORT,
USHORT, USHORT,
ULONG, ULONG,
TIME, // same as ULONG TIME, // same as ULONG (32 bits)
ENUM, ENUM,
TEXT TEXT
}; };
// Unit Of Measurement mapping // Unit Of Measurement mapping - maps to DeviceValueUOM_s in emsdevice.cpp
// uom - also used with HA
MAKE_PSTR(percent, "%")
MAKE_PSTR(degrees, "°C")
MAKE_PSTR(kwh, "kWh")
MAKE_PSTR(wh, "Wh")
MAKE_PSTR(bar, "bar")
MAKE_PSTR(minutes, "minutes")
MAKE_PSTR(hours, "hours")
MAKE_PSTR(ua, "uA")
MAKE_PSTR(lmin, "l/min")
enum DeviceValueUOM : uint8_t { enum DeviceValueUOM : uint8_t {
DEGREES, DEGREES,
PERCENT, PERCENT,
@@ -58,6 +76,34 @@ enum DeviceValueUOM : uint8_t {
}; };
// TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp
MAKE_PSTR(tag_boiler_data, "boiler_data")
MAKE_PSTR(tag_boiler_data_ww, "boiler_data_ww")
MAKE_PSTR(tag_boiler_data_info, "boiler_data_info")
MAKE_PSTR(tag_hc1, "hc1")
MAKE_PSTR(tag_hc2, "hc2")
MAKE_PSTR(tag_hc3, "hc3")
MAKE_PSTR(tag_hc4, "hc4")
MAKE_PSTR(tag_wwc1, "wwc1")
MAKE_PSTR(tag_wwc2, "wwc2")
MAKE_PSTR(tag_wwc3, "wwc3")
MAKE_PSTR(tag_wwc4, "wwc4")
enum DeviceValueTAG : uint8_t {
TAG_NONE = 0,
TAG_BOILER_DATA,
TAG_BOILER_DATA_WW,
TAG_BOILER_DATA_INFO,
TAG_HC1,
TAG_HC2,
TAG_HC3,
TAG_HC4,
TAG_WWC1,
TAG_WWC2,
TAG_WWC3,
TAG_WWC4
};
class EMSdevice { class EMSdevice {
public: public:
virtual ~EMSdevice() = default; // destructor of base class must always be virtual because it's a polymorphic class virtual ~EMSdevice() = default; // destructor of base class must always be virtual because it's a polymorphic class
@@ -86,7 +132,8 @@ class EMSdevice {
static std::string device_type_2_device_name(const uint8_t device_type); static std::string device_type_2_device_name(const uint8_t device_type);
static uint8_t device_name_2_device_type(const char * topic); static uint8_t device_name_2_device_type(const char * topic);
static const __FlashStringHelper * uom_to_string(uint8_t uom); static const std::string uom_to_string(uint8_t uom);
static const std::string tag_to_string(uint8_t tag);
inline uint8_t product_id() const { inline uint8_t product_id() const {
return product_id_; return product_id_;
@@ -173,10 +220,10 @@ class EMSdevice {
bool handle_telegram(std::shared_ptr<const Telegram> telegram); bool handle_telegram(std::shared_ptr<const Telegram> telegram);
std::string get_value_uom(const char * key); std::string get_value_uom(const char * key);
bool generate_values_json(JsonObject & json, const std::string & tag_filter, const bool verbose = false); bool generate_values_json(JsonObject & json, const uint8_t tag_filter, const bool verbose = false);
bool generate_values_json_web(JsonObject & json); bool generate_values_json_web(JsonObject & json);
void register_device_value(std::string & tag, void register_device_value(uint8_t tag,
void * value_p, void * value_p,
uint8_t type, uint8_t type,
const flash_string_vector & options, const flash_string_vector & options,
@@ -273,7 +320,7 @@ class EMSdevice {
struct DeviceValue { struct DeviceValue {
uint8_t device_type; // EMSdevice::DeviceType uint8_t device_type; // EMSdevice::DeviceType
const std::string tag; // MQTT topic or ID 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 flash_string_vector options; // list of options for ENUM, or divider const flash_string_vector options; // list of options for ENUM, or divider
@@ -283,7 +330,7 @@ class EMSdevice {
const __FlashStringHelper * icon; // HA icon const __FlashStringHelper * icon; // HA icon
DeviceValue(uint8_t device_type, DeviceValue(uint8_t device_type,
const std::string & tag, uint8_t tag,
void * value_p, void * value_p,
uint8_t type, uint8_t type,
const flash_string_vector options, const flash_string_vector options,
@@ -304,6 +351,10 @@ class EMSdevice {
}; };
const std::vector<DeviceValue> devicevalues() const; const std::vector<DeviceValue> devicevalues() const;
void init_devicevalues(uint8_t size) {
devicevalues_.reserve(size);
}
private: private:
uint8_t unique_id_; uint8_t unique_id_;
uint8_t device_type_ = DeviceType::SYSTEM; uint8_t device_type_ = DeviceType::SYSTEM;

View File

@@ -276,7 +276,7 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) {
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE_DYN); // use max size DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE_DYN); // use max size
JsonObject json = doc.to<JsonObject>(); JsonObject json = doc.to<JsonObject>();
emsdevice->generate_values_json(json, "", true); // verbose mode emsdevice->generate_values_json(json, DeviceValueTAG::TAG_NONE, true); // verbose mode
// print line // print line
uint8_t id = 0; uint8_t id = 0;
@@ -401,7 +401,7 @@ void EMSESP::publish_device_values(uint8_t device_type) {
// create the configs for each value as a sensor // create the configs for each value as a sensor
for (const auto & dv : emsdevice->devicevalues()) { for (const auto & dv : emsdevice->devicevalues()) {
if (dv.device_type == device_type) { if (dv.device_type == device_type) {
Mqtt::register_mqtt_ha_sensor(dv.type, dv.tag.c_str(), dv.full_name, device_type, dv.short_name, dv.uom, dv.icon); Mqtt::register_mqtt_ha_sensor(dv.type, dv.tag, dv.full_name, device_type, dv.short_name, dv.uom, dv.icon);
} }
} }
@@ -412,19 +412,19 @@ void EMSESP::publish_device_values(uint8_t device_type) {
// if its a boiler, generate json for each group and publish it // if its a boiler, generate json for each group and publish it
if (device_type == DeviceType::BOILER) { if (device_type == DeviceType::BOILER) {
emsdevice->generate_values_json(json, "boiler_data"); emsdevice->generate_values_json(json, DeviceValueTAG::TAG_BOILER_DATA);
Mqtt::publish("boiler_data", json); Mqtt::publish("boiler_data", json);
json.clear(); json.clear();
emsdevice->generate_values_json(json, "boiler_data_ww"); emsdevice->generate_values_json(json, DeviceValueTAG::TAG_BOILER_DATA_WW);
Mqtt::publish("boiler_data_ww", json); Mqtt::publish("boiler_data_ww", json);
json.clear(); json.clear();
emsdevice->generate_values_json(json, "boiler_data_info"); emsdevice->generate_values_json(json, DeviceValueTAG::TAG_BOILER_DATA_INFO);
Mqtt::publish("boiler_data_info", json); Mqtt::publish("boiler_data_info", json);
return; return;
} }
// for all other devices add the values to the json, without verbose mode // for all other devices add the values to the json, without verbose mode
has_value |= emsdevice->generate_values_json(json, ""); has_value |= emsdevice->generate_values_json(json, DeviceValueTAG::TAG_NONE);
} }
} }
@@ -761,6 +761,24 @@ void EMSESP::show_devices(uuid::console::Shell & shell) {
emsdevice->show_telegram_handlers(shell); emsdevice->show_telegram_handlers(shell);
// emsdevice->show_mqtt_handlers(shell); // emsdevice->show_mqtt_handlers(shell);
shell.println(); shell.println();
#if defined(EMSESP_DEBUG)
// TODO debug stuff - count size of objects
size_t total_s = 0;
uint8_t count = 0;
for (const auto & dv : emsdevice->devicevalues()) {
size_t s = sizeof(dv);
if (dv.full_name) {
shell.printfln("[%s] %d", uuid::read_flash_string(dv.full_name).c_str(), s);
} else {
shell.printfln("[%s]* %d", uuid::read_flash_string(dv.short_name).c_str(), s);
}
total_s += s;
count++;
}
shell.printfln("Total size of %d elements: %d", count, total_s);
shell.println();
#endif
} }
} }
} }
@@ -788,7 +806,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, std::
// find the name and flags in our database // find the name and flags in our database
for (const auto & device : device_library_) { for (const auto & device : device_library_) {
if (device.product_id == product_id) { if (device.product_id == product_id) {
emsdevice->name(uuid::read_flash_string(device.name)); emsdevice->name(std::move(uuid::read_flash_string(device.name)));
emsdevice->add_flags(device.flags); emsdevice->add_flags(device.flags);
} }
} }
@@ -853,7 +871,7 @@ bool EMSESP::command_info(uint8_t device_type, JsonObject & json) {
bool has_value = false; bool has_value = false;
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice && (emsdevice->device_type() == device_type)) { if (emsdevice && (emsdevice->device_type() == device_type)) {
has_value |= emsdevice->generate_values_json(json, "", true); // verbose mode has_value |= emsdevice->generate_values_json(json, DeviceValueTAG::TAG_NONE, true); // verbose mode
} }
} }

View File

@@ -422,7 +422,7 @@ std::string Helpers::toLower(std::string const & s) {
// checks if we can convert a char string to a lowercase string // checks if we can convert a char string to a lowercase string
bool Helpers::value2string(const char * v, std::string & value) { bool Helpers::value2string(const char * v, std::string & value) {
if ((v == nullptr) || (strlen(v) == 0)) { if ((v == nullptr) || (strlen(v) == 0)) {
value = {}; value = std::string{};
return false; return false;
} }
value = toLower(v); value = toLower(v);

View File

@@ -90,6 +90,7 @@ MAKE_PSTR_WORD(generic)
MAKE_PSTR_WORD(dallassensor) MAKE_PSTR_WORD(dallassensor)
MAKE_PSTR_WORD(unknown) MAKE_PSTR_WORD(unknown)
// strings
MAKE_PSTR(EMSESP, "EMS-ESP") MAKE_PSTR(EMSESP, "EMS-ESP")
MAKE_PSTR(master_thermostat_fmt, "Master Thermostat Device ID = %s") MAKE_PSTR(master_thermostat_fmt, "Master Thermostat Device ID = %s")
MAKE_PSTR(host_fmt, "Host = %s") MAKE_PSTR(host_fmt, "Host = %s")
@@ -107,26 +108,6 @@ MAKE_PSTR(watchid_optional, "[ID]")
MAKE_PSTR(watch_format_optional, "[off | on | raw | unknown]") MAKE_PSTR(watch_format_optional, "[off | on | raw | unknown]")
MAKE_PSTR(invalid_watch, "Invalid watch type") MAKE_PSTR(invalid_watch, "Invalid watch type")
MAKE_PSTR(data_mandatory, "\"XX XX ...\"") MAKE_PSTR(data_mandatory, "\"XX XX ...\"")
// uom - also used with HA
MAKE_PSTR(percent, "%")
MAKE_PSTR(degrees, "°C")
MAKE_PSTR(kwh, "kWh")
MAKE_PSTR(wh, "Wh")
MAKE_PSTR(bar, "bar")
MAKE_PSTR(minutes, "minutes")
MAKE_PSTR(hours, "hours")
MAKE_PSTR(ua, "uA")
MAKE_PSTR(lmin, "l/min")
// Home Assistant icons (https://materialdesignicons.com/)
MAKE_PSTR(icontemperature, "mdi:temperature-celsius")
MAKE_PSTR(iconpercent, "mdi:percent-outline")
MAKE_PSTR(iconfire, "mdi:fire")
MAKE_PSTR(iconfan, "mdi:fan")
MAKE_PSTR(iconflame, "mdi:flash")
MAKE_PSTR(iconvalve, "mdi:valve")
MAKE_PSTR(asterisks, "********") MAKE_PSTR(asterisks, "********")
MAKE_PSTR(n_mandatory, "<n>") MAKE_PSTR(n_mandatory, "<n>")
MAKE_PSTR(id_optional, "[id|hc]") MAKE_PSTR(id_optional, "[id|hc]")

View File

@@ -729,7 +729,7 @@ void Mqtt::process_queue() {
// entity must match the key/value pair in the *_data topic // entity must match the key/value pair in the *_data topic
// some string copying here into chars, it looks messy but does help with heap fragmentation issues // some string copying here into chars, it looks messy but does help with heap fragmentation issues
void Mqtt::register_mqtt_ha_sensor(uint8_t type, // device value type void Mqtt::register_mqtt_ha_sensor(uint8_t type, // device value type
const char * prefix, uint8_t tag,
const __FlashStringHelper * name, const __FlashStringHelper * name,
const uint8_t device_type, const uint8_t device_type,
const __FlashStringHelper * entity, const __FlashStringHelper * entity,
@@ -743,14 +743,14 @@ void Mqtt::register_mqtt_ha_sensor(uint8_t type, // device v
// DynamicJsonDocument doc(EMSESP_JSON_SIZE_HA_CONFIG); // DynamicJsonDocument doc(EMSESP_JSON_SIZE_HA_CONFIG);
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc; // TODO see if this crashes ESP8266? StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc; // TODO see if this crashes ESP8266?
bool have_prefix = ((prefix[0] != '\0') && (device_type != EMSdevice::DeviceType::BOILER)); bool have_prefix = ((tag != DeviceValueTAG::TAG_NONE) && (device_type != EMSdevice::DeviceType::BOILER));
// create entity by inserting any given prefix // create entity by inserting any given prefix
// we ignore the prefix (tag) if BOILER // we ignore the tag if BOILER
char new_entity[50]; char new_entity[50];
// special case for boiler - don't use the prefix // special case for boiler - don't use the prefix
if (have_prefix) { if (have_prefix) {
snprintf_P(new_entity, sizeof(new_entity), PSTR("%s.%s"), prefix, uuid::read_flash_string(entity).c_str()); snprintf_P(new_entity, sizeof(new_entity), PSTR("%s.%s"), EMSdevice::tag_to_string(tag).c_str(), uuid::read_flash_string(entity).c_str());
} else { } else {
snprintf_P(new_entity, sizeof(new_entity), PSTR("%s"), uuid::read_flash_string(entity).c_str()); snprintf_P(new_entity, sizeof(new_entity), PSTR("%s"), uuid::read_flash_string(entity).c_str());
} }
@@ -764,35 +764,29 @@ void Mqtt::register_mqtt_ha_sensor(uint8_t type, // device v
std::string uniq(50, '\0'); std::string uniq(50, '\0');
snprintf_P(&uniq[0], uniq.capacity() + 1, PSTR("%s_%s"), device_name, new_entity); snprintf_P(&uniq[0], uniq.capacity() + 1, PSTR("%s_%s"), device_name, new_entity);
std::replace(uniq.begin(), uniq.end(), '.', '_'); std::replace(uniq.begin(), uniq.end(), '.', '_');
doc["uniq_id"] = uniq;
// topic
char topic[MQTT_TOPIC_MAX_SIZE];
// state topic // state topic
// if its a boiler we use the tag // if its a boiler we use the tag
char stat_t[MQTT_TOPIC_MAX_SIZE]; char stat_t[MQTT_TOPIC_MAX_SIZE];
if (device_type == EMSdevice::DeviceType::BOILER) { if (device_type == EMSdevice::DeviceType::BOILER) {
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s"), hostname_.c_str(), prefix); snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s"), hostname_.c_str(), EMSdevice::tag_to_string(tag).c_str());
} else { } else {
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s_data"), hostname_.c_str(), device_name); snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s_data"), hostname_.c_str(), device_name);
} }
doc["stat_t"] = stat_t;
// ha device
char ha_device[40];
snprintf_P(ha_device, sizeof(ha_device), PSTR("ems-esp-%s"), device_name);
// name // name
char new_name[50]; char new_name[50];
if (have_prefix) { if (have_prefix) {
snprintf_P(new_name, sizeof(new_name), PSTR("%s %s %s"), device_name, prefix, uuid::read_flash_string(name).c_str()); snprintf_P(new_name, sizeof(new_name), PSTR("%s %s %s"), device_name, EMSdevice::tag_to_string(tag).c_str(), uuid::read_flash_string(name).c_str());
} else { } else {
snprintf_P(new_name, sizeof(new_name), PSTR("%s %s"), device_name, uuid::read_flash_string(name).c_str()); snprintf_P(new_name, sizeof(new_name), PSTR("%s %s"), device_name, uuid::read_flash_string(name).c_str());
} }
new_name[0] = toupper(new_name[0]); // capitalize first letter new_name[0] = toupper(new_name[0]); // capitalize first letter
doc["name"] = new_name; doc["name"] = new_name;
doc["uniq_id"] = uniq;
doc["stat_t"] = stat_t; char topic[MQTT_TOPIC_MAX_SIZE]; // reserved for topic
// look at the device value type // look at the device value type
if (type != DeviceValueType::BOOL) { if (type != DeviceValueType::BOOL) {
@@ -845,6 +839,10 @@ void Mqtt::register_mqtt_ha_sensor(uint8_t type, // device v
JsonObject dev = doc.createNestedObject("dev"); JsonObject dev = doc.createNestedObject("dev");
JsonArray ids = dev.createNestedArray("ids"); JsonArray ids = dev.createNestedArray("ids");
// ha device
char ha_device[40];
snprintf_P(ha_device, sizeof(ha_device), PSTR("ems-esp-%s"), device_name);
ids.add(ha_device); ids.add(ha_device);
publish_ha(topic, doc.as<JsonObject>()); publish_ha(topic, doc.as<JsonObject>());

View File

@@ -99,7 +99,7 @@ class Mqtt {
static void publish_ha(const __FlashStringHelper * topic, const JsonObject & payload); static void publish_ha(const __FlashStringHelper * topic, const JsonObject & payload);
static void register_mqtt_ha_sensor(uint8_t type, static void register_mqtt_ha_sensor(uint8_t type,
const char * prefix, uint8_t tag,
const __FlashStringHelper * name, const __FlashStringHelper * name,
const uint8_t device_type, const uint8_t device_type,
const __FlashStringHelper * entity, const __FlashStringHelper * entity,

View File

@@ -192,6 +192,10 @@ void System::start() {
#endif #endif
} }
#if defined(EMSESP_DEBUG)
show_mem("Startup");
#endif
// print boot message // print boot message
EMSESP::esp8266React.getWiFiSettingsService()->read( EMSESP::esp8266React.getWiFiSettingsService()->read(
[&](WiFiSettings & wifiSettings) { LOG_INFO(F("System %s booted (EMS-ESP version %s)"), wifiSettings.hostname.c_str(), EMSESP_APP_VERSION); }); [&](WiFiSettings & wifiSettings) { LOG_INFO(F("System %s booted (EMS-ESP version %s)"), wifiSettings.hostname.c_str(), EMSESP_APP_VERSION); });
@@ -287,7 +291,7 @@ void System::loop() {
#if defined(ESP8266) #if defined(ESP8266)
#if defined(EMSESP_DEBUG) #if defined(EMSESP_DEBUG)
static uint32_t last_memcheck_ = 0; static uint32_t last_memcheck_ = 0;
if (currentMillis - last_memcheck_ > 10000) { // 10 seconds if (currentMillis - last_memcheck_ > 5000) { // 5 seconds
last_memcheck_ = currentMillis; last_memcheck_ = currentMillis;
show_mem("core"); show_mem("core");
} }
@@ -300,7 +304,19 @@ void System::loop() {
void System::show_mem(const char * note) { void System::show_mem(const char * note) {
#if defined(ESP8266) #if defined(ESP8266)
#if defined(EMSESP_DEBUG) #if defined(EMSESP_DEBUG)
LOG_INFO(F("(%s) Free heap: %d%% (%lu), frag:%u%%"), note, free_mem(), (unsigned long)ESP.getFreeHeap(), ESP.getHeapFragmentation()); static uint32_t old_free_heap = 0;
static uint8_t old_heap_frag = 0;
uint32_t free_heap = ESP.getFreeHeap();
uint8_t heap_frag = ESP.getHeapFragmentation();
LOG_INFO(F("(%s) Free heap: %d%% (%lu) (~%lu), frag:%d%% (~%d)"),
note,
free_mem(),
free_heap,
(uint32_t)abs(free_heap - old_free_heap),
heap_frag,
(uint8_t)abs(heap_frag - old_heap_frag));
old_free_heap = free_heap;
old_heap_frag = heap_frag;
#endif #endif
#endif #endif
} }

View File

@@ -43,8 +43,8 @@ namespace emsesp {
// #define EMSESP_TEST_DEFAULT "solar" // #define EMSESP_TEST_DEFAULT "solar"
// #define EMSESP_TEST_DEFAULT "mixer" // #define EMSESP_TEST_DEFAULT "mixer"
// #define EMSESP_TEST_DEFAULT "web" // #define EMSESP_TEST_DEFAULT "web"
#define EMSESP_TEST_DEFAULT "general" // #define EMSESP_TEST_DEFAULT "general"
// #define EMSESP_TEST_DEFAULT "boiler" #define EMSESP_TEST_DEFAULT "boiler"
class Test { class Test {
public: public: