diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 795276cca..eb5e011a2 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -9,6 +9,7 @@ - SysLog has enable/disable flag in WebUI - Add solar configuration telegrams (#616) [thanks @hpanther] - log trace shows decoded telegrams, watch 0xFF for unknown telegrams +- WM10 switch ### Fixed - mixer IPM pumpstatus diff --git a/src/devices/switch.cpp b/src/devices/switch.cpp index f39d617d7..4faaff5cc 100644 --- a/src/devices/switch.cpp +++ b/src/devices/switch.cpp @@ -28,28 +28,134 @@ uuid::log::Logger Switch::logger_ { Switch::Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const std::string & version, const std::string & name, uint8_t flags, uint8_t brand) : EMSdevice(device_type, device_id, product_id, version, name, flags, brand) { + LOG_DEBUG(F("Adding new Switch with device ID 0x%02X"), device_id); + + register_telegram_type(0x9C, F("WM10MonitorMessage"), false, [&](std::shared_ptr t) { process_WM10MonitorMessage(t); }); + register_telegram_type(0x9B, F("WM10SetMessage"), false, [&](std::shared_ptr t) { process_WM10SetMessage(t); }); } void Switch::device_info_web(JsonArray & root) { + // fetch the values into a JSON document + StaticJsonDocument doc; + JsonObject json = doc.to(); + if (export_values(json)) { + print_value_json(root, F("activated"), nullptr, F_(activated), nullptr, json); + print_value_json(root, F("flowTemp"), nullptr, F_(flowTemp), F_(degrees), json); + print_value_json(root, F("status"), nullptr, F_(status), nullptr, json); + } } // display all values into the shell console void Switch::show_values(uuid::console::Shell & shell) { // EMSdevice::show_values(shell); // always call this to show header + // fetch the values into a JSON document + StaticJsonDocument doc; + JsonObject json = doc.to(); + if (export_values(json)) { + print_value_json(shell, F("activated"), nullptr, F_(activated), nullptr, json); + print_value_json(shell, F("flowTemp"), F_(2spaces), F_(flowTemp), F_(degrees), json); + print_value_json(shell, F("status"), nullptr, F_(status), nullptr, json); + } } // publish values via MQTT void Switch::publish_values(JsonObject & json, bool force) { + if (Mqtt::mqtt_format() == Mqtt::Format::HA) { + if (!mqtt_ha_config_ || force) { + register_mqtt_ha_config(); + return; + } + } + StaticJsonDocument doc; + JsonObject json_data = doc.to(); + if (export_values(json_data)) { + Mqtt::publish(F("switch_data"), doc.as()); + } } // export values to JSON bool Switch::export_values(JsonObject & json) { + + if (Helpers::hasValue(flowTemp_)) { + char s[7]; + json["activated"] = Helpers::render_value(s, activated_, EMS_VALUE_BOOL); + } + + if (Helpers::hasValue(flowTemp_)) { + json["flowTemp"] = (float)flowTemp_ / 10; + } + + if (Helpers::hasValue(flowTemp_)) { + json["status"] = status_; + } + return true; } // check to see if values have been updated bool Switch::updated_values() { + if (changed_) { + changed_ = false; + return true; + } return false; } +// publish config topic for HA MQTT Discovery +void Switch::register_mqtt_ha_config() { + if (!Mqtt::connected()) { + return; + } + + // if we don't have valid values for this HC don't add it ever again + if (!Helpers::hasValue(flowTemp_)) { + return; + } + + // Create the Master device + StaticJsonDocument doc; + + char name[10]; + snprintf_P(name, sizeof(name), PSTR("Switch")); + doc["name"] = name; + + char uniq_id[10]; + snprintf_P(uniq_id, sizeof(uniq_id), PSTR("switch")); + doc["uniq_id"] = uniq_id; + + doc["ic"] = F("mdi:home-thermometer-outline"); + + char stat_t[50]; + snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/switch_data"), System::hostname().c_str()); + doc["stat_t"] = stat_t; + + doc["val_tpl"] = F("{{value_json.type}}"); // HA needs a single value. We take the type which is wwc or hc + + JsonObject dev = doc.createNestedObject("dev"); + dev["name"] = F("EMS-ESP Switch"); + dev["sw"] = EMSESP_APP_VERSION; + dev["mf"] = this->brand_to_string(); + dev["mdl"] = this->name(); + JsonArray ids = dev.createNestedArray("ids"); + ids.add("ems-esp-switch"); + + Mqtt::publish_retain(F("homeassistant/sensor/ems-esp/switch/config"), doc.as(), true); // publish the config payload with retain flag + Mqtt::register_mqtt_ha_sensor(PSTR("switch"), nullptr, F_(flowTemp), this->device_type(), "activated", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(PSTR("switch"), nullptr, F_(flowTemp), this->device_type(), "flowTemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(PSTR("switch"), nullptr, F_(flowTemp), this->device_type(), "status", nullptr, nullptr); + + mqtt_ha_config_ = true; // done +} + +// message 0x9B switch on/off +void Switch::process_WM10SetMessage(std::shared_ptr telegram){ + changed_ |= telegram->read_value(activated_, 0); +} + +// message 0x9C holds flowtemp and unknown statusvalue +void Switch::process_WM10MonitorMessage(std::shared_ptr telegram){ + changed_ |= telegram->read_value(flowTemp_, 0); // is * 10 + changed_ |= telegram->read_value(status_, 2); +} + } // namespace emsesp \ No newline at end of file diff --git a/src/devices/switch.h b/src/devices/switch.h index e9fb33800..e7afaba2e 100644 --- a/src/devices/switch.h +++ b/src/devices/switch.h @@ -25,6 +25,7 @@ #include #include "emsdevice.h" +#include "emsesp.h" #include "telegram.h" #include "helpers.h" #include "mqtt.h" @@ -43,6 +44,17 @@ class Switch : public EMSdevice { private: static uuid::log::Logger logger_; + + void process_WM10SetMessage(std::shared_ptr telegram); + void process_WM10MonitorMessage(std::shared_ptr telegram); + void register_mqtt_ha_config(); + + uint16_t flowTemp_ = EMS_VALUE_USHORT_NOTSET; + uint8_t status_ = EMS_VALUE_UINT_NOTSET; + uint8_t activated_ = EMS_VALUE_BOOL_NOTSET; + bool changed_ = false; + bool mqtt_ha_config_ = false; // for HA MQTT Discovery + }; } // namespace emsesp