customze device brand #2784

This commit is contained in:
MichaelDvP
2026-02-12 12:01:39 +01:00
parent 909edf394d
commit 96ae3bbbba
11 changed files with 306 additions and 244 deletions

View File

@@ -72,6 +72,21 @@ const char * EMSdevice::tag_to_mqtt(int8_t tag) {
return (DeviceValue::DeviceValueTAG_mqtt[tag > DeviceValue::NUM_TAGS ? 0 : tag]);
}
uint8_t EMSdevice::tag_to_flag(const uint8_t tag) {
if (tag >= DeviceValueTAG::TAG_HC1 && tag <= DeviceValueTAG::TAG_HC8) {
return CommandFlag::CMD_FLAG_HC;
} else if (tag >= DeviceValueTAG::TAG_DHW1 && tag <= DeviceValueTAG::TAG_DHW10) {
return CommandFlag::CMD_FLAG_DHW;
} else if (tag >= DeviceValueTAG::TAG_HS1 && tag <= DeviceValueTAG::TAG_HS16) {
return CommandFlag::CMD_FLAG_HS;
} else if (tag >= DeviceValueTAG::TAG_AHS1 && tag <= DeviceValueTAG::TAG_AHS1) {
return CommandFlag::CMD_FLAG_AHS;
} else if (tag >= DeviceValueTAG::TAG_SRC1 && tag <= DeviceValueTAG::TAG_SRC16) {
return CommandFlag::CMD_FLAG_SRC;
}
return 0;
}
// convert UOM to a char string - translating only for hours/minutes/seconds
const char * EMSdevice::uom_to_string(uint8_t uom) {
switch (uom) {
@@ -90,6 +105,9 @@ const char * EMSdevice::uom_to_string(uint8_t uom) {
}
const char * EMSdevice::brand_to_char() {
if (!custom_brand().empty()) {
return custom_brand().c_str();
}
switch (brand_) {
case EMSdevice::Brand::BOSCH:
return F_(bosch);
@@ -316,7 +334,7 @@ std::string EMSdevice::to_string() {
return std::string(name()) + " (DeviceID:" + Helpers::hextoa(device_id_) + ")";
}
if (brand_ == Brand::NO_BRAND) {
if (brand_ == Brand::NO_BRAND && custom_brand().empty()) {
return std::string(name()) + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_) + ", Version:" + version_ + ")";
}
@@ -332,7 +350,7 @@ std::string EMSdevice::to_string_version() {
// returns out brand + device name
// translated
std::string EMSdevice::to_string_short() {
if (brand_ == Brand::NO_BRAND) {
if (brand_ == Brand::NO_BRAND && custom_brand().empty()) {
return std::string(device_type_2_device_name_translated()) + ": " + name();
}
@@ -650,25 +668,21 @@ void EMSdevice::add_device_value(int8_t tag, // to b
// add a new command if it has a function attached
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::CMD_FLAG_HC;
} else if (tag >= DeviceValueTAG::TAG_DHW1 && tag <= DeviceValueTAG::TAG_DHW10) {
flags |= CommandFlag::CMD_FLAG_DHW;
} else if (tag >= DeviceValueTAG::TAG_HS1 && tag <= DeviceValueTAG::TAG_HS16) {
flags |= CommandFlag::CMD_FLAG_HS;
} else if (tag >= DeviceValueTAG::TAG_AHS1 && tag <= DeviceValueTAG::TAG_AHS1) {
flags |= CommandFlag::CMD_FLAG_AHS;
} else if (tag >= DeviceValueTAG::TAG_SRC1 && tag <= DeviceValueTAG::TAG_SRC16) {
flags |= CommandFlag::CMD_FLAG_SRC;
}
uint8_t flags = CommandFlag::ADMIN_ONLY | tag_to_flag(tag); // executing commands require admin privileges
// add the command to our library
Command::add(device_type_, device_id_, short_name, f, fullname, flags);
}
}
void EMSdevice::erase_device_values() {
for (auto & dv : devicevalues_) {
if (dv.has_cmd) {
Command::erase_command(device_type_, dv.short_name, tag_to_flag(dv.tag));
}
}
devicevalues_.clear();
}
// single list of options
void EMSdevice::register_device_value(int8_t tag,
void * value_p,

View File

@@ -55,6 +55,7 @@ class EMSdevice {
static const char * tag_to_mqtt(int8_t tag);
static uint8_t decode_brand(uint8_t value);
static bool export_values(uint8_t device_type, JsonObject output, const int8_t id, const uint8_t output_target);
static uint8_t tag_to_flag(const uint8_t tag);
// non static functions
@@ -124,6 +125,14 @@ class EMSdevice {
return custom_name_;
}
// set custom brand
void custom_brand(std::string const & custom_brand) {
custom_brand_ = custom_brand;
}
std::string custom_brand() const {
return custom_brand_;
}
// set device model
void model(std::string const & model) {
model_ = model;
@@ -282,6 +291,8 @@ class EMSdevice {
int16_t min,
uint32_t max);
void erase_device_values();
void
register_device_value(int8_t tag, void * value_p, uint8_t type, const char * const ** options, const char * const * name, uint8_t uom, const cmd_function_p f);
@@ -524,12 +535,13 @@ class EMSdevice {
uint8_t device_id_ = 0;
uint8_t product_id_ = 0;
char version_[6];
const char * default_name_; // the fixed name the EMS model taken from the device library
std::string custom_name_ = ""; // custom name
std::string model_ = ""; // model, taken from the 0x01 telegram. see process_deviceName()
uint8_t flags_ = 0;
uint8_t brand_ = Brand::NO_BRAND;
bool active_ = true;
const char * default_name_; // the fixed name the EMS model taken from the device library
std::string custom_name_ = ""; // custom name
std::string custom_brand_ = ""; // custom brand
std::string model_ = ""; // model, taken from the 0x01 telegram. see process_deviceName()
uint8_t flags_ = 0;
uint8_t brand_ = Brand::NO_BRAND;
bool active_ = true;
bool ha_config_done_ = false;
bool has_update_ = false;

View File

@@ -1310,6 +1310,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
if (product_id == 0 || (*it)->product_id() != 0) { // update only with valid product_id
return true;
}
(*it)->erase_device_values();
emsdevices.erase(it); // erase the old device without product_id and re detect
break;
}
@@ -1450,6 +1451,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
if ((e.device_id == device_id) && (e.product_id == product_id)) {
LOG_DEBUG("Have customizations for %s with deviceID 0x%02X productID %d", e.custom_name.c_str(), device_id, product_id);
emsdevices.back()->custom_name(e.custom_name);
emsdevices.back()->custom_brand(e.custom_brand);
break;
}
}
@@ -1760,7 +1762,7 @@ void EMSESP::start() {
nvs_.begin("ems-esp", false, "nvs"); // fallback to small nvs
}
LOG_DEBUG("NVS device information: %s", system_.getBBQKeesGatewayDetails().isEmpty() ? "not set" : system_.getBBQKeesGatewayDetails().c_str());
LOG_DEBUG("Fuse device information: %s", system_.getBBQKeesGatewayDetails().isEmpty() ? "not set" : system_.getBBQKeesGatewayDetails().c_str());
webSettingsService.begin(); // load EMS-ESP Application settings

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.8.2-dev.3"
#define EMSESP_APP_VERSION "3.8.2-dev.4"

View File

@@ -76,10 +76,11 @@ void WebCustomization::read(WebCustomization & customizations, JsonObject root)
// Masked entities customization and custom device name (optional)
JsonArray masked_entitiesJson = root["masked_entities"].to<JsonArray>();
for (const EntityCustomization & entityCustomization : customizations.entityCustomizations) {
JsonObject entityJson = masked_entitiesJson.add<JsonObject>();
entityJson["product_id"] = entityCustomization.product_id;
entityJson["device_id"] = entityCustomization.device_id;
entityJson["custom_name"] = entityCustomization.custom_name;
JsonObject entityJson = masked_entitiesJson.add<JsonObject>();
entityJson["product_id"] = entityCustomization.product_id;
entityJson["device_id"] = entityCustomization.device_id;
entityJson["custom_name"] = entityCustomization.custom_name;
entityJson["custom_brand"] = entityCustomization.custom_brand;
// entries are in the form <XX><shortname>[optional customname] e.g "08heatingactive|heating is on"
JsonArray masked_entityJson = entityJson["entity_ids"].to<JsonArray>();
@@ -134,7 +135,7 @@ StateUpdateResult WebCustomization::update(JsonObject root, WebCustomization & c
analog.type = analogJson["type"];
analog.is_system = analogJson["is_system"] | false;
if (_start && analog.type == EMSESP::analogsensor_.AnalogType::DIGITAL_OUT && analog.uom > DeviceValue::DeviceValueUOM::NONE) {
analog.offset = analog.uom - 1;
analog.offset = analog.uom > 1 ? 1 : 0;
}
customizations.analogCustomizations.push_back(analog); // add to list
}
@@ -146,10 +147,11 @@ StateUpdateResult WebCustomization::update(JsonObject root, WebCustomization & c
if (root["masked_entities"].is<JsonArray>()) {
auto masked_entities = root["masked_entities"].as<JsonArray>();
for (const JsonObject masked_entity : masked_entities) {
auto emsEntity = EntityCustomization();
emsEntity.product_id = masked_entity["product_id"];
emsEntity.device_id = masked_entity["device_id"];
emsEntity.custom_name = masked_entity["custom_name"] | "";
auto emsEntity = EntityCustomization();
emsEntity.product_id = masked_entity["product_id"];
emsEntity.device_id = masked_entity["device_id"];
emsEntity.custom_name = masked_entity["custom_name"] | "";
emsEntity.custom_brand = masked_entity["custom_brand"] | "";
auto masked_entity_ids = masked_entity["entity_ids"].as<JsonArray>();
for (const JsonVariant masked_entity_id : masked_entity_ids) {
@@ -242,17 +244,19 @@ void WebCustomizationService::writeDeviceName(AsyncWebServerRequest * request, J
uint8_t unique_device_id = json["id"];
// find product id and device id using the unique id
if (emsdevice->unique_id() == unique_device_id) {
uint8_t product_id = emsdevice->product_id();
uint8_t device_id = emsdevice->device_id();
auto custom_name = json["name"].as<std::string>();
uint8_t product_id = emsdevice->product_id();
uint8_t device_id = emsdevice->device_id();
std::string custom_name = json["name"] | "";
std::string custom_brand = json["brand"] | "";
// updates current record or creates a new one
bool entry_exists = false;
update([&](WebCustomization & settings) {
for (auto it = settings.entityCustomizations.begin(); it != settings.entityCustomizations.end();) {
if ((*it).product_id == product_id && (*it).device_id == device_id) {
(*it).custom_name = custom_name;
entry_exists = true;
(*it).custom_name = custom_name;
(*it).custom_brand = custom_brand;
entry_exists = true;
break;
} else {
++it;
@@ -262,9 +266,10 @@ void WebCustomizationService::writeDeviceName(AsyncWebServerRequest * request, J
// if we don't have any customization for this device, create a new entry
if (!entry_exists) {
EntityCustomization new_entry;
new_entry.product_id = product_id;
new_entry.device_id = device_id;
new_entry.custom_name = custom_name;
new_entry.product_id = product_id;
new_entry.device_id = device_id;
new_entry.custom_name = custom_name;
new_entry.custom_brand = custom_brand;
settings.entityCustomizations.push_back(new_entry);
}
@@ -273,6 +278,7 @@ void WebCustomizationService::writeDeviceName(AsyncWebServerRequest * request, J
// update the EMS Device record real-time
emsdevice->custom_name(custom_name);
emsdevice->custom_brand(custom_brand);
}
}
}
@@ -459,10 +465,11 @@ void WebCustomizationService::load_test_data() {
// EMS entities, mark some as favorites
webCustomization.entityCustomizations.clear();
auto emsEntity = EntityCustomization();
emsEntity.product_id = 123;
emsEntity.device_id = 8;
emsEntity.custom_name = "My Custom Boiler";
auto emsEntity = EntityCustomization();
emsEntity.product_id = 123;
emsEntity.device_id = 8;
emsEntity.custom_name = "My Custom Boiler";
emsEntity.custom_brand = "My Brand";
emsEntity.entity_ids.push_back("08heatingactive|is my heating on?");
emsEntity.entity_ids.push_back("08tapwateractive");
emsEntity.entity_ids.push_back("08selflowtemp|<90");
@@ -472,6 +479,7 @@ void WebCustomizationService::load_test_data() {
for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice->is_device_id(emsEntity.device_id)) {
emsdevice->custom_name(emsEntity.custom_name);
emsdevice->custom_brand(emsEntity.custom_brand);
break;
}
}

View File

@@ -63,10 +63,11 @@ class AnalogCustomization {
// we use product_id and device_id to make the device unique
class EntityCustomization {
public:
uint8_t product_id; // device's product id
uint8_t device_id; // device's device id
std::string custom_name; // custom device name
std::vector<std::string> entity_ids; // array of entity ids with masks and optional custom fullname
uint8_t product_id; // device's product id
uint8_t device_id; // device's device id
std::string custom_name; // custom device name
std::string custom_brand; // custom brand name
std::vector<std::string> entity_ids; // array of entity ids with masks and optional custom fullname
};
class WebCustomization {