From 1f1422bedd40a743a8a6ac9c0fb51c03e6ebf732 Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 28 Dec 2022 22:18:43 +0100 Subject: [PATCH 1/6] fix for #828 - show thermostat hc1 and mixer wwc --- src/devices/thermostat.cpp | 5 +++++ src/emsdevice.cpp | 4 ++++ src/emsdevicevalue.cpp | 2 +- src/emsesp.cpp | 9 ++++++++- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index e06823acc..20d49d7b4 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -194,6 +194,11 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i EMSESP::send_read_request(EMS_TYPE_RCTime, device_id); EMSESP::send_read_request(0x12, device_id); // read last error (only published on errors) EMSESP::send_read_request(0xA2, device_id); // read errorCode (only published on errors) + +#if defined(EMSESP_STANDALONE_DUMP) + // if we're just dumping out values, create a single dummy hc + register_device_values_hc(std::make_shared(1, 0)); // hc=1, no flags +#endif } // returns the heating circuit object based on the hc number diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 4d3cc0dd4..f89dcd66f 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -1067,6 +1067,10 @@ void EMSdevice::getCustomEntities(std::vector & entity_ids) { // device name,device type,product_id,shortname,fullname,type [(enum values) | (min/max)],uom,writeable,discovery_entityid void EMSdevice::dump_value_info() { for (auto & dv : devicevalues_) { + if (dv.fullname == nullptr) { + break; // ignore entities that don't have a fullname, like the thermostat climate thingy + } + Serial.print(name_); Serial.print(','); Serial.print(device_type_name().c_str()); diff --git a/src/emsdevicevalue.cpp b/src/emsdevicevalue.cpp index efa0b7ec1..12299d999 100644 --- a/src/emsdevicevalue.cpp +++ b/src/emsdevicevalue.cpp @@ -63,7 +63,7 @@ DeviceValue::DeviceValue(uint8_t device_type, // set the min/max set_custom_minmax(); -/* + /* #ifdef EMSESP_STANDALONE // only added for debugging Serial.print(COLOR_BRIGHT_RED_BACKGROUND); diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 63f2a3c00..8ebcc22db 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -320,7 +320,14 @@ void EMSESP::dump_all_values(uuid::console::Shell & shell) { // go through each device type so they are sorted for (const auto & device : device_library_) { if (device_class.first == device.device_type) { - emsdevices.push_back(EMSFactory::add(device.device_type, 0, device.product_id, "1.0", device.name, device.flags, EMSdevice::Brand::NO_BRAND)); + uint8_t device_id = 0; + // Mixer class looks at device_id to determine type, so fixing to 0x28 which will give all the settings except flowSetTemp + if ((device.device_type == DeviceType::MIXER) && (device.flags == EMSdevice::EMS_DEVICE_FLAG_MMPLUS)) { + device_id = 0x28; // hard code + } + + emsdevices.push_back( + EMSFactory::add(device.device_type, device_id, device.product_id, "1.0", device.name, device.flags, EMSdevice::Brand::NO_BRAND)); emsdevices.back()->dump_value_info(); // dump all the entity information } } From 6de577839b0767f1701a24c91c75c106c0bb87cb Mon Sep 17 00:00:00 2001 From: Proddy Date: Thu, 29 Dec 2022 22:01:48 +0100 Subject: [PATCH 2/6] update package --- interface/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/package.json b/interface/package.json index 862eb4655..3d885ba97 100644 --- a/interface/package.json +++ b/interface/package.json @@ -16,7 +16,7 @@ "@types/react-dom": "^18.0.10", "@types/react-router-dom": "^5.3.3", "async-validator": "^4.2.5", - "axios": "^1.2.1", + "axios": "^1.2.2", "http-proxy-middleware": "^2.0.6", "jwt-decode": "^3.1.2", "lodash": "^4.17.21", From 14cfbf78bd655caba7f78b9aecfe18b24666e601 Mon Sep 17 00:00:00 2001 From: Proddy Date: Thu, 29 Dec 2022 22:02:04 +0100 Subject: [PATCH 3/6] update package --- interface/package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/package-lock.json b/interface/package-lock.json index f07f3bc3f..02121819b 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -20,7 +20,7 @@ "@types/react-dom": "^18.0.10", "@types/react-router-dom": "^5.3.3", "async-validator": "^4.2.5", - "axios": "^1.2.1", + "axios": "^1.2.2", "http-proxy-middleware": "^2.0.6", "jwt-decode": "^3.1.2", "lodash": "^4.17.21", @@ -5081,9 +5081,9 @@ } }, "node_modules/axios": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz", - "integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.2.tgz", + "integrity": "sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", From 6dce5f5931d432b94ed7adb1ca60e28ca31c0b9a Mon Sep 17 00:00:00 2001 From: Proddy Date: Thu, 29 Dec 2022 22:02:36 +0100 Subject: [PATCH 4/6] more fixes for Create table of all EMS-ESP entities, by device, shortname/fullname and characteristics #828 --- src/devices/boiler.cpp | 1 + src/devices/thermostat.cpp | 2 +- src/emsdevice.cpp | 129 ++++++++++++++++++++----------------- src/emsesp.cpp | 9 ++- 4 files changed, 78 insertions(+), 63 deletions(-) diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index b842925e9..1ba1ff2bc 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -402,6 +402,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const 99); } */ + // heatpump info if (model() == EMS_DEVICE_FLAG_HEATPUMP) { register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 20d49d7b4..984285b8f 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -197,7 +197,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i #if defined(EMSESP_STANDALONE_DUMP) // if we're just dumping out values, create a single dummy hc - register_device_values_hc(std::make_shared(1, 0)); // hc=1, no flags + register_device_values_hc(std::make_shared(1, model)); // hc=1 #endif } diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index f89dcd66f..4f7062e87 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -1064,7 +1064,9 @@ void EMSdevice::getCustomEntities(std::vector & entity_ids) { #if defined(EMSESP_STANDALONE_DUMP) // dumps all entity values in native English -// device name,device type,product_id,shortname,fullname,type [(enum values) | (min/max)],uom,writeable,discovery_entityid +// the code is intended to run only once standalone, outside the ESP32 so not optimized for memory efficiency +// pipe symbols (|) are escaped so they can be converted to Markdown in the Wiki +// format is: device name,device type,product id,shortname,fullname,type [options...] \\| (min/max),uom,writeable,discovery entityid v3.4, discovery entityid void EMSdevice::dump_value_info() { for (auto & dv : devicevalues_) { if (dv.fullname == nullptr) { @@ -1085,33 +1087,25 @@ void EMSdevice::dump_value_info() { Serial.print(dv.fullname[0]); Serial.print(','); - // type and optional enum values and min/max + // per type switch (dv.type) { - case DeviceValueType::ENUM: { - Serial.print("enum"); - Serial.print(" ("); - for (uint8_t i = 0; i < dv.options_size; i++) { - Serial.print(Helpers::translated_word(dv.options[i])); - if (i < dv.options_size - 1) { - Serial.print('|'); - } + case DeviceValueType::ENUM: + case DeviceValueType::CMD: + if (dv.type == DeviceValueType::ENUM) { + Serial.print("enum"); + } else { + Serial.print("cmd"); } - Serial.print(')'); - break; - } - case DeviceValueType::CMD: { - Serial.print("cmd"); - Serial.print(" ("); + Serial.print(" ["); for (uint8_t i = 0; i < dv.options_size; i++) { - Serial.print(Helpers::translated_word(dv.options[i])); + Serial.print(dv.options[i][0]); if (i < dv.options_size - 1) { - Serial.print('|'); + Serial.print("\\|"); } } - Serial.print(')'); + Serial.print(']'); break; - } case DeviceValueType::USHORT: Serial.print("ushort"); @@ -1174,50 +1168,65 @@ void EMSdevice::dump_value_info() { Serial.print(dv.has_cmd ? "true" : "false"); Serial.print(","); - // MQTT Discovery entity name, assuming we're using the default v3.5 option - char entity_with_tag[50]; - if (dv.tag >= DeviceValueTAG::TAG_HC1) { - snprintf(entity_with_tag, - sizeof(entity_with_tag), - "%s_%s_%s", - device_type_2_device_name(device_type_), - EMSdevice::tag_to_mqtt(dv.tag).c_str(), - dv.short_name); - } else { - // should really test for which device types have tags (like hc, wwc etc) - // snprintf(entity_with_tag, sizeof(entity_with_tag), "%s_[_]%s", device_type_2_device_name(device_type_), dv.short_name); - snprintf(entity_with_tag, sizeof(entity_with_tag), "%s_%s", device_type_2_device_name(device_type_), dv.short_name); - } + // MQTT Discovery entity name + // do this twice for the old and new formats + char entity_with_tag[200]; + char entityid[500]; + char entity_name[100]; - char entityid[150]; - if (dv.has_cmd) { - switch (dv.type) { - case DeviceValueType::INT: - case DeviceValueType::UINT: - case DeviceValueType::SHORT: - case DeviceValueType::USHORT: - case DeviceValueType::ULONG: - snprintf(entityid, sizeof(entityid), "number.%s", entity_with_tag); - break; - case DeviceValueType::BOOL: - snprintf(entityid, sizeof(entityid), "switch.%s", entity_with_tag); - break; - case DeviceValueType::ENUM: - snprintf(entityid, sizeof(entityid), "select.%s", entity_with_tag); - break; - default: - snprintf(entityid, sizeof(entityid), "sensor.%s", entity_with_tag); - break; - } - } else { - if (dv.type == DeviceValueType::BOOL) { - snprintf(entityid, sizeof(entityid), "binary_sensor.%s", entity_with_tag); // binary sensor (for booleans) + for (uint8_t count = 0; count < 2; count++) { + if (count) { + // new name, comes as last + Serial.print(","); + strcpy(entity_name, dv.short_name); } else { - snprintf(entityid, sizeof(entityid), "sensor.%s", entity_with_tag); // normal HA sensor + // old format, comes first + char uniq_s[100]; + strlcpy(uniq_s, dv.fullname[0], sizeof(uniq_s)); + Helpers::replace_char(uniq_s, ' ', '_'); + strcpy(entity_name, uniq_s); } - } - Serial.print(entityid); + if (dv.tag >= DeviceValueTAG::TAG_HC1) { + snprintf(entity_with_tag, + sizeof(entity_with_tag), + "%s_%s_%s", + device_type_2_device_name(device_type_), + EMSdevice::tag_to_mqtt(dv.tag).c_str(), + entity_name); + } else { + snprintf(entity_with_tag, sizeof(entity_with_tag), "%s_%s", device_type_2_device_name(device_type_), entity_name); + } + + if (dv.has_cmd) { + switch (dv.type) { + case DeviceValueType::INT: + case DeviceValueType::UINT: + case DeviceValueType::SHORT: + case DeviceValueType::USHORT: + case DeviceValueType::ULONG: + snprintf(entityid, sizeof(entityid), "number.%s", entity_with_tag); + break; + case DeviceValueType::BOOL: + snprintf(entityid, sizeof(entityid), "switch.%s", entity_with_tag); + break; + case DeviceValueType::ENUM: + snprintf(entityid, sizeof(entityid), "select.%s", entity_with_tag); + break; + default: + snprintf(entityid, sizeof(entityid), "sensor.%s", entity_with_tag); + break; + } + } else { + if (dv.type == DeviceValueType::BOOL) { + snprintf(entityid, sizeof(entityid), "binary_sensor.%s", entity_with_tag); // binary sensor (for booleans) + } else { + snprintf(entityid, sizeof(entityid), "sensor.%s", entity_with_tag); // normal HA sensor + } + } + + Serial.print(entityid); + } Serial.println(); } diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 8ebcc22db..ee4c8f0ef 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -313,7 +313,7 @@ void EMSESP::show_ems(uuid::console::Shell & shell) { void EMSESP::dump_all_values(uuid::console::Shell & shell) { Serial.println("---- CSV START ----"); // marker use by py script // add header for CSV - Serial.print("device name,device type,product_id,shortname,fullname,type [(enum values) | (min/max)],uom,writeable,discovery_entityid"); + Serial.print("device name,device type,product id,shortname,fullname,type [options...] \\| (min/max),uom,writeable,discovery entityid v3.4, discovery entityid"); Serial.println(); for (const auto & device_class : EMSFactory::device_handlers()) { @@ -323,7 +323,12 @@ void EMSESP::dump_all_values(uuid::console::Shell & shell) { uint8_t device_id = 0; // Mixer class looks at device_id to determine type, so fixing to 0x28 which will give all the settings except flowSetTemp if ((device.device_type == DeviceType::MIXER) && (device.flags == EMSdevice::EMS_DEVICE_FLAG_MMPLUS)) { - device_id = 0x28; // hard code + // pick one as hc and the other as having wwc + if (device.product_id == 160) { // MM100 + device_id = 0x28; // wwc + } else { + device_id = 0x20; // hc + } } emsdevices.push_back( From 8eeebb0cef8a740e62f326e4759364bebd6d3b15 Mon Sep 17 00:00:00 2001 From: Proddy Date: Fri, 30 Dec 2022 11:50:52 +0100 Subject: [PATCH 5/6] use espressif32 5.2.0 - #862 --- pio_local.ini_example | 2 +- platformio.ini | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pio_local.ini_example b/pio_local.ini_example index 4a173ecae..cfa98cc78 100644 --- a/pio_local.ini_example +++ b/pio_local.ini_example @@ -37,7 +37,7 @@ extra_scripts = ; options for debugging are: EMSESP_DEBUG EMSESP_UART_DEBUG EMSESP_DEBUG_SENSOR [env:debug] board = esp32dev -platform = espressif32 +platform = espressif32@5.2.0 board_build.partitions = esp32_partition_debug.csv upload_protocol = esptool build_type = debug diff --git a/platformio.ini b/platformio.ini index 987ca1252..87989d63a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -56,7 +56,7 @@ check_flags = [env:ci] extra_scripts = scripts/rename_fw.py board = esp32dev -platform = espressif32 +platform = espressif32@5.2.0 board_build.partitions = esp32_partition_4M.csv board_build.filesystem = littlefs build_flags = ${common.build_flags} @@ -67,7 +67,7 @@ extra_scripts = pre:scripts/build_interface.py scripts/rename_fw.py board = esp32dev -platform = espressif32 +platform = espressif32@5.2.0 board_upload.flash_size = 4MB board_build.partitions = esp32_partition_4M.csv build_flags = ${common.build_flags} @@ -78,7 +78,7 @@ extra_scripts = pre:scripts/build_interface.py scripts/rename_fw.py board = esp32dev -platform = espressif32 +platform = espressif32@5.2.0 board_upload.flash_size = 16MB board_build.partitions = esp32_partition_16M.csv build_flags = ${common.build_flags} @@ -89,7 +89,7 @@ extra_scripts = pre:scripts/build_interface.py scripts/rename_fw.py board = lolin_c3_mini -platform = espressif32 +platform = espressif32@5.2.0 board_upload.flash_size = 4MB board_build.partitions = esp32_partition_4M.csv build_flags = ${common.build_flags} @@ -102,7 +102,7 @@ extra_scripts = pre:scripts/build_interface.py scripts/rename_fw.py board = lolin_c3_mini -platform = espressif32 +platform = espressif32@5.2.0 board_upload.flash_size = 4MB board_build.partitions = esp32_partition_4M.csv build_flags = ${common.build_flags} -DBOARD_C3_MINI_V1 @@ -113,7 +113,7 @@ extra_scripts = pre:scripts/build_interface.py scripts/rename_fw.py board = lolin_s2_mini -platform = espressif32 +platform = espressif32@5.2.0 board_upload.flash_size = 4MB board_build.partitions = esp32_partition_4M.csv build_flags = ${common.build_flags} From 263c011a7b597bf02ebedde8084404d3b7f3f37b Mon Sep 17 00:00:00 2001 From: Proddy Date: Fri, 30 Dec 2022 15:36:25 +0100 Subject: [PATCH 6/6] fix again for #828 --- src/devices/thermostat.cpp | 17 +- src/emsdevice.cpp | 354 ++++++++++++++++++------------------- src/emsesp.cpp | 3 +- 3 files changed, 185 insertions(+), 189 deletions(-) diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 984285b8f..f1e8474f1 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -26,8 +26,6 @@ uuid::log::Logger Thermostat::logger_{F_(thermostat), uuid::log::Facility::CONSO Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand) : EMSdevice(device_type, device_id, product_id, version, name, flags, brand) { - uint8_t model = this->model(); - // RF remote sensor seen at 0x40, maybe this is also for different hc with id 0x40 - 0x47? emsesp.cpp maps only 0x40 if (device_id >= 0x40 && device_id <= 0x47) { register_telegram_type(0x0435, "RFTemp", false, MAKE_PF_CB(process_RemoteTemp)); @@ -48,6 +46,9 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i register_telegram_type(0xA2, "RCError", false, MAKE_PF_CB(process_RCError)); register_telegram_type(0x12, "RCErrorMessage", false, MAKE_PF_CB(process_RCErrorMessage)); register_telegram_type(0x13, "RCErrorMessage2", false, MAKE_PF_CB(process_RCErrorMessage)); + + uint8_t model = this->model(); + // RC10 if (model == EMSdevice::EMS_DEVICE_FLAG_RC10) { monitor_typeids = {0xB1}; @@ -194,11 +195,6 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i EMSESP::send_read_request(EMS_TYPE_RCTime, device_id); EMSESP::send_read_request(0x12, device_id); // read last error (only published on errors) EMSESP::send_read_request(0xA2, device_id); // read errorCode (only published on errors) - -#if defined(EMSESP_STANDALONE_DUMP) - // if we're just dumping out values, create a single dummy hc - register_device_values_hc(std::make_shared(1, model)); // hc=1 -#endif } // returns the heating circuit object based on the hc number @@ -3389,6 +3385,7 @@ void Thermostat::register_device_values() { register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &errorCode_, DeviceValueType::STRING, FL_(errorCode), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &lastCode_, DeviceValueType::STRING, FL_(lastCode), DeviceValueUOM::NONE); + switch (this->model()) { case EMS_DEVICE_FLAG_RC100: case EMS_DEVICE_FLAG_RC300: @@ -4013,6 +4010,11 @@ void Thermostat::register_device_values() { register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, FL_(dateTime), DeviceValueUOM::NONE); // can't set datetime break; } + +#if defined(EMSESP_STANDALONE_DUMP) + // if we're just dumping out values, create a single dummy hc + register_device_values_hc(std::make_shared(1, this->model())); // hc=1 +#endif } // registers the values for a heating circuit @@ -4036,6 +4038,7 @@ void Thermostat::register_device_values_hc(std::shared_ptrselTemp, DeviceValueType::SHORT, seltemp_divider, FL_(selRoomTemp), DeviceValueUOM::DEGREES); } else { diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 4f7062e87..12df734e1 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -431,17 +431,6 @@ void EMSdevice::add_device_value(uint8_t tag, const cmd_function_p f, int16_t min, uint16_t max) { - bool has_cmd = (f != nullptr); - - auto short_name = name[0]; - - const char * const * fullname; - if (Helpers::count_items(name) == 1) { - fullname = nullptr; // no translations available, use empty to prevent crash - } else { - fullname = &name[1]; // translations start at index 1 - } - // initialize the device value depending on it's type // ignoring DeviceValueType::CMD and DeviceValueType::TIME if (type == DeviceValueType::STRING) { @@ -462,11 +451,18 @@ void EMSdevice::add_device_value(uint8_t tag, *(uint8_t *)(value_p) = EMS_VALUE_DEFAULT_ENUM; // enums behave as uint8_t } - // determine state - uint8_t state = DeviceValueState::DV_DEFAULT; + uint8_t state = DeviceValueState::DV_DEFAULT; // determine state + std::string custom_fullname = std::string(""); // custom fullname + auto short_name = name[0]; // entity name + bool has_cmd = (f != nullptr); // is it a command? - // custom fullname - std::string custom_fullname = std::string(""); + // get fullname, getting translation if it exists + const char * const * fullname; + if (Helpers::count_items(name) == 1) { + fullname = nullptr; // no translations available, use empty to prevent crash + } else { + fullname = &name[1]; // translations start at index 1 + } // scan through customizations to see if it's on the exclusion list by matching the productID and deviceID EMSESP::webCustomizationService.read([&](WebCustomization & settings) { @@ -506,22 +502,20 @@ void EMSdevice::add_device_value(uint8_t tag, device_type_, tag, value_p, type, options, options_single, numeric_operator, short_name, fullname, custom_fullname, uom, has_cmd, min, max, state); // add a new command if it has a function attached - if (!has_cmd) { - return; + if (has_cmd) { + uint8_t flags = CommandFlag::ADMIN_ONLY; // executing commands require admin privileges + + if (tag >= DeviceValueTAG::TAG_HC1 && tag <= DeviceValueTAG::TAG_HC8) { + flags |= CommandFlag::MQTT_SUB_FLAG_HC; + } else if (tag >= DeviceValueTAG::TAG_WWC1 && tag <= DeviceValueTAG::TAG_WWC10) { + flags |= CommandFlag::MQTT_SUB_FLAG_WWC; + } else if (tag == DeviceValueTAG::TAG_DEVICE_DATA_WW || tag == DeviceValueTAG::TAG_BOILER_DATA_WW) { + flags |= CommandFlag::MQTT_SUB_FLAG_WW; + } + + // add the command to our library + Command::add(device_type_, device_id_, short_name, f, fullname, flags); } - - uint8_t flags = CommandFlag::ADMIN_ONLY; // executing commands require admin privileges - - if (tag >= DeviceValueTAG::TAG_HC1 && tag <= DeviceValueTAG::TAG_HC8) { - flags |= CommandFlag::MQTT_SUB_FLAG_HC; - } else if (tag >= DeviceValueTAG::TAG_WWC1 && tag <= DeviceValueTAG::TAG_WWC10) { - flags |= CommandFlag::MQTT_SUB_FLAG_WWC; - } else if (tag == DeviceValueTAG::TAG_DEVICE_DATA_WW || tag == DeviceValueTAG::TAG_BOILER_DATA_WW) { - flags |= CommandFlag::MQTT_SUB_FLAG_WW; - } - - // add the command to our library - Command::add(device_type_, device_id_, short_name, f, fullname, flags); } // single list of options @@ -1069,166 +1063,164 @@ void EMSdevice::getCustomEntities(std::vector & entity_ids) { // format is: device name,device type,product id,shortname,fullname,type [options...] \\| (min/max),uom,writeable,discovery entityid v3.4, discovery entityid void EMSdevice::dump_value_info() { for (auto & dv : devicevalues_) { - if (dv.fullname == nullptr) { - break; // ignore entities that don't have a fullname, like the thermostat climate thingy - } + if (dv.fullname != nullptr) { + Serial.print(name_); + Serial.print(','); + Serial.print(device_type_name().c_str()); + Serial.print(','); - Serial.print(name_); - Serial.print(','); - Serial.print(device_type_name().c_str()); - Serial.print(','); + Serial.print(product_id_); + Serial.print(','); - Serial.print(product_id_); - Serial.print(','); + Serial.print(dv.short_name); + Serial.print(','); - Serial.print(dv.short_name); - Serial.print(','); + Serial.print(dv.fullname[0]); + Serial.print(','); - Serial.print(dv.fullname[0]); - Serial.print(','); - - // per type - switch (dv.type) { - case DeviceValueType::ENUM: - case DeviceValueType::CMD: - if (dv.type == DeviceValueType::ENUM) { - Serial.print("enum"); - } else { - Serial.print("cmd"); - } - - Serial.print(" ["); - for (uint8_t i = 0; i < dv.options_size; i++) { - Serial.print(dv.options[i][0]); - if (i < dv.options_size - 1) { - Serial.print("\\|"); - } - } - Serial.print(']'); - break; - - case DeviceValueType::USHORT: - Serial.print("ushort"); - break; - - case DeviceValueType::UINT: - Serial.print("uint"); - break; - - case DeviceValueType::SHORT: - Serial.print("short"); - break; - - case DeviceValueType::INT: - Serial.print("int"); - break; - - case DeviceValueType::ULONG: - Serial.print("ulong"); - break; - - case DeviceValueType::BOOL: - Serial.print("boolean"); - break; - - case DeviceValueType::TIME: - Serial.print("time"); - break; - - case DeviceValueType::STRING: - Serial.print("string"); - break; - - default: - break; - } - - // min/max range - int16_t dv_set_min; - uint16_t dv_set_max; - if (dv.get_min_max(dv_set_min, dv_set_max)) { - Serial.print(" (>="); - Serial.print(dv_set_min); - Serial.print("<="); - Serial.print(dv_set_max); - Serial.print(")"); - } - - Serial.print(","); - - // uom - if (dv.uom == DeviceValue::DeviceValueUOM::DEGREES || dv.uom == DeviceValue::DeviceValueUOM::DEGREES_R) { - Serial.print('C'); // the degrees symbol doesn't print nicely in XLS - } else { - Serial.print(DeviceValue::DeviceValueUOM_s[dv.uom]); - } - Serial.print(","); - - // writeable flag - Serial.print(dv.has_cmd ? "true" : "false"); - Serial.print(","); - - // MQTT Discovery entity name - // do this twice for the old and new formats - char entity_with_tag[200]; - char entityid[500]; - char entity_name[100]; - - for (uint8_t count = 0; count < 2; count++) { - if (count) { - // new name, comes as last - Serial.print(","); - strcpy(entity_name, dv.short_name); - } else { - // old format, comes first - char uniq_s[100]; - strlcpy(uniq_s, dv.fullname[0], sizeof(uniq_s)); - Helpers::replace_char(uniq_s, ' ', '_'); - strcpy(entity_name, uniq_s); - } - - if (dv.tag >= DeviceValueTAG::TAG_HC1) { - snprintf(entity_with_tag, - sizeof(entity_with_tag), - "%s_%s_%s", - device_type_2_device_name(device_type_), - EMSdevice::tag_to_mqtt(dv.tag).c_str(), - entity_name); - } else { - snprintf(entity_with_tag, sizeof(entity_with_tag), "%s_%s", device_type_2_device_name(device_type_), entity_name); - } - - if (dv.has_cmd) { - switch (dv.type) { - case DeviceValueType::INT: - case DeviceValueType::UINT: - case DeviceValueType::SHORT: - case DeviceValueType::USHORT: - case DeviceValueType::ULONG: - snprintf(entityid, sizeof(entityid), "number.%s", entity_with_tag); - break; - case DeviceValueType::BOOL: - snprintf(entityid, sizeof(entityid), "switch.%s", entity_with_tag); - break; - case DeviceValueType::ENUM: - snprintf(entityid, sizeof(entityid), "select.%s", entity_with_tag); - break; - default: - snprintf(entityid, sizeof(entityid), "sensor.%s", entity_with_tag); - break; - } - } else { - if (dv.type == DeviceValueType::BOOL) { - snprintf(entityid, sizeof(entityid), "binary_sensor.%s", entity_with_tag); // binary sensor (for booleans) + // per type + switch (dv.type) { + case DeviceValueType::ENUM: + case DeviceValueType::CMD: + if (dv.type == DeviceValueType::ENUM) { + Serial.print("enum"); } else { - snprintf(entityid, sizeof(entityid), "sensor.%s", entity_with_tag); // normal HA sensor + Serial.print("cmd"); } + + Serial.print(" ["); + for (uint8_t i = 0; i < dv.options_size; i++) { + Serial.print(dv.options[i][0]); + if (i < dv.options_size - 1) { + Serial.print("\\|"); + } + } + Serial.print(']'); + break; + + case DeviceValueType::USHORT: + Serial.print("ushort"); + break; + + case DeviceValueType::UINT: + Serial.print("uint"); + break; + + case DeviceValueType::SHORT: + Serial.print("short"); + break; + + case DeviceValueType::INT: + Serial.print("int"); + break; + + case DeviceValueType::ULONG: + Serial.print("ulong"); + break; + + case DeviceValueType::BOOL: + Serial.print("boolean"); + break; + + case DeviceValueType::TIME: + Serial.print("time"); + break; + + case DeviceValueType::STRING: + Serial.print("string"); + break; + + default: + break; } - Serial.print(entityid); - } + // min/max range + int16_t dv_set_min; + uint16_t dv_set_max; + if (dv.get_min_max(dv_set_min, dv_set_max)) { + Serial.print(" (>="); + Serial.print(dv_set_min); + Serial.print("<="); + Serial.print(dv_set_max); + Serial.print(")"); + } + Serial.print(","); - Serial.println(); + // uom + if (dv.uom == DeviceValue::DeviceValueUOM::DEGREES || dv.uom == DeviceValue::DeviceValueUOM::DEGREES_R) { + Serial.print('C'); // the degrees symbol doesn't print nicely in XLS + } else { + Serial.print(DeviceValue::DeviceValueUOM_s[dv.uom]); + } + Serial.print(","); + + // writeable flag + Serial.print(dv.has_cmd ? "true" : "false"); + Serial.print(","); + + // MQTT Discovery entity name + // do this twice for the old and new formats + char entity_with_tag[200]; + char entityid[500]; + char entity_name[100]; + + + for (uint8_t count = 0; count < 2; count++) { + if (count) { + // new name, comes as last + Serial.print(","); + strcpy(entity_name, dv.short_name); + } else { + // old format, comes first + char uniq_s[100]; + strlcpy(uniq_s, dv.fullname[0], sizeof(uniq_s)); + Helpers::replace_char(uniq_s, ' ', '_'); + strcpy(entity_name, uniq_s); + } + + if (dv.tag >= DeviceValueTAG::TAG_HC1) { + snprintf(entity_with_tag, + sizeof(entity_with_tag), + "%s_%s_%s", + device_type_2_device_name(device_type_), + EMSdevice::tag_to_mqtt(dv.tag).c_str(), + entity_name); + } else { + snprintf(entity_with_tag, sizeof(entity_with_tag), "%s_%s", device_type_2_device_name(device_type_), entity_name); + } + + if (dv.has_cmd) { + switch (dv.type) { + case DeviceValueType::INT: + case DeviceValueType::UINT: + case DeviceValueType::SHORT: + case DeviceValueType::USHORT: + case DeviceValueType::ULONG: + snprintf(entityid, sizeof(entityid), "number.%s", entity_with_tag); + break; + case DeviceValueType::BOOL: + snprintf(entityid, sizeof(entityid), "switch.%s", entity_with_tag); + break; + case DeviceValueType::ENUM: + snprintf(entityid, sizeof(entityid), "select.%s", entity_with_tag); + break; + default: + snprintf(entityid, sizeof(entityid), "sensor.%s", entity_with_tag); + break; + } + } else { + if (dv.type == DeviceValueType::BOOL) { + snprintf(entityid, sizeof(entityid), "binary_sensor.%s", entity_with_tag); // binary sensor (for booleans) + } else { + snprintf(entityid, sizeof(entityid), "sensor.%s", entity_with_tag); // normal HA sensor + } + } + + Serial.print(entityid); + } + + Serial.println(); + } } } #endif diff --git a/src/emsesp.cpp b/src/emsesp.cpp index ee4c8f0ef..2ecc0301e 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -313,7 +313,8 @@ void EMSESP::show_ems(uuid::console::Shell & shell) { void EMSESP::dump_all_values(uuid::console::Shell & shell) { Serial.println("---- CSV START ----"); // marker use by py script // add header for CSV - Serial.print("device name,device type,product id,shortname,fullname,type [options...] \\| (min/max),uom,writeable,discovery entityid v3.4, discovery entityid"); + Serial.print( + "device name,device type,product id,shortname,fullname,type [options...] \\| (min/max),uom,writeable,discovery entityid v3.4, discovery entityid"); Serial.println(); for (const auto & device_class : EMSFactory::device_handlers()) {