diff --git a/interface/src/project/SettingsCustomization.tsx b/interface/src/project/SettingsCustomization.tsx index 0dd054888..247d9fd1c 100644 --- a/interface/src/project/SettingsCustomization.tsx +++ b/interface/src/project/SettingsCustomization.tsx @@ -260,7 +260,7 @@ const SettingsCustomization: FC = () => { } try { - const response = await EMSESP.writeMaskedEntities({ + const response = await EMSESP.writeCustomEntities({ id: devices?.devices[selectedDevice].i, entity_ids: masked_entities }); diff --git a/interface/src/project/api.ts b/interface/src/project/api.ts index d6804cda4..266338214 100644 --- a/interface/src/project/api.ts +++ b/interface/src/project/api.ts @@ -12,7 +12,7 @@ import { DeviceData, DeviceEntity, UniqueID, - MaskedEntities, + CustomEntities, WriteValue, WriteSensor, WriteAnalog, @@ -63,8 +63,8 @@ export function readDeviceEntities(unique_id: UniqueID): AxiosPromise { - return AXIOS.post('/maskedEntities', maskedEntities); +export function writeCustomEntities(customEntities: CustomEntities): AxiosPromise { + return AXIOS.post('/customEntities', customEntities); } export function writeValue(writevalue: WriteValue): AxiosPromise { diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts index 648d6c908..7cac14bd7 100644 --- a/interface/src/project/types.ts +++ b/interface/src/project/types.ts @@ -144,7 +144,7 @@ export interface DeviceEntity { w: boolean; // writeable } -export interface MaskedEntities { +export interface CustomEntities { id: number; entity_ids: string[]; } diff --git a/mock-api/server.js b/mock-api/server.js index df672c133..b5e353ff9 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -302,7 +302,7 @@ const EMSESP_BOARDPROFILE_ENDPOINT = REST_ENDPOINT_ROOT + 'boardProfile' const EMSESP_WRITE_VALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeValue' const EMSESP_WRITE_SENSOR_ENDPOINT = REST_ENDPOINT_ROOT + 'writeSensor' const EMSESP_WRITE_ANALOG_ENDPOINT = REST_ENDPOINT_ROOT + 'writeAnalog' -const EMSESP_MASKED_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'maskedEntities' +const EMSESP_CUSTOM_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'customEntities' const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'resetCustomizations' settings = { @@ -978,7 +978,7 @@ function updateMask(entity, de, dd) { } } -rest_server.post(EMSESP_MASKED_ENTITIES_ENDPOINT, (req, res) => { +rest_server.post(EMSESP_CUSTOM_ENTITIES_ENDPOINT, (req, res) => { const id = req.body.id console.log('customization id = ' + id) console.log(req.body.entity_ids) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index cb5408b1b..8ac30c9db 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -37,18 +37,18 @@ void AnalogSensor::start() { EMSdevice::DeviceType::ANALOGSENSOR, F_(info), [&](const char * value, const int8_t id, JsonObject & output) { return command_info(value, id, output); }, - F_(info_cmd)); + uuid::read_flash_string(F_(info_cmd))); Command::add( EMSdevice::DeviceType::ANALOGSENSOR, F_(setvalue), [&](const char * value, const int8_t id) { return command_setvalue(value, id); }, - F("set io value"), + "set io value", // TODO this needs translating CommandFlag::ADMIN_ONLY); Command::add( EMSdevice::DeviceType::ANALOGSENSOR, F_(commands), [&](const char * value, const int8_t id, JsonObject & output) { return command_commands(value, id, output); }, - F_(commands_cmd)); + uuid::read_flash_string(F_(commands_cmd))); Mqtt::subscribe(EMSdevice::DeviceType::ANALOGSENSOR, "analogsensor/#", nullptr); // use empty function callback } diff --git a/src/command.cpp b/src/command.cpp index b4583c5cb..6b2a8291f 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -264,15 +264,15 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * if ((value == nullptr) || (strlen(value) == 0)) { if (EMSESP::system_.readonly_mode()) { - LOG_INFO(F("[readonly] Calling command '%s/%s' (%s)"), dname.c_str(), cmd, read_flash_string(cf->description_).c_str()); + LOG_INFO(F("[readonly] Calling command '%s/%s' (%s)"), dname.c_str(), cmd, cf->description_.c_str()); } else { - LOG_DEBUG(F("Calling command '%s/%s' (%s)"), dname.c_str(), cmd, read_flash_string(cf->description_).c_str()); + LOG_DEBUG(F("Calling command '%s/%s' (%s)"), dname.c_str(), cmd, cf->description_.c_str()); } } else { if (EMSESP::system_.readonly_mode()) { - LOG_INFO(F("[readonly] Calling command '%s/%s' (%s) with value %s"), dname.c_str(), cmd, read_flash_string(cf->description_).c_str(), value); + LOG_INFO(F("[readonly] Calling command '%s/%s' (%s) with value %s"), dname.c_str(), cmd, cf->description_.c_str(), value); } else { - LOG_DEBUG(F("Calling command '%s/%s' (%s) with value %s"), dname.c_str(), cmd, read_flash_string(cf->description_).c_str(), value); + LOG_DEBUG(F("Calling command '%s/%s' (%s) with value %s"), dname.c_str(), cmd, cf->description_.c_str(), value); } } @@ -299,14 +299,14 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * } // add a command to the list, which does not return json -void Command::add(const uint8_t device_type, const __FlashStringHelper * cmd, const cmd_function_p cb, const __FlashStringHelper * description, uint8_t flags) { +void Command::add(const uint8_t device_type, const __FlashStringHelper * cmd, const cmd_function_p cb, const std::string & description, uint8_t flags) { // if the command already exists for that device type don't add it if (find_command(device_type, read_flash_string(cmd).c_str()) != nullptr) { return; } // if the description is empty, it's hidden which means it will not show up in Web API or Console as an available command - if (description == nullptr) { + if (description.empty()) { flags |= CommandFlag::HIDDEN; } @@ -314,7 +314,7 @@ void Command::add(const uint8_t device_type, const __FlashStringHelper * cmd, co } // add a command to the list, which does return a json object as output -void Command::add(const uint8_t device_type, const __FlashStringHelper * cmd, const cmd_json_function_p cb, const __FlashStringHelper * description, uint8_t flags) { +void Command::add(const uint8_t device_type, const __FlashStringHelper * cmd, const cmd_json_function_p cb, const std::string & description, uint8_t flags) { // if the command already exists for that device type don't add it if (find_command(device_type, read_flash_string(cmd).c_str()) != nullptr) { return; @@ -364,7 +364,7 @@ bool Command::list(const uint8_t device_type, JsonObject & output) { for (const auto & cl : sorted_cmds) { for (const auto & cf : cmdfunctions_) { - if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && cf.description_ && (cl == read_flash_string(cf.cmd_))) { + if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && !cf.description_.empty() && (cl == read_flash_string(cf.cmd_))) { output[cl] = cf.description_; } } @@ -404,7 +404,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo for (const auto & cl : sorted_cmds) { // find and print the description for (const auto & cf : cmdfunctions_) { - if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && cf.description_ && (cl == read_flash_string(cf.cmd_))) { + if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && !cf.description_.empty() && (cl == read_flash_string(cf.cmd_))) { uint8_t i = cl.length(); shell.print(" "); if (cf.has_flags(MQTT_SUB_FLAG_HC)) { @@ -424,7 +424,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo shell.print(EMSdevice::tag_to_string(DeviceValueTAG::TAG_DEVICE_DATA_WW)); shell.print(' '); } - shell.print(read_flash_string(cf.description_)); + shell.print(cf.description_.c_str()); if (!cf.has_flags(CommandFlag::ADMIN_ONLY)) { shell.print(' '); shell.print(COLOR_BRIGHT_RED); diff --git a/src/command.h b/src/command.h index e12eab87a..87a55d472 100644 --- a/src/command.h +++ b/src/command.h @@ -59,14 +59,14 @@ class Command { const __FlashStringHelper * cmd_; const cmd_function_p cmdfunction_; const cmd_json_function_p cmdfunction_json_; - const __FlashStringHelper * description_; + const std::string description_; CmdFunction(const uint8_t device_type, const uint8_t flags, const __FlashStringHelper * cmd, const cmd_function_p cmdfunction, const cmd_json_function_p cmdfunction_json, - const __FlashStringHelper * description) + const std::string & description) : device_type_(device_type) , flags_(flags) , cmd_(cmd) @@ -102,14 +102,14 @@ class Command { static void add(const uint8_t device_type, const __FlashStringHelper * cmd, const cmd_function_p cb, - const __FlashStringHelper * description, + const std::string & description, uint8_t flags = CommandFlag::MQTT_SUB_FLAG_DEFAULT); // callback function taking value, id and a json object for its output static void add(const uint8_t device_type, const __FlashStringHelper * cmd, const cmd_json_function_p cb, - const __FlashStringHelper * description, + const std::string & description, uint8_t flags = CommandFlag::MQTT_SUB_FLAG_DEFAULT); static void show_all(uuid::console::Shell & shell); diff --git a/src/dallassensor.cpp b/src/dallassensor.cpp index 030ad5474..1a66688b8 100644 --- a/src/dallassensor.cpp +++ b/src/dallassensor.cpp @@ -50,12 +50,12 @@ void DallasSensor::start() { EMSdevice::DeviceType::DALLASSENSOR, F_(info), [&](const char * value, const int8_t id, JsonObject & output) { return command_info(value, id, output); }, - F_(info_cmd)); + uuid::read_flash_string(F_(info_cmd))); Command::add( EMSdevice::DeviceType::DALLASSENSOR, F_(commands), [&](const char * value, const int8_t id, JsonObject & output) { return command_commands(value, id, output); }, - F_(commands_cmd)); + uuid::read_flash_string(F_(commands_cmd))); Mqtt::subscribe(EMSdevice::DeviceType::DALLASSENSOR, "dallasssensor/#", nullptr); // use empty function callback } diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index fba59676d..a376e9bce 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -444,13 +444,13 @@ void EMSdevice::add_device_value(uint8_t tag, for (std::string entity_id : entityCustomization.entity_ids) { // if there is an appended custom name, strip it to get the true entity name // and extract the new custom name - std::string matched_entity; + std::string shortname; auto custom_name_pos = entity_id.find('|'); bool has_custom_name = (custom_name_pos != std::string::npos); if (has_custom_name) { - matched_entity = entity_id.substr(2, custom_name_pos - 2); + shortname = entity_id.substr(2, custom_name_pos - 2); } else { - matched_entity = entity_id.substr(2); + shortname = entity_id.substr(2); } /* @@ -465,7 +465,7 @@ void EMSdevice::add_device_value(uint8_t tag, */ // we found the device entity - if (matched_entity == entity) { + if (shortname == entity) { // get Mask uint8_t mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); state = mask << 4; // set state high bits to flag, turn off active and ha flags @@ -506,8 +506,7 @@ void EMSdevice::add_device_value(uint8_t tag, // add the command to our library // cmd is the short_name and the description is the fullname - // TODO this needs adapting to take the custom fullname since its not a FPTR() - Command::add(device_type_, short_name, f, Helpers::translated_fword(fullname), flags); + Command::add(device_type_, short_name, f, Helpers::translated_word(fullname), flags); } // single list of options @@ -989,34 +988,59 @@ void EMSdevice::generate_values_web_customization(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) -void EMSdevice::mask_entity(const std::string & entity_id) { +void EMSdevice::setCustomEntity(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); - if (entity_name == entity_id.substr(2)) { - // this entity has a new mask set + + // extra shortname + std::string shortname; + auto custom_name_pos = entity_id.find('|'); + bool has_custom_name = (custom_name_pos != std::string::npos); + if (has_custom_name) { + shortname = entity_id.substr(2, custom_name_pos - 2); + } else { + shortname = entity_id.substr(2); + } + + if (entity_name == shortname) { + // check the masks 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 it's a new mask, reconfigure HA 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) } + + // always write the mask dv.state = ((dv.state & 0x0F) | (new_mask << 4)); // set state high bits to flag + + // set the custom name if it has one + if (has_custom_name) { + dv.custom_fullname = entity_id.substr(custom_name_pos + 1); + } + return; } } } -// populate a string vector with entities that have masks set -void EMSdevice::getMaskedEntities(std::vector & entity_ids) { +// populate a string vector with entities that have masks set or have a custom name +void EMSdevice::getCustomEntities(std::vector & entity_ids) { for (const 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); + if (mask || !dv.custom_fullname.empty()) { + if (dv.custom_fullname.empty()) { + entity_ids.push_back(Helpers::hextoa(mask, false) + entity_name); + } else { + entity_ids.push_back(Helpers::hextoa(mask, false) + entity_name + "|" + dv.custom_fullname); + } } } } diff --git a/src/emsdevice.h b/src/emsdevice.h index d9bf4af37..0ff13ba38 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -187,8 +187,8 @@ class EMSdevice { void list_device_entries(JsonObject & output) const; void add_handlers_ignored(const uint16_t handler); - void mask_entity(const std::string & entity_id); - void getMaskedEntities(std::vector & entity_ids); + void setCustomEntity(const std::string & entity_id); + void getCustomEntities(std::vector & entity_ids); using process_function_p = std::function)>; diff --git a/src/emsdevicevalue.cpp b/src/emsdevicevalue.cpp index d40a97d5c..649d4fff8 100644 --- a/src/emsdevicevalue.cpp +++ b/src/emsdevicevalue.cpp @@ -32,7 +32,7 @@ DeviceValue::DeviceValue(uint8_t device_type, int8_t numeric_operator, const __FlashStringHelper * const short_name, const __FlashStringHelper * const * fullname, - const std::string & custom_fullname, + std::string & custom_fullname, uint8_t uom, bool has_cmd, int16_t min, diff --git a/src/emsdevicevalue.h b/src/emsdevicevalue.h index a3419262e..6420692fa 100644 --- a/src/emsdevicevalue.h +++ b/src/emsdevicevalue.h @@ -153,7 +153,7 @@ class DeviceValue { uint8_t options_size; // number of options in the char array, calculated const __FlashStringHelper * const short_name; // used in MQTT and API const __FlashStringHelper * const * fullname; // used in Web and Console, is translated - const std::string custom_fullname; // optional, from customization + std::string custom_fullname; // optional, from customization uint8_t uom; // DeviceValueUOM::* bool has_cmd; // true if there is a Console/MQTT command which matches the short_name int16_t min; // min range @@ -169,7 +169,7 @@ class DeviceValue { int8_t numeric_operator, const __FlashStringHelper * const short_name, const __FlashStringHelper * const * fullname, - const std::string & custom_fullname, + std::string & custom_fullname, uint8_t uom, bool has_cmd, int16_t min, diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 5d5ced4fc..e095eeb4b 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -1052,25 +1052,25 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const [device_type](const char * value, const int8_t id, JsonObject & output) { return command_info(device_type, output, id, EMSdevice::OUTPUT_TARGET::API_VERBOSE); }, - F_(info_cmd)); + uuid::read_flash_string(F_(info_cmd))); Command::add( device_type, F("values"), [device_type](const char * value, const int8_t id, JsonObject & output) { return command_info(device_type, output, id, EMSdevice::OUTPUT_TARGET::API_SHORTNAMES); // HIDDEN command showing short names, used in e.g. /api/boiler }, - nullptr, + "", CommandFlag::HIDDEN); // this command is hidden Command::add( device_type, F_(commands), [device_type](const char * value, const int8_t id, JsonObject & output) { return command_commands(device_type, output, id); }, - F_(commands_cmd)); + uuid::read_flash_string(F_(commands_cmd))); Command::add( device_type, F_(entities), [device_type](const char * value, const int8_t id, JsonObject & output) { return command_entities(device_type, output, id); }, - F_(entities_cmd)); + uuid::read_flash_string(F_(entities_cmd))); // MQTT subscribe to the device e.g. "ems-esp/boiler/#" Mqtt::subscribe(device_type, EMSdevice::device_type_2_device_name(device_type) + "/#", nullptr); diff --git a/src/mqtt.cpp b/src/mqtt.cpp index bf2bd1850..1198ca6ec 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -958,7 +958,7 @@ void Mqtt::publish_system_ha_sensor_config(uint8_t type, const __FlashStringHelp JsonArray ids = dev_json.createNestedArray("ids"); ids.add("ems-esp"); - auto fullname = read_flash_string(name); // TODO make sure it works, it may need a std::move()? + auto fullname = read_flash_string(name); publish_ha_sensor_config(type, DeviceValueTAG::TAG_HEARTBEAT, fullname, EMSdevice::DeviceType::SYSTEM, entity, uom, false, false, nullptr, 0, 0, 0, dev_json); } diff --git a/src/system.cpp b/src/system.cpp index 0b763649e..18cedfc1a 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -291,7 +291,8 @@ void System::syslog_init() { syslog_.hostname(hostname().c_str()); // register the command - Command::add(EMSdevice::DeviceType::SYSTEM, F_(syslog), System::command_syslog_level, F("change the syslog level"), CommandFlag::ADMIN_ONLY); + // TODO translate this + Command::add(EMSdevice::DeviceType::SYSTEM, F_(syslog), System::command_syslog_level, "change the syslog level", CommandFlag::ADMIN_ONLY); } else if (was_enabled) { // in case service is still running, this flushes the queue @@ -695,23 +696,26 @@ void System::system_check() { // commands - takes static function pointers void System::commands_init() { // Command::add(EMSdevice::DeviceType::SYSTEM, F_(pin), System::command_pin, F("set a GPIO on/off"), CommandFlag::ADMIN_ONLY); - Command::add(EMSdevice::DeviceType::SYSTEM, F_(send), System::command_send, F("send a telegram"), CommandFlag::ADMIN_ONLY); - Command::add(EMSdevice::DeviceType::SYSTEM, F_(fetch), System::command_fetch, F("refresh all EMS values"), CommandFlag::ADMIN_ONLY); - Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, F("restart EMS-ESP"), CommandFlag::ADMIN_ONLY); - Command::add(EMSdevice::DeviceType::SYSTEM, F_(watch), System::command_watch, F("watch incoming telegrams")); + + // TODO these should be translated too + Command::add(EMSdevice::DeviceType::SYSTEM, F_(send), System::command_send, "send a telegram", CommandFlag::ADMIN_ONLY); + Command::add(EMSdevice::DeviceType::SYSTEM, F_(fetch), System::command_fetch, "refresh all EMS values", CommandFlag::ADMIN_ONLY); + Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, "restart EMS-ESP", CommandFlag::ADMIN_ONLY); + Command::add(EMSdevice::DeviceType::SYSTEM, F_(watch), System::command_watch, "watch incoming telegrams"); + // register syslog command in syslog init // Command::add(EMSdevice::DeviceType::SYSTEM, F_(syslog), System::command_syslog_level, F("set syslog level"), CommandFlag::ADMIN_ONLY); if (Mqtt::enabled()) { - Command::add(EMSdevice::DeviceType::SYSTEM, F_(publish), System::command_publish, F("force a MQTT publish")); + Command::add(EMSdevice::DeviceType::SYSTEM, F_(publish), System::command_publish, "force a MQTT publish"); } // these commands will return data in JSON format - Command::add(EMSdevice::DeviceType::SYSTEM, F_(info), System::command_info, F("show system status")); - Command::add(EMSdevice::DeviceType::SYSTEM, F_(commands), System::command_commands, F("fetch system commands")); + Command::add(EMSdevice::DeviceType::SYSTEM, F_(info), System::command_info, "show system status"); + Command::add(EMSdevice::DeviceType::SYSTEM, F_(commands), System::command_commands, "fetch system commands"); #if defined(EMSESP_DEBUG) - Command::add(EMSdevice::DeviceType::SYSTEM, F("test"), System::command_test, F("run a specific test")); + Command::add(EMSdevice::DeviceType::SYSTEM, F("test"), System::command_test, "run a specific test"); #endif // MQTT subscribe "ems-esp/system/#" diff --git a/src/test/test.cpp b/src/test/test.cpp index 6a553d902..349a95f6f 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -616,7 +616,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice->unique_id() == 1) { // boiler std::string a = "07wwseltemp"; - emsdevice->mask_entity(a); + emsdevice->setCustomEntity(a); break; } } diff --git a/src/web/WebCustomizationService.cpp b/src/web/WebCustomizationService.cpp index a8f5cef9f..5a641e91a 100644 --- a/src/web/WebCustomizationService.cpp +++ b/src/web/WebCustomizationService.cpp @@ -31,8 +31,8 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f securityManager, AuthenticationPredicates::IS_AUTHENTICATED) , _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE) - , _masked_entities_handler(MASKED_ENTITIES_PATH, - securityManager->wrapCallback(std::bind(&WebCustomizationService::masked_entities, this, _1, _2), + , _masked_entities_handler(CUSTOM_ENTITIES_PATH, + securityManager->wrapCallback(std::bind(&WebCustomizationService::custom_entities, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED)) , _device_entities_handler(DEVICE_ENTITIES_PATH, securityManager->wrapCallback(std::bind(&WebCustomizationService::device_entities, this, _1, _2), @@ -85,6 +85,7 @@ void WebCustomization::read(WebCustomization & settings, JsonObject & root) { entityJson["product_id"] = entityCustomization.product_id; entityJson["device_id"] = entityCustomization.device_id; + // entries are in the form [|optional customname] e.g "08heatingactive|heating is on" JsonArray masked_entityJson = entityJson.createNestedArray("entity_ids"); for (std::string entity_id : entityCustomization.entity_ids) { masked_entityJson.add(entity_id); @@ -97,9 +98,8 @@ void WebCustomization::read(WebCustomization & settings, JsonObject & root) { StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & settings) { #ifdef EMSESP_STANDALONE // invoke some fake data for testing - // using https://arduinojson.org/v5/assistant/ - const char * json = - "{\"sensors\":[],\"analogs\":[],\"masked_entities\":[{\"product_id\":123,\"device_id\":8,\"entity_ids\":[\"08heatingactive|my custom name for heating active\",\"08tapwateractive\"]}]}"; + const char * json = "{\"sensors\":[],\"analogs\":[],\"masked_entities\":[{\"product_id\":123,\"device_id\":8,\"entity_ids\":[\"08heatingactive|my custom " + "name for heating active\",\"08tapwateractive\"]}]}"; StaticJsonDocument<500> doc; deserializeJson(doc, json); @@ -222,7 +222,7 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request, J // 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) { +void WebCustomizationService::custom_entities(AsyncWebServerRequest * request, JsonVariant & json) { if (json.is()) { // find the device using the unique_id for (const auto & emsdevice : EMSESP::emsdevices) { @@ -232,10 +232,10 @@ void WebCustomizationService::masked_entities(AsyncWebServerRequest * request, J uint8_t product_id = emsdevice->product_id(); uint8_t device_id = emsdevice->device_id(); - // and set the mask immediately for the changed entities + // and set the mask and custom names immediately for any listed entities JsonArray entity_ids_json = json["entity_ids"]; for (const JsonVariant id : entity_ids_json) { - emsdevice->mask_entity(id.as()); + emsdevice->setCustomEntity(id.as()); } // Save the list to the customization file @@ -260,9 +260,9 @@ void WebCustomizationService::masked_entities(AsyncWebServerRequest * request, J new_entry.product_id = product_id; new_entry.device_id = device_id; - // get list of entities that have masks + // get list of entities that have masks set or a custom fullname std::vector entity_ids; - emsdevice->getMaskedEntities(entity_ids); + emsdevice->getCustomEntities(entity_ids); new_entry.entity_ids = entity_ids; // add the record and save diff --git a/src/web/WebCustomizationService.h b/src/web/WebCustomizationService.h index d595c1f43..e5d7a9512 100644 --- a/src/web/WebCustomizationService.h +++ b/src/web/WebCustomizationService.h @@ -27,7 +27,7 @@ // POST #define DEVICE_ENTITIES_PATH "/rest/deviceEntities" -#define MASKED_ENTITIES_PATH "/rest/maskedEntities" +#define CUSTOM_ENTITIES_PATH "/rest/customEntities" #define RESET_CUSTOMIZATION_SERVICE_PATH "/rest/resetCustomizations" namespace emsesp { @@ -63,7 +63,7 @@ class EntityCustomization { public: uint8_t product_id; // device's product id uint8_t device_id; // device's device id - std::vector entity_ids; // array of entity ids with masks + std::vector entity_ids; // array of entity ids with masks and optional custom fullname }; class WebCustomization { @@ -93,7 +93,7 @@ class WebCustomizationService : public StatefulService { void devices(AsyncWebServerRequest * request); // POST - void masked_entities(AsyncWebServerRequest * request, JsonVariant & json); + void custom_entities(AsyncWebServerRequest * request, JsonVariant & json); void device_entities(AsyncWebServerRequest * request, JsonVariant & json); void reset_customization(AsyncWebServerRequest * request);