optimize tags for mqtt nesting - #738

This commit is contained in:
proddy
2021-03-11 21:56:45 +01:00
parent 581288b751
commit 1ca905d71a
17 changed files with 262 additions and 242 deletions

View File

@@ -13,7 +13,7 @@
- Support for chunked MQTT payloads to allow large data sets > 2kb - Support for chunked MQTT payloads to allow large data sets > 2kb
- External Button support (#708) for resetting to factory defaults and other actions - External Button support (#708) for resetting to factory defaults and other actions
- new console set command in `system`, `set ethernet <profile>` for quickly enabling cabled ethernet connections without using the captive wifi portal - new console set command in `system`, `set ethernet <profile>` for quickly enabling cabled ethernet connections without using the captive wifi portal
- Added in MQTT nested mode, for thermostat and mixer, like we had in v2 - Added in MQTT nested mode, for thermostat and mixer, like we had back in v2
- Cascade MC400 (product-id 210) (3.0.0b6) - Cascade MC400 (product-id 210) (3.0.0b6)
- values for wwMaxPower, wwFlowtempOffset - values for wwMaxPower, wwFlowtempOffset

View File

@@ -58,7 +58,6 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_telegram_type(0x19, F("UBAMonitorSlow"), true, [&](std::shared_ptr<const Telegram> t) { process_UBAMonitorSlow(t); }); register_telegram_type(0x19, F("UBAMonitorSlow"), true, [&](std::shared_ptr<const Telegram> t) { process_UBAMonitorSlow(t); });
register_telegram_type(0x1A, F("UBASetPoints"), false, [&](std::shared_ptr<const Telegram> t) { process_UBASetPoints(t); }); register_telegram_type(0x1A, F("UBASetPoints"), false, [&](std::shared_ptr<const Telegram> t) { process_UBASetPoints(t); });
register_telegram_type(0x1C, F("UBAMaintenanceStatus"), false, [&](std::shared_ptr<const Telegram> t) { process_UBAMaintenanceStatus(t); }); register_telegram_type(0x1C, F("UBAMaintenanceStatus"), false, [&](std::shared_ptr<const Telegram> t) { process_UBAMaintenanceStatus(t); });
register_telegram_type(0x26, F("UBASettingsWW"), true, [&](std::shared_ptr<const Telegram> t) { process_UBASettingsWW(t); });
register_telegram_type(0x2A, F("MC10Status"), false, [&](std::shared_ptr<const Telegram> t) { process_MC10Status(t); }); register_telegram_type(0x2A, F("MC10Status"), false, [&](std::shared_ptr<const Telegram> t) { process_MC10Status(t); });
register_telegram_type(0x33, F("UBAParameterWW"), true, [&](std::shared_ptr<const Telegram> t) { process_UBAParameterWW(t); }); register_telegram_type(0x33, F("UBAParameterWW"), true, [&](std::shared_ptr<const Telegram> t) { process_UBAParameterWW(t); });
register_telegram_type(0x34, F("UBAMonitorWW"), false, [&](std::shared_ptr<const Telegram> t) { process_UBAMonitorWW(t); }); register_telegram_type(0x34, F("UBAMonitorWW"), false, [&](std::shared_ptr<const Telegram> t) { process_UBAMonitorWW(t); });
@@ -73,21 +72,16 @@ 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, EMSESP::send_read_request(0x10, device_id); // read last errorcode on start (only published on errors)
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(0x11, EMSESP::send_read_request(0x15, device_id); // read maintenace data on start (only published on change)
device_id); // read last errorcode on start (only published on errors) EMSESP::send_read_request(0x1C, device_id); // read maintenace status on start (only published on change)
EMSESP::send_read_request(0x15,
device_id); // read maintenace data on start (only published on change)
EMSESP::send_read_request(0x1C,
device_id); // read maintenace status on start (only published on change)
// 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); });
register_mqtt_cmd(F("wwtapactivated"), [&](const char * value, const int8_t id) { return set_tapwarmwater_activated(value, id); }); register_mqtt_cmd(F("wwtapactivated"), [&](const char * value, const int8_t id) { return set_tapwarmwater_activated(value, id); });
register_mqtt_cmd(F("wwflowtempoffset"), [&](const char * value, const int8_t id) { return set_wWFlowTempOffset(value, id); }); register_mqtt_cmd(F("wwflowtempoffset"), [&](const char * value, const int8_t id) { return set_wWFlowTempOffset(value, id); });
register_mqtt_cmd(F("wwmaxpower"), [&](const char * value, const int8_t id) { return set_warmwater_maxpower(value, id); });
register_mqtt_cmd(F("wwonetime"), [&](const char * value, const int8_t id) { return set_warmwater_onetime(value, id); }); register_mqtt_cmd(F("wwonetime"), [&](const char * value, const int8_t id) { return set_warmwater_onetime(value, id); });
register_mqtt_cmd(F("wwcircpump"), [&](const char * value, const int8_t id) { return set_warmwater_circulation_pump(value, id); }); register_mqtt_cmd(F("wwcircpump"), [&](const char * value, const int8_t id) { return set_warmwater_circulation_pump(value, id); });
register_mqtt_cmd(F("wwcirculation"), [&](const char * value, const int8_t id) { return set_warmwater_circulation(value, id); }); register_mqtt_cmd(F("wwcirculation"), [&](const char * value, const int8_t id) { return set_warmwater_circulation(value, id); });
@@ -116,12 +110,10 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_device_value(TAG_BOILER_DATA, &heatingActive_, DeviceValueType::BOOL, nullptr, F("heatingActive"), F("heating active")); register_device_value(TAG_BOILER_DATA, &heatingActive_, DeviceValueType::BOOL, nullptr, F("heatingActive"), F("heating active"));
register_device_value(TAG_BOILER_DATA, &tapwaterActive_, DeviceValueType::BOOL, nullptr, F("tapwaterActive"), F("warm water active")); register_device_value(TAG_BOILER_DATA, &tapwaterActive_, DeviceValueType::BOOL, nullptr, F("tapwaterActive"), F("warm water active"));
register_device_value(TAG_BOILER_DATA, &selFlowTemp_, DeviceValueType::UINT, nullptr, F("selFlowTemp"), F("selected flow temperature"), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &selFlowTemp_, DeviceValueType::UINT, nullptr, F("selFlowTemp"), F("selected flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA, &selBurnPow_, DeviceValueType::UINT, nullptr, F("selBurnPow"), F("burner selected max power"), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA, &selBurnPow_, DeviceValueType::UINT, nullptr, F("selBurnPow"), F("burner selected max power"), DeviceValueUOM::PERCENT);
register_device_value(TAG_BOILER_DATA, &heatingPumpMod_, DeviceValueType::UINT, nullptr, F("heatingPumpMod"), F("heating pump modulation"), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA, &heatingPumpMod_, DeviceValueType::UINT, nullptr, F("heatingPumpMod"), F("heating pump modulation"), DeviceValueUOM::PERCENT);
register_device_value(TAG_BOILER_DATA, &heatingPump2Mod_, DeviceValueType::UINT, nullptr, F("heatingPump2Mod"), F("heating pump 2 modulation"), DeviceValueUOM::PERCENT); register_device_value(TAG_BOILER_DATA, &heatingPump2Mod_, DeviceValueType::UINT, nullptr, F("heatingPump2Mod"), F("heating pump 2 modulation"), DeviceValueUOM::PERCENT);
register_device_value(TAG_BOILER_DATA, &outdoorTemp_, DeviceValueType::SHORT, FL_(div10), F("outdoorTemp"), F("outside temperature"), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &outdoorTemp_, DeviceValueType::SHORT, FL_(div10), F("outdoorTemp"), F("outside temperature"), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA, &curFlowTemp_, DeviceValueType::USHORT, FL_(div10), F("curFlowTemp"), F("current flow temperature"), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &curFlowTemp_, DeviceValueType::USHORT, FL_(div10), F("curFlowTemp"), F("current flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA, &retTemp_, DeviceValueType::USHORT, FL_(div10), F("retTemp"), F("return temperature"), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &retTemp_, DeviceValueType::USHORT, FL_(div10), F("retTemp"), F("return temperature"), DeviceValueUOM::DEGREES);
@@ -129,7 +121,6 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_device_value(TAG_BOILER_DATA, &sysPress_, DeviceValueType::UINT, FL_(div10), F("sysPress"), F("system pressure"), DeviceValueUOM::BAR); register_device_value(TAG_BOILER_DATA, &sysPress_, DeviceValueType::UINT, FL_(div10), F("sysPress"), F("system pressure"), DeviceValueUOM::BAR);
register_device_value(TAG_BOILER_DATA, &boilTemp_, DeviceValueType::USHORT, FL_(div10), F("boilTemp"), F("max boiler temperature"), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &boilTemp_, DeviceValueType::USHORT, FL_(div10), F("boilTemp"), F("max boiler temperature"), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA, &exhaustTemp_, DeviceValueType::USHORT, FL_(div10), F("exhaustTemp"), F("exhaust temperature"), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA, &exhaustTemp_, DeviceValueType::USHORT, FL_(div10), F("exhaustTemp"), F("exhaust temperature"), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA, &burnGas_, DeviceValueType::BOOL, nullptr, F("burnGas"), F("gas")); register_device_value(TAG_BOILER_DATA, &burnGas_, DeviceValueType::BOOL, nullptr, F("burnGas"), F("gas"));
register_device_value(TAG_BOILER_DATA, &flameCurr_, DeviceValueType::USHORT, FL_(div10), F("flameCurr"), F("flame current"), DeviceValueUOM::UA); register_device_value(TAG_BOILER_DATA, &flameCurr_, DeviceValueType::USHORT, FL_(div10), F("flameCurr"), F("flame current"), DeviceValueUOM::UA);
register_device_value(TAG_BOILER_DATA, &heatingPump_, DeviceValueType::BOOL, nullptr, F("heatingPump"), F("heating pump"), DeviceValueUOM::PUMP); register_device_value(TAG_BOILER_DATA, &heatingPump_, DeviceValueType::BOOL, nullptr, F("heatingPump"), F("heating pump"), DeviceValueUOM::PUMP);
@@ -156,12 +147,35 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_device_value(TAG_BOILER_DATA, &serviceCode_, DeviceValueType::TEXT, nullptr, F("serviceCode"), F("service code")); register_device_value(TAG_BOILER_DATA, &serviceCode_, DeviceValueType::TEXT, nullptr, F("serviceCode"), F("service code"));
register_device_value(TAG_BOILER_DATA, &serviceCodeNumber_, DeviceValueType::USHORT, nullptr, F("serviceCodeNumber"), F("service code number")); register_device_value(TAG_BOILER_DATA, &serviceCodeNumber_, DeviceValueType::USHORT, nullptr, F("serviceCodeNumber"), F("service code number"));
// ww - boiler_data_ww topic // info
register_device_value(TAG_BOILER_DATA, &upTimeControl_, DeviceValueType::TIME, FL_(div60), F("upTimeControl"), F("operating time total heat"), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA, &upTimeCompHeating_, DeviceValueType::TIME, FL_(div60), F("upTimeCompHeating"), F("operating time compressor heating"), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA, &upTimeCompCooling_, DeviceValueType::TIME, FL_(div60), F("upTimeCompCooling"), F("operating time compressor cooling"), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA, &upTimeCompWw_, DeviceValueType::TIME, FL_(div60), F("upTimeCompWw"), F("operating time compressor warm water"), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA, &heatingStarts_, DeviceValueType::ULONG, nullptr, F("heatingStarts"), F("# heating control starts"));
register_device_value(TAG_BOILER_DATA, &coolingStarts_, DeviceValueType::ULONG, nullptr, F("coolingStarts"), F("# cooling control starts"));
register_device_value(TAG_BOILER_DATA, &nrgConsTotal_, DeviceValueType::ULONG, nullptr, F("nrgConsTotal"), F("total energy consumption"));
register_device_value(TAG_BOILER_DATA, &nrgConsCompTotal_, DeviceValueType::ULONG, nullptr, F("nrgConsCompTotal"), F("energy consumption compressor total"));
register_device_value(TAG_BOILER_DATA, &nrgConsCompHeating_, DeviceValueType::ULONG, nullptr, F("nrgConsCompHeating"), F("energy consumption compressor heating"));
register_device_value(TAG_BOILER_DATA, &nrgConsCompWw_, DeviceValueType::ULONG, nullptr, F("nrgConsCompWw"), F("energy consumption compressor warm water"));
register_device_value(TAG_BOILER_DATA, &nrgConsCompCooling_, DeviceValueType::ULONG, nullptr, F("nrgConsCompCooling"), F("energy consumption compressor cooling"));
register_device_value(TAG_BOILER_DATA, &nrgSuppTotal_, DeviceValueType::ULONG, nullptr, F("nrgSuppTotal"), F("total energy supplied"));
register_device_value(TAG_BOILER_DATA, &nrgSuppHeating_, DeviceValueType::ULONG, nullptr, F("nrgSuppHeating"), F("total energy supplied heating"));
register_device_value(TAG_BOILER_DATA, &nrgSuppWw_, DeviceValueType::ULONG, nullptr, F("nrgSuppWw"), F("total energy warm supplied warm water"));
register_device_value(TAG_BOILER_DATA, &nrgSuppCooling_, DeviceValueType::ULONG, nullptr, F("nrgSuppCooling"), F("total energy supplied cooling"));
register_device_value(TAG_BOILER_DATA, &auxElecHeatNrgConsTotal_, DeviceValueType::ULONG, nullptr, F("auxElecHeatNrgConsTotal"), F("auxiliary electrical heater energy consumption total"));
register_device_value(TAG_BOILER_DATA, &auxElecHeatNrgConsHeating_, DeviceValueType::ULONG, nullptr, F("auxElecHeatNrgConsHeating"), F("auxiliary electrical heater energy consumption heating"));
register_device_value(TAG_BOILER_DATA, &auxElecHeatNrgConsDHW_, DeviceValueType::ULONG, nullptr, F("auxElecHeatNrgConsDHW"), F("auxiliary electrical heater energy consumption DHW"));
register_device_value(TAG_BOILER_DATA, &maintenanceMessage_, DeviceValueType::TEXT, nullptr, F("maintenanceMessage"), F("maintenance message"));
register_device_value(TAG_BOILER_DATA, &maintenanceDate_, DeviceValueType::TEXT, nullptr, F("maintenanceDate"), F("maintenance set date"));
register_device_value(TAG_BOILER_DATA, &maintenanceType_, DeviceValueType::ENUM, FL_(enum_off_time_date), F("maintenanceType"), F("maintenance scheduled"));
register_device_value(TAG_BOILER_DATA, &maintenanceTime_, DeviceValueType::USHORT, nullptr, F("maintenanceTime"), F("maintenance set time"), DeviceValueUOM::HOURS);
// warm water - boiler_data_ww topic
register_device_value(TAG_BOILER_DATA_WW, &wWSelTemp_, DeviceValueType::UINT, nullptr, F("wWSelTemp"), F("selected temperature"), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA_WW, &wWSelTemp_, DeviceValueType::UINT, nullptr, F("wWSelTemp"), F("selected temperature"), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA_WW, &wWSetTemp_, DeviceValueType::UINT, nullptr, F("wWSetTemp"), F("set temperature"), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA_WW, &wWSetTemp_, DeviceValueType::UINT, nullptr, F("wWSetTemp"), F("set temperature"), DeviceValueUOM::DEGREES);
register_device_value(TAG_BOILER_DATA_WW, &wWType_, DeviceValueType::ENUM, FL_(enum_flow), F("wWType"), F("type")); register_device_value(TAG_BOILER_DATA_WW, &wWType_, DeviceValueType::ENUM, FL_(enum_flow), F("wWType"), F("type"));
register_device_value(TAG_BOILER_DATA_WW, &wWComfort_, DeviceValueType::ENUM, FL_(enum_comfort), F("wWComfort"), F("comfort")); register_device_value(TAG_BOILER_DATA_WW, &wWComfort_, DeviceValueType::ENUM, FL_(enum_comfort), F("wWComfort"), F("comfort"));
register_device_value(TAG_BOILER_DATA_WW, &wWFlowTempOffset_, DeviceValueType::UINT, nullptr, F("wWFlowTempOffset"), F("flow offset temperature"));
register_device_value(TAG_BOILER_DATA_WW, &wWCircPump_, DeviceValueType::BOOL, nullptr, F("wWCircPump"), F("circulation pump available")); register_device_value(TAG_BOILER_DATA_WW, &wWCircPump_, DeviceValueType::BOOL, nullptr, F("wWCircPump"), F("circulation pump available"));
register_device_value(TAG_BOILER_DATA_WW, &wWChargeType_, DeviceValueType::BOOL, FL_(enum_charge), F("wWChargeType"), F("charging type")); register_device_value(TAG_BOILER_DATA_WW, &wWChargeType_, DeviceValueType::BOOL, FL_(enum_charge), F("wWChargeType"), F("charging type"));
register_device_value(TAG_BOILER_DATA_WW, &wWDisinfectionTemp_, DeviceValueType::UINT, nullptr, F("wWDisinfectionTemp"), F("disinfection temperature"), DeviceValueUOM::DEGREES); register_device_value(TAG_BOILER_DATA_WW, &wWDisinfectionTemp_, DeviceValueType::UINT, nullptr, F("wWDisinfectionTemp"), F("disinfection temperature"), DeviceValueUOM::DEGREES);
@@ -186,31 +200,6 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_device_value(TAG_BOILER_DATA_WW, &wWStarts_, DeviceValueType::ULONG, nullptr, F("wWStarts"), F("# starts")); register_device_value(TAG_BOILER_DATA_WW, &wWStarts_, DeviceValueType::ULONG, nullptr, F("wWStarts"), F("# starts"));
register_device_value(TAG_BOILER_DATA_WW, &wWStarts2_, DeviceValueType::ULONG, nullptr, F("wWStarts2"), F("# control starts")); register_device_value(TAG_BOILER_DATA_WW, &wWStarts2_, DeviceValueType::ULONG, nullptr, F("wWStarts2"), F("# control starts"));
register_device_value(TAG_BOILER_DATA_WW, &wWWorkM_, DeviceValueType::TIME, nullptr, F("wWWorkM"), F("active time"), DeviceValueUOM::MINUTES); register_device_value(TAG_BOILER_DATA_WW, &wWWorkM_, DeviceValueType::TIME, nullptr, F("wWWorkM"), F("active time"), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA_WW, &wWMaxPower_, DeviceValueType::UINT, nullptr, F("wWMaxPower"), F("max power"), DeviceValueUOM::PERCENT);
// info - boiler_data_info topic
register_device_value(TAG_BOILER_DATA_INFO, &upTimeControl_, DeviceValueType::TIME, FL_(div60), F("upTimeControl"), F("operating time total heat"), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA_INFO, &upTimeCompHeating_, DeviceValueType::TIME, FL_(div60), F("upTimeCompHeating"), F("operating time compressor heating"), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA_INFO, &upTimeCompCooling_, DeviceValueType::TIME, FL_(div60), F("upTimeCompCooling"), F("operating time compressor cooling"), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA_INFO, &upTimeCompWw_, DeviceValueType::TIME, FL_(div60), F("upTimeCompWw"), F("operating time compressor warm water"), DeviceValueUOM::MINUTES);
register_device_value(TAG_BOILER_DATA_INFO, &heatingStarts_, DeviceValueType::ULONG, nullptr, F("heatingStarts"), F("# heating starts (control)"));
register_device_value(TAG_BOILER_DATA_INFO, &coolingStarts_, DeviceValueType::ULONG, nullptr, F("coolingStarts"), F("# cooling starts (control)"));
register_device_value(TAG_BOILER_DATA_INFO, &nrgConsTotal_, DeviceValueType::ULONG, nullptr, F("nrgConsTotal"), F("total energy consumption"));
register_device_value(TAG_BOILER_DATA_INFO, &nrgConsCompTotal_, DeviceValueType::ULONG, nullptr, F("nrgConsCompTotal"), F("energy consumption compressor total"));
register_device_value(TAG_BOILER_DATA_INFO, &nrgConsCompHeating_, DeviceValueType::ULONG, nullptr, F("nrgConsCompHeating"), F("energy consumption compressor heating"));
register_device_value(TAG_BOILER_DATA_INFO, &nrgConsCompWw_, DeviceValueType::ULONG, nullptr, F("nrgConsCompWw"), F("energy consumption compressor warm water"));
register_device_value(TAG_BOILER_DATA_INFO, &nrgConsCompCooling_, DeviceValueType::ULONG, nullptr, F("nrgConsCompCooling"), F("energy consumption compressor cooling"));
register_device_value(TAG_BOILER_DATA_INFO, &nrgSuppTotal_, DeviceValueType::ULONG, nullptr, F("nrgSuppTotal"), F("total energy supplied"));
register_device_value(TAG_BOILER_DATA_INFO, &nrgSuppHeating_, DeviceValueType::ULONG, nullptr, F("nrgSuppHeating"), F("total energy supplied heating"));
register_device_value(TAG_BOILER_DATA_INFO, &nrgSuppWw_, DeviceValueType::ULONG, nullptr, F("nrgSuppWw"), F("total energy warm supplied warm water"));
register_device_value(TAG_BOILER_DATA_INFO, &nrgSuppCooling_, DeviceValueType::ULONG, nullptr, F("nrgSuppCooling"), F("total energy supplied cooling"));
register_device_value(TAG_BOILER_DATA_INFO, &auxElecHeatNrgConsTotal_, DeviceValueType::ULONG, nullptr, F("auxElecHeatNrgConsTotal"), F("auxiliary electrical heater energy consumption total"));
register_device_value(TAG_BOILER_DATA_INFO, &auxElecHeatNrgConsHeating_, DeviceValueType::ULONG, nullptr, F("auxElecHeatNrgConsHeating"), F("auxiliary electrical heater energy consumption heating"));
register_device_value(TAG_BOILER_DATA_INFO, &auxElecHeatNrgConsDHW_, DeviceValueType::ULONG, nullptr, F("auxElecHeatNrgConsDHW"), F("auxiliary electrical heater energy consumption DHW"));
register_device_value(TAG_BOILER_DATA_INFO, &maintenanceMessage_, DeviceValueType::TEXT, nullptr, F("maintenanceMessage"), F("maintenance message"));
register_device_value(TAG_BOILER_DATA_INFO, &maintenanceDate_, DeviceValueType::TEXT, nullptr, F("maintenanceDate"), F("maintenance set date"));
register_device_value(TAG_BOILER_DATA_INFO, &maintenanceType_, DeviceValueType::ENUM, FL_(enum_off_time_date), F("maintenanceType"), F("maintenance scheduled"));
register_device_value(TAG_BOILER_DATA_INFO, &maintenanceTime_, DeviceValueType::USHORT, nullptr, F("maintenanceTime"), F("maintenance set time"), DeviceValueUOM::HOURS);
} }
// publish HA config // publish HA config
@@ -219,7 +208,7 @@ bool Boiler::publish_ha_config() {
doc["uniq_id"] = F_(boiler); doc["uniq_id"] = F_(boiler);
char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE]; char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/boiler_data"), Mqtt::base().c_str()); snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s"), Mqtt::base().c_str(), Mqtt::tag_to_topic(device_type(), DeviceValueTAG::TAG_NONE).c_str());
doc["stat_t"] = stat_t; doc["stat_t"] = stat_t;
doc["name"] = FJSON("ID"); doc["name"] = FJSON("ID");
@@ -284,10 +273,8 @@ void Boiler::check_active(const bool force) {
void Boiler::process_UBAParameterWW(std::shared_ptr<const Telegram> telegram) { void Boiler::process_UBAParameterWW(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(wWActivated_, 1)); // 0xFF means on has_update(telegram->read_value(wWActivated_, 1)); // 0xFF means on
has_update(telegram->read_value(wWCircPump_, 6)); // 0xFF means on has_update(telegram->read_value(wWCircPump_, 6)); // 0xFF means on
has_update(telegram->read_value(wWCircPumpMode_, has_update(telegram->read_value(wWCircPumpMode_, 7)); // 1=1x3min 6=6x3min 7=continuous
7)); // 1=1x3min... 6=6x3min, 7=continuous has_update(telegram->read_value(wWChargeType_, 10)); // 0 = charge pump, 0xff = 3-way valve
has_update(telegram->read_value(wWChargeType_,
10)); // 0 = charge pump, 0xff = 3-way valve
has_update(telegram->read_value(wWSelTemp_, 2)); has_update(telegram->read_value(wWSelTemp_, 2));
has_update(telegram->read_value(wWDisinfectionTemp_, 8)); has_update(telegram->read_value(wWDisinfectionTemp_, 8));
has_update(telegram->read_value(wWFlowTempOffset_, 5)); has_update(telegram->read_value(wWFlowTempOffset_, 5));
@@ -322,8 +309,7 @@ void Boiler::process_UBAMonitorFast(std::shared_ptr<const Telegram> telegram) {
// warm water storage sensors (if present) // warm water storage sensors (if present)
// wWStorageTemp2 is also used by some brands as the boiler temperature - see https://github.com/proddy/EMS-ESP/issues/206 // wWStorageTemp2 is also used by some brands as the boiler temperature - see https://github.com/proddy/EMS-ESP/issues/206
has_update(telegram->read_value(wWStorageTemp1_, 9)); // 0x8300 if not available has_update(telegram->read_value(wWStorageTemp1_, 9)); // 0x8300 if not available
has_update(telegram->read_value(wWStorageTemp2_, has_update(telegram->read_value(wWStorageTemp2_, 11)); // 0x8000 if not available - this is boiler temp
11)); // 0x8000 if not available - this is boiler temp
has_update(telegram->read_value(retTemp_, 13)); has_update(telegram->read_value(retTemp_, 13));
has_update(telegram->read_value(flameCurr_, 15)); has_update(telegram->read_value(flameCurr_, 15));
@@ -356,7 +342,7 @@ void Boiler::process_UBATotalUptime(std::shared_ptr<const Telegram> telegram) {
/* /*
* UBAParameters - type 0x16 * UBAParameters - type 0x16
* data: FF 5A 64 00 0A FA 0F 02 06 64 64 02 08 F8 0F 0F 0F 0F 1E 05 04 09 09 00 28 00 3C * data: FF 5A 64 00 0A FA 0F 02 06 64 64 02 08 F8 0F 0F 0F 0F 1E 05 04 09 09 00 28 00 3C
*/ */
void Boiler::process_UBAParameters(std::shared_ptr<const Telegram> telegram) { void Boiler::process_UBAParameters(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(heatingActivated_, 0)); has_update(telegram->read_value(heatingActivated_, 0));
has_update(telegram->read_value(heatingTemp_, 1)); has_update(telegram->read_value(heatingTemp_, 1));
@@ -370,13 +356,6 @@ void Boiler::process_UBAParameters(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(pumpModMin_, 10)); has_update(telegram->read_value(pumpModMin_, 10));
} }
/*
* UBASettingsWW - type 0x26 - max power on offset 7
*/
void Boiler::process_UBASettingsWW(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(wWMaxPower_, 7));
}
/* /*
* UBAMonitorWW - type 0x34 - warm water monitor. 19 bytes long * UBAMonitorWW - type 0x34 - warm water monitor. 19 bytes long
* received every 10 seconds * received every 10 seconds
@@ -456,8 +435,7 @@ void Boiler::process_UBAMonitorSlow(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(outdoorTemp_, 0)); has_update(telegram->read_value(outdoorTemp_, 0));
has_update(telegram->read_value(boilTemp_, 2)); has_update(telegram->read_value(boilTemp_, 2));
has_update(telegram->read_value(exhaustTemp_, 4)); has_update(telegram->read_value(exhaustTemp_, 4));
has_update(telegram->read_value(switchTemp_, has_update(telegram->read_value(switchTemp_, 25)); // only if there is a mixer module present
25)); // only if there is a mixer module present
has_update(telegram->read_value(heatingPumpMod_, 9)); has_update(telegram->read_value(heatingPumpMod_, 9));
has_update(telegram->read_value(burnStarts_, 10, 3)); // force to 3 bytes has_update(telegram->read_value(burnStarts_, 10, 3)); // force to 3 bytes
has_update(telegram->read_value(burnWorkMin_, 13, 3)); // force to 3 bytes has_update(telegram->read_value(burnWorkMin_, 13, 3)); // force to 3 bytes
@@ -491,7 +469,7 @@ void Boiler::process_UBAMonitorSlowPlus(std::shared_ptr<const Telegram> telegram
} }
/* /*
* UBAParametersPlus - type 0xe6 * UBAParametersPlus - type 0xE6
* parameters originaly taken from * parameters originaly taken from
* https://github.com/Th3M3/buderus_ems-wiki/blob/master/Einstellungen%20des%20Regelger%C3%A4ts%20MC110.md * https://github.com/Th3M3/buderus_ems-wiki/blob/master/Einstellungen%20des%20Regelger%C3%A4ts%20MC110.md
* 88 0B E6 00 01 46 00 00 46 0A 00 01 06 FA 0A 01 02 64 01 00 00 1E 00 3C 01 00 00 00 01 00 9A * 88 0B E6 00 01 46 00 00 46 0A 00 01 06 FA 0A 01 02 64 01 00 00 1E 00 3C 01 00 00 00 01 00 9A
@@ -709,27 +687,12 @@ bool Boiler::set_warmwater_temp(const char * value, const int8_t id) {
write_command(EMS_TYPE_UBAParameterWWPlus, 6, v, EMS_TYPE_UBAParameterWWPlus); write_command(EMS_TYPE_UBAParameterWWPlus, 6, v, EMS_TYPE_UBAParameterWWPlus);
} else { } else {
write_command(EMS_TYPE_UBAFlags, 3, v, 0x34); // for i9000, see #397 write_command(EMS_TYPE_UBAFlags, 3, v, 0x34); // for i9000, see #397
write_command(EMS_TYPE_UBAParameterWW, 2, v, write_command(EMS_TYPE_UBAParameterWW, 2, v, EMS_TYPE_UBAParameterWW); // read seltemp back
EMS_TYPE_UBAParameterWW); // read seltemp back
} }
return true; return true;
} }
// Set the warm water flow temperature offset 0x33
bool Boiler::set_wWFlowTempOffset(const char * value, const int8_t id) {
int v = 0;
if (!Helpers::value2number(value, v)) {
LOG_WARNING(F("Set boiler warm water flow temperature offset: Invalid value"));
return false;
}
LOG_INFO(F("Setting boiler warm water flow temperature offset to %d C"), v);
write_command(EMS_TYPE_UBAParameterWW, 5, v, EMS_TYPE_UBAParameterWW);
return true;
}
// flow temp // flow temp
bool Boiler::set_flow_temp(const char * value, const int8_t id) { bool Boiler::set_flow_temp(const char * value, const int8_t id) {
int v = 0; int v = 0;
@@ -743,6 +706,19 @@ bool Boiler::set_flow_temp(const char * value, const int8_t id) {
write_command(EMS_TYPE_UBASetPoints, 0, v, EMS_TYPE_UBASetPoints); write_command(EMS_TYPE_UBASetPoints, 0, v, EMS_TYPE_UBASetPoints);
// write_command(0x35, 3, v, 0x35); // write_command(0x35, 3, v, 0x35);
return true;
}
// Set the warm water flow temperature offset 0x33
bool Boiler::set_wWFlowTempOffset(const char * value, const int8_t id) {
int v = 0;
if (!Helpers::value2number(value, v)) {
LOG_WARNING(F("Set boiler warm water flow temperature offset: Invalid value"));
return false;
}
LOG_INFO(F("Setting boiler warm water flow temperature offset to %d C"), v);
write_command(EMS_TYPE_UBAParameterWW, 5, v, EMS_TYPE_UBAParameterWW);
return true; return true;
} }
@@ -819,20 +795,6 @@ bool Boiler::set_max_power(const char * value, const int8_t id) {
return true; return true;
} }
// set warm water max power
bool Boiler::set_warmwater_maxpower(const char * value, const int8_t id) {
int v = 0;
if (!Helpers::value2number(value, v)) {
LOG_WARNING(F("Set warm water max power: Invalid value"));
return false;
}
LOG_INFO(F("Setting warm water max power to %d %%"), v);
write_command(EMS_TYPE_UBASettingsWW, 7, v, EMS_TYPE_UBASettingsWW);
return true;
}
// set min pump modulation // set min pump modulation
bool Boiler::set_min_pump(const char * value, const int8_t id) { bool Boiler::set_min_pump(const char * value, const int8_t id) {
int v = 0; int v = 0;
@@ -1042,8 +1004,7 @@ bool Boiler::set_warmwater_onetime(const char * value, const int8_t id) {
LOG_INFO(F("Setting warm water OneTime loading %s"), v ? "on" : "off"); LOG_INFO(F("Setting warm water OneTime loading %s"), v ? "on" : "off");
if (get_toggle_fetch(EMS_TYPE_UBAParameterWWPlus)) { if (get_toggle_fetch(EMS_TYPE_UBAParameterWWPlus)) {
write_command(EMS_TYPE_UBAFlags, 0, (v ? 0x22 : 0x02), write_command(EMS_TYPE_UBAFlags, 0, (v ? 0x22 : 0x02), 0xE9); // not sure if this is in flags
0xE9); // not sure if this is in flags
} else { } else {
write_command(EMS_TYPE_UBAFlags, 0, (v ? 0x22 : 0x02), 0x34); write_command(EMS_TYPE_UBAFlags, 0, (v ? 0x22 : 0x02), 0x34);
} }
@@ -1062,8 +1023,7 @@ bool Boiler::set_warmwater_circulation(const char * value, const int8_t id) {
LOG_INFO(F("Setting warm water circulation %s"), v ? "on" : "off"); LOG_INFO(F("Setting warm water circulation %s"), v ? "on" : "off");
if (get_toggle_fetch(EMS_TYPE_UBAParameterWWPlus)) { if (get_toggle_fetch(EMS_TYPE_UBAParameterWWPlus)) {
write_command(EMS_TYPE_UBAFlags, 1, (v ? 0x22 : 0x02), write_command(EMS_TYPE_UBAFlags, 1, (v ? 0x22 : 0x02), 0xE9); // not sure if this is in flags
0xE9); // not sure if this is in flags
} else { } else {
write_command(EMS_TYPE_UBAFlags, 1, (v ? 0x22 : 0x02), 0x34); write_command(EMS_TYPE_UBAFlags, 1, (v ? 0x22 : 0x02), 0x34);
} }

View File

@@ -36,7 +36,6 @@ class Boiler : public EMSdevice {
uint8_t boilerState_ = EMS_VALUE_UINT_NOTSET; // Boiler state flag - FOR INTERNAL USE uint8_t boilerState_ = EMS_VALUE_UINT_NOTSET; // Boiler state flag - FOR INTERNAL USE
static constexpr uint8_t EMS_TYPE_UBASettingsWW = 0x26;
static constexpr uint8_t EMS_TYPE_UBAParameterWW = 0x33; static constexpr uint8_t EMS_TYPE_UBAParameterWW = 0x33;
static constexpr uint8_t EMS_TYPE_UBAFunctionTest = 0x1D; static constexpr uint8_t EMS_TYPE_UBAFunctionTest = 0x1D;
static constexpr uint8_t EMS_TYPE_UBAFlags = 0x35; static constexpr uint8_t EMS_TYPE_UBAFlags = 0x35;
@@ -74,9 +73,8 @@ class Boiler : public EMSdevice {
uint8_t wWHeat_; // 3-way valve on WW uint8_t wWHeat_; // 3-way valve on WW
uint8_t wWSetPumpPower_; // ww pump speed/power? uint8_t wWSetPumpPower_; // ww pump speed/power?
uint8_t wWFlowTempOffset_; // Boiler offset for ww heating uint8_t wWFlowTempOffset_; // Boiler offset for ww heating
uint8_t wWMaxPower_; // Warm Water maximum power
uint32_t wWStarts_; // Warm Water # starts uint32_t wWStarts_; // Warm Water # starts
uint32_t wWStarts2_; // Warm water starts (control) uint32_t wWStarts2_; // Warm water control starts
uint32_t wWWorkM_; // Warm Water # minutes uint32_t wWWorkM_; // Warm Water # minutes
uint16_t mixerTemp_; // mixing temperature uint16_t mixerTemp_; // mixing temperature
@@ -128,8 +126,8 @@ class Boiler : public EMSdevice {
uint32_t upTimeCompHeating_; // Operating time compressor heating uint32_t upTimeCompHeating_; // Operating time compressor heating
uint32_t upTimeCompCooling_; // Operating time compressor cooling uint32_t upTimeCompCooling_; // Operating time compressor cooling
uint32_t upTimeCompWw_; // Operating time compressor warm water uint32_t upTimeCompWw_; // Operating time compressor warm water
uint32_t heatingStarts_; // Heating starts (control) uint32_t heatingStarts_; // Heating control starts
uint32_t coolingStarts_; // Cooling starts (control) uint32_t coolingStarts_; // Cooling control starts
uint32_t nrgConsTotal_; // Energy consumption total uint32_t nrgConsTotal_; // Energy consumption total
uint32_t nrgConsCompTotal_; // Energy consumption compressor total uint32_t nrgConsCompTotal_; // Energy consumption compressor total
uint32_t nrgConsCompHeating_; // Energy consumption compressor heating uint32_t nrgConsCompHeating_; // Energy consumption compressor heating
@@ -169,7 +167,6 @@ class Boiler : public EMSdevice {
void process_UBAInformation(std::shared_ptr<const Telegram> telegram); void process_UBAInformation(std::shared_ptr<const Telegram> telegram);
void process_UBAEnergySupplied(std::shared_ptr<const Telegram> telegram); void process_UBAEnergySupplied(std::shared_ptr<const Telegram> telegram);
void process_CascadeMessage(std::shared_ptr<const Telegram> telegram); void process_CascadeMessage(std::shared_ptr<const Telegram> telegram);
void process_UBASettingsWW(std::shared_ptr<const Telegram> telegram);
// commands - none of these use the additional id parameter // commands - none of these use the additional id parameter
bool set_warmwater_mode(const char * value, const int8_t id); bool set_warmwater_mode(const char * value, const int8_t id);
@@ -180,7 +177,6 @@ class Boiler : public EMSdevice {
bool set_warmwater_circulation_pump(const char * value, const int8_t id); bool set_warmwater_circulation_pump(const char * value, const int8_t id);
bool set_warmwater_circulation_mode(const char * value, const int8_t id); bool set_warmwater_circulation_mode(const char * value, const int8_t id);
bool set_warmwater_temp(const char * value, const int8_t id); bool set_warmwater_temp(const char * value, const int8_t id);
bool set_warmwater_maxpower(const char * value, const int8_t id);
bool set_wWFlowTempOffset(const char * value, const int8_t id); bool set_wWFlowTempOffset(const char * value, const int8_t id);
bool set_flow_temp(const char * value, const int8_t id); bool set_flow_temp(const char * value, const int8_t id);
bool set_heating_activated(const char * value, const int8_t id); bool set_heating_activated(const char * value, const int8_t id);

View File

@@ -47,7 +47,7 @@ bool Heatpump::publish_ha_config() {
doc["ic"] = F_(iconheatpump); doc["ic"] = F_(iconheatpump);
char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE]; char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/heatpump_data"), Mqtt::base().c_str()); snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s"), Mqtt::base().c_str(), Mqtt::tag_to_topic(device_type(), DeviceValueTAG::TAG_NONE).c_str());
doc["stat_t"] = stat_t; doc["stat_t"] = stat_t;
doc["name"] = FJSON("ID"); doc["name"] = FJSON("ID");

View File

@@ -87,7 +87,7 @@ bool Mixer::publish_ha_config() {
doc["uniq_id"] = uniq_id; doc["uniq_id"] = uniq_id;
char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE]; char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/mixer_data"), Mqtt::base().c_str()); snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s"), Mqtt::base().c_str(), Mqtt::tag_to_topic(device_type(), DeviceValueTAG::TAG_NONE).c_str());
doc["stat_t"] = stat_t; doc["stat_t"] = stat_t;
char name[20]; char name[20];

View File

@@ -99,7 +99,7 @@ bool Solar::publish_ha_config() {
doc["uniq_id"] = F_(solar); doc["uniq_id"] = F_(solar);
char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE]; char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/solar_data"), Mqtt::base().c_str()); snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s"), Mqtt::base().c_str(), Mqtt::tag_to_topic(device_type(), DeviceValueTAG::TAG_NONE).c_str());
doc["stat_t"] = stat_t; doc["stat_t"] = stat_t;
doc["val_tpl"] = FJSON("{{value_json.id}}"); doc["val_tpl"] = FJSON("{{value_json.id}}");

View File

@@ -53,7 +53,7 @@ bool Switch::publish_ha_config() {
doc["uniq_id"] = F_(switch); doc["uniq_id"] = F_(switch);
char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE]; char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/switch_data"), Mqtt::base().c_str()); snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s"), Mqtt::base().c_str(), Mqtt::tag_to_topic(device_type(), DeviceValueTAG::TAG_NONE).c_str());
doc["stat_t"] = stat_t; doc["stat_t"] = stat_t;
doc["name"] = FJSON("ID"); doc["name"] = FJSON("ID");

View File

@@ -191,7 +191,7 @@ bool Thermostat::publish_ha_config() {
doc["uniq_id"] = F_(thermostat); doc["uniq_id"] = F_(thermostat);
char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE]; char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/thermostat_data"), Mqtt::base().c_str()); snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s"), Mqtt::base().c_str(), Mqtt::tag_to_topic(device_type(), DeviceValueTAG::TAG_NONE).c_str());
doc["stat_t"] = stat_t; doc["stat_t"] = stat_t;
doc["name"] = FJSON("ID"); doc["name"] = FJSON("ID");
@@ -376,13 +376,14 @@ void Thermostat::register_mqtt_ha_config_hc(uint8_t hc_num) {
doc["mode_cmd_t"] = str3; doc["mode_cmd_t"] = str3;
doc["temp_cmd_t"] = str3; doc["temp_cmd_t"] = str3;
doc["~"] = Mqtt::base(); // ems-esp doc["~"] = Mqtt::base(); // ems-esp
doc["mode_stat_t"] = FJSON("~/thermostat_data");
doc["temp_stat_t"] = FJSON("~/thermostat_data");
doc["curr_temp_t"] = FJSON("~/thermostat_data");
char mode_str[30]; char topic_t[80];
snprintf_P(mode_str, sizeof(mode_str), PSTR("{{value_json.hc%d.hamode}}"), hc_num); if (Mqtt::nested_format()) {
doc["mode_stat_tpl"] = mode_str; snprintf_P(topic_t, sizeof(topic_t), PSTR("~/%s"), Mqtt::tag_to_topic(EMSdevice::DeviceType::THERMOSTAT, DeviceValueTAG::TAG_NONE).c_str());
char mode_str_tpl[40];
snprintf_P(mode_str_tpl, sizeof(mode_str_tpl), PSTR("{{value_json.hc%d.hamode}}"), hc_num);
doc["mode_stat_tpl"] = mode_str_tpl;
char seltemp_str[30]; char seltemp_str[30];
snprintf_P(seltemp_str, sizeof(seltemp_str), PSTR("{{value_json.hc%d.seltemp}}"), hc_num); snprintf_P(seltemp_str, sizeof(seltemp_str), PSTR("{{value_json.hc%d.seltemp}}"), hc_num);
@@ -392,6 +393,18 @@ void Thermostat::register_mqtt_ha_config_hc(uint8_t hc_num) {
snprintf_P(currtemp_str, sizeof(currtemp_str), PSTR("{{value_json.hc%d.hatemp}}"), hc_num); snprintf_P(currtemp_str, sizeof(currtemp_str), PSTR("{{value_json.hc%d.hatemp}}"), hc_num);
doc["curr_temp_tpl"] = currtemp_str; doc["curr_temp_tpl"] = currtemp_str;
} else {
snprintf_P(topic_t, sizeof(topic_t), PSTR("~/%s"), Mqtt::tag_to_topic(EMSdevice::DeviceType::THERMOSTAT, DeviceValueTAG::TAG_HC1 + hc_num - 1).c_str());
doc["mode_stat_tpl"] = FJSON("{{value_json.hamode}}");
doc["temp_stat_tpl"] = FJSON("{{value_json.seltemp}}");
doc["curr_temp_tpl"] = FJSON("{{value_json.hatemp}}");
}
doc["mode_stat_t"] = topic_t;
doc["temp_stat_t"] = topic_t;
doc["curr_temp_t"] = topic_t;
doc["min_temp"] = FJSON("5"); doc["min_temp"] = FJSON("5");
doc["max_temp"] = FJSON("30"); doc["max_temp"] = FJSON("30");
doc["temp_step"] = FJSON("0.5"); doc["temp_step"] = FJSON("0.5");

View File

@@ -41,22 +41,49 @@ static const __FlashStringHelper * DeviceValueUOM_s[] __attribute__((__aligned__
// must be an int of 4 bytes, 32bit aligned // must be an int of 4 bytes, 32bit aligned
static const __FlashStringHelper * const DeviceValueTAG_s[] PROGMEM = { static const __FlashStringHelper * const DeviceValueTAG_s[] PROGMEM = {
F_(tag_none), F_(tag_none), // ""
F_(tag_boiler_data), F_(tag_system_data), // ""
F_(tag_boiler_data_ww), F_(tag_boiler_data), // ""
F_(tag_boiler_data_info), F_(tag_boiler_data_ww), // "warm water"
F_(tag_thermostat_data), F_(tag_thermostat_data), // ""
F_(tag_hc1), F_(tag_hc1), // "hc1"
F_(tag_hc2), F_(tag_hc2), // "hc2"
F_(tag_hc3), F_(tag_hc3), // "hc3"
F_(tag_hc4), F_(tag_hc4), // "hc4"
F_(tag_wwc1), F_(tag_wwc1), // "wwc1"
F_(tag_wwc2), F_(tag_wwc2), // "Wwc2"
F_(tag_wwc3), F_(tag_wwc3), // "wwc3"
F_(tag_wwc4) F_(tag_wwc4) // "wwc4"
}; };
// MQTT topics derived from tags
static const __FlashStringHelper * const DeviceValueTAG_mqtt[] PROGMEM = {
F_(tag_none), // ""
F_(tag_system_data_mqtt), // "heartbeat"
F_(tag_boiler_data_mqtt), // ""
F_(tag_boiler_data_ww_mqtt), // "ww"
F_(tag_thermostat_data), // ""
F_(tag_hc1), // "hc1"
F_(tag_hc2), // "hc2"
F_(tag_hc3), // "hc3"
F_(tag_hc4), // "hc4"
F_(tag_wwc1), // "wwc1"
F_(tag_wwc2), // "Wwc2"
F_(tag_wwc3), // "wwc3"
F_(tag_wwc4) // "wwc4"
};
const std::string EMSdevice::tag_to_string(uint8_t tag) {
return uuid::read_flash_string(DeviceValueTAG_s[tag]);
}
const std::string EMSdevice::tag_to_mqtt(uint8_t tag) {
return uuid::read_flash_string(DeviceValueTAG_mqtt[tag]);
}
const std::string EMSdevice::uom_to_string(uint8_t uom) { const std::string EMSdevice::uom_to_string(uint8_t uom) {
if (uom == DeviceValueUOM::NONE || uom >= DeviceValueUOM::PUMP) { if (uom == DeviceValueUOM::NONE || uom >= DeviceValueUOM::PUMP) {
return std::string{}; return std::string{};
@@ -64,10 +91,6 @@ const std::string EMSdevice::uom_to_string(uint8_t uom) {
return uuid::read_flash_string(DeviceValueUOM_s[uom - 1]); // offset by 1 to account for NONE return uuid::read_flash_string(DeviceValueUOM_s[uom - 1]); // offset by 1 to account for NONE
} }
const std::string EMSdevice::tag_to_string(uint8_t tag) {
return uuid::read_flash_string(DeviceValueTAG_s[tag]);
}
const std::vector<EMSdevice::DeviceValue> EMSdevice::devicevalues() const { const std::vector<EMSdevice::DeviceValue> EMSdevice::devicevalues() const {
return devicevalues_; return devicevalues_;
} }

View File

@@ -69,14 +69,12 @@ MAKE_PSTR(lmin, "l/min")
enum DeviceValueUOM : uint8_t { NONE = 0, DEGREES, PERCENT, LMIN, KWH, WH, HOURS, MINUTES, UA, BAR, PUMP }; enum DeviceValueUOM : uint8_t { NONE = 0, DEGREES, PERCENT, LMIN, KWH, WH, HOURS, MINUTES, UA, BAR, PUMP };
// TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp // TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp
MAKE_PSTR(tag_none, "") // use empty string if want to suppress showing tags // use empty string if want to suppress showing tags
// MAKE_PSTR(tag_boiler_data, "boiler") MAKE_PSTR(tag_none, "")
// MAKE_PSTR(tag_boiler_data_ww, "warm water") MAKE_PSTR(tag_system_data, "")
// MAKE_PSTR(tag_boiler_data_info, "info")
MAKE_PSTR(tag_boiler_data, "") MAKE_PSTR(tag_boiler_data, "")
MAKE_PSTR(tag_boiler_data_ww, "") MAKE_PSTR(tag_boiler_data_ww, "warm water")
MAKE_PSTR(tag_boiler_data_info, "") MAKE_PSTR(tag_thermostat_data, "")
MAKE_PSTR(tag_thermostat_data, "") // use empty string if want to suppress showing tags
MAKE_PSTR(tag_hc1, "hc1") MAKE_PSTR(tag_hc1, "hc1")
MAKE_PSTR(tag_hc2, "hc2") MAKE_PSTR(tag_hc2, "hc2")
MAKE_PSTR(tag_hc3, "hc3") MAKE_PSTR(tag_hc3, "hc3")
@@ -85,11 +83,17 @@ MAKE_PSTR(tag_wwc1, "wwc1")
MAKE_PSTR(tag_wwc2, "wwc2") MAKE_PSTR(tag_wwc2, "wwc2")
MAKE_PSTR(tag_wwc3, "wwc3") MAKE_PSTR(tag_wwc3, "wwc3")
MAKE_PSTR(tag_wwc4, "wwc4") MAKE_PSTR(tag_wwc4, "wwc4")
// MQTT topic names
MAKE_PSTR(tag_system_data_mqtt, "heartbeat")
MAKE_PSTR(tag_boiler_data_mqtt, "")
MAKE_PSTR(tag_boiler_data_ww_mqtt, "ww")
enum DeviceValueTAG : uint8_t { enum DeviceValueTAG : uint8_t {
TAG_NONE = 0, // wild card TAG_NONE = 0, // wild card
TAG_SYSTEM_DATA,
TAG_BOILER_DATA, TAG_BOILER_DATA,
TAG_BOILER_DATA_WW, TAG_BOILER_DATA_WW,
TAG_BOILER_DATA_INFO,
TAG_THERMOSTAT_DATA, TAG_THERMOSTAT_DATA,
TAG_HC1, TAG_HC1,
TAG_HC2, TAG_HC2,
@@ -132,6 +136,7 @@ class EMSdevice {
static const std::string 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); static const std::string tag_to_string(uint8_t tag);
static const std::string tag_to_mqtt(uint8_t tag);
inline uint8_t product_id() const { inline uint8_t product_id() const {
return product_id_; return product_id_;

View File

@@ -425,6 +425,7 @@ void EMSESP::publish_device_values(uint8_t device_type) {
bool nested = Mqtt::nested_format(); bool nested = Mqtt::nested_format();
// group by device type
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice && (emsdevice->device_type() == device_type)) { if (emsdevice && (emsdevice->device_type() == device_type)) {
// if we're using HA and it's not already done, send the config topics first. only do this once // if we're using HA and it's not already done, send the config topics first. only do this once
@@ -434,14 +435,11 @@ void EMSESP::publish_device_values(uint8_t device_type) {
// if its a boiler, generate json for each group and publish it directly // if its a boiler, generate json for each group and publish it directly
if (device_type == DeviceType::BOILER) { if (device_type == DeviceType::BOILER) {
emsdevice->generate_values_json(json, DeviceValueTAG::TAG_BOILER_DATA, false); // not nested emsdevice->generate_values_json(json, DeviceValueTAG::TAG_BOILER_DATA, false);
Mqtt::publish("boiler_data", json); Mqtt::publish(Mqtt::tag_to_topic(device_type, DeviceValueTAG::TAG_BOILER_DATA), json);
json.clear(); json.clear();
emsdevice->generate_values_json(json, DeviceValueTAG::TAG_BOILER_DATA_WW, false); // not nested emsdevice->generate_values_json(json, DeviceValueTAG::TAG_BOILER_DATA_WW, false);
Mqtt::publish("boiler_data_ww", json); Mqtt::publish(Mqtt::tag_to_topic(device_type, DeviceValueTAG::TAG_BOILER_DATA_WW), json);
json.clear();
emsdevice->generate_values_json(json, DeviceValueTAG::TAG_BOILER_DATA_INFO, false); // not nested
Mqtt::publish("boiler_data_info", json);
need_publish = false; need_publish = false;
} }
@@ -453,14 +451,12 @@ void EMSESP::publish_device_values(uint8_t device_type) {
need_publish |= emsdevice->generate_values_json(json, DeviceValueTAG::TAG_NONE, true); // nested need_publish |= emsdevice->generate_values_json(json, DeviceValueTAG::TAG_NONE, true); // nested
} else { } else {
emsdevice->generate_values_json(json, DeviceValueTAG::TAG_THERMOSTAT_DATA, false); // not nested emsdevice->generate_values_json(json, DeviceValueTAG::TAG_THERMOSTAT_DATA, false); // not nested
Mqtt::publish("thermostat_data", json); Mqtt::publish(Mqtt::tag_to_topic(device_type, DeviceValueTAG::TAG_NONE), json);
json.clear(); json.clear();
for (uint8_t hc_tag = TAG_HC1; hc_tag <= DeviceValueTAG::TAG_HC4; hc_tag++) { for (uint8_t hc_tag = TAG_HC1; hc_tag <= DeviceValueTAG::TAG_HC4; hc_tag++) {
emsdevice->generate_values_json(json, hc_tag, false); // not nested emsdevice->generate_values_json(json, hc_tag, false); // not nested
char topic[20]; Mqtt::publish(Mqtt::tag_to_topic(device_type, hc_tag), json);
snprintf_P(topic, sizeof(topic), PSTR("thermostat_data_%s"), EMSdevice::tag_to_string(hc_tag).c_str());
Mqtt::publish(topic, json);
json.clear(); json.clear();
} }
need_publish = false; need_publish = false;
@@ -475,9 +471,7 @@ void EMSESP::publish_device_values(uint8_t device_type) {
} else { } else {
for (uint8_t hc_tag = TAG_HC1; hc_tag <= DeviceValueTAG::TAG_WWC4; hc_tag++) { for (uint8_t hc_tag = TAG_HC1; hc_tag <= DeviceValueTAG::TAG_WWC4; hc_tag++) {
emsdevice->generate_values_json(json, hc_tag, false); // not nested emsdevice->generate_values_json(json, hc_tag, false); // not nested
char topic[20]; Mqtt::publish(Mqtt::tag_to_topic(device_type, hc_tag), json);
snprintf_P(topic, sizeof(topic), PSTR("mixer_data_%s"), EMSdevice::tag_to_string(hc_tag).c_str());
Mqtt::publish(topic, json);
json.clear(); json.clear();
} }
need_publish = false; need_publish = false;
@@ -878,8 +872,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, std::
// sometimes boilers share the same product id as controllers // sometimes boilers share the same product id as controllers
// so only add boilers if the device_id is 0x08, which is fixed for EMS // so only add boilers if the device_id is 0x08, which is fixed for EMS
if (device.device_type == DeviceType::BOILER) { if (device.device_type == DeviceType::BOILER) {
if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER || if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER || (device_id >= EMSdevice::EMS_DEVICE_ID_BOILER_1 && device_id <= EMSdevice::EMS_DEVICE_ID_BOILER_F)) {
(device_id >= EMSdevice::EMS_DEVICE_ID_BOILER_1 && device_id <= EMSdevice::EMS_DEVICE_ID_BOILER_F)) {
device_p = &device; device_p = &device;
break; break;
} }
@@ -933,7 +926,7 @@ bool EMSESP::command_info(uint8_t device_type, JsonObject & json, const int8_t i
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice && (emsdevice->device_type() == device_type) && ((device_type != DeviceType::THERMOSTAT) || (emsdevice->device_id() == EMSESP::actual_master_thermostat()))) { if (emsdevice && (emsdevice->device_type() == device_type) && ((device_type != DeviceType::THERMOSTAT) || (emsdevice->device_id() == EMSESP::actual_master_thermostat()))) {
has_value |= emsdevice->generate_values_json(json, tag, true, (id == -1)); // nested, console as default has_value |= emsdevice->generate_values_json(json, tag, (id == -1), true); // console & nested
} }
} }

View File

@@ -204,20 +204,27 @@ void Mqtt::show_mqtt(uuid::console::Shell & shell) {
for (const auto & message : mqtt_messages_) { for (const auto & message : mqtt_messages_) {
auto content = message.content_; auto content = message.content_;
char topic[MQTT_TOPIC_MAX_SIZE];
if ((strncmp(content->topic.c_str(), "homeassistant/", 13) != 0)) {
snprintf_P(topic, sizeof(topic), PSTR("%s/%s"), Mqtt::base().c_str(), content->topic.c_str());
} else {
snprintf_P(topic, sizeof(topic), PSTR("%s"), content->topic.c_str());
}
if (content->operation == Operation::PUBLISH) { if (content->operation == Operation::PUBLISH) {
// Publish messages // Publish messages
if (message.retry_count_ == 0) { if (message.retry_count_ == 0) {
if (message.packet_id_ == 0) { if (message.packet_id_ == 0) {
shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s"), message.id_, content->topic.c_str(), content->payload.c_str()); shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s"), message.id_, topic, content->payload.c_str());
} else { } else {
shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s (pid %d)"), message.id_, content->topic.c_str(), content->payload.c_str(), message.packet_id_); shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s (pid %d)"), message.id_, topic, content->payload.c_str(), message.packet_id_);
} }
} else { } else {
shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s (pid %d, retry #%d)"), message.id_, content->topic.c_str(), content->payload.c_str(), message.packet_id_, message.retry_count_); shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s (pid %d, retry #%d)"), message.id_, topic, content->payload.c_str(), message.packet_id_, message.retry_count_);
} }
} else { } else {
// Subscribe messages // Subscribe messages
shell.printfln(F(" [%02d] (Sub) topic=%s"), message.id_, content->topic.c_str()); shell.printfln(F(" [%02d] (Sub) topic=%s"), message.id_, topic);
} }
} }
shell.println(); shell.println();
@@ -370,17 +377,36 @@ void Mqtt::reset_mqtt() {
} }
} }
void Mqtt::load_settings() {
EMSESP::esp8266React.getMqttSettingsService()->read([&](MqttSettings & mqttSettings) {
mqtt_base_ = mqttSettings.base.c_str(); // Convert String to std::string
mqtt_qos_ = mqttSettings.mqtt_qos;
mqtt_retain_ = mqttSettings.mqtt_retain;
mqtt_enabled_ = mqttSettings.enabled;
ha_enabled_ = mqttSettings.ha_enabled;
ha_climate_format_ = mqttSettings.ha_climate_format;
dallas_format_ = mqttSettings.dallas_format;
bool_format_ = mqttSettings.bool_format;
nested_format_ = mqttSettings.nested_format;
// convert to milliseconds
publish_time_boiler_ = mqttSettings.publish_time_boiler * 1000;
publish_time_thermostat_ = mqttSettings.publish_time_thermostat * 1000;
publish_time_solar_ = mqttSettings.publish_time_solar * 1000;
publish_time_mixer_ = mqttSettings.publish_time_mixer * 1000;
publish_time_other_ = mqttSettings.publish_time_other * 1000;
publish_time_sensor_ = mqttSettings.publish_time_sensor * 1000;
});
}
void Mqtt::start() { void Mqtt::start() {
mqttClient_ = EMSESP::esp8266React.getMqttClient(); mqttClient_ = EMSESP::esp8266React.getMqttClient();
// fetch MQTT settings, to see if MQTT is enabled load_settings(); // fetch MQTT settings
EMSESP::esp8266React.getMqttSettingsService()->read([&](MqttSettings & mqttSettings) {
mqtt_enabled_ = mqttSettings.enabled;
mqtt_base_ = mqttSettings.base.c_str(); // Convert String to std::string
if (!mqtt_enabled_) { if (!mqtt_enabled_) {
return; // quit, not using MQTT return; // quit, not using MQTT
} }
});
// if already initialized, don't do it again // if already initialized, don't do it again
if (initialized_) { if (initialized_) {
@@ -498,23 +524,7 @@ void Mqtt::on_connect() {
connecting_ = true; connecting_ = true;
connectcount_++; connectcount_++;
// fetch MQTT settings load_settings(); // reload MQTT settings - in case they have changes
EMSESP::esp8266React.getMqttSettingsService()->read([&](MqttSettings & mqttSettings) {
publish_time_boiler_ = mqttSettings.publish_time_boiler * 1000; // convert to milliseconds
publish_time_thermostat_ = mqttSettings.publish_time_thermostat * 1000;
publish_time_solar_ = mqttSettings.publish_time_solar * 1000;
publish_time_mixer_ = mqttSettings.publish_time_mixer * 1000;
publish_time_other_ = mqttSettings.publish_time_other * 1000;
publish_time_sensor_ = mqttSettings.publish_time_sensor * 1000;
mqtt_qos_ = mqttSettings.mqtt_qos;
mqtt_retain_ = mqttSettings.mqtt_retain;
mqtt_enabled_ = mqttSettings.enabled;
ha_enabled_ = mqttSettings.ha_enabled;
ha_climate_format_ = mqttSettings.ha_climate_format;
dallas_format_ = mqttSettings.dallas_format;
bool_format_ = mqttSettings.bool_format;
nested_format_ = mqttSettings.nested_format;
});
// send info topic appended with the version information as JSON // send info topic appended with the version information as JSON
StaticJsonDocument<EMSESP_JSON_SIZE_SMALL> doc; StaticJsonDocument<EMSESP_JSON_SIZE_SMALL> doc;
@@ -589,16 +599,16 @@ void Mqtt::ha_status() {
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
// create the sensors // create the sensors
publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_NONE, F("Wifi strength"), EMSdevice::DeviceType::SYSTEM, F("rssi")); publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_SYSTEM_DATA, F("Wifi strength"), EMSdevice::DeviceType::SYSTEM, F("rssi"));
publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_NONE, F("Uptime"), EMSdevice::DeviceType::SYSTEM, F("uptime")); publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_SYSTEM_DATA, F("Uptime"), EMSdevice::DeviceType::SYSTEM, F("uptime"));
publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_NONE, F("Uptime (sec)"), EMSdevice::DeviceType::SYSTEM, F("uptime_sec")); publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_SYSTEM_DATA, F("Uptime (sec)"), EMSdevice::DeviceType::SYSTEM, F("uptime_sec"));
publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_NONE, F("Free heap memory"), EMSdevice::DeviceType::SYSTEM, F("freemem")); publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_SYSTEM_DATA, F("Free heap memory"), EMSdevice::DeviceType::SYSTEM, F("freemem"));
publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_NONE, F("# Failed MQTT publishes"), EMSdevice::DeviceType::SYSTEM, F("mqttfails")); publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_SYSTEM_DATA, F("# Failed MQTT publishes"), EMSdevice::DeviceType::SYSTEM, F("mqttfails"));
publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_NONE, F("# Rx Sent"), EMSdevice::DeviceType::SYSTEM, F("rxsent")); publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_SYSTEM_DATA, F("# Rx Sent"), EMSdevice::DeviceType::SYSTEM, F("rxsent"));
publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_NONE, F("# Rx Fails"), EMSdevice::DeviceType::SYSTEM, F("rxfails")); publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_SYSTEM_DATA, F("# Rx Fails"), EMSdevice::DeviceType::SYSTEM, F("rxfails"));
publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_NONE, F("# Tx Reads"), EMSdevice::DeviceType::SYSTEM, F("txread")); publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_SYSTEM_DATA, F("# Tx Reads"), EMSdevice::DeviceType::SYSTEM, F("txread"));
publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_NONE, F("# Tx Writes"), EMSdevice::DeviceType::SYSTEM, F("txwrite")); publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_SYSTEM_DATA, F("# Tx Writes"), EMSdevice::DeviceType::SYSTEM, F("txwrite"));
publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_NONE, F("# Tx Fails"), EMSdevice::DeviceType::SYSTEM, F("txfails")); publish_mqtt_ha_sensor(DeviceValueType::INT, DeviceValueTAG::TAG_SYSTEM_DATA, F("# Tx Fails"), EMSdevice::DeviceType::SYSTEM, F("txfails"));
} }
// add sub or pub task to the queue. // add sub or pub task to the queue.
@@ -792,11 +802,11 @@ void Mqtt::process_queue() {
// //
// note: some string copying here into chars, it looks messy but does help with heap fragmentation issues // note: some string copying here into chars, it looks messy but does help with heap fragmentation issues
void Mqtt::publish_mqtt_ha_sensor(uint8_t type, // EMSdevice::DeviceValueType void Mqtt::publish_mqtt_ha_sensor(uint8_t type, // EMSdevice::DeviceValueType
uint8_t tag, uint8_t tag, // EMSdevice::DeviceValueTAG
const __FlashStringHelper * name, const __FlashStringHelper * name,
const uint8_t device_type, // EMSdevice::DeviceType const uint8_t device_type, // EMSdevice::DeviceType
const __FlashStringHelper * entity, const __FlashStringHelper * entity,
const uint8_t uom) { // DeviceValueUOM (0=NONE) const uint8_t uom) { // EMSdevice::DeviceValueUOM (0=NONE)
// ignore if name (fullname) is empty // ignore if name (fullname) is empty
if (name == nullptr) { if (name == nullptr) {
return; return;
@@ -804,13 +814,12 @@ void Mqtt::publish_mqtt_ha_sensor(uint8_t type, // EMSdevice
DynamicJsonDocument doc(EMSESP_JSON_SIZE_HA_CONFIG); DynamicJsonDocument doc(EMSESP_JSON_SIZE_HA_CONFIG);
// special case for boiler - don't use the prefix bool have_tag = !EMSdevice::tag_to_string(tag).empty() && (device_type != EMSdevice::DeviceType::BOILER); // ignore boiler
bool have_prefix = ((tag != DeviceValueTAG::TAG_NONE) && (device_type != EMSdevice::DeviceType::BOILER)); bool is_nested = nested_format_ || (device_type == EMSdevice::DeviceType::BOILER); // boiler never uses nested
// create entity by inserting any given prefix // create entity by add the tag if present, seperating with a .
// we ignore the tag if BOILER
char new_entity[50]; char new_entity[50];
if (have_prefix) { if (have_tag) {
snprintf_P(new_entity, sizeof(new_entity), PSTR("%s.%s"), EMSdevice::tag_to_string(tag).c_str(), 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());
@@ -830,28 +839,13 @@ void Mqtt::publish_mqtt_ha_sensor(uint8_t type, // EMSdevice
doc["~"] = mqtt_base_; doc["~"] = mqtt_base_;
// state topic // state topic
// 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) { snprintf_P(stat_t, sizeof(stat_t), PSTR("~/%s"), tag_to_topic(device_type, tag).c_str());
if (tag == DeviceValueTAG::TAG_BOILER_DATA) {
snprintf_P(stat_t, sizeof(stat_t), PSTR("~/boiler_data"));
} else if (tag == DeviceValueTAG::TAG_BOILER_DATA_WW) {
snprintf_P(stat_t, sizeof(stat_t), PSTR("~/boiler_data_ww"));
} else {
snprintf_P(stat_t, sizeof(stat_t), PSTR("~/boiler_data_info"));
}
} else if (device_type == EMSdevice::DeviceType::SYSTEM) {
snprintf_P(stat_t, sizeof(stat_t), PSTR("~/heartbeat"));
} else if (nested_format_ || !have_prefix) {
snprintf_P(stat_t, sizeof(stat_t), PSTR("~/%s_data"), device_name);
} else {
snprintf_P(stat_t, sizeof(stat_t), PSTR("~/%s_data_%s"), device_name, EMSdevice::tag_to_string(tag).c_str());
}
doc["stat_t"] = stat_t; doc["stat_t"] = stat_t;
// name // name
char new_name[50]; char new_name[80];
if (have_prefix) { if (have_tag) {
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()); 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());
@@ -861,22 +855,21 @@ void Mqtt::publish_mqtt_ha_sensor(uint8_t type, // EMSdevice
// value template // value template
char val_tpl[50]; char val_tpl[50];
if (nested_format_) { if (is_nested) {
snprintf_P(val_tpl, sizeof(val_tpl), PSTR("{{value_json.%s}}"), new_entity); snprintf_P(val_tpl, sizeof(val_tpl), PSTR("{{value_json.%s}}"), new_entity);
} else { } else {
snprintf_P(val_tpl, sizeof(val_tpl), PSTR("{{value_json.%s}}"), uuid::read_flash_string(entity).c_str()); snprintf_P(val_tpl, sizeof(val_tpl), PSTR("{{value_json.%s}}"), uuid::read_flash_string(entity).c_str());
} }
doc["val_tpl"] = val_tpl; doc["val_tpl"] = val_tpl;
char topic[MQTT_TOPIC_MAX_SIZE]; // reserved for topic char topic[MQTT_TOPIC_MAX_SIZE];
// look at the device value type // look at the device value type
if (type == DeviceValueType::BOOL) { if (type == DeviceValueType::BOOL) {
// binary sensor // binary sensor
snprintf_P(topic, sizeof(topic), PSTR("homeassistant/binary_sensor/%s/%s/config"), mqtt_base_.c_str(), uniq.c_str()); // topic snprintf_P(topic, sizeof(topic), PSTR("homeassistant/binary_sensor/%s/%s/config"), mqtt_base_.c_str(), uniq.c_str()); // topic
// how to render boolean // how to render boolean. HA only accepts String values
// HA only accepts String values
char result[10]; char result[10];
doc[F("payload_on")] = Helpers::render_boolean(result, true); doc[F("payload_on")] = Helpers::render_boolean(result, true);
doc[F("payload_off")] = Helpers::render_boolean(result, false); doc[F("payload_off")] = Helpers::render_boolean(result, false);
@@ -905,7 +898,6 @@ void Mqtt::publish_mqtt_ha_sensor(uint8_t type, // EMSdevice
} }
JsonObject dev = doc.createNestedObject("dev"); JsonObject dev = doc.createNestedObject("dev");
JsonArray ids = dev.createNestedArray("ids"); JsonArray ids = dev.createNestedArray("ids");
// for System commands we'll use the ID EMS-ESP // for System commands we'll use the ID EMS-ESP
@@ -920,4 +912,21 @@ void Mqtt::publish_mqtt_ha_sensor(uint8_t type, // EMSdevice
publish_ha(topic, doc.as<JsonObject>()); publish_ha(topic, doc.as<JsonObject>());
} }
// based on the device and tag, create the MQTT topic name (without the basename)
// differs based on whether MQTT nested is enabled
// tag = EMSdevice::DeviceValueTAG
const std::string Mqtt::tag_to_topic(uint8_t device_type, uint8_t tag) {
if (device_type == EMSdevice::DeviceType::SYSTEM) {
return EMSdevice::tag_to_mqtt(tag);
}
// if there is a tag add it
if ((EMSdevice::tag_to_mqtt(tag).empty()) || (nested_format_ && (device_type != EMSdevice::DeviceType::BOILER))) {
return EMSdevice::device_type_2_device_name(device_type) + "_data";
} else {
return EMSdevice::device_type_2_device_name(device_type) + "_data_" + EMSdevice::tag_to_mqtt(tag);
}
}
} // namespace emsesp } // namespace emsesp

View File

@@ -71,6 +71,8 @@ class Mqtt {
void loop(); void loop();
void start(); void start();
static void load_settings();
void set_publish_time_boiler(uint16_t publish_time); void set_publish_time_boiler(uint16_t publish_time);
void set_publish_time_thermostat(uint16_t publish_time); void set_publish_time_thermostat(uint16_t publish_time);
void set_publish_time_solar(uint16_t publish_time); void set_publish_time_solar(uint16_t publish_time);
@@ -192,6 +194,8 @@ class Mqtt {
return mqtt_messages_.empty(); return mqtt_messages_.empty();
} }
static const std::string tag_to_topic(uint8_t device_type, uint8_t tag);
struct QueuedMqttMessage { struct QueuedMqttMessage {
const uint16_t id_; const uint16_t id_;
const std::shared_ptr<const MqttMessage> content_; const std::shared_ptr<const MqttMessage> content_;
@@ -208,6 +212,7 @@ class Mqtt {
}; };
static std::deque<QueuedMqttMessage> mqtt_messages_; static std::deque<QueuedMqttMessage> mqtt_messages_;
private: private:
static uuid::log::Logger logger_; static uuid::log::Logger logger_;

View File

@@ -388,6 +388,21 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd) {
shell.invoke_command("show devices"); shell.invoke_command("show devices");
} }
if (command == "ha") {
shell.printfln(F("Testing HA discovery"));
Mqtt::ha_enabled(true);
// Mqtt::nested_format(true);
Mqtt::nested_format(false);
// run_test("boiler");
run_test("thermostat");
// run_test("solar");
// run_test("mixer");
shell.invoke_command("call system publish");
shell.invoke_command("show mqtt");
}
if (command == "mqtt_nested") { if (command == "mqtt_nested") {
shell.printfln(F("Testing nested MQTT")); shell.printfln(F("Testing nested MQTT"));
Mqtt::ha_enabled(false); // turn off HA Discovery to stop the chatter Mqtt::ha_enabled(false); // turn off HA Discovery to stop the chatter

View File

@@ -33,6 +33,7 @@ namespace emsesp {
// #define EMSESP_TEST_DEFAULT "boiler" // #define EMSESP_TEST_DEFAULT "boiler"
// #define EMSESP_TEST_DEFAULT "mqtt2" // #define EMSESP_TEST_DEFAULT "mqtt2"
#define EMSESP_TEST_DEFAULT "mqtt_nested" #define EMSESP_TEST_DEFAULT "mqtt_nested"
// #define EMSESP_TEST_DEFAULT "ha"
class Test { class Test {
public: public:

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.0.0b6" #define EMSESP_APP_VERSION "3.0.0b7"