mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
fixes Excluding entities from the Customization page does not remove the MQTT Discovery entry #357
This commit is contained in:
@@ -455,7 +455,7 @@ void EMSdevice::register_device_value(uint8_t tag,
|
||||
if ((entityCustomization.product_id == product_id()) && (entityCustomization.device_id == device_id())) {
|
||||
for (uint8_t entity_id : entityCustomization.entity_ids) {
|
||||
if (entity_id == dv_id) {
|
||||
state = DeviceValueState::DV_DEFAULT; // it's on the list, exclude it by making it not visible
|
||||
state = DeviceValueState::DV_DEFAULT; // it's on the exclude list, turn off active and visible flags
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -757,12 +757,23 @@ void EMSdevice::generate_values_web(JsonObject & output) {
|
||||
}
|
||||
}
|
||||
|
||||
// reset all entities to being visible
|
||||
// this is called before loading in the exclude entities list from the customization service
|
||||
void EMSdevice::reset_exclude_entities() {
|
||||
for (auto & dv : devicevalues_) {
|
||||
dv.add_state(DeviceValueState::DV_VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
// disable/exclude a device entity based on its unique id
|
||||
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.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
|
||||
dv.remove_state(DeviceValueState::DV_ACTIVE); // this will ensure it'll be removed from any HA MQTT /config topics
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1007,7 +1018,7 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
|
||||
}
|
||||
|
||||
json["writeable"] = dv.has_cmd;
|
||||
json["visible"] = dv.has_state(DeviceValue::DeviceValueState::DV_VISIBLE);
|
||||
json["visible"] = dv.has_state(DeviceValueState::DV_VISIBLE);
|
||||
|
||||
// if there is no value, mention it
|
||||
if (!json.containsKey(value)) {
|
||||
@@ -1042,6 +1053,7 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
|
||||
|
||||
for (auto & dv : devicevalues_) {
|
||||
// check if it exists, there is a value for the entity. Set the flag to ACTIVE
|
||||
// not that this will override any previously removed states
|
||||
if (dv.hasValue()) {
|
||||
dv.add_state(DeviceValueState::DV_ACTIVE);
|
||||
} else {
|
||||
@@ -1210,21 +1222,34 @@ 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();
|
||||
|
||||
// check the state of each of the device values
|
||||
for (auto & dv : devicevalues_) {
|
||||
if (dv.has_state(DeviceValueState::DV_ACTIVE)) {
|
||||
// add it if not already done and if it's visible (not on the exclusion list)
|
||||
// don't do this for commands (like reset)
|
||||
if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && dv.has_state(DeviceValueState::DV_VISIBLE) && 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;
|
||||
// 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)) {
|
||||
// if the HA config has already been created and now the value has gone dormant, delete the config
|
||||
// https://github.com/emsesp/EMS-ESP32/issues/196
|
||||
Mqtt::publish_ha_sensor_config(dv, name(), brand_to_string(), true, create_device_config); // remove /config
|
||||
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||
}
|
||||
|
||||
@@ -184,6 +184,7 @@ class EMSdevice {
|
||||
void show_mqtt_handlers(uuid::console::Shell & shell);
|
||||
void list_device_entries(JsonObject & output);
|
||||
void exclude_entity(uint8_t entity_id);
|
||||
void reset_exclude_entities();
|
||||
|
||||
using process_function_p = std::function<void(std::shared_ptr<const Telegram>)>;
|
||||
|
||||
|
||||
@@ -171,13 +171,6 @@ bool DeviceValue::hasValue() {
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(EMSESP_DEBUG)
|
||||
// https://github.com/emsesp/EMS-ESP32/issues/196
|
||||
// if (has_state(DeviceValueState::DV_ACTIVE) && !has_value) {
|
||||
// emsesp::EMSESP::logger().warning(F("[DEBUG] Lost device value %s"), short_name);
|
||||
// }
|
||||
#endif
|
||||
|
||||
return has_value;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,9 +109,9 @@ class DeviceValue {
|
||||
// states of a device value
|
||||
enum DeviceValueState : uint8_t {
|
||||
DV_DEFAULT = 0, // 0 - does not yet have a value
|
||||
DV_ACTIVE = (1 << 0), // 1 - has a valid value
|
||||
DV_VISIBLE = (1 << 1), // 2 - shown on web and console, otherwise hidden
|
||||
DV_HA_CONFIG_CREATED = (1 << 2) // 4 - set if the HA config has been created
|
||||
DV_ACTIVE = (1 << 0), // 1 - has a validated real value
|
||||
DV_VISIBLE = (1 << 1), // 2 - shown on web, console and on MQTT payload. Otherwise hidden
|
||||
DV_HA_CONFIG_CREATED = (1 << 2) // 4 - set if the HA config topic has been created
|
||||
};
|
||||
|
||||
uint8_t device_type; // EMSdevice::DeviceType
|
||||
|
||||
@@ -625,11 +625,11 @@ void EMSESP::publish_device_values(uint8_t device_type) {
|
||||
json = doc.to<JsonObject>();
|
||||
need_publish |= emsdevice->generate_values(json, DeviceValueTAG::TAG_NONE, true, EMSdevice::OUTPUT_TARGET::MQTT); // nested
|
||||
}
|
||||
}
|
||||
|
||||
// we want to create the /config topic after the data payload to prevent HA from throwing up a warning
|
||||
if (Mqtt::ha_enabled()) {
|
||||
emsdevice->publish_mqtt_ha_entity_config();
|
||||
// we want to create the /config topic after the data payload to prevent HA from throwing up a warning
|
||||
if (Mqtt::ha_enabled()) {
|
||||
emsdevice->publish_mqtt_ha_entity_config();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -595,9 +595,41 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
EMSESP::system_.healthcheck(n);
|
||||
}
|
||||
|
||||
if (command == "exclude") {
|
||||
shell.printfln(F("Testing exclude entities"));
|
||||
|
||||
Mqtt::ha_enabled(true);
|
||||
Mqtt::send_response(false);
|
||||
|
||||
run_test("boiler");
|
||||
|
||||
shell.invoke_command("call boiler wwseltemp");
|
||||
shell.invoke_command("call system publish");
|
||||
|
||||
// toggle mode
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
if (emsdevice->unique_id() == 1) { // boiler
|
||||
uint8_t entity_id = 47; // wwseltemp
|
||||
emsdevice->exclude_entity(entity_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shell.invoke_command("call boiler wwseltemp");
|
||||
shell.invoke_command("call system publish");
|
||||
}
|
||||
|
||||
if (command == "dv2") {
|
||||
shell.printfln(F("Testing device value lost"));
|
||||
|
||||
Mqtt::ha_enabled(true);
|
||||
Mqtt::send_response(false);
|
||||
|
||||
run_test("boiler");
|
||||
|
||||
shell.invoke_command("call boiler wwseltemp");
|
||||
shell.invoke_command("call system publish");
|
||||
|
||||
// Boiler -> Me, UBAParameterWW(0x33)
|
||||
// wwseltemp = goes from 52 degrees (0x34) to void (0xFF)
|
||||
// it should delete the HA config topic homeassistant/sensor/ems-esp/boiler_wwseltemp/config
|
||||
@@ -608,6 +640,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
}
|
||||
|
||||
if (command == "api_values") {
|
||||
#ifndef EMSESP_DEBUG
|
||||
shell.printfln(F("Testing API getting values"));
|
||||
Mqtt::ha_enabled(false);
|
||||
Mqtt::nested_format(1);
|
||||
@@ -626,6 +659,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
EMSESP::webAPIService.webAPIService_get(&request);
|
||||
request.url("/api/boiler/values");
|
||||
EMSESP::webAPIService.webAPIService_get(&request);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (command == "mqtt_post") {
|
||||
|
||||
@@ -35,7 +35,8 @@ namespace emsesp {
|
||||
// #define EMSESP_DEBUG_DEFAULT "boiler"
|
||||
// #define EMSESP_DEBUG_DEFAULT "mqtt2"
|
||||
// #define EMSESP_DEBUG_DEFAULT "mqtt_nested"
|
||||
#define EMSESP_DEBUG_DEFAULT "ha"
|
||||
// #define EMSESP_DEBUG_DEFAULT "ha"
|
||||
#define EMSESP_DEBUG_DEFAULT "exclude"
|
||||
// #define EMSESP_DEBUG_DEFAULT "board_profile"
|
||||
// #define EMSESP_DEBUG_DEFAULT "shower_alert"
|
||||
// #define EMSESP_DEBUG_DEFAULT "310"
|
||||
|
||||
@@ -216,13 +216,16 @@ void WebCustomizationService::exclude_entities(AsyncWebServerRequest * request,
|
||||
if (emsdevice) {
|
||||
uint8_t unique_device_id = json["id"];
|
||||
if (emsdevice->unique_id() == unique_device_id) {
|
||||
JsonArray entity_ids = json["entity_ids"];
|
||||
// first reset all the entity ids
|
||||
emsdevice->reset_exclude_entities();
|
||||
|
||||
std::vector<uint8_t> temp;
|
||||
for (JsonVariant id : entity_ids) {
|
||||
// build a list of entities to exclude and then set the flag to non-visible
|
||||
JsonArray entity_ids_json = json["entity_ids"];
|
||||
std::vector<uint8_t> entity_ids;
|
||||
for (JsonVariant id : entity_ids_json) {
|
||||
uint8_t entity_id = id.as<int>();
|
||||
emsdevice->exclude_entity(entity_id); // this will have immediate affect
|
||||
temp.push_back(entity_id);
|
||||
entity_ids.push_back(entity_id);
|
||||
}
|
||||
|
||||
// Save the list to the customization file
|
||||
@@ -236,8 +239,8 @@ void WebCustomizationService::exclude_entities(AsyncWebServerRequest * request,
|
||||
if ((entityCustomization.product_id == product_id) && (entityCustomization.device_id == device_id)) {
|
||||
// already exists, clear the list and add the new values
|
||||
entityCustomization.entity_ids.clear();
|
||||
for (uint8_t i = 0; i < temp.size(); i++) {
|
||||
entityCustomization.entity_ids.push_back(temp[i]);
|
||||
for (uint8_t i = 0; i < entity_ids.size(); i++) {
|
||||
entityCustomization.entity_ids.push_back(entity_ids[i]);
|
||||
}
|
||||
return StateUpdateResult::CHANGED;
|
||||
}
|
||||
@@ -246,8 +249,8 @@ void WebCustomizationService::exclude_entities(AsyncWebServerRequest * request,
|
||||
EntityCustomization new_entry;
|
||||
new_entry.product_id = product_id;
|
||||
new_entry.device_id = device_id;
|
||||
for (uint8_t i = 0; i < temp.size(); i++) {
|
||||
new_entry.entity_ids.push_back(temp[i]);
|
||||
for (uint8_t i = 0; i < entity_ids.size(); i++) {
|
||||
new_entry.entity_ids.push_back(entity_ids[i]);
|
||||
}
|
||||
settings.entityCustomizations.push_back(new_entry);
|
||||
return StateUpdateResult::CHANGED;
|
||||
|
||||
Reference in New Issue
Block a user