From dfdaf596bc38d806ed5cd4348d25a9609371f092 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 5 Mar 2023 12:03:47 +0100 Subject: [PATCH 1/9] domoticz setting, analog boolformat, dallas discovery --- .../src/framework/mqtt/MqttSettingsForm.tsx | 2 +- src/analogsensor.cpp | 33 ++++++++++++++++--- src/dallassensor.cpp | 4 +-- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/interface/src/framework/mqtt/MqttSettingsForm.tsx b/interface/src/framework/mqtt/MqttSettingsForm.tsx index ff649b19d..00d4920c5 100644 --- a/interface/src/framework/mqtt/MqttSettingsForm.tsx +++ b/interface/src/framework/mqtt/MqttSettingsForm.tsx @@ -229,7 +229,7 @@ const MqttSettingsForm: FC = () => { Date: Sun, 5 Mar 2023 15:32:45 +0100 Subject: [PATCH 2/9] fix typo and text size --- src/analogsensor.cpp | 2 +- src/dallassensor.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index ce6116a53..b9910774a 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -482,7 +482,7 @@ void AnalogSensor::publish_values(const bool force) { config["stat_t"] = stat_t; char val_obj[50]; - char val_cond[65]; + char val_cond[95]; if (Mqtt::is_nested()) { snprintf(val_obj, sizeof(val_obj), "value_json['%02d'].value", sensor.gpio()); snprintf(val_cond, sizeof(val_cond), "value_json['%02d'] is defined and %s is defined", sensor.gpio(), val_obj); diff --git a/src/dallassensor.cpp b/src/dallassensor.cpp index bc3576511..8c11c0fe8 100644 --- a/src/dallassensor.cpp +++ b/src/dallassensor.cpp @@ -517,10 +517,10 @@ void DallasSensor::publish_values(const bool force) { config["unit_of_meas"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES); char val_obj[50]; - char val_cond[65]; + char val_cond[95]; if (Mqtt::is_nested()) { snprintf(val_obj, sizeof(val_obj), "value_json['%s'].temp", sensor.id().c_str()); - snprintf(val_cond, sizeof(val_cond), "%s is defined and %s is defined", sensor.id().c_str(), val_obj); + snprintf(val_cond, sizeof(val_cond), "value_json['%s'] is defined and %s is defined", sensor.id().c_str(), val_obj); } else { snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str()); snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); From af7d0724869905a76642997415560f74b53b175d Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 5 Mar 2023 17:54:04 +0100 Subject: [PATCH 3/9] Test for domoticz discovery --- src/analogsensor.cpp | 20 +++++++++++++++----- src/dallassensor.cpp | 22 ++++++++++++++++------ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index b9910774a..f0db84a67 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -483,12 +483,22 @@ void AnalogSensor::publish_values(const bool force) { char val_obj[50]; char val_cond[95]; - if (Mqtt::is_nested()) { - snprintf(val_obj, sizeof(val_obj), "value_json['%02d'].value", sensor.gpio()); - snprintf(val_cond, sizeof(val_cond), "value_json['%02d'] is defined and %s is defined", sensor.gpio(), val_obj); + if (Mqtt::discovery_type() == 0) { // Homeassistant + if (Mqtt::is_nested()) { + snprintf(val_obj, sizeof(val_obj), "value_json['%02d'].value", sensor.gpio()); + snprintf(val_cond, sizeof(val_cond), "value_json['%02d'] is defined and %s is defined", sensor.gpio(), val_obj); + } else { + snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str()); + snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); + } } else { - snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str()); - snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); + if (Mqtt::is_nested()) { + snprintf(val_obj, sizeof(val_obj), "value_json.%02d.value", sensor.gpio()); + snprintf(val_cond, sizeof(val_cond), "value_json.%02d is defined and %s is defined", sensor.gpio(), val_obj); + } else { + snprintf(val_obj, sizeof(val_obj), "value_json.%s", sensor.name().c_str()); + snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); + } } char sample_val[12] = "0"; if (sensor.type() == AnalogType::DIGITAL_IN || sensor.type() == AnalogType::DIGITAL_OUT) { diff --git a/src/dallassensor.cpp b/src/dallassensor.cpp index 8c11c0fe8..a756e34a0 100644 --- a/src/dallassensor.cpp +++ b/src/dallassensor.cpp @@ -518,12 +518,22 @@ void DallasSensor::publish_values(const bool force) { char val_obj[50]; char val_cond[95]; - if (Mqtt::is_nested()) { - snprintf(val_obj, sizeof(val_obj), "value_json['%s'].temp", sensor.id().c_str()); - snprintf(val_cond, sizeof(val_cond), "value_json['%s'] is defined and %s is defined", sensor.id().c_str(), val_obj); - } else { - snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str()); - snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); + if (Mqtt::discovery_type() == 0) { // Homeassistant + if (Mqtt::is_nested()) { + snprintf(val_obj, sizeof(val_obj), "value_json['%s'].temp", sensor.id().c_str()); + snprintf(val_cond, sizeof(val_cond), "value_json['%s'] is defined and %s is defined", sensor.id().c_str(), val_obj); + } else { + snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str()); + snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); + } + } else { // domoticz + if (Mqtt::is_nested()) { + snprintf(val_obj, sizeof(val_obj), "value_json.%s.temp", sensor.id().c_str()); + snprintf(val_cond, sizeof(val_cond), "value_json.%s is defined and %s is defined", sensor.id().c_str(), val_obj); + } else { + snprintf(val_obj, sizeof(val_obj), "value_json.%s", sensor.name().c_str()); + snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); + } } config["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else -55}}"; From 5f3212afc455541e65adc8b6249516df733e102e Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 5 Mar 2023 18:17:57 +0100 Subject: [PATCH 4/9] fix domoticz setting (was ignored) --- src/mqtt.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 446ec9f24..c84c99fc1 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -424,6 +424,7 @@ void Mqtt::load_settings() { send_response_ = mqttSettings.send_response; discovery_prefix_ = mqttSettings.discovery_prefix.c_str(); entity_format_ = mqttSettings.entity_format; + discovery_type_ = mqttSettings.discovery_type; // convert to milliseconds publish_time_boiler_ = mqttSettings.publish_time_boiler * 1000; @@ -648,7 +649,7 @@ void Mqtt::ha_status() { // create the sensors - must match the MQTT payload keys // these are all from the heartbeat MQTT topic - if (!EMSESP::system_.ethernet_connected()) { + if (!EMSESP::system_.ethernet_connected() || WiFi.isConnected()) { publish_system_ha_sensor_config(DeviceValueType::INT, "WiFi RSSI", "rssi", DeviceValueUOM::DBM); publish_system_ha_sensor_config(DeviceValueType::INT, "WiFi strength", "wifistrength", DeviceValueUOM::PERCENT); } From c9dbf282f6fba0a933effd8b8ec1120333f2ff6a Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 6 Mar 2023 16:26:52 +0100 Subject: [PATCH 5/9] add scheduler api commands/info/value --- src/command.cpp | 19 ++++++--- src/emsesp.cpp | 11 +++-- src/web/WebSchedulerService.cpp | 72 ++++++++++++++++++++++++++++++++- src/web/WebSchedulerService.h | 1 + 4 files changed, 93 insertions(+), 10 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index c997fddb1..1649b2fcd 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -565,6 +565,9 @@ bool Command::device_has_commands(const uint8_t device_type) { void Command::show_devices(uuid::console::Shell & shell) { shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM)); + if (EMSESP::webSchedulerService.has_commands()) { + shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SCHEDULER)); + } if (EMSESP::dallassensor_.have_sensors()) { shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::DALLASSENSOR)); } @@ -596,11 +599,17 @@ void Command::show_all(uuid::console::Shell & shell) { show(shell, EMSdevice::DeviceType::SYSTEM, true); // show scheduler - shell.print(COLOR_BOLD_ON); - shell.print(COLOR_YELLOW); - shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SCHEDULER)); - shell.print(COLOR_RESET); - show(shell, EMSdevice::DeviceType::SCHEDULER, true); + if (EMSESP::webSchedulerService.has_commands()) { + shell.print(COLOR_BOLD_ON); + shell.print(COLOR_YELLOW); + shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SCHEDULER)); + shell.println(COLOR_RESET); + shell.printf(" info: %slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_RED); + shell.println(COLOR_RESET); + shell.printf(" commands: %slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_RED); + shell.print(COLOR_RESET); + show(shell, EMSdevice::DeviceType::SCHEDULER, true); + } // show sensors if (EMSESP::dallassensor_.have_sensors()) { diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 2272db1e6..f6bf067b9 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -653,14 +653,17 @@ bool EMSESP::get_device_value_info(JsonObject & root, const char * cmd, const in // specific for the dallassensor if (devicetype == DeviceType::DALLASSENSOR) { - EMSESP::dallassensor_.get_value_info(root, cmd, id); - return true; + return EMSESP::dallassensor_.get_value_info(root, cmd, id); } // analog sensor if (devicetype == DeviceType::ANALOGSENSOR) { - EMSESP::analogsensor_.get_value_info(root, cmd, id); - return true; + return EMSESP::analogsensor_.get_value_info(root, cmd, id); + } + + // scheduler + if (devicetype == DeviceType::SCHEDULER) { + return EMSESP::webSchedulerService.get_value_info(root, cmd); } char error[100]; diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index 201ffcaff..8a9cfe5ae 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -128,6 +128,74 @@ bool WebSchedulerService::command_setvalue(const char * value, const std::string return false; } +// process json output for info/commands and value_info +bool WebSchedulerService::get_value_info(JsonObject & output, const char * cmd) { + EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) { scheduleItems = &webScheduler.scheduleItems; }); + if (scheduleItems->size() == 0) { + return false; + } + if (Helpers::toLower(cmd) == "commands") { + output["info"] = "lists all values"; + output["commands"] = "lists all commands"; + for (const ScheduleItem & scheduleItem : *scheduleItems) { + if (!scheduleItem.name.empty()) { + output[scheduleItem.name] = "activate schedule"; + } + } + return true; + } + if (strlen(cmd) == 0 || Helpers::toLower(cmd) == "values" || Helpers::toLower(cmd) == "info") { + // list all names + for (const ScheduleItem & scheduleItem : *scheduleItems) { + if (!scheduleItem.name.empty()) { + if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) { + output[scheduleItem.name] = scheduleItem.active; + } else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) { + output[scheduleItem.name] = scheduleItem.active ? 1 : 0; + } else { + char result[12]; + output[scheduleItem.name] = Helpers::render_boolean(result, scheduleItem.active); + } + } + } + return (output.size() > 0); + } + char command_s[30]; + strlcpy(command_s, cmd, sizeof(command_s)); + char * attribute_s = nullptr; + + // check specific attribute to fetch instead of the complete record + char * breakp = strchr(command_s, '/'); + if (breakp) { + *breakp = '\0'; + attribute_s = breakp + 1; + } + JsonVariant data; + for (const ScheduleItem & scheduleItem : *scheduleItems) { + if (Helpers::toLower(scheduleItem.name) == Helpers::toLower(command_s)) { + if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) { + output[scheduleItem.name] = scheduleItem.active; + } else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) { + output[scheduleItem.name] = scheduleItem.active ? 1 : 0; + } else { + char result[12]; + output[scheduleItem.name] = Helpers::render_boolean(result, scheduleItem.active); + } + data = output[scheduleItem.name]; + } + } + if (attribute_s && !strcmp(attribute_s, "value")) { + output.clear(); + output["api_data"] = data; + } + if (output.size()) { + return true; + } + output["message"] = "unknown command"; + return false; +} + +// publish single value void WebSchedulerService::publish_single(const char * name, const bool state) { if (!Mqtt::publish_single() || name == nullptr || name[0] == '\0') { return; @@ -213,7 +281,9 @@ void WebSchedulerService::publish(const bool force) { } } } - Mqtt::queue_publish("scheduler_data", doc.as()); + if (doc.size() > 0) { + Mqtt::queue_publish("scheduler_data", doc.as()); + } } bool WebSchedulerService::has_commands() { diff --git a/src/web/WebSchedulerService.h b/src/web/WebSchedulerService.h index 52341d8e4..e723185e4 100644 --- a/src/web/WebSchedulerService.h +++ b/src/web/WebSchedulerService.h @@ -58,6 +58,7 @@ class WebSchedulerService : public StatefulService { void publish(const bool force = false); bool has_commands(); bool command_setvalue(const char * value, const std::string name); + bool get_value_info(JsonObject & output, const char * cmd); private: bool command(const char * cmd, const char * data); From 57590129149d2cc99451f8834653cdeacae45b6b Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 6 Mar 2023 18:36:27 +0100 Subject: [PATCH 6/9] fix avty --- src/mqtt.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mqtt.cpp b/src/mqtt.cpp index c84c99fc1..8ded6e39c 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -1445,22 +1445,23 @@ void Mqtt::add_avty_to_doc(const char * state_t, const JsonObject & doc, const c snprintf(tpl, sizeof(tpl), tpl_draft, "value == 'online'"); avty_json["val_tpl"] = tpl; avty.add(avty_json); - avty.clear(); - + avty_json.clear(); avty_json["t"] = state_t; snprintf(tpl, sizeof(tpl), tpl_draft, cond1 == nullptr ? "value is defined" : cond1); avty_json["val_tpl"] = tpl; avty.add(avty_json); if (cond2 != nullptr) { - avty.clear(); + avty_json.clear(); + avty_json["t"] = state_t; snprintf(tpl, sizeof(tpl), tpl_draft, cond2); avty_json["val_tpl"] = tpl; avty.add(avty_json); } if (negcond != nullptr) { - avty.clear(); + avty_json.clear(); + avty_json["t"] = state_t; snprintf(tpl, sizeof(tpl), "{{'offline' if %s else 'online'}}", negcond); avty_json["val_tpl"] = tpl; avty.add(avty_json); From bafe23431e44f00680bd2617e4c7b8398b2e9004 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 6 Mar 2023 18:36:27 +0100 Subject: [PATCH 7/9] fix avty --- src/mqtt.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mqtt.cpp b/src/mqtt.cpp index c84c99fc1..8ded6e39c 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -1445,22 +1445,23 @@ void Mqtt::add_avty_to_doc(const char * state_t, const JsonObject & doc, const c snprintf(tpl, sizeof(tpl), tpl_draft, "value == 'online'"); avty_json["val_tpl"] = tpl; avty.add(avty_json); - avty.clear(); - + avty_json.clear(); avty_json["t"] = state_t; snprintf(tpl, sizeof(tpl), tpl_draft, cond1 == nullptr ? "value is defined" : cond1); avty_json["val_tpl"] = tpl; avty.add(avty_json); if (cond2 != nullptr) { - avty.clear(); + avty_json.clear(); + avty_json["t"] = state_t; snprintf(tpl, sizeof(tpl), tpl_draft, cond2); avty_json["val_tpl"] = tpl; avty.add(avty_json); } if (negcond != nullptr) { - avty.clear(); + avty_json.clear(); + avty_json["t"] = state_t; snprintf(tpl, sizeof(tpl), "{{'offline' if %s else 'online'}}", negcond); avty_json["val_tpl"] = tpl; avty.add(avty_json); From 261cfe3911129a3ee2f99d13d04c4735b16f46a3 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 6 Mar 2023 18:48:57 +0100 Subject: [PATCH 8/9] remove dallas/analo domoticz test --- src/analogsensor.cpp | 20 +++++--------------- src/dallassensor.cpp | 22 ++++++---------------- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index f0db84a67..b9910774a 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -483,22 +483,12 @@ void AnalogSensor::publish_values(const bool force) { char val_obj[50]; char val_cond[95]; - if (Mqtt::discovery_type() == 0) { // Homeassistant - if (Mqtt::is_nested()) { - snprintf(val_obj, sizeof(val_obj), "value_json['%02d'].value", sensor.gpio()); - snprintf(val_cond, sizeof(val_cond), "value_json['%02d'] is defined and %s is defined", sensor.gpio(), val_obj); - } else { - snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str()); - snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); - } + if (Mqtt::is_nested()) { + snprintf(val_obj, sizeof(val_obj), "value_json['%02d'].value", sensor.gpio()); + snprintf(val_cond, sizeof(val_cond), "value_json['%02d'] is defined and %s is defined", sensor.gpio(), val_obj); } else { - if (Mqtt::is_nested()) { - snprintf(val_obj, sizeof(val_obj), "value_json.%02d.value", sensor.gpio()); - snprintf(val_cond, sizeof(val_cond), "value_json.%02d is defined and %s is defined", sensor.gpio(), val_obj); - } else { - snprintf(val_obj, sizeof(val_obj), "value_json.%s", sensor.name().c_str()); - snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); - } + snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str()); + snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); } char sample_val[12] = "0"; if (sensor.type() == AnalogType::DIGITAL_IN || sensor.type() == AnalogType::DIGITAL_OUT) { diff --git a/src/dallassensor.cpp b/src/dallassensor.cpp index a756e34a0..8c11c0fe8 100644 --- a/src/dallassensor.cpp +++ b/src/dallassensor.cpp @@ -518,22 +518,12 @@ void DallasSensor::publish_values(const bool force) { char val_obj[50]; char val_cond[95]; - if (Mqtt::discovery_type() == 0) { // Homeassistant - if (Mqtt::is_nested()) { - snprintf(val_obj, sizeof(val_obj), "value_json['%s'].temp", sensor.id().c_str()); - snprintf(val_cond, sizeof(val_cond), "value_json['%s'] is defined and %s is defined", sensor.id().c_str(), val_obj); - } else { - snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str()); - snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); - } - } else { // domoticz - if (Mqtt::is_nested()) { - snprintf(val_obj, sizeof(val_obj), "value_json.%s.temp", sensor.id().c_str()); - snprintf(val_cond, sizeof(val_cond), "value_json.%s is defined and %s is defined", sensor.id().c_str(), val_obj); - } else { - snprintf(val_obj, sizeof(val_obj), "value_json.%s", sensor.name().c_str()); - snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); - } + if (Mqtt::is_nested()) { + snprintf(val_obj, sizeof(val_obj), "value_json['%s'].temp", sensor.id().c_str()); + snprintf(val_cond, sizeof(val_cond), "value_json['%s'] is defined and %s is defined", sensor.id().c_str(), val_obj); + } else { + snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str()); + snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); } config["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else -55}}"; From 6f396087d293d249554ee89e3dc6690e13090ead Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 6 Mar 2023 19:12:02 +0100 Subject: [PATCH 9/9] fix climate publish --- src/mqtt.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 8ded6e39c..68c657ea0 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -1312,8 +1312,8 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp, char seltemp_s[30]; char currtemp_s[30]; char hc_mode_cond[80]; - char seltemp_cond[80]; - char currtemp_cond[170]; + char seltemp_cond[100]; + char currtemp_cond[100]; char mode_str_tpl[400]; char name_s[10]; char uniq_id_s[60]; @@ -1372,9 +1372,9 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp, } snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num); - snprintf(mode_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/mode", hc_num); + snprintf(mode_cmd_s, sizeof(mode_cmd_s), "~/thermostat/hc%d/mode", hc_num); - StaticJsonDocument doc; // doc is 787 typically so 1024 should be enough + StaticJsonDocument doc; // 1024 is not enough doc["~"] = mqtt_base_; doc["uniq_id"] = uniq_id_s;