From 503df0842bd92d820dbfc66f378c41a9a37e19b1 Mon Sep 17 00:00:00 2001 From: Proddy Date: Tue, 5 Apr 2022 23:28:34 +0200 Subject: [PATCH] fix saving customizatons #450 --- src/emsdevice.cpp | 23 +++++++++---- src/emsdevice.h | 4 ++- src/web/WebCustomizationService.cpp | 53 +++++++++++++++-------------- 3 files changed, 47 insertions(+), 33 deletions(-) diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 54bbd16f0..105d15002 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -849,27 +849,38 @@ void EMSdevice::generate_values_web_all(JsonArray & output) { // set mask per device entity based on the id which is prefixed with the 2 char hex mask value // returns true if the entity has a mask set (not 0 the default) -bool EMSdevice::mask_entity(const std::string & entity_id) { +void EMSdevice::mask_entity(const std::string & entity_id) { for (auto & dv : devicevalues_) { std::string entity_name = dv.tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(dv.short_name) : tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name); - uint8_t current_mask = dv.state >> 4; if (entity_name == entity_id.substr(2)) { // this entity has a new mask set - uint8_t new_mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); // first character contains mask flags + uint8_t current_mask = dv.state >> 4; + uint8_t new_mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); // first character contains mask flags if (Mqtt::ha_enabled() && ((current_mask ^ new_mask) & (DeviceValueState::DV_READONLY >> 4))) { // remove ha config on change of dv_readonly flag dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED); Mqtt::publish_ha_sensor_config(dv, "", "", true); // delete topic (remove = true) } dv.state = ((dv.state & 0x0F) | (new_mask << 4)); // set state high bits to flag - return new_mask; // true if entity mask is not the deafult 0 + return; } } - - return false; // we didn't find the entity } +// populate a string vector with entities that have masks set +void EMSdevice::getMaskedEntities(std::vector & entity_ids) { + for (auto & dv : devicevalues_) { + std::string entity_name = + dv.tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(dv.short_name) : tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name); + uint8_t mask = dv.state >> 4; + if (mask) { + entity_ids.push_back(Helpers::hextoa(mask, false) + entity_name); + } + } +} + + // builds json for a specific device value / entity // cmd is the endpoint or name of the device entity // returns false if failed, otherwise true diff --git a/src/emsdevice.h b/src/emsdevice.h index fdfbba7e2..99cadae76 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -183,7 +183,9 @@ class EMSdevice { char * show_telegram_handlers(char * result, const size_t len, const uint8_t handlers); void show_mqtt_handlers(uuid::console::Shell & shell) const; void list_device_entries(JsonObject & output) const; - bool mask_entity(const std::string & entity_id); + + void mask_entity(const std::string & entity_id); + void getMaskedEntities(std::vector & entity_ids); using process_function_p = std::function)>; diff --git a/src/web/WebCustomizationService.cpp b/src/web/WebCustomizationService.cpp index 7c51ecf0e..3b01c0291 100644 --- a/src/web/WebCustomizationService.cpp +++ b/src/web/WebCustomizationService.cpp @@ -210,52 +210,53 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request, J request->send(response); } -// takes a list of masked ids sent from the webUI +// takes a list of updated entities with new masks from the web UI // saves it in the customization service // and updates the entity list real-time void WebCustomizationService::masked_entities(AsyncWebServerRequest * request, JsonVariant & json) { if (json.is()) { - // EMSESP::logger().debug(F("Masked entities json size: %d"), measureJson(json)); // find the device using the unique_id for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice) { uint8_t unique_device_id = json["id"]; if (emsdevice->unique_id() == unique_device_id) { - // build a list of entities - JsonArray entity_ids_json = json["entity_ids"]; - std::vector entity_ids; - for (const JsonVariant id : entity_ids_json) { - std::string entity_id = id.as(); - // set the new mask and add to the list of customized entities if the value is different from the default (mask == 0) - if (emsdevice->mask_entity(entity_id)) { - entity_ids.push_back(entity_id); - } - } - uint8_t product_id = emsdevice->product_id(); uint8_t device_id = emsdevice->device_id(); + // and set the mask immediately for the changed entities + JsonArray entity_ids_json = json["entity_ids"]; + for (const JsonVariant id : entity_ids_json) { + emsdevice->mask_entity(id.as()); + } + // Save the list to the customization file EMSESP::webCustomizationService.update( [&](WebCustomization & settings) { - // if it exists (productid and deviceid match) overwrite it - for (auto & entityCustomization : settings.entityCustomizations) { - 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 < entity_ids.size(); i++) { - entityCustomization.entity_ids.push_back(entity_ids[i]); - } - return StateUpdateResult::CHANGED; + // see if we already have a mask list for this device, if so remove it + for (auto it = settings.entityCustomizations.begin(); it != settings.entityCustomizations.end();) { + if ((*it).product_id == product_id && (*it).device_id == device_id) { + it = settings.entityCustomizations.erase(it); + break; + } else { + ++it; } } - // create a new entry in the list + + if (!entity_ids_json.size()) { + return StateUpdateResult::UNCHANGED; // nothing to add + } + + // create a new entry for this device if there are values EntityCustomization new_entry; new_entry.product_id = product_id; new_entry.device_id = device_id; - for (uint8_t i = 0; i < entity_ids.size(); i++) { - new_entry.entity_ids.push_back(entity_ids[i]); - } + + // get list of entities that have masks + std::vector entity_ids; + emsdevice->getMaskedEntities(entity_ids); + new_entry.entity_ids = entity_ids; + + // add the record and save settings.entityCustomizations.push_back(new_entry); return StateUpdateResult::CHANGED; },