From f081d7fd3c880f7a667efa048e3b28d840dacb34 Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 10 Oct 2022 20:09:29 +0200 Subject: [PATCH 1/7] remove TODO --- lib/uuid-syslog/src/syslog.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/uuid-syslog/src/syslog.cpp b/lib/uuid-syslog/src/syslog.cpp index 2d9bcd4e8..327b0c7d7 100644 --- a/lib/uuid-syslog/src/syslog.cpp +++ b/lib/uuid-syslog/src/syslog.cpp @@ -443,7 +443,6 @@ bool SyslogService::transmit(const QueuedLogMessage & message) { udp_.print('-'); } - // TODO should use flash? udp_.printf_P(PSTR(" %s %s - - - "), hostname_.c_str(), (message.content_->name)); char id_c_str[15]; From 9adfa0ecfcc4828fd7626e1f690cbadfed54419e Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 10 Oct 2022 20:10:01 +0200 Subject: [PATCH 2/7] use const char * where possible --- src/command.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index ae4c7137f..d5426c7f2 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -238,7 +238,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * value, const bool is_admin, const int8_t id, JsonObject & output) { uint8_t return_code = CommandRet::OK; - std::string dname = EMSdevice::device_type_2_device_name(device_type); + auto dname = EMSdevice::device_type_2_device_name(device_type); // see if there is a command registered auto cf = find_command(device_type, cmd); @@ -248,7 +248,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * if ((device_type > EMSdevice::DeviceType::SYSTEM) && (!value || !strlen(value))) { if (!cf || !cf->cmdfunction_json_) { #if defined(EMSESP_DEBUG) - LOG_DEBUG("[DEBUG] Calling %s command '%s' to retrieve attributes", dname.c_str(), cmd); + LOG_DEBUG("[DEBUG] Calling %s command '%s' to retrieve attributes", dname, cmd); #endif return EMSESP::get_device_value_info(output, cmd, id, device_type) ? CommandRet::OK : CommandRet::ERROR; // entity = cmd } @@ -262,17 +262,19 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * return CommandRet::NOT_ALLOWED; // command not allowed } + auto description = Helpers::translated_word(cf->description_); + if ((value == nullptr) || (strlen(value) == 0)) { if (EMSESP::system_.readonly_mode()) { - LOG_INFO(("[readonly] Calling command '%s/%s' (%s)"), dname.c_str(), cmd, cf->description_); + LOG_INFO(("[readonly] Calling command '%s/%s' (%s)"), dname, cmd, description); } else { - LOG_DEBUG(("Calling command '%s/%s' (%s)"), dname.c_str(), cmd, cf->description_); + LOG_DEBUG(("Calling command '%s/%s' (%s)"), dname, cmd, description); } } else { if (EMSESP::system_.readonly_mode()) { - LOG_INFO(("[readonly] Calling command '%s/%s' (%s) with value %s"), dname.c_str(), cmd, cf->description_, value); + LOG_INFO(("[readonly] Calling command '%s/%s' (%s) with value %s"), dname, cmd, description, value); } else { - LOG_DEBUG(("Calling command '%s/%s' (%s) with value %s"), dname.c_str(), cmd, cf->description_, value); + LOG_DEBUG(("Calling command '%s/%s' (%s) with value %s"), dname, cmd, description, value); } } @@ -365,7 +367,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 == std::string(cf.cmd_))) { - output[cl] = Helpers::translated_fullname(cf.description_); + output[cl] = Helpers::translated_word(cf.description_); } } } @@ -424,7 +426,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(Helpers::translated_fullname(cf.description_)); + shell.print(Helpers::translated_word(cf.description_)); if (!cf.has_flags(CommandFlag::ADMIN_ONLY)) { shell.print(' '); shell.print(COLOR_BRIGHT_RED); @@ -474,19 +476,19 @@ bool Command::device_has_commands(const uint8_t device_type) { // list sensors and EMS devices void Command::show_devices(uuid::console::Shell & shell) { - shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM).c_str()); + shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM)); if (EMSESP::dallassensor_.have_sensors()) { - shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::DALLASSENSOR).c_str()); + shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::DALLASSENSOR)); } if (EMSESP::analogsensor_.have_sensors()) { - shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR).c_str()); + shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR)); } for (const auto & device_class : EMSFactory::device_handlers()) { for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice && (emsdevice->device_type() == device_class.first) && (device_has_commands(device_class.first))) { - shell.printf("%s ", EMSdevice::device_type_2_device_name(device_class.first).c_str()); + shell.printf("%s ", EMSdevice::device_type_2_device_name(device_class.first)); break; // we only want to show one (not multiple of the same device types) } } @@ -502,7 +504,7 @@ void Command::show_all(uuid::console::Shell & shell) { // show system first shell.print(COLOR_BOLD_ON); shell.print(COLOR_YELLOW); - shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM).c_str()); + shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM)); shell.print(COLOR_RESET); show(shell, EMSdevice::DeviceType::SYSTEM, true); @@ -510,14 +512,14 @@ void Command::show_all(uuid::console::Shell & shell) { if (EMSESP::dallassensor_.have_sensors()) { shell.print(COLOR_BOLD_ON); shell.print(COLOR_YELLOW); - shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::DALLASSENSOR).c_str()); + shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::DALLASSENSOR)); shell.print(COLOR_RESET); show(shell, EMSdevice::DeviceType::DALLASSENSOR, true); } if (EMSESP::analogsensor_.have_sensors()) { shell.print(COLOR_BOLD_ON); shell.print(COLOR_YELLOW); - shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR).c_str()); + shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR)); shell.print(COLOR_RESET); show(shell, EMSdevice::DeviceType::ANALOGSENSOR, true); } @@ -527,7 +529,7 @@ void Command::show_all(uuid::console::Shell & shell) { if (Command::device_has_commands(device_class.first)) { shell.print(COLOR_BOLD_ON); shell.print(COLOR_YELLOW); - shell.printf(" %s: ", EMSdevice::device_type_2_device_name(device_class.first).c_str()); + shell.printf(" %s: ", EMSdevice::device_type_2_device_name(device_class.first)); shell.print(COLOR_RESET); show(shell, device_class.first, true); } From 3afbe832cc45e1c2faafc6b86f7c08dc214ff4c8 Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 10 Oct 2022 20:10:20 +0200 Subject: [PATCH 3/7] don't use translations for commands in console --- src/console.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/console.cpp b/src/console.cpp index 5530f4808..948bd7e1f 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -277,15 +277,16 @@ void EMSESPShell::add_console_commands() { [](Shell & shell, const std::vector & arguments) { uint16_t watch_id = WATCH_ID_NONE; + // only use english commands, not the translations if (!arguments.empty()) { // get raw/pretty if (arguments[0] == (F_(raw))) { EMSESP::watch(EMSESP::WATCH_RAW); // raw - } else if (arguments[0] == Helpers::translated_word(FL_(on), true) || arguments[0] == (FL_(on)[0])) { + } else if (arguments[0] == (FL_(on)[0])) { EMSESP::watch(EMSESP::WATCH_ON); // on - } else if (arguments[0] == Helpers::translated_word(FL_(off), true) || arguments[0] == (FL_(off)[0])) { + } else if (arguments[0] == (FL_(off)[0])) { EMSESP::watch(EMSESP::WATCH_OFF); // off - } else if (arguments[0] == Helpers::translated_word(FL_(unknown), true) || arguments[0] == (FL_(unknown)[0])) { + } else if (arguments[0] == (FL_(unknown)[0])) { EMSESP::watch(EMSESP::WATCH_UNKNOWN); // unknown watch_id = WATCH_ID_NONE; } else { From b67113fc1f0f2425043893d37ece71a793527c61 Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 10 Oct 2022 20:11:23 +0200 Subject: [PATCH 4/7] use const char * where possible --- src/devices/boiler.cpp | 2 +- src/emsdevice.cpp | 24 +++++++++++------------ src/emsdevice.h | 10 +++++----- src/emsdevicevalue.cpp | 4 ++-- src/emsesp.cpp | 5 +++-- src/helpers.cpp | 44 +++++++++++++++--------------------------- src/helpers.h | 4 +--- src/mqtt.cpp | 22 +++++++++++---------- 8 files changed, 52 insertions(+), 63 deletions(-) diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index e35571d5f..938dfd859 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -2227,7 +2227,7 @@ bool Boiler::set_maintenance(const char * value, const int8_t id) { std::string s; if (Helpers::value2string(value, s)) { - if (s == Helpers::translated_word(FL_(reset))) { + if (s == std::string(Helpers::translated_word(FL_(reset)))) { // LOG_INFO("Reset boiler maintenance message"); write_command(0x05, 0x08, 0xFF, 0x1C); return true; diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 7fdb48186..58400dbc1 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -81,7 +81,7 @@ std::string EMSdevice::brand_to_string() const { } // returns the name of the MQTT topic to use for a specific device, without the base -std::string EMSdevice::device_type_2_device_name(const uint8_t device_type) { +const char * EMSdevice::device_type_2_device_name(const uint8_t device_type) { switch (device_type) { case DeviceType::SYSTEM: return (F_(system)); @@ -259,7 +259,7 @@ bool EMSdevice::has_tag(const uint8_t tag) const { // called from the command 'entities' void EMSdevice::list_device_entries(JsonObject & output) const { for (const auto & dv : devicevalues_) { - std::string fullname = dv.get_fullname(); + auto fullname = dv.get_fullname(); if (!dv.has_state(DeviceValueState::DV_WEB_EXCLUDE) && dv.type != DeviceValueType::CMD && !fullname.empty()) { // if we have a tag prefix it char key[50]; @@ -637,9 +637,9 @@ void EMSdevice::publish_value(void * value_p) const { char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; if (Mqtt::publish_single2cmd()) { if (dv.tag >= DeviceValueTAG::TAG_HC1) { - snprintf(topic, sizeof(topic), "%s/%s/%s", device_type_2_device_name(device_type_).c_str(), tag_to_mqtt(dv.tag).c_str(), (dv.short_name)); + snprintf(topic, sizeof(topic), "%s/%s/%s", device_type_2_device_name(device_type_), tag_to_mqtt(dv.tag).c_str(), (dv.short_name)); } else { - snprintf(topic, sizeof(topic), "%s/%s", device_type_2_device_name(device_type_).c_str(), (dv.short_name)); + snprintf(topic, sizeof(topic), "%s/%s", device_type_2_device_name(device_type_), (dv.short_name)); } } else if (Mqtt::is_nested() && dv.tag >= DeviceValueTAG::TAG_HC1) { snprintf(topic, sizeof(topic), "%s/%s/%s", Mqtt::tag_to_topic(device_type_, dv.tag).c_str(), tag_to_mqtt(dv.tag).c_str(), (dv.short_name)); @@ -662,7 +662,7 @@ void EMSdevice::publish_value(void * value_p) const { Helpers::render_value(payload, *(uint8_t *)(value_p), 0); } else { auto enum_str = Helpers::translated_word(dv.options[*(uint8_t *)(value_p)]); - strlcpy(payload, enum_str.c_str(), sizeof(payload)); + strlcpy(payload, enum_str, sizeof(payload)); } } break; @@ -823,7 +823,7 @@ void EMSdevice::generate_values_web(JsonObject & output) { JsonArray l = obj.createNestedArray("l"); for (uint8_t i = 0; i < dv.options_size; i++) { auto enum_str = Helpers::translated_word(dv.options[i]); - if (!enum_str.empty()) { + if (enum_str) { l.add(enum_str); } } @@ -917,12 +917,12 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) { // don't add the fullname if its a command auto fullname = Helpers::translated_word(dv.fullname); if (dv.type != DeviceValueType::CMD) { - if (!fullname.empty()) { + if (fullname) { if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) { obj["n"] = fullname; } else { char name[50]; - snprintf(name, sizeof(name), "%s %s", tag_to_string(dv.tag).c_str(), fullname.c_str()); + snprintf(name, sizeof(name), "%s %s", tag_to_string(dv.tag).c_str(), fullname); obj["n"] = name; } } @@ -933,7 +933,7 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) { obj["cn"] = custom_fullname; } } else { - obj["n"] = "!" + fullname; // prefix commands with a ! + obj["n"] = "!" + std::string(fullname); // prefix commands with a ! } // add the custom name, is optional @@ -1362,11 +1362,11 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c sizeof(time_s), "%d %s %d %s %d %s", (time_value / 1440), - Helpers::translated_word(FL_(days)).c_str(), + Helpers::translated_word(FL_(days)), ((time_value % 1440) / 60), - Helpers::translated_word(FL_(hours)).c_str(), + Helpers::translated_word(FL_(hours)), (time_value % 60), - Helpers::translated_word(FL_(minutes)).c_str()); + Helpers::translated_word(FL_(minutes))); json[name] = time_s; } else { json[name] = time_value; diff --git a/src/emsdevice.h b/src/emsdevice.h index d4ea9ad0d..6a582e982 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -46,11 +46,11 @@ class EMSdevice { std::string device_type_name() const; - static std::string device_type_2_device_name(const uint8_t device_type); - static uint8_t device_name_2_device_type(const char * topic); - static std::string uom_to_string(uint8_t uom); - static std::string tag_to_string(uint8_t tag); - static std::string tag_to_mqtt(uint8_t tag); + static const char * device_type_2_device_name(const uint8_t device_type); + static uint8_t device_name_2_device_type(const char * topic); + static std::string uom_to_string(uint8_t uom); + static std::string tag_to_string(uint8_t tag); + static std::string tag_to_mqtt(uint8_t tag); bool has_tag(const uint8_t tag) const; diff --git a/src/emsdevicevalue.cpp b/src/emsdevicevalue.cpp index 87452232c..538930b70 100644 --- a/src/emsdevicevalue.cpp +++ b/src/emsdevicevalue.cpp @@ -74,7 +74,7 @@ DeviceValue::DeviceValue(uint8_t device_type, Serial.print(custom_fullname.c_str()); Serial.print(COLOR_RESET); } else { - Serial.print(Helpers::translated_word(fullname).c_str()); + Serial.print(Helpers::translated_word(fullname)); } Serial.print(" (#options="); Serial.print(options_size); @@ -88,7 +88,7 @@ DeviceValue::DeviceValue(uint8_t device_type, Serial.print(i + 1); Serial.print(":"); auto str = Helpers::translated_word(options[i]); - Serial.print((str.c_str())); + Serial.print(str); i++; } } else if (options_single != nullptr) { diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 9e12cb41c..e20342e2d 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -1039,7 +1039,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const fetch_device_values(device_id); // go and fetch its data // Print to LOG showing we've added a new device - LOG_INFO("Recognized new %s with deviceID 0x%02X", EMSdevice::device_type_2_device_name(device_type).c_str(), device_id); + LOG_INFO("Recognized new %s with deviceID 0x%02X", EMSdevice::device_type_2_device_name(device_type), device_id); // add command commands for all devices, except for connect, controller and gateway if ((device_type == DeviceType::CONNECT) || (device_type == DeviceType::CONTROLLER) || (device_type == DeviceType::GATEWAY)) { @@ -1073,7 +1073,8 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const FL_(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); + auto topic = std::string(EMSdevice::device_type_2_device_name(device_type)) + "/#"; + Mqtt::subscribe(device_type, topic, nullptr); return true; } diff --git a/src/helpers.cpp b/src/helpers.cpp index 2a248bce2..ce2ea6eb3 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -179,9 +179,9 @@ char * Helpers::render_boolean(char * result, const bool value, const bool dashb uint8_t bool_format_ = dashboard ? EMSESP::system_.bool_dashboard() : EMSESP::system_.bool_format(); if (bool_format_ == BOOL_FORMAT_ONOFF_STR) { - strlcpy(result, value ? translated_word(FL_(on)).c_str() : translated_word(FL_(off)).c_str(), 5); + strlcpy(result, value ? translated_word(FL_(on)) : translated_word(FL_(off)), 5); } else if (bool_format_ == BOOL_FORMAT_ONOFF_STR_CAP) { - strlcpy(result, value ? translated_word(FL_(ON)).c_str() : translated_word(FL_(OFF)).c_str(), 5); + strlcpy(result, value ? translated_word(FL_(ON)) : translated_word(FL_(OFF)), 5); } else if ((bool_format_ == BOOL_FORMAT_10) || (bool_format_ == BOOL_FORMAT_10_STR)) { strlcpy(result, value ? "1" : "0", 2); } else { @@ -593,12 +593,12 @@ bool Helpers::value2bool(const char * value, bool & value_b) { std::string bool_str = toLower(value); // convert to lower case - if ((bool_str == Helpers::translated_word(FL_(on))) || (bool_str == "on") || (bool_str == "1") || (bool_str == "true")) { + if ((bool_str == std::string(Helpers::translated_word(FL_(on)))) || (bool_str == "on") || (bool_str == "1") || (bool_str == "true")) { value_b = true; return true; // is a bool } - if ((bool_str == Helpers::translated_word(FL_(off))) || (bool_str == "off") || (bool_str == "0") || (bool_str == "false")) { + if ((bool_str == std::string(Helpers::translated_word(FL_(off)))) || (bool_str == "off") || (bool_str == "0") || (bool_str == "false")) { value_b = false; return true; // is a bool } @@ -615,7 +615,7 @@ bool Helpers::value2enum(const char * value, uint8_t & value_ui, const char * co std::string str = toLower(value); for (value_ui = 0; strs[value_ui]; value_ui++) { - std::string str1 = toLower(Helpers::translated_word(strs[value_ui])); + std::string str1 = toLower(std::string(Helpers::translated_word(strs[value_ui]))); std::string str2 = toLower((strs[value_ui][0])); // also check for default language if ((str1 != "") && ((str2 == "off" && str == "false") || (str2 == "on" && str == "true") || (str == str1) || (str == str2) @@ -627,19 +627,25 @@ bool Helpers::value2enum(const char * value, uint8_t & value_ui, const char * co return false; } -// checks to see if a string is member of a vector and return the index, also allow true/false for on/off +// finds the string (value) of a list vector (strs) +// returns true if found, and sets the value_ui to the index, else false +// also allow true/false for on/off bool Helpers::value2enum(const char * value, uint8_t & value_ui, const char * const * strs) { if ((value == nullptr) || (strlen(value) == 0)) { return false; } std::string str = toLower(value); + std::string s_on = Helpers::translated_word(FL_(on)); + std::string s_off = Helpers::translated_word(FL_(off)); + + // stops when a nullptr is found, which is the end delimeter of a MAKE_PSTR_LIST() + // could use count_items() to avoid buffer over-run but this works for (value_ui = 0; strs[value_ui]; value_ui++) { std::string enum_str = toLower((strs[value_ui])); if ((enum_str != "") - && ((enum_str == "off" && (str == Helpers::translated_word(FL_(off)) || str == "false")) - || (enum_str == "on" && (str == Helpers::translated_word(FL_(on)) || str == "true")) || (str == enum_str) + && ((enum_str == "off" && (str == s_off || str == "false")) || (enum_str == "on" && (str == s_on || str == "true")) || (str == enum_str) || (value[0] == ('0' + value_ui) && value[1] == '\0'))) { return true; } @@ -702,31 +708,13 @@ uint8_t Helpers::count_items(const char * const ** list) { return list_size; } -// return translated string as a std::string, optionally converting to lowercase (for console commands) -std::string Helpers::translated_word(const char * const * strings, bool to_lower) { - uint8_t language_index = EMSESP::system_.language_index(); - uint8_t index = 0; - - // check for empty - if (!strings) { - return ""; // it's a nullptr with no translations, return empty to prevent unwanted crash - } - - // see how many translations we have for this entity. if there is no translation for this, revert to EN - if (Helpers::count_items(strings) >= language_index + 1 && strlen(strings[language_index])) { - index = language_index; - } - return to_lower ? toLower((strings[index])) : (strings[index]); -} - // returns char pointer to translated description or fullname -const char * Helpers::translated_fullname(const char * const * strings) { +const char * Helpers::translated_word(const char * const * strings) { uint8_t language_index = EMSESP::system_.language_index(); uint8_t index = 0; - // check for empty if (!strings) { - return nullptr; // it's a nullptr with no translations, return empty to prevent unwanted crash + return ""; // no translations } // see how many translations we have for this entity. if there is no translation for this, revert to EN diff --git a/src/helpers.h b/src/helpers.h index 0c164f283..95fa7a5db 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -77,9 +77,7 @@ class Helpers { static uint8_t count_items(const char * const ** list); static uint8_t count_items(const char * const * list); - static std::string translated_word(const char * const * strings, bool to_lower = false); - static const char * translated_fullname(const char * const * strings); - + static const char * translated_word(const char * const * strings); #ifdef EMSESP_STANDALONE static char * ultostr(char * ptr, uint32_t value, const uint8_t base); diff --git a/src/mqtt.cpp b/src/mqtt.cpp index b04ae6cf4..74a6385d8 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -899,15 +899,16 @@ void Mqtt::publish_ha_sensor_config(DeviceValue & dv, const std::string & model, StaticJsonDocument dev_json; // always create the ids - JsonArray ids = dev_json.createNestedArray("ids"); - char ha_device[40]; - std::string device_type_name = EMSdevice::device_type_2_device_name(dv.device_type); - snprintf(ha_device, sizeof(ha_device), "ems-esp-%s", device_type_name.c_str()); + JsonArray ids = dev_json.createNestedArray("ids"); + char ha_device[40]; + auto device_type_name = EMSdevice::device_type_2_device_name(dv.device_type); + snprintf(ha_device, sizeof(ha_device), "ems-esp-%s", device_type_name); ids.add(ha_device); if (create_device_config) { - device_type_name[0] = toupper(device_type_name[0]); // capitalize - dev_json["name"] = "EMS-ESP " + device_type_name; + auto cap_name = strdup(device_type_name); + cap_name[0] = toupper(cap_name[0]); // capitalize + dev_json["name"] = std::string("EMS-ESP ") + cap_name; dev_json["mf"] = brand; dev_json["mdl"] = model; dev_json["via_device"] = "ems-esp"; @@ -972,8 +973,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdevice } // create the device name - char device_name[50]; - strlcpy(device_name, EMSdevice::device_type_2_device_name(device_type).c_str(), sizeof(device_name)); + auto device_name = EMSdevice::device_type_2_device_name(device_type); // create entity by add the hc/wwc tag if present, separating with a . char new_entity[50]; @@ -1341,11 +1341,13 @@ std::string Mqtt::tag_to_topic(uint8_t device_type, uint8_t tag) { return EMSdevice::tag_to_mqtt(tag); } + std::string topic = EMSdevice::device_type_2_device_name(device_type); + // if there is a tag add it if (!EMSdevice::tag_to_mqtt(tag).empty() && ((tag == DeviceValueTAG::TAG_BOILER_DATA_WW) || (!is_nested() && tag >= DeviceValueTAG::TAG_HC1))) { - return EMSdevice::device_type_2_device_name(device_type) + "_data_" + EMSdevice::tag_to_mqtt(tag); + return topic + "_data_" + EMSdevice::tag_to_mqtt(tag); } else { - return EMSdevice::device_type_2_device_name(device_type) + "_data"; + return topic + "_data"; } } From 008903cbbd01c56ad30d4d8c1d2ffb8ad1746789 Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 10 Oct 2022 20:12:16 +0200 Subject: [PATCH 5/7] optimize set_mode command --- src/devices/thermostat.cpp | 131 +++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 70 deletions(-) diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 543099b3a..70361777b 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -594,7 +594,6 @@ void Thermostat::process_RC20Timer(std::shared_ptr telegram) { // we use EN settings for the day abbreviation std::string sday = (FL_(enum_dayOfWeek)[day][0]); - // std::string sday = Helpers::translated_word(FL_(enum_dayOfWeek)[day]); if (day == 7) { snprintf(data, sizeof(data), "%02d not_set", no); @@ -802,19 +801,10 @@ void Thermostat::process_RC35wwTimer(std::shared_ptr telegram) { char data[sizeof(wwSwitchTime_)]; // we use EN settings for the day abbreviation std::string sday = (FL_(enum_dayOfWeek)[day][0]); - // std::string sday = Helpers::translated_word(FL_(enum_dayOfWeek)[day]); if (day == 7) { snprintf(data, sizeof(data), "%02d not_set", no); } else { - snprintf(data, - sizeof(data), - "%02d %s %02d:%02d %s", - no, - sday.c_str(), - time / 6, - 10 * (time % 6), - // on ? (Helpers::translated_word(FL_(on))).c_str() : (Helpers::translated_word(FL_(off))).c_str()); - on ? "on" : "off"); + snprintf(data, sizeof(data), "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off"); } if (telegram->type_id == 0x38) { has_update(wwSwitchTime_, data, sizeof(wwSwitchTime_)); @@ -1281,7 +1271,6 @@ void Thermostat::process_RC35Timer(std::shared_ptr telegram) { // we use EN settings for the day abbreviation std::string sday = (FL_(enum_dayOfWeek)[day][0]); - // std::string sday = Helpers::translated_word(FL_(enum_dayOfWeek)[day]); if (day == 7) { snprintf(data, sizeof(data), "%02d not_set", no); } else if (model() == EMS_DEVICE_FLAG_RC30) { @@ -2220,82 +2209,93 @@ bool Thermostat::set_roominfl_factor(const char * value, const int8_t id) { return true; } -// sets the thermostat working mode, where mode is a string -// converts string mode to HeatingCircuit::Mode +// sets the thermostat working mode bool Thermostat::set_mode(const char * value, const int8_t id) { if ((value == nullptr) || (strlen(value) >= 20)) { return false; } - std::string mode; - - if (value[0] >= '0' && value[0] <= '9') { - uint8_t num = value[0] - '0'; - switch (model()) { - case EMSdevice::EMS_DEVICE_FLAG_RC10: - mode = Helpers::translated_word(FL_(enum_mode6)[num], true); - break; - case EMSdevice::EMS_DEVICE_FLAG_RC20: - case EMSdevice::EMS_DEVICE_FLAG_RC20_N: - mode = Helpers::translated_word(FL_(enum_mode2)[num], true); - break; - case EMSdevice::EMS_DEVICE_FLAG_RC25: - case EMSdevice::EMS_DEVICE_FLAG_RC30: - case EMSdevice::EMS_DEVICE_FLAG_RC35: - case EMSdevice::EMS_DEVICE_FLAG_RC30_N: - mode = Helpers::translated_word(FL_(enum_mode3)[num], true); - break; - case EMSdevice::EMS_DEVICE_FLAG_RC300: - case EMSdevice::EMS_DEVICE_FLAG_RC100: - mode = Helpers::translated_word(FL_(enum_mode)[num], true); - break; - case EMSdevice::EMS_DEVICE_FLAG_JUNKERS: - mode = Helpers::translated_word(FL_(enum_mode4)[num], true); - break; - case EMSdevice::EMS_DEVICE_FLAG_CRF: - mode = Helpers::translated_word(FL_(enum_mode5)[num], true); - break; - default: - return false; - } - } else if (!Helpers::value2string(value, mode)) { + // first determine which enum we are using + const char * const ** mode_list = nullptr; // points to a translated list of modes + switch (model()) { + case EMSdevice::EMS_DEVICE_FLAG_RC10: + mode_list = FL_(enum_mode6); + break; + case EMSdevice::EMS_DEVICE_FLAG_RC20: + case EMSdevice::EMS_DEVICE_FLAG_RC20_N: + mode_list = FL_(enum_mode2); + break; + case EMSdevice::EMS_DEVICE_FLAG_RC25: + case EMSdevice::EMS_DEVICE_FLAG_RC30: + case EMSdevice::EMS_DEVICE_FLAG_RC35: + case EMSdevice::EMS_DEVICE_FLAG_RC30_N: + mode_list = FL_(enum_mode3); + break; + case EMSdevice::EMS_DEVICE_FLAG_RC300: + case EMSdevice::EMS_DEVICE_FLAG_RC100: + mode_list = FL_(enum_mode); + break; + case EMSdevice::EMS_DEVICE_FLAG_JUNKERS: + mode_list = FL_(enum_mode4); + break; + case EMSdevice::EMS_DEVICE_FLAG_CRF: + mode_list = FL_(enum_mode5); + break; + default: return false; } - uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; + uint8_t enum_index = 0; - if (Helpers::translated_word(FL_(off), true) == mode) { - return set_mode_n(HeatingCircuit::Mode::OFF, hc_num); + // check for a mode number as a string with a single digit (0..9) + if (value[0] >= '0' && value[0] <= '9') { + enum_index = value[0] - '0'; + if (enum_index >= Helpers::count_items(mode_list)) { + return false; // invalid number, not in enum + } + } else { + // check for the mode being a full string name + if (!Helpers::value2enum(value, enum_index, mode_list)) { + return false; // not found + } } - if (Helpers::translated_word(FL_(manual), true) == mode) { - return set_mode_n(HeatingCircuit::Mode::MANUAL, hc_num); - } - if (Helpers::translated_word(FL_(auto), true) == mode) { + + uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; // heating circuit + + // compare the english string + auto mode = mode_list[enum_index][0]; + if (!strcmp(mode, FL_(auto)[0])) { return set_mode_n(HeatingCircuit::Mode::AUTO, hc_num); } - if (Helpers::translated_word(FL_(day), true) == mode) { + if (!strcmp(mode, FL_(off)[0])) { + return set_mode_n(HeatingCircuit::Mode::OFF, hc_num); + } + if (!strcmp(mode, FL_(manual)[0])) { + return set_mode_n(HeatingCircuit::Mode::MANUAL, hc_num); + } + if (!strcmp(mode, FL_(day)[0])) { return set_mode_n(HeatingCircuit::Mode::DAY, hc_num); } - if (Helpers::translated_word(FL_(night), true) == mode) { + if (!strcmp(mode, FL_(night)[0])) { return set_mode_n(HeatingCircuit::Mode::NIGHT, hc_num); } - if (Helpers::translated_word(FL_(heat), true) == mode) { + if (!strcmp(mode, FL_(heat)[0])) { return set_mode_n(HeatingCircuit::Mode::HEAT, hc_num); } - if (Helpers::translated_word(FL_(nofrost), true) == mode) { + if (!strcmp(mode, FL_(nofrost)[0])) { return set_mode_n(HeatingCircuit::Mode::NOFROST, hc_num); } - if (Helpers::translated_word(FL_(eco), true) == mode) { + if (!strcmp(mode, FL_(eco)[0])) { return set_mode_n(HeatingCircuit::Mode::ECO, hc_num); } - if (Helpers::translated_word(FL_(holiday), true) == mode) { + if (!strcmp(mode, FL_(holiday)[0])) { return set_mode_n(HeatingCircuit::Mode::HOLIDAY, hc_num); } - if (Helpers::translated_word(FL_(comfort), true) == mode) { + if (!strcmp(mode, FL_(comfort)[0])) { return set_mode_n(HeatingCircuit::Mode::COMFORT, hc_num); } - return false; + return false; // not found } // Set the thermostat working mode @@ -2318,14 +2318,12 @@ bool Thermostat::set_mode_n(const uint8_t mode, const uint8_t hc_num) { case HeatingCircuit::Mode::OFF: set_mode_value = 0; break; - case HeatingCircuit::Mode::DAY: case HeatingCircuit::Mode::HEAT: case HeatingCircuit::Mode::MANUAL: case HeatingCircuit::Mode::NOFROST: set_mode_value = 1; break; - default: // AUTO & ECO set_mode_value = 2; break; @@ -2690,11 +2688,6 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char if (!strncmp(&value[3], (FL_(enum_dayOfWeek)[i][0]), 2)) { day = i; } - - // auto translated_dow = Helpers::translated_word(FL_(enum_dayOfWeek)[i]); - // if (!strncmp(&value[3], translated_dow.c_str(), translated_dow.length())) { - // day = i; - // } } } if (strlen(value) > 10) { @@ -2734,14 +2727,12 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char if (data[0] != 0xE7) { // we use EN settings for the day abbreviation std::string sday = (FL_(enum_dayOfWeek)[day][0]); - // std::string sday = Helpers::translated_word(FL_(enum_dayOfWeek)[day]); if (model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N) { snprintf(out, len, "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off"); } else if ((model() == EMS_DEVICE_FLAG_RC20) || (model() == EMS_DEVICE_FLAG_RC30)) { snprintf(out, len, "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on); } else { std::string son = (FL_(enum_switchmode)[on][0]); - // std::string son = Helpers::translated_word(FL_(enum_switchmode)[on]); snprintf(out, len, "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), son.c_str()); } } else { From dcbdb040097e66c5851ade769d60c1106964c6bd Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 10 Oct 2022 20:12:25 +0200 Subject: [PATCH 6/7] typo --- src/locale_translations.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locale_translations.h b/src/locale_translations.h index d1e42ff6c..db56ce01a 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -28,7 +28,7 @@ #define EMSESP_LOCALE_PL "pl" #define EMSESP_LOCALE_NO "no" -// translations are in order en, de, nl, se, pl, se, no, .... +// translations are in order en, de, nl, se, pl, no, .... // if there is no translation, it will default to en // commands From 2f706b33fa56ae390f2e1c256900f47343cb5b0b Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 10 Oct 2022 20:12:35 +0200 Subject: [PATCH 7/7] add test for modes --- src/test/test.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/test.cpp b/src/test/test.cpp index be722d6df..f791b5f9d 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -246,6 +246,14 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const shell.invoke_command("show mqtt"); } + if (command == "modes") { + shell.printfln("Testing thermostat modes..."); + run_test("general"); + shell.invoke_command("call thermostat mode auto"); + shell.invoke_command("call thermostat mode Manuell"); // DE + shell.invoke_command("call thermostat mode 1"); + } + if (command == "render") { shell.printfln("Testing render...");