diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_1_attributes.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_1_attributes.ino index 75f2537c2..17be8d13f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_1_attributes.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_1_attributes.ino @@ -264,6 +264,28 @@ EF00_0372,last_irrigation_duration */ +void Z_setString(char*& attr, const char * str) { + if (nullptr == str) { str = PSTR(""); } // nullptr is considered empty string + size_t str_len = strlen(str); + + if ((nullptr == attr) && (0 == str_len)) { return; } // if both empty, don't do anything + if (attr) { + // we already have a value + if (strcmp(attr, str) != 0) { + // new value + free(attr); // free previous value + attr = nullptr; + } else { + return; // same value, don't change anything + } + } + if (str_len) { + if (str_len > 31) { str_len = 31; } + attr = (char*) malloc(str_len + 1); + strlcpy(attr, str, str_len + 1); + } +} + // // // Class for a single attribute from a plugin @@ -275,12 +297,22 @@ public: Z_plugin_attribute(void) : type(Zunk), multiplier(1), divider(1), base(0), - cluster(0xFFFF), attribute(0xFFFF), manuf(0) + cluster(0xFFFF), attribute(0xFFFF), manuf(0), + name(nullptr) {}; + + ~Z_plugin_attribute(void) { + if (name != nullptr) { free((void*)name); } + } - void set(uint16_t cluster, uint16_t attribute, const char *name, uint8_t type = Zunk) { + inline void setName(const char *_name) { + Z_setString(this->name, _name); + } + + void set(uint16_t cluster, uint16_t attribute, const char *_name, uint8_t type = Zunk) { this->cluster = cluster; this->attribute = attribute; + Z_setString(this->name, _name); this->name = name; this->type = type; } @@ -292,7 +324,7 @@ public: uint16_t cluster; // cluster number uint16_t attribute; // attribute number uint16_t manuf; // manufacturer code, 0 if none - String name; // name of attribute once converted + char * name; // name of attribute once converted }; // @@ -337,9 +369,18 @@ public: Z_plugin_matcher(void) {}; - inline void setModelManuf(const char *_model, const char *_manuf) { - model = (const char*)_model; - manufacturer = (const char*)_manuf; + inline void setModel(const char *_model) { + Z_setString(this->model, _model); + } + + + inline void setManuf(const char *_manuf) { + Z_setString(this->manufacturer, _manuf); + } + + ~Z_plugin_matcher(void) { + if (model) { free((void*)model); } + if (manufacturer) { free((void*)manufacturer); } } // check if a matches b, return true if so @@ -372,18 +413,18 @@ public: bool match(const char *match_model, const char *match_manuf) const { bool match = true; - if (!matchStar(model.c_str(), match_model)) { + if (!matchStar(model, match_model)) { match = false; } - if (!matchStar(manufacturer.c_str(), match_manuf)) { + if (!matchStar(manufacturer, match_manuf)) { match = false; } - // AddLog(LOG_LEVEL_DEBUG, ">match device(%s, %s) compared to (%s, %s) = %i", match_model, match_manuf, model.c_str(), manufacturer.c_str(), match); + // AddLog(LOG_LEVEL_DEBUG, ">match device(%s, %s) compared to (%s, %s) = %i", match_model, match_manuf, model ? model : "", manufacturer ? manufacturer : "", match); return match; } - String model; - String manufacturer; + char * model = nullptr; + char * manufacturer = nullptr; }; // @@ -468,7 +509,7 @@ const Z_plugin_attribute * Z_plugin_templates::matchAttributeByName(const char * if (mtch.match(model, manufacturer)) { // got a match, apply template for (const Z_plugin_attribute & attr : attributes) { - if (attr.name.equals(name)) { + if (0 == strcasecmp_P(name, attr.name ? attr.name : "")) { return &attr; } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_7_6_plugin.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_7_6_plugin.ino index d6f9a0089..4a1ef2b59 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_7_6_plugin.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_7_6_plugin.ino @@ -58,7 +58,7 @@ Z_attribute_match Z_plugin_matchAttributeById(const char *model, const char *man if (attr_tmpl != nullptr) { attr.cluster = attr_tmpl->cluster; attr.attribute = attr_tmpl->attribute; - attr.name = attr_tmpl->name.c_str(); + attr.name = attr_tmpl->name; attr.zigbee_type = attr_tmpl->type; attr.multiplier = attr_tmpl->multiplier; attr.divider = attr_tmpl->divider; @@ -80,7 +80,7 @@ Z_attribute_match Z_plugin_matchAttributeByName(const char *model, const char *m if (attr_tmpl != nullptr) { attr.cluster = attr_tmpl->cluster; attr.attribute = attr_tmpl->attribute; - attr.name = attr_tmpl->name.c_str(); + attr.name = attr_tmpl->name; attr.zigbee_type = attr_tmpl->type; attr.multiplier = attr_tmpl->multiplier; attr.divider = attr_tmpl->divider; @@ -203,11 +203,11 @@ bool ZbLoad(const char *filename_raw) { char *token = strtok_r(rest, ",", &rest); Z_plugin_matcher & matcher = tmpl->matchers.addToLast(); if (token != nullptr) { - matcher.model = token; + matcher.setModel(token); } token = strtok_r(rest, ",", &rest); if (token != nullptr) { - matcher.manufacturer = token; + matcher.setManuf(token); } } else { if (tmpl == nullptr) { @@ -285,7 +285,7 @@ bool ZbLoad(const char *filename_raw) { plugin_attr.cluster = cluster_id; plugin_attr.attribute = attr_id; plugin_attr.type = type_id; - plugin_attr.name = name; + plugin_attr.setName(name); plugin_attr.multiplier = multiplier; plugin_attr.divider = divider; plugin_attr.base = base; @@ -413,7 +413,7 @@ void ZbLoadDump(void) { AddLog(LOG_LEVEL_INFO, PSTR("%s"), buf); } else { for (const Z_plugin_matcher & matcher : tmpl.matchers) { - ext_snprintf_P(buf, sizeof(buf), ":%s,%s", matcher.model.c_str(), matcher.manufacturer.c_str()); + ext_snprintf_P(buf, sizeof(buf), ":%s,%s", matcher.model ? matcher.model : "", matcher.manufacturer ? matcher.manufacturer : ""); AddLog(LOG_LEVEL_INFO, PSTR("%s"), buf); } } @@ -430,6 +430,7 @@ void ZbLoadDump(void) { Z_getTypeByNumber(type_str, sizeof(type_str), attr.type); ext_snprintf_P(buf, sizeof(buf), "%s%%%s", buf, type_str); } + ext_snprintf_P(buf, sizeof(buf), "%s,%s", buf, attr.name); Z_AppendModifiers(buf, sizeof(buf), attr.multiplier, attr.divider, attr.base, attr.manuf); AddLog(LOG_LEVEL_INFO, PSTR("%s"), buf); }