diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 1ad7a1832..06254b663 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -1561,7 +1561,7 @@ void EMSdevice::publish_all_values() { // For each value in the device create the json object pair and add it to given json // return false if empty -// this is used to create the MQTT payloads, Console messages and Web API calls +// this is used to create the MQTT payloads, Console messages and Web API call responses bool EMSdevice::generate_values(JsonObject output, const uint8_t tag_filter, const bool nested, const uint8_t output_target) { bool has_values = false; // to see if we've added a value. it's faster than doing a json.size() at the end uint8_t old_tag = 255; // NAN @@ -1697,8 +1697,8 @@ bool EMSdevice::generate_values(JsonObject output, const uint8_t tag_filter, con } } - // commenting out - we don't want Commands in MQTT or Console - // else if (dv.type == DeviceValueType::CMD && output_target != EMSdevice::OUTPUT_TARGET::MQTT) { + // commenting out as we don't want Commands in Console ('show values') + // else if (dv.type == DeviceValueType::CMD && output_target != EMSdevice::OUTPUT_TARGET::MQTT) { // json[name] = ""; // } @@ -1748,7 +1748,7 @@ void EMSdevice::mqtt_ha_entity_config_create() { } } - if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && (dv.type != DeviceValueType::CMD) && dv.has_state(DeviceValueState::DV_ACTIVE) + if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && dv.has_state(DeviceValueState::DV_ACTIVE) && !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) { // create_device_config is only done once for the EMS device. It can added to any entity, so we take the first if (Mqtt::publish_ha_sensor_config(dv, name(), brand_to_char(), false, create_device_config)) { diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 0137c5c54..3a2bdf819 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -878,6 +878,7 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev readonly_sensors = false; break; case DeviceValueType::ENUM: + case DeviceValueType::CMD: // hardcoded commands are always ENUMS // select - https://www.home-assistant.io/integrations/select.mqtt snprintf(topic, sizeof(topic), "select/%s", config_topic); readonly_sensors = false; @@ -927,8 +928,8 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev } doc["cmd_t"] = command_topic; - // extend for enums, add options - if (type == DeviceValueType::ENUM) { + // extend for enums and also commands, add options + if ((type == DeviceValueType::ENUM) || (type == DeviceValueType::CMD)) { JsonArray option_list = doc["ops"].to(); if (EMSESP::system_.enum_format() == ENUM_FORMAT_INDEX) { // use index numbers @@ -943,7 +944,6 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev } snprintf(sample_val, sizeof(sample_val), "'%s'", Helpers::translated_word(options[0])); } - } else if (type != DeviceValueType::STRING && type != DeviceValueType::BOOL) { // For numeric's add the range doc["mode"] = "box"; // auto, slider or box @@ -979,11 +979,6 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev } } - // state topic - char stat_t[MQTT_TOPIC_MAX_SIZE]; - snprintf(stat_t, sizeof(stat_t), "%s/%s", Mqtt::base().c_str(), tag_to_topic(device_type, tag).c_str()); - doc["stat_t"] = stat_t; - // friendly name = char ha_name[70]; char * F_name = strdup(fullname); @@ -997,38 +992,49 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev free(F_name); // very important! doc["name"] = ha_name; - // value template - // if its nested mqtt format then use the appended entity name, otherwise take the original name - char val_obj[100]; - char val_cond[200]; - if (is_nested() && tag >= DeviceValueTAG::TAG_HC1) { - snprintf(val_obj, sizeof(val_obj), "value_json.%s.%s", EMSdevice::tag_to_mqtt(tag), entity); - snprintf(val_cond, sizeof(val_cond), "value_json.%s is defined and %s is defined", EMSdevice::tag_to_mqtt(tag), val_obj); - } else { - snprintf(val_obj, sizeof(val_obj), "value_json.%s", entity); - snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); - } - // special case to handle booleans - // applies to both Binary Sensor (read only) and a Switch (for a command) - // has no unit of measure or icon - if (type == DeviceValueType::BOOL) { - if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) { - doc["pl_on"] = true; - doc["pl_off"] = false; - snprintf(sample_val, sizeof(sample_val), "false"); - } else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) { - doc["pl_on"] = 1; - doc["pl_off"] = 0; + // not needed for commands + if (type != DeviceValueType::CMD) { + // state topic, except for commands + char stat_t[MQTT_TOPIC_MAX_SIZE]; + snprintf(stat_t, sizeof(stat_t), "%s/%s", Mqtt::base().c_str(), tag_to_topic(device_type, tag).c_str()); + doc["stat_t"] = stat_t; + + // value template + // if its nested mqtt format then use the appended entity name, otherwise take the original name + char val_obj[100]; + char val_cond[200]; + if (is_nested() && tag >= DeviceValueTAG::TAG_HC1) { + snprintf(val_obj, sizeof(val_obj), "value_json.%s.%s", EMSdevice::tag_to_mqtt(tag), entity); + snprintf(val_cond, sizeof(val_cond), "value_json.%s is defined and %s is defined", EMSdevice::tag_to_mqtt(tag), val_obj); } else { - char result[12]; - doc["pl_on"] = Helpers::render_boolean(result, true); - doc["pl_off"] = Helpers::render_boolean(result, false); - snprintf(sample_val, sizeof(sample_val), "'%s'", Helpers::render_boolean(result, false)); + snprintf(val_obj, sizeof(val_obj), "value_json.%s", entity); + snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj); } - } - doc["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else " + sample_val + "}}"; + // special case to handle booleans + // applies to both Binary Sensor (read only) and a Switch (for a command) + // has no unit of measure or icon + if (type == DeviceValueType::BOOL) { + if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) { + doc["pl_on"] = true; + doc["pl_off"] = false; + snprintf(sample_val, sizeof(sample_val), "false"); + } else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) { + doc["pl_on"] = 1; + doc["pl_off"] = 0; + } else { + char result[12]; + doc["pl_on"] = Helpers::render_boolean(result, true); + doc["pl_off"] = Helpers::render_boolean(result, false); + snprintf(sample_val, sizeof(sample_val), "'%s'", Helpers::render_boolean(result, false)); + } + } + doc["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else " + sample_val + "}}"; + + // add the dev json object to the end, not for commands + add_ha_sections_to_doc(nullptr, stat_t, doc, false, val_cond); // no name, since the "dev" has already been adde + } // Add the state class, device class and sometimes the icon. Used only for read-only sensors like Sensor and Binary Sensor if (readonly_sensors) { @@ -1037,12 +1043,10 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev if (device_type == EMSdevice::DeviceType::SYSTEM) { doc["ent_cat"] = "diagnostic"; } - add_ha_uom(doc.as(), type, uom, entity); // add the UoM, device and state class } - doc["dev"] = dev_json; // add the dev json object to the end - add_ha_sections_to_doc(nullptr, stat_t, doc, false, val_cond); // no name, since the "dev" has already been added + doc["dev"] = dev_json; return queue_ha(topic, doc.as()); }