diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index db80f594f..310dac535 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -459,15 +459,7 @@ void Thermostat::publish_ha_config_hc(std::shared_ptr()); // publish the config payload with retain flag - - /* - // enable the a special "thermostat_hc" topic to take both mode strings and floats for each of the heating circuits - std::string topic2(Mqtt::MQTT_TOPIC_MAX_SIZE, '\0'); - snprintf(&topic2[0], topic2.capacity() + 1, "thermostat_hc%d", hc_num); - Mqtt::subscribe(EMSdevice::DeviceType::THERMOSTAT, topic2, [=](const char * m) { return thermostat_ha_cmd(m, hc_num); }); - */ } // for HA specifically when receiving over MQTT in the thermostat topic @@ -679,12 +671,21 @@ void Thermostat::process_RC10Monitor(std::shared_ptr telegram) { // add the HVAC/Climate HA component for the HC void Thermostat::add_ha_climate(std::shared_ptr hc) { - if (!Mqtt::ha_enabled() || (hc->ha_climate_created())) { + if (!Mqtt::ha_enabled()) { return; } - // only if it has a valid seltemp (roomtemp is optional) - if (Helpers::hasValue(hc->selTemp)) { + bool has_values = Helpers::hasValue(hc->selTemp) && Helpers::hasValue(hc->roomTemp); + + // see if we need to remove the HA climate component because some of the values have been lost + // note, this doesn't account for whether any of the device values have been excluded + if (hc->ha_climate_created() && !has_values) { + // remove the whole climate component + char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; + snprintf(topic, sizeof(topic), "climate/%s/thermostat_hc%d/config", Mqtt::base().c_str(), hc->hc_num()); + Mqtt::publish_ha(topic); + } else { + // create publish_ha_config_hc(hc); hc->ha_climate_created(true); // only create it once } diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 17a0f4434..8d4cd336d 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -779,7 +779,7 @@ void EMSdevice::exclude_entity(uint8_t id) { for (auto & dv : devicevalues_) { if (dv.id == id) { #if defined(EMSESP_USE_SERIAL) - Serial.print("exclude_entity() Removing state for device value: "); + Serial.print("exclude_entity() Removing Visible for device value: "); Serial.println(read_flash_string(dv.full_name).c_str()); #endif dv.remove_state(DeviceValueState::DV_VISIBLE); // this will remove from MQTT payloads and showing in web & console @@ -1225,47 +1225,36 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c return has_values; } +// remove the Home Assistant configs for each device value/entity if its not visible or active +// this is called when an MQTT publish is done via an EMS Device in emsesp.cpp::publish_device_values() +void EMSdevice::mqtt_ha_entity_config_remove() { + for (auto & dv : devicevalues_) { + if (dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) + && ((!dv.has_state(DeviceValueState::DV_VISIBLE)) || (!dv.has_state(DeviceValueState::DV_ACTIVE)))) { + Mqtt::publish_ha_sensor_config(dv, "", "", true); // delete topic (remove = true) + dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED); + } + } +} + // create the Home Assistant configs for each device value / entity -// this is called when an MQTT publish is done via an EMS Device in emsesp.cpp -void EMSdevice::publish_mqtt_ha_entity_config() { - // create the main device config if not already done, per device type - bool create_device_config = !ha_config_done(); +// this is called when an MQTT publish is done via an EMS Device in emsesp.cpp::publish_device_values() +void EMSdevice::mqtt_ha_entity_config_create() { + bool create_device_config = !ha_config_done(); // do we need to create the main Discovery device config with this entity? // check the state of each of the device values + // create the discovery topic if if hasn't already been created, not a command (like reset) and is active and visible for (auto & dv : devicevalues_) { - if (dv.has_state(DeviceValueState::DV_ACTIVE)) { - // entity has an active value (it means it contains a valid value) - - if (dv.has_state(DeviceValueState::DV_VISIBLE)) { - // visible - // if the HA config topic hasn't been created it, do it now (unless its a command like reset) - if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && dv.type != DeviceValueType::CMD) { - Mqtt::publish_ha_sensor_config(dv, name(), brand_to_string(), false, create_device_config); - dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED); - if (create_device_config) { - create_device_config = false; - } - } - } else { - // not visible. It must be on the entity exclusion list defined in the Customizations service - // if a HA config topic was created then remove it. This entity has become 'lost' - if (dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED)) { - Mqtt::publish_ha_sensor_config(dv, name(), brand_to_string(), true, create_device_config); // remove /config - dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED); - } - } - } else { - // entity does not have an active value - // if a HA config topic was created then remove it. This entity has become 'lost' - // https://github.com/emsesp/EMS-ESP32/issues/196 - if (dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED)) { - Mqtt::publish_ha_sensor_config(dv, name(), brand_to_string(), true, create_device_config); // remove /config - dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED); - } + if ((!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && dv.type != DeviceValueType::CMD) && dv.has_state(DeviceValueState::DV_ACTIVE) + && dv.has_state(DeviceValueState::DV_VISIBLE)) { + // create_device_config is only done once for the EMS device. It can added to any entity, so we take the first + Mqtt::publish_ha_sensor_config(dv, name(), brand_to_string(), false, create_device_config); + dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED); + create_device_config = false; // only create the main config once } } - ha_config_done(true); // assume we've created the config + ha_config_done(!create_device_config); } // remove all config topics in HA