From d1f4e21a746bae2836f6194d7678fd7e5ada55c0 Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 19 Oct 2020 23:20:53 +0200 Subject: [PATCH] HA MQTT changes --- src/devices/mixing.cpp | 14 +++---- src/devices/thermostat.cpp | 77 +++++++++++++++++++------------------- src/mqtt.cpp | 30 ++++++++++++--- src/mqtt.h | 5 +++ 4 files changed, 75 insertions(+), 51 deletions(-) diff --git a/src/devices/mixing.cpp b/src/devices/mixing.cpp index 7cbb84824..ca3b23a13 100644 --- a/src/devices/mixing.cpp +++ b/src/devices/mixing.cpp @@ -194,19 +194,19 @@ void Mixing::register_mqtt_ha_config() { Mqtt::publish_retain(topic, doc.as(), true); // publish the config payload with retain flag char hc_name[10]; snprintf_P(hc_name, sizeof(hc_name), PSTR("hc%d"), hc_); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(flowTemp), this->device_type(), "flowTemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(flowSetTemp), this->device_type(), "flowSetTemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(pumpStatus), this->device_type(), "pumpStatus", nullptr, nullptr); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(valveStatus), this->device_type(), "valveStatus", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(flowTemp), this->device_type(), "flowTemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(flowSetTemp), this->device_type(), "flowSetTemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(pumpStatus), this->device_type(), "pumpStatus", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(valveStatus), this->device_type(), "valveStatus", nullptr, nullptr); } else { // WWC snprintf_P(&topic[0], topic.capacity() + 1, PSTR("homeassistant/climate/ems-esp/mixing_wwc%d/config"), hc_); Mqtt::publish_retain(topic, doc.as(), true); // publish the config payload with retain flag char wwc_name[10]; snprintf_P(wwc_name, sizeof(wwc_name), PSTR("wwc%d"), hc_); - Mqtt::register_mqtt_ha_sensor(wwc_name, F_(wwTemp), this->device_type(), "wwTemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(wwc_name, F_(pumpStatus), this->device_type(), "pumpStatus", nullptr, nullptr); - Mqtt::register_mqtt_ha_sensor(wwc_name, F_(tempStatus), this->device_type(), "tempStatus", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(wwc_name, nullptr, F_(wwTemp), this->device_type(), "wwTemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(wwc_name, nullptr, F_(pumpStatus), this->device_type(), "pumpStatus", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(wwc_name, nullptr, F_(tempStatus), this->device_type(), "tempStatus", nullptr, nullptr); } } diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index e119a5ad2..e171441a7 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -194,6 +194,7 @@ void Thermostat::device_info_web(JsonArray & root) { StaticJsonDocument doc_hc; JsonObject output_hc = doc_hc.to(); + if (export_values_hc(Mqtt::Format::NESTED, output_hc)) { // display for each active heating circuit for (const auto & hc : heating_circuits_) { @@ -254,8 +255,8 @@ bool Thermostat::command_info(const char * value, const int8_t id, JsonObject & void Thermostat::show_values(uuid::console::Shell & shell) { EMSdevice::show_values(shell); // always call this to show header - StaticJsonDocument doc_main; - JsonObject output_main = doc_main.to(); + StaticJsonDocument doc_main; + JsonObject output_main = doc_main.to(); if (export_values_main(output_main)) { print_value_json(shell, F("time"), nullptr, F_(time), nullptr, output_main); print_value_json(shell, F("errorcode"), nullptr, F_(error), nullptr, output_main); @@ -734,10 +735,9 @@ std::shared_ptr Thermostat::heating_circuit(std::sha } // publish config topic for HA MQTT Discovery -// homeassistant/climate/ems-esp/thermostat_/config +// homeassistant/climate/ems-esp/thermostat/config void Thermostat::register_mqtt_ha_config() { StaticJsonDocument doc; - doc["name"] = F("Thermostat"); doc["uniq_id"] = F("thermostat"); doc["ic"] = F("mdi:home-thermometer-outline"); @@ -745,7 +745,8 @@ void Thermostat::register_mqtt_ha_config() { snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/thermostat_data"), System::hostname().c_str()); doc["stat_t"] = stat_t; - doc["val_tpl"] = F("{{value_json.time}}"); + doc["name"] = F("Thermostat Status"); + doc["val_tpl"] = F("{{value_json.errorcode}}"); // default value - must have one, so we use errorcode JsonObject dev = doc.createNestedObject("dev"); dev["name"] = F("EMS-ESP Thermostat"); dev["sw"] = EMSESP_APP_VERSION; @@ -755,25 +756,25 @@ void Thermostat::register_mqtt_ha_config() { ids.add("ems-esp-thermostat"); Mqtt::publish_retain(F("homeassistant/sensor/ems-esp/thermostat/config"), doc.as(), true); // publish the config payload with retain flag - Mqtt::register_mqtt_ha_sensor(nullptr, F_(time), this->device_type(), "time", nullptr, nullptr); - Mqtt::register_mqtt_ha_sensor(nullptr, F_(error), this->device_type(), "errorcode", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(time), this->device_type(), "time", nullptr, nullptr); + // Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(error), this->device_type(), "errorcode", nullptr, nullptr); uint8_t model = this->model(); if (model == EMS_DEVICE_FLAG_RC30_1) { - Mqtt::register_mqtt_ha_sensor(nullptr, F_(display), this->device_type(), "display", nullptr, nullptr); - Mqtt::register_mqtt_ha_sensor(nullptr, F_(language), this->device_type(), "language", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(display), this->device_type(), "display", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(language), this->device_type(), "language", nullptr, nullptr); } if (model == EMS_DEVICE_FLAG_RC35 || model == EMS_DEVICE_FLAG_RC35) { // excluding inttemp1, inttemp2, intoffset, minexttemp - Mqtt::register_mqtt_ha_sensor(nullptr, F_(dampedtemp), this->device_type(), "dampedtemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(nullptr, F_(building), this->device_type(), "building", nullptr, nullptr); - Mqtt::register_mqtt_ha_sensor(nullptr, F_(minexttemp), this->device_type(), "minexttemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(nullptr, F_(wwmode), this->device_type(), "wwmode", nullptr, nullptr); - Mqtt::register_mqtt_ha_sensor(nullptr, F_(wwtemp), this->device_type(), "wwtemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(nullptr, F_(wwtemplow), this->device_type(), "wwtemplow", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(nullptr, F_(wwcircmode), this->device_type(), "wwcircmode", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(dampedtemp), this->device_type(), "dampedtemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(building), this->device_type(), "building", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(minexttemp), this->device_type(), "minexttemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(wwmode), this->device_type(), "wwmode", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(wwtemp), this->device_type(), "wwtemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(wwtemplow), this->device_type(), "wwtemplow", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(wwcircmode), this->device_type(), "wwcircmode", nullptr, nullptr); } } @@ -867,40 +868,40 @@ void Thermostat::register_mqtt_ha_config(uint8_t hc_num) { char s[3]; strlcat(hc_name, Helpers::itoa(s, hc_num), 10); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(mode), this->device_type(), "mode", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(mode), this->device_type(), "mode", nullptr, nullptr); uint8_t model = this->model(); switch (model) { case EMS_DEVICE_FLAG_RC100: case EMS_DEVICE_FLAG_RC300: - Mqtt::register_mqtt_ha_sensor(hc_name, F_(modetype), this->device_type(), "modetype", nullptr, nullptr); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(ecotemp), this->device_type(), "ecotemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(manualtemp), this->device_type(), "manualtemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(comforttemp), this->device_type(), "comforttemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(summertemp), this->device_type(), "summertemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(modetype), this->device_type(), "modetype", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(ecotemp), this->device_type(), "ecotemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(manualtemp), this->device_type(), "manualtemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(comforttemp), this->device_type(), "comforttemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(summertemp), this->device_type(), "summertemp", F_(degrees), F_(icontemperature)); break; case EMS_DEVICE_FLAG_RC20_2: - Mqtt::register_mqtt_ha_sensor(hc_name, F_(daytemp), this->device_type(), "daytemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(nighttemp), this->device_type(), "nighttemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(daytemp), this->device_type(), "daytemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(nighttemp), this->device_type(), "nighttemp", F_(degrees), F_(icontemperature)); break; case EMS_DEVICE_FLAG_RC30_1: case EMS_DEVICE_FLAG_RC35: - Mqtt::register_mqtt_ha_sensor(hc_name, F_(modetype), this->device_type(), "modetype", nullptr, nullptr); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(nighttemp), this->device_type(), "nighttemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(daytemp), this->device_type(), "daytemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(designtemp), this->device_type(), "designtemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(offsettemp), this->device_type(), "offsettemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(holidaytemp), this->device_type(), "holidaytemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(targetflowtemp), this->device_type(), "targetflowtemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(summertemp), this->device_type(), "summertemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(nofrosttemp), this->device_type(), "nofrosttemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(roominfluence), this->device_type(), "roominfluence", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(modetype), this->device_type(), "modetype", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(nighttemp), this->device_type(), "nighttemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(daytemp), this->device_type(), "daytemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(designtemp), this->device_type(), "designtemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(offsettemp), this->device_type(), "offsettemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(holidaytemp), this->device_type(), "holidaytemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(targetflowtemp), this->device_type(), "targetflowtemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(summertemp), this->device_type(), "summertemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(nofrosttemp), this->device_type(), "nofrosttemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(roominfluence), this->device_type(), "roominfluence", F_(degrees), F_(icontemperature)); break; case EMS_DEVICE_FLAG_JUNKERS: - Mqtt::register_mqtt_ha_sensor(hc_name, F_(modetype), this->device_type(), "modetype", nullptr, nullptr); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(heattemp), this->device_type(), "heattemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(ecotemp), this->device_type(), "ecotemp", F_(degrees), F_(icontemperature)); - Mqtt::register_mqtt_ha_sensor(hc_name, F_(nofrosttemp), this->device_type(), "nofrosttemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(modetype), this->device_type(), "modetype", nullptr, nullptr); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(heattemp), this->device_type(), "heattemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(ecotemp), this->device_type(), "ecotemp", F_(degrees), F_(icontemperature)); + Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(nofrosttemp), this->device_type(), "nofrosttemp", F_(degrees), F_(icontemperature)); break; default: break; diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 571c24888..2c703e118 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -657,7 +657,12 @@ void Mqtt::process_queue() { // else try and publish it uint16_t packet_id = mqttClient_->publish(message->topic.c_str(), mqtt_qos_, message->retain, message->payload.c_str(), message->payload.size(), false, mqtt_message.id_); - LOG_DEBUG(F("Publishing topic %s (#%02d, attempt #%d, pid %d)"), message->topic.c_str(), mqtt_message.id_, mqtt_message.retry_count_ + 1, packet_id); + LOG_DEBUG(F("Publishing topic %s (#%02d, attempt #%d, size %d, pid %d)"), + message->topic.c_str(), + mqtt_message.id_, + mqtt_message.retry_count_ + 1, + message->payload.size(), + packet_id); if (packet_id == 0) { // it failed. if we retried n times, give up. remove from queue @@ -692,7 +697,7 @@ void Mqtt::register_mqtt_ha_binary_sensor(const __FlashStringHelper * name, cons return; } - DynamicJsonDocument doc(EMSESP_MAX_JSON_SIZE_MEDIUM); + StaticJsonDocument doc; doc["name"] = name; doc["uniq_id"] = entity; @@ -724,7 +729,6 @@ void Mqtt::register_mqtt_ha_binary_sensor(const __FlashStringHelper * name, cons snprintf_P(topic, sizeof(topic), PSTR("homeassistant/binary_sensor/ems-esp/%s/config"), entity); // convert json to string and publish immediately with retain forced to true - doc.shrinkToFit(); std::string payload_text; serializeJson(doc, payload_text); // convert json to string uint16_t packet_id = mqttClient_->publish(topic, 0, true, payload_text.c_str(), payload_text.size()); @@ -744,6 +748,7 @@ void Mqtt::register_mqtt_ha_binary_sensor(const __FlashStringHelper * name, cons // HA config for a normal 'sensor' type // entity must match the key/value pair in the _data topic void Mqtt::register_mqtt_ha_sensor(const char * prefix, + const __FlashStringHelper * suffix, const __FlashStringHelper * name, const uint8_t device_type, const char * entity, @@ -773,8 +778,12 @@ void Mqtt::register_mqtt_ha_sensor(const char * prefix, snprintf_P(topic, sizeof(topic), PSTR("homeassistant/sensor/ems-esp/%s/config"), uniq.c_str()); // state topic - char stat_t[50]; - snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s_data"), hostname_.c_str(), device_name.c_str()); + char stat_t[MQTT_TOPIC_MAX_SIZE]; + if (suffix != nullptr) { + snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s_data%s"), hostname_.c_str(), device_name.c_str(), uuid::read_flash_string(suffix).c_str()); + } else { + snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/%s_data"), hostname_.c_str(), device_name.c_str()); + } // value template char val_tpl[50]; @@ -784,8 +793,17 @@ void Mqtt::register_mqtt_ha_sensor(const char * prefix, char ha_device[40]; snprintf_P(ha_device, sizeof(ha_device), PSTR("ems-esp-%s"), device_name.c_str()); + // name + char new_name[50]; + if (prefix != nullptr) { + snprintf_P(new_name, sizeof(new_name), PSTR("%s %s %s"), device_name.c_str(), prefix, name); + } else { + snprintf_P(new_name, sizeof(new_name), PSTR("%s %s"), device_name.c_str(), name); + } + new_name[0] = toupper(new_name[0]); // capitalize first letter + DynamicJsonDocument doc(EMSESP_MAX_JSON_SIZE_MEDIUM); - doc["name"] = name; + doc["name"] = new_name; doc["uniq_id"] = uniq; if (uom != nullptr) { doc["unit_of_meas"] = uom; diff --git a/src/mqtt.h b/src/mqtt.h index 0894f0438..c273a767f 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -100,6 +100,7 @@ class Mqtt { static void register_mqtt_ha_binary_sensor(const __FlashStringHelper * name, const uint8_t device_type, const char * entity); static void register_mqtt_ha_sensor(const char * prefix, + const __FlashStringHelper * suffix, const __FlashStringHelper * name, const uint8_t device_type, const char * entity, @@ -145,6 +146,10 @@ class Mqtt { return mqtt_format_; } + static AsyncMqttClient * client() { + return mqttClient_; + } + private: static uuid::log::Logger logger_;