optimizations and show # entities and languages

This commit is contained in:
proddy
2025-11-05 22:29:15 +01:00
parent 5908fd9d9c
commit 12635ff4a5
2 changed files with 184 additions and 149 deletions

View File

@@ -45,55 +45,38 @@ using string_vector = std::vector<const char *>;
// clang-format off // clang-format off
#define FPSTR(pstr_pointer) pstr_pointer #define FPSTR(pstr_pointer) pstr_pointer
#define MAKE_WORD_CUSTOM(string_name, string_literal) static const char __pstr__##string_name[] = string_literal; #define MAKE_WORD_CUSTOM(string_name, string_literal) static const char __pstr__##string_name[] = string_literal;
#define MAKE_WORD(string_name) MAKE_WORD_CUSTOM(string_name, #string_name) #define MAKE_WORD(string_name) MAKE_WORD_CUSTOM(string_name, #string_name)
#define F_(string_name) (__pstr__##string_name) #define F_(string_name) (__pstr__##string_name)
#define FL_(list_name) (__pstr__L_##list_name) #define FL_(list_name) (__pstr__L_##list_name)
// Counter for translations created by MAKE_TRANSLATION // Translation counter - capture baseline before any MAKE_TRANSLATION calls
extern uint32_t translation_count_; enum { EMSESP_TRANSLATION_COUNT_START = __COUNTER__ };
#include <set>
#include <string>
inline void increment_translation_count_impl(const char * translation_name) {
// Use a static set to track which translations we've already counted by name
// Using std::string ensures we compare by value, not by pointer address
// This ensures we only count each unique translation once, even if included in multiple files
static std::set<std::string> counted_translations;
std::string name(translation_name);
if (counted_translations.find(name) == counted_translations.end()) {
extern uint32_t translation_count_;
translation_count_++;
counted_translations.insert(name);
}
}
// The language settings below must match system.cpp // The language settings below must match system.cpp
#if defined(EMSESP_TEST) #if defined(EMSESP_EN_ONLY)
// in Test mode use two languages (en & de) to save flash memory needed for the tests // EN only
#define MAKE_WORD_TRANSLATION(list_name, en, de, ...) static const char * const __pstr__L_##list_name[] = {en, de, nullptr}; #define MAKE_WORD_TRANSLATION(list_name, en, ...) static const char * const __pstr__L_##list_name[] = {en, nullptr};
#define MAKE_TRANSLATION(list_name, shortname, en, de, ...) static const char * const __pstr__L_##list_name[] = {shortname, en, de, nullptr}; static int __translation_counter_##list_name = (increment_translation_count_impl(#list_name), 0); #define MAKE_TRANSLATION(list_name, shortname, en, ...) static constexpr int __translation_counter_##list_name = __COUNTER__; static const char * const __pstr__L_##list_name[] = {shortname, en, nullptr};
#elif defined(EMSESP_EN_ONLY) #elif defined(EMSESP_TEST) || defined(EMSESP_DE_ONLY)
// EN only // EN + DE (Test mode uses two languages to save flash memory)
#define MAKE_WORD_TRANSLATION(list_name, en, ...) static const char * const __pstr__L_##list_name[] = {en, nullptr}; #define MAKE_WORD_TRANSLATION(list_name, en, de, ...) static const char * const __pstr__L_##list_name[] = {en, de, nullptr};
#define MAKE_TRANSLATION(list_name, shortname, en, ...) static const char * const __pstr__L_##list_name[] = {shortname, en, nullptr}; static int __translation_counter_##list_name = (increment_translation_count_impl(#list_name), 0); #define MAKE_TRANSLATION(list_name, shortname, en, de, ...) static constexpr int __translation_counter_##list_name = __COUNTER__; static const char * const __pstr__L_##list_name[] = {shortname, en, de, nullptr};
#elif defined(EMSESP_DE_ONLY) #else
// EN + DE // All languages
#define MAKE_WORD_TRANSLATION(list_name, en, de, ...) static const char * const __pstr__L_##list_name[] = {en, de, nullptr}; #define MAKE_WORD_TRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
#define MAKE_TRANSLATION(list_name, shortname, en, de, ...) static const char * const __pstr__L_##list_name[] = {shortname, en, de, nullptr}; static int __translation_counter_##list_name = (increment_translation_count_impl(#list_name), 0); #define MAKE_TRANSLATION(list_name, ...) static constexpr int __translation_counter_##list_name = __COUNTER__; static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
#else #endif
#define MAKE_WORD_TRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
#define MAKE_TRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr}; static int __translation_counter_##list_name = (increment_translation_count_impl(#list_name), 0);
#endif
#define MAKE_NOTRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr}; #define MAKE_NOTRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
// fixed strings, no translations // fixed strings, no translations
#define MAKE_ENUM_FIXED(enum_name, ...) static const char * const __pstr__L_##enum_name[] = {__VA_ARGS__, nullptr}; #define MAKE_ENUM_FIXED(enum_name, ...) static const char * const __pstr__L_##enum_name[] = {__VA_ARGS__, nullptr};
// with translations // with translations
#define MAKE_ENUM(enum_name, ...) static const char * const * __pstr__L_##enum_name[] = {__VA_ARGS__, nullptr}; #define MAKE_ENUM(enum_name, ...) static const char * const * __pstr__L_##enum_name[] = {__VA_ARGS__, nullptr};
// clang-format on // clang-format on
@@ -101,4 +84,8 @@ inline void increment_translation_count_impl(const char * translation_name) {
#include "locale_translations.h" #include "locale_translations.h"
#include "locale_common.h" #include "locale_common.h"
// Translation count - dynamically calculated at compile-time
enum { EMSESP_TRANSLATION_COUNT_END = __COUNTER__ };
static constexpr uint16_t EMSESP_TRANSLATION_COUNT = EMSESP_TRANSLATION_COUNT_END - EMSESP_TRANSLATION_COUNT_START - 1;
#endif #endif

View File

@@ -26,9 +26,6 @@ static_assert(uuid::thread_safe, "uuid-common must be thread-safe");
static_assert(uuid::log::thread_safe, "uuid-log must be thread-safe"); static_assert(uuid::log::thread_safe, "uuid-log must be thread-safe");
static_assert(uuid::console::thread_safe, "uuid-console must be thread-safe"); static_assert(uuid::console::thread_safe, "uuid-console must be thread-safe");
// Translation counter - incremented by MAKE_TRANSLATION macro (must be global, not in namespace)
uint32_t translation_count_ = 0;
namespace emsesp { namespace emsesp {
// Static member definitions // Static member definitions
@@ -99,18 +96,35 @@ Preferences EMSESP::nvs_; // NV Storage
// for a specific EMS device go and request data values // for a specific EMS device go and request data values
// or if device_id is 0 it will fetch from all our known and active devices // or if device_id is 0 it will fetch from all our known and active devices
void EMSESP::fetch_device_values(const uint8_t device_id) { void EMSESP::fetch_device_values(const uint8_t device_id) {
for (const auto & emsdevice : emsdevices) { // Early return if no devices
if ((device_id == 0) || emsdevice->is_device_id(device_id)) { if (emsdevices.empty()) {
return;
}
// If device_id is 0, fetch all
if (device_id == 0) {
for (const auto & emsdevice : emsdevices) {
emsdevice->fetch_values(); emsdevice->fetch_values();
if (device_id != 0) { }
return; // quit, we only want to return the selected device return;
} }
// Fetch specific device
for (const auto & emsdevice : emsdevices) {
if (emsdevice->is_device_id(device_id)) {
emsdevice->fetch_values();
return; // quit, we only want to return the selected device
} }
} }
} }
// see if the deviceID exists // see if the deviceID exists
bool EMSESP::valid_device(const uint8_t device_id) { bool EMSESP::valid_device(const uint8_t device_id) {
// Early return if devices list is empty
if (emsdevices.empty()) {
return false;
}
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice && emsdevice->is_device_id(device_id)) { if (emsdevice && emsdevice->is_device_id(device_id)) {
return true; return true;
@@ -121,6 +135,10 @@ bool EMSESP::valid_device(const uint8_t device_id) {
// for a specific EMS device type go and request data values // for a specific EMS device type go and request data values
void EMSESP::fetch_device_values_type(const uint8_t device_type) { void EMSESP::fetch_device_values_type(const uint8_t device_type) {
if (emsdevices.empty()) {
return;
}
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice && (emsdevice->device_type() == device_type)) { if (emsdevice && (emsdevice->device_type() == device_type)) {
emsdevice->fetch_values(); emsdevice->fetch_values();
@@ -129,6 +147,10 @@ void EMSESP::fetch_device_values_type(const uint8_t device_type) {
} }
bool EMSESP::cmd_is_readonly(const uint8_t device_type, const uint8_t device_id, const char * cmd, const int8_t id) { bool EMSESP::cmd_is_readonly(const uint8_t device_type, const uint8_t device_id, const char * cmd, const int8_t id) {
if (emsdevices.empty()) {
return false;
}
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice && (emsdevice->device_type() == device_type) && (!device_id || emsdevice->device_id() == device_id)) { if (emsdevice && (emsdevice->device_type() == device_type) && (!device_id || emsdevice->device_id() == device_id)) {
return emsdevice->is_readonly(cmd, id); return emsdevice->is_readonly(cmd, id);
@@ -138,6 +160,10 @@ bool EMSESP::cmd_is_readonly(const uint8_t device_type, const uint8_t device_id,
} }
uint8_t EMSESP::device_id_from_cmd(const uint8_t device_type, const char * cmd, const int8_t id) { uint8_t EMSESP::device_id_from_cmd(const uint8_t device_type, const char * cmd, const int8_t id) {
if (emsdevices.empty()) {
return 0;
}
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice && emsdevice->device_type() == device_type && emsdevice->has_cmd(cmd, id)) { if (emsdevice && emsdevice->device_type() == device_type && emsdevice->has_cmd(cmd, id)) {
return emsdevice->device_id(); return emsdevice->device_id();
@@ -154,10 +180,14 @@ void EMSESP::clear_all_devices() {
// return number of devices of a known type // return number of devices of a known type
uint8_t EMSESP::count_devices(const uint8_t device_type) { uint8_t EMSESP::count_devices(const uint8_t device_type) {
if (emsdevices.empty()) {
return 0;
}
uint8_t count = 0; uint8_t count = 0;
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice) { if (emsdevice && emsdevice->device_type() == device_type) {
count += (emsdevice->device_type() == device_type); count++;
} }
} }
return count; return count;
@@ -165,10 +195,14 @@ uint8_t EMSESP::count_devices(const uint8_t device_type) {
// return total number of devices excluding the Controller // return total number of devices excluding the Controller
uint8_t EMSESP::count_devices() { uint8_t EMSESP::count_devices() {
if (emsdevices.empty()) {
return 0;
}
uint8_t count = 0; uint8_t count = 0;
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice) { if (emsdevice && emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER) {
count += (emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER); count++;
} }
} }
return count; return count;
@@ -177,20 +211,22 @@ uint8_t EMSESP::count_devices() {
// returns the index of a device if there are more of the same type // returns the index of a device if there are more of the same type
// or 0 if there is only one or none // or 0 if there is only one or none
uint8_t EMSESP::device_index(const uint8_t device_type, const uint8_t unique_id) { uint8_t EMSESP::device_index(const uint8_t device_type, const uint8_t unique_id) {
if (count_devices(device_type) <= 1) { uint8_t count = 0;
return 0; // none or only 1 device exists uint8_t index = 0;
} uint8_t current_index = 1;
uint8_t index = 1;
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice->device_type() == device_type) { if (emsdevice->device_type() == device_type) {
// did we find it? count++;
if (emsdevice->unique_id() == unique_id) { if (emsdevice->unique_id() == unique_id) {
return index; index = current_index;
} }
index++; current_index++;
} }
} }
return 0; // didn't find it
// Return 0 if only one device exists or not found
return (count <= 1) ? 0 : index;
} }
// scans for new devices // scans for new devices
@@ -245,13 +281,8 @@ uint8_t EMSESP::bus_status() {
uint32_t total_fail = txservice_.telegram_read_fail_count() + txservice_.telegram_write_fail_count(); uint32_t total_fail = txservice_.telegram_read_fail_count() + txservice_.telegram_write_fail_count();
// nothing sent and also no errors - must be ok // nothing sent and also no errors - must be ok
if ((total_sent == 0) && (total_fail == 0)) { if (total_sent == 0) {
return BUS_STATUS_CONNECTED; return (total_fail == 0) ? BUS_STATUS_CONNECTED : BUS_STATUS_TX_ERRORS;
}
// nothing sent, but have Tx errors
if ((total_sent == 0) && (total_fail != 0)) {
return BUS_STATUS_TX_ERRORS;
} }
// Tx Failure rate > 10% // Tx Failure rate > 10%
@@ -849,41 +880,55 @@ std::string EMSESP::pretty_telegram(std::shared_ptr<const Telegram> telegram) {
std::string src_name(""); std::string src_name("");
std::string dest_name(""); std::string dest_name("");
std::string type_name(""); std::string type_name("");
// Single loop to find all device information
bool src_found = false;
bool dest_found = false;
bool type_found = false;
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
// get src & dest // get src name
if (emsdevice->is_device_id(src)) { if (!src_found && emsdevice->is_device_id(src)) {
src_name = emsdevice->device_type_name(); src_name = emsdevice->device_type_name();
} else if (emsdevice->is_device_id(dest)) { src_found = true;
dest_name = emsdevice->device_type_name();
} }
// get the type name
if (type_name.empty()) { // get dest name
if (!dest_found && emsdevice->is_device_id(dest)) {
dest_name = emsdevice->device_type_name();
dest_found = true;
}
// get the type name (try primary conditions first)
if (!type_found) {
if ((telegram->operation == Telegram::Operation::RX_READ && emsdevice->is_device_id(dest)) if ((telegram->operation == Telegram::Operation::RX_READ && emsdevice->is_device_id(dest))
|| (telegram->operation != Telegram::Operation::RX_READ && dest == 0 && emsdevice->is_device_id(src)) || (telegram->operation != Telegram::Operation::RX_READ && dest == 0 && emsdevice->is_device_id(src))
|| (telegram->operation != Telegram::Operation::RX_READ && src == EMSbus::ems_bus_id() && emsdevice->is_device_id(dest))) { || (telegram->operation != Telegram::Operation::RX_READ && src == EMSbus::ems_bus_id() && emsdevice->is_device_id(dest))) {
type_name = emsdevice->telegram_type_name(telegram); type_name = emsdevice->telegram_type_name(telegram);
if (!type_name.empty()) {
type_found = true;
}
} }
} }
// Early exit if we found everything
if (src_found && dest_found && type_found) {
break;
}
} }
if (type_name.empty()) {
// fallback, get the type name from src // Fallback for type name if not found - try src or dest
if (!type_found && telegram->operation != Telegram::Operation::RX_READ) {
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (telegram->operation != Telegram::Operation::RX_READ && emsdevice->is_device_id(src)) { if (emsdevice->is_device_id(src) || emsdevice->is_device_id(dest)) {
type_name = emsdevice->telegram_type_name(telegram); type_name = emsdevice->telegram_type_name(telegram);
break; if (!type_name.empty()) {
break;
}
} }
} }
} }
if (type_name.empty()) {
// 2nd fallback, get the type name from dest
for (const auto & emsdevice : emsdevices) {
if (telegram->operation != Telegram::Operation::RX_READ && emsdevice->is_device_id(dest)) {
type_name = emsdevice->telegram_type_name(telegram);
break;
}
}
}
// if we can't find names for the devices, use their hex values // if we can't find names for the devices, use their hex values
if (src_name.empty()) { if (src_name.empty()) {
src_name = device_tostring(src); src_name = device_tostring(src);
@@ -1012,11 +1057,16 @@ void EMSESP::process_version(std::shared_ptr<const Telegram> telegram) {
if (telegram->offset != 0) { if (telegram->offset != 0) {
return; return;
} }
const uint8_t msg_len = telegram->message_length;
// for empty telegram add device with empty product, version and brand // for empty telegram add device with empty product, version and brand
if (telegram->message_length == 0) { if (msg_len == 0) {
(void)add_device(telegram->src, 0, "00.00", 0); (void)add_device(telegram->src, 0, "00.00", 0);
return; return;
} else if (telegram->message_length < 3) { }
if (msg_len < 3) {
(void)add_device(telegram->src, telegram->message_data[0], "00.00", 0); (void)add_device(telegram->src, telegram->message_data[0], "00.00", 0);
send_read_request(EMSdevice::EMS_TYPE_NAME, telegram->src, 27); send_read_request(EMSdevice::EMS_TYPE_NAME, telegram->src, 27);
return; return;
@@ -1026,7 +1076,7 @@ void EMSESP::process_version(std::shared_ptr<const Telegram> telegram) {
uint8_t offset = 0; uint8_t offset = 0;
if (telegram->message_data[0] == 0x00) { if (telegram->message_data[0] == 0x00) {
// see if we have a 2nd subscriber // see if we have a 2nd subscriber
if (telegram->message_length > 5 && telegram->message_data[3] != 0x00) { if (msg_len > 5 && telegram->message_data[3] != 0x00) {
offset = 3; offset = 3;
} else { } else {
return; // ignore whole telegram return; // ignore whole telegram
@@ -1043,7 +1093,7 @@ void EMSESP::process_version(std::shared_ptr<const Telegram> telegram) {
// some devices store the protocol type (HT3, Buderus) in the last byte // some devices store the protocol type (HT3, Buderus) in the last byte
uint8_t brand; uint8_t brand;
if (telegram->message_length >= 10) { if (msg_len >= 10) {
brand = EMSdevice::decode_brand(telegram->message_data[9]); brand = EMSdevice::decode_brand(telegram->message_data[9]);
} else { } else {
brand = EMSdevice::Brand::NO_BRAND; // unknown brand = EMSdevice::Brand::NO_BRAND; // unknown
@@ -1119,57 +1169,53 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
// calls the associated process function for that EMS device // calls the associated process function for that EMS device
// returns false if the device_id doesn't recognize it // returns false if the device_id doesn't recognize it
// after the telegram has been processed, see if there have been values changed and we need to do a MQTT publish // after the telegram has been processed, see if there have been values changed and we need to do a MQTT publish
bool telegram_found = false; bool telegram_found = false;
uint8_t device_found = 0; uint8_t device_found = 0;
// broadcast or send to us EMSdevice * found_device = nullptr;
// Combined loop: check all conditions in a single pass
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
// broadcast or send to us
if (emsdevice->is_device_id(telegram->src) && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) { if (emsdevice->is_device_id(telegram->src) && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) {
telegram_found = emsdevice->handle_telegram(telegram); telegram_found = emsdevice->handle_telegram(telegram);
device_found = emsdevice->unique_id(); found_device = emsdevice.get();
break; break;
} }
}
if (!telegram_found) {
// check for command to the device // check for command to the device
for (const auto & emsdevice : emsdevices) { if (!telegram_found && emsdevice->is_device_id(telegram->dest) && telegram->src != EMSbus::ems_bus_id()) {
if (emsdevice->is_device_id(telegram->dest) && telegram->src != EMSbus::ems_bus_id()) { telegram_found = emsdevice->handle_telegram(telegram);
telegram_found = emsdevice->handle_telegram(telegram); found_device = emsdevice.get();
device_found = emsdevice->unique_id();
break;
}
}
}
if (!telegram_found) {
// check for sends to master thermostat
for (const auto & emsdevice : emsdevices) {
if (emsdevice->is_device_id(telegram->src) && telegram->dest == 0x10) {
telegram_found = emsdevice->handle_telegram(telegram);
device_found = emsdevice->unique_id();
break;
}
}
}
for (const auto & emsdevice : emsdevices) {
if (emsdevice->unique_id() == device_found) {
if (!telegram_found && telegram->message_length > 0) {
emsdevice->add_handlers_ignored(telegram->type_id);
}
if (wait_validate_ == telegram->type_id) {
wait_validate_ = 0;
}
if (Mqtt::connected() && telegram_found
&& ((mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update())
|| (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id()))) {
if (telegram->type_id == publish_id_) {
publish_id_ = 0;
}
emsdevice->has_update(false); // reset flag
if (!Mqtt::publish_single()) {
publish_device_values(emsdevice->device_type()); // publish to MQTT if we explicitly have too
}
}
break; break;
} }
// check for sends to master thermostat
if (!telegram_found && emsdevice->is_device_id(telegram->src) && telegram->dest == 0x10) {
telegram_found = emsdevice->handle_telegram(telegram);
found_device = emsdevice.get();
break;
}
}
if (found_device) {
device_found = found_device->unique_id();
// Process the found device directly without another loop
if (!telegram_found && telegram->message_length > 0) {
found_device->add_handlers_ignored(telegram->type_id);
}
if (wait_validate_ == telegram->type_id) {
wait_validate_ = 0;
}
if (Mqtt::connected() && telegram_found
&& ((mqtt_.get_publish_onchange(found_device->device_type()) && found_device->has_update())
|| (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id()))) {
if (telegram->type_id == publish_id_) {
publish_id_ = 0;
}
found_device->has_update(false); // reset flag
if (!Mqtt::publish_single()) {
publish_device_values(found_device->device_type()); // publish to MQTT if we explicitly have too
}
}
} }
// handle unknown broadcasted telegrams (or send to us) // handle unknown broadcasted telegrams (or send to us)
if (!telegram_found && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) { if (!telegram_found && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) {
@@ -1187,6 +1233,10 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
// return true if we have this device already registered // return true if we have this device already registered
bool EMSESP::device_exists(const uint8_t device_id) { bool EMSESP::device_exists(const uint8_t device_id) {
if (emsdevices.empty()) {
return false;
}
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice && emsdevice->is_device_id(device_id)) { if (emsdevice && emsdevice->is_device_id(device_id)) {
return true; return true;
@@ -1254,16 +1304,14 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
} }
// first check to see if we already have it, if so update the record // first check to see if we already have it, if so update the record
auto it = emsdevices.begin(); for (auto it = emsdevices.begin(); it != emsdevices.end(); ++it) {
for (const auto & emsdevice : emsdevices) { if ((*it) && (*it)->is_device_id(device_id)) {
if (emsdevice && emsdevice->is_device_id(device_id)) { if (product_id == 0 || (*it)->product_id() != 0) { // update only with valid product_id
if (product_id == 0 || emsdevice->product_id() != 0) { // update only with valid product_id
return true; return true;
} }
emsdevices.erase(it); // erase the old device without product_id and re detect emsdevices.erase(it); // erase the old device without product_id and re detect
break; break;
} }
it++;
} }
// look up the rest of the details using the product_id and create the new device object // look up the rest of the details using the product_id and create the new device object
@@ -1694,7 +1742,7 @@ void EMSESP::start() {
device_library_ = { device_library_ = {
#include "device_library.h" #include "device_library.h"
}; };
LOG_INFO("Library loaded: %d EMS devices, %d device entities, %s", device_library_.size(), ::translation_count_, system_.languages_string().c_str()); LOG_INFO("Library loaded: %d EMS devices, %d device entities, %s", device_library_.size(), EMSESP_TRANSLATION_COUNT, system_.languages_string().c_str());
system_.reload_settings(); // ... and store some of the settings locally system_.reload_settings(); // ... and store some of the settings locally