mirror of https://github.com/arendst/Tasmota.git
Zigbee extend div and offset for plugin
This commit is contained in:
parent
74414d8304
commit
42d26fecb2
|
@ -110,7 +110,8 @@ public:
|
||||||
// The high 8 bits are `0` command sent to device or `1` command received from device
|
// The high 8 bits are `0` command sent to device or `1` command received from device
|
||||||
uint8_t key_suffix; // append a suffix to key (default is 1, explicitly output if >1)
|
uint8_t key_suffix; // append a suffix to key (default is 1, explicitly output if >1)
|
||||||
uint8_t attr_type; // [opt] type of the attribute, default to Zunk (0xFF)
|
uint8_t attr_type; // [opt] type of the attribute, default to Zunk (0xFF)
|
||||||
uint8_t attr_multiplier; // [opt] multiplier for attribute, defaults to 0x01 (no change)
|
int8_t attr_multiplier; // [opt] multiplier for attribute, defaults to 0x01 (no change)
|
||||||
|
int8_t attr_divider; // [opt] divider
|
||||||
uint16_t manuf; // manufacturer id (0 if none)
|
uint16_t manuf; // manufacturer id (0 if none)
|
||||||
|
|
||||||
// Constructor with all defaults
|
// Constructor with all defaults
|
||||||
|
@ -127,6 +128,7 @@ public:
|
||||||
key_suffix(1),
|
key_suffix(1),
|
||||||
attr_type(0xFF),
|
attr_type(0xFF),
|
||||||
attr_multiplier(1),
|
attr_multiplier(1),
|
||||||
|
attr_divider(1),
|
||||||
manuf(0)
|
manuf(0)
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
@ -784,6 +786,7 @@ void Z_attribute::deepCopy(const Z_attribute & rhs) {
|
||||||
key_suffix = rhs.key_suffix;
|
key_suffix = rhs.key_suffix;
|
||||||
attr_type = rhs.attr_type;
|
attr_type = rhs.attr_type;
|
||||||
attr_multiplier = rhs.attr_multiplier;
|
attr_multiplier = rhs.attr_multiplier;
|
||||||
|
attr_divider = rhs.attr_divider;
|
||||||
// copy value
|
// copy value
|
||||||
copyVal(rhs);
|
copyVal(rhs);
|
||||||
// don't touch next pointer
|
// don't touch next pointer
|
||||||
|
|
|
@ -273,7 +273,9 @@ class Z_plugin_attribute {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Z_plugin_attribute(void) :
|
Z_plugin_attribute(void) :
|
||||||
type(Zunk), multiplier(1), cluster(0xFFFF), attribute(0xFFFF), manuf(0)
|
type(Zunk),
|
||||||
|
multiplier(1), divider(1), base(0),
|
||||||
|
cluster(0xFFFF), attribute(0xFFFF), manuf(0)
|
||||||
{};
|
{};
|
||||||
|
|
||||||
void set(uint16_t cluster, uint16_t attribute, const char *name, uint8_t type = Zunk) {
|
void set(uint16_t cluster, uint16_t attribute, const char *name, uint8_t type = Zunk) {
|
||||||
|
@ -284,7 +286,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t type; // zigbee type, Zunk by default
|
uint8_t type; // zigbee type, Zunk by default
|
||||||
int8_t multiplier; // multiplier, values 0, 1, 2, 5, 10, 100, -2, -5, -10, -100,
|
int8_t multiplier; // multiply by x (ignore if 0 or 1)
|
||||||
|
int8_t divider; // divide by x (ignore if 0 or 1)
|
||||||
|
int16_t base; // add x (ignore if 0)
|
||||||
uint16_t cluster; // cluster number
|
uint16_t cluster; // cluster number
|
||||||
uint16_t attribute; // attribute number
|
uint16_t attribute; // attribute number
|
||||||
uint16_t manuf; // manufacturer code, 0 if none
|
uint16_t manuf; // manufacturer code, 0 if none
|
||||||
|
@ -298,15 +302,18 @@ class Z_attribute_synonym {
|
||||||
public:
|
public:
|
||||||
Z_attribute_synonym(void) :
|
Z_attribute_synonym(void) :
|
||||||
cluster(0xFFFF), attribute(0xFFFF), new_cluster(0xFFFF), new_attribute(0xFFFF),
|
cluster(0xFFFF), attribute(0xFFFF), new_cluster(0xFFFF), new_attribute(0xFFFF),
|
||||||
multiplier(1)
|
multiplier(1), divider(1), base(0)
|
||||||
{};
|
{};
|
||||||
|
|
||||||
void set(uint16_t cluster, uint16_t attribute, uint16_t new_cluster, uint16_t new_attribute, int8_t multiplier = 1) {
|
void set(uint16_t cluster, uint16_t attribute, uint16_t new_cluster, uint16_t new_attribute,
|
||||||
|
int8_t multiplier = 1, int8_t divider = 1, int16_t base = 0) {
|
||||||
this->cluster = cluster;
|
this->cluster = cluster;
|
||||||
this->attribute = attribute;
|
this->attribute = attribute;
|
||||||
this->new_cluster = new_cluster;
|
this->new_cluster = new_cluster;
|
||||||
this->new_attribute = new_attribute;
|
this->new_attribute = new_attribute;
|
||||||
this->multiplier = multiplier;
|
this->multiplier = multiplier;
|
||||||
|
this->divider = divider;
|
||||||
|
this->base = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool found(void) const { return cluster != 0xFFFF && attribute != 0xFFFF; }
|
inline bool found(void) const { return cluster != 0xFFFF && attribute != 0xFFFF; }
|
||||||
|
@ -315,7 +322,9 @@ public:
|
||||||
uint16_t attribute; // attribute to match
|
uint16_t attribute; // attribute to match
|
||||||
uint16_t new_cluster; // replace with this cluster
|
uint16_t new_cluster; // replace with this cluster
|
||||||
uint16_t new_attribute; // replace with this attribute
|
uint16_t new_attribute; // replace with this attribute
|
||||||
int8_t multiplier; // mutliplier if different than 1 (otherwise don't change value)
|
int8_t multiplier; // multiply by x (ignore if 0 or 1)
|
||||||
|
int8_t divider; // divide by x (ignore if 0 or 1)
|
||||||
|
int16_t base; // add x (ignore if 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -457,6 +466,8 @@ public:
|
||||||
const char * name = nullptr;
|
const char * name = nullptr;
|
||||||
uint8_t zigbee_type = Znodata;
|
uint8_t zigbee_type = Znodata;
|
||||||
int8_t multiplier = 1;
|
int8_t multiplier = 1;
|
||||||
|
int8_t divider = 1;
|
||||||
|
int8_t base = 0;
|
||||||
uint8_t map_offset = 0;
|
uint8_t map_offset = 0;
|
||||||
Z_Data_Type map_type = Z_Data_Type::Z_Unknown;
|
Z_Data_Type map_type = Z_Data_Type::Z_Unknown;
|
||||||
uint16_t manuf = 0x0000; // manuf code (if any)
|
uint16_t manuf = 0x0000; // manuf code (if any)
|
||||||
|
|
|
@ -46,7 +46,9 @@ class Z_attribute_match Z_findAttributeMatcherByName(uint16_t shortaddr, const c
|
||||||
matched_attr.cluster = CxToCluster(pgm_read_byte(&converter->cluster_short));
|
matched_attr.cluster = CxToCluster(pgm_read_byte(&converter->cluster_short));
|
||||||
matched_attr.attribute = pgm_read_word(&converter->attribute);
|
matched_attr.attribute = pgm_read_word(&converter->attribute);
|
||||||
matched_attr.name = (Z_strings + pgm_read_word(&converter->name_offset));
|
matched_attr.name = (Z_strings + pgm_read_word(&converter->name_offset));
|
||||||
matched_attr.multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx));
|
int8_t multiplier8 = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx));
|
||||||
|
if (multiplier8 > 1) { matched_attr.multiplier = multiplier8; }
|
||||||
|
if (multiplier8 < 0) { matched_attr.divider = -multiplier8; }
|
||||||
matched_attr.zigbee_type = pgm_read_byte(&converter->type);
|
matched_attr.zigbee_type = pgm_read_byte(&converter->type);
|
||||||
uint8_t conv_mapping = pgm_read_byte(&converter->mapping);
|
uint8_t conv_mapping = pgm_read_byte(&converter->mapping);
|
||||||
matched_attr.map_type = (Z_Data_Type) ((conv_mapping & 0xF0)>>4);
|
matched_attr.map_type = (Z_Data_Type) ((conv_mapping & 0xF0)>>4);
|
||||||
|
@ -77,7 +79,9 @@ class Z_attribute_match Z_findAttributeMatcherById(uint16_t shortaddr, uint16_t
|
||||||
matched_attr.cluster = cluster;
|
matched_attr.cluster = cluster;
|
||||||
matched_attr.attribute = attr_id;
|
matched_attr.attribute = attr_id;
|
||||||
matched_attr.name = (Z_strings + pgm_read_word(&converter->name_offset));
|
matched_attr.name = (Z_strings + pgm_read_word(&converter->name_offset));
|
||||||
matched_attr.multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx));
|
int8_t multiplier8 = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx));
|
||||||
|
if (multiplier8 > 1) { matched_attr.multiplier = multiplier8; }
|
||||||
|
if (multiplier8 < 0) { matched_attr.divider = -multiplier8; }
|
||||||
matched_attr.zigbee_type = pgm_read_byte(&converter->type);
|
matched_attr.zigbee_type = pgm_read_byte(&converter->type);
|
||||||
uint8_t conv_mapping = pgm_read_byte(&converter->mapping);
|
uint8_t conv_mapping = pgm_read_byte(&converter->mapping);
|
||||||
matched_attr.map_type = (Z_Data_Type) ((conv_mapping & 0xF0)>>4);
|
matched_attr.map_type = (Z_Data_Type) ((conv_mapping & 0xF0)>>4);
|
||||||
|
@ -697,11 +701,18 @@ void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) {
|
||||||
attr.cluster, attr.attr_id);
|
attr.cluster, attr.attr_id);
|
||||||
if (syn.found()) {
|
if (syn.found()) {
|
||||||
attr.setKeyId(syn.new_cluster, syn.new_attribute);
|
attr.setKeyId(syn.new_cluster, syn.new_attribute);
|
||||||
if (syn.multiplier != 1 && syn.multiplier != 0) {
|
if ((syn.multiplier != 1 && syn.multiplier != 0) || (syn.divider != 1 && syn.divider != 0) || (syn.base != 0)) {
|
||||||
// we need to change the value
|
// we need to change the value
|
||||||
float fval = attr.getFloat();
|
float fval = attr.getFloat();
|
||||||
if (syn.multiplier > 0) { fval = fval * syn.multiplier; }
|
if (syn.multiplier != 1 && syn.multiplier != 0) {
|
||||||
else { fval = fval / (-syn.multiplier); }
|
fval = fval * syn.multiplier;
|
||||||
|
}
|
||||||
|
if (syn.divider != 1 && syn.divider != 0) {
|
||||||
|
fval = fval / syn.divider;
|
||||||
|
}
|
||||||
|
if (syn.base != 0) {
|
||||||
|
fval = fval + syn.base;
|
||||||
|
}
|
||||||
attr.setFloat(fval);
|
attr.setFloat(fval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -945,10 +956,14 @@ void ZCLFrame::parseReadConfigAttributes(uint16_t shortaddr, Z_attribute_list& a
|
||||||
|
|
||||||
// find the multiplier
|
// find the multiplier
|
||||||
int8_t multiplier = 1;
|
int8_t multiplier = 1;
|
||||||
|
int8_t divider = 1;
|
||||||
|
int16_t base = 0;
|
||||||
Z_attribute_match matched_attr = Z_findAttributeMatcherById(shortaddr, cluster, attrid, false);
|
Z_attribute_match matched_attr = Z_findAttributeMatcherById(shortaddr, cluster, attrid, false);
|
||||||
if (matched_attr.found()) {
|
if (matched_attr.found()) {
|
||||||
attr_2.addAttribute(matched_attr.name, true).setBool(true);
|
attr_2.addAttribute(matched_attr.name, true).setBool(true);
|
||||||
multiplier = matched_attr.multiplier;
|
multiplier = matched_attr.multiplier;
|
||||||
|
divider = matched_attr.divider;
|
||||||
|
base = matched_attr.base;
|
||||||
}
|
}
|
||||||
i += 4;
|
i += 4;
|
||||||
if (0 != status) {
|
if (0 != status) {
|
||||||
|
@ -974,10 +989,18 @@ void ZCLFrame::parseReadConfigAttributes(uint16_t shortaddr, Z_attribute_list& a
|
||||||
// decode Reportable Change
|
// decode Reportable Change
|
||||||
Z_attribute &attr_change = attr_2.addAttributePMEM(PSTR("ReportableChange"));
|
Z_attribute &attr_change = attr_2.addAttributePMEM(PSTR("ReportableChange"));
|
||||||
i += parseSingleAttribute(attr_change, payload, i, attr_type);
|
i += parseSingleAttribute(attr_change, payload, i, attr_type);
|
||||||
if ((1 != multiplier) && (0 != multiplier)) {
|
|
||||||
|
if ((multiplier != 1 && multiplier != 0) || (divider != 1 && divider != 0) || (base != 0)) {
|
||||||
float fval = attr_change.getFloat();
|
float fval = attr_change.getFloat();
|
||||||
if (multiplier > 0) { fval = fval * multiplier; }
|
if (multiplier != 1 && multiplier != 0) {
|
||||||
else { fval = fval / (-multiplier); }
|
fval = fval * multiplier;
|
||||||
|
}
|
||||||
|
if (divider != 1 && divider != 0) {
|
||||||
|
fval = fval / divider;
|
||||||
|
}
|
||||||
|
if (base != 0) {
|
||||||
|
fval = fval + base;
|
||||||
|
}
|
||||||
attr_change.setFloat(fval);
|
attr_change.setFloat(fval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1480,9 +1503,16 @@ void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attrib
|
||||||
// now apply the multiplier to make it human readable
|
// now apply the multiplier to make it human readable
|
||||||
if (found) {
|
if (found) {
|
||||||
if (0 == matched_attr.multiplier) { attr_list.removeAttribute(&attr); continue; } // remove attribute if multiplier is zero
|
if (0 == matched_attr.multiplier) { attr_list.removeAttribute(&attr); continue; } // remove attribute if multiplier is zero
|
||||||
if (1 != matched_attr.multiplier) {
|
if ((matched_attr.multiplier != 1 && matched_attr.multiplier != 0) || (matched_attr.divider != 1 && matched_attr.divider != 0) || (matched_attr.base != 0)) {
|
||||||
if (matched_attr.multiplier > 0) { fval = fval * matched_attr.multiplier; }
|
if (matched_attr.multiplier != 1 && matched_attr.multiplier != 0) {
|
||||||
else { fval = fval / (-matched_attr.multiplier); }
|
fval = fval * matched_attr.multiplier;
|
||||||
|
}
|
||||||
|
if (matched_attr.divider != 1 && matched_attr.divider != 0) {
|
||||||
|
fval = fval / matched_attr.divider;
|
||||||
|
}
|
||||||
|
if (matched_attr.base != 0) {
|
||||||
|
fval = fval + matched_attr.base;
|
||||||
|
}
|
||||||
attr.setFloat(fval);
|
attr.setFloat(fval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1509,6 +1539,7 @@ void Z_parseAttributeKey_inner(uint16_t shortaddr, class Z_attribute & attr, uin
|
||||||
attr.setKeyId(matched_attr.cluster, matched_attr.attribute);
|
attr.setKeyId(matched_attr.cluster, matched_attr.attribute);
|
||||||
attr.attr_type = matched_attr.zigbee_type;
|
attr.attr_type = matched_attr.zigbee_type;
|
||||||
attr.attr_multiplier = matched_attr.multiplier;
|
attr.attr_multiplier = matched_attr.multiplier;
|
||||||
|
attr.attr_divider = matched_attr.divider;
|
||||||
attr.manuf = matched_attr.manuf;
|
attr.manuf = matched_attr.manuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1592,7 +1623,11 @@ void Z_Data::toAttributes(Z_attribute_list & attr_list) const {
|
||||||
const Z_AttributeConverter *converter = &Z_PostProcess[i];
|
const Z_AttributeConverter *converter = &Z_PostProcess[i];
|
||||||
uint8_t conv_export = pgm_read_byte(&converter->multiplier_idx) & Z_EXPORT_DATA;
|
uint8_t conv_export = pgm_read_byte(&converter->multiplier_idx) & Z_EXPORT_DATA;
|
||||||
uint8_t conv_mapping = pgm_read_byte(&converter->mapping);
|
uint8_t conv_mapping = pgm_read_byte(&converter->mapping);
|
||||||
int8_t multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx));
|
int8_t multiplier = 1;
|
||||||
|
int8_t divider = 1;
|
||||||
|
int8_t multiplier8 = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx));
|
||||||
|
if (multiplier8 > 1) { multiplier = multiplier8; }
|
||||||
|
if (multiplier8 < 0) { divider = -multiplier8; }
|
||||||
Z_Data_Type map_type = (Z_Data_Type) ((conv_mapping & 0xF0)>>4);
|
Z_Data_Type map_type = (Z_Data_Type) ((conv_mapping & 0xF0)>>4);
|
||||||
uint8_t map_offset = (conv_mapping & 0x0F);
|
uint8_t map_offset = (conv_mapping & 0x0F);
|
||||||
|
|
||||||
|
@ -1624,9 +1659,13 @@ void Z_Data::toAttributes(Z_attribute_list & attr_list) const {
|
||||||
float fval;
|
float fval;
|
||||||
if (data_size > 0) { fval = uval32; }
|
if (data_size > 0) { fval = uval32; }
|
||||||
else { fval = ival32; }
|
else { fval = ival32; }
|
||||||
if ((1 != multiplier) && (0 != multiplier)) {
|
if ((multiplier != 1 && multiplier != 0) || (divider != 1 && divider != 0)) {
|
||||||
if (multiplier > 0) { fval = fval * multiplier; }
|
if (multiplier != 1 && multiplier != 0) {
|
||||||
else { fval = fval / (-multiplier); }
|
fval = fval * multiplier;
|
||||||
|
}
|
||||||
|
if (divider != 1 && divider != 0) {
|
||||||
|
fval = fval / divider;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
attr.setFloat(fval);
|
attr.setFloat(fval);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
const char Z_MUL[] PROGMEM = "mul:";
|
const char Z_MUL[] PROGMEM = "mul:";
|
||||||
const char Z_DIV[] PROGMEM = "div:";
|
const char Z_DIV[] PROGMEM = "div:";
|
||||||
const char Z_MANUF[] PROGMEM = "manuf:";
|
const char Z_MANUF[] PROGMEM = "manuf:";
|
||||||
|
const char Z_OFFSET[] PROGMEM = "offset:";
|
||||||
|
|
||||||
char * Z_subtoken(char * token, const char * prefix) {
|
char * Z_subtoken(char * token, const char * prefix) {
|
||||||
size_t prefix_len = strlen_P(prefix);
|
size_t prefix_len = strlen_P(prefix);
|
||||||
|
@ -60,6 +61,8 @@ Z_attribute_match Z_plugin_matchAttributeById(const char *model, const char *man
|
||||||
attr.name = attr_tmpl->name.c_str();
|
attr.name = attr_tmpl->name.c_str();
|
||||||
attr.zigbee_type = attr_tmpl->type;
|
attr.zigbee_type = attr_tmpl->type;
|
||||||
attr.multiplier = attr_tmpl->multiplier;
|
attr.multiplier = attr_tmpl->multiplier;
|
||||||
|
attr.divider = attr_tmpl->divider;
|
||||||
|
attr.base = attr_tmpl->base;
|
||||||
attr.manuf = attr_tmpl->manuf;
|
attr.manuf = attr_tmpl->manuf;
|
||||||
}
|
}
|
||||||
return attr;
|
return attr;
|
||||||
|
@ -80,6 +83,8 @@ Z_attribute_match Z_plugin_matchAttributeByName(const char *model, const char *m
|
||||||
attr.name = attr_tmpl->name.c_str();
|
attr.name = attr_tmpl->name.c_str();
|
||||||
attr.zigbee_type = attr_tmpl->type;
|
attr.zigbee_type = attr_tmpl->type;
|
||||||
attr.multiplier = attr_tmpl->multiplier;
|
attr.multiplier = attr_tmpl->multiplier;
|
||||||
|
attr.divider = attr_tmpl->divider;
|
||||||
|
attr.base = attr_tmpl->base;
|
||||||
attr.manuf = attr_tmpl->manuf;
|
attr.manuf = attr_tmpl->manuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,6 +236,8 @@ bool ZbLoad(const char *filename_raw) {
|
||||||
uint16_t cluster_id = 0xFFFF;
|
uint16_t cluster_id = 0xFFFF;
|
||||||
uint8_t type_id = Zunk;
|
uint8_t type_id = Zunk;
|
||||||
int8_t multiplier = 1;
|
int8_t multiplier = 1;
|
||||||
|
int8_t divider = 1;
|
||||||
|
int16_t base = 0;
|
||||||
char * name = nullptr;
|
char * name = nullptr;
|
||||||
uint16_t manuf = 0;
|
uint16_t manuf = 0;
|
||||||
|
|
||||||
|
@ -254,11 +261,15 @@ bool ZbLoad(const char *filename_raw) {
|
||||||
char * sub_token;
|
char * sub_token;
|
||||||
// look for multiplier
|
// look for multiplier
|
||||||
if (sub_token = Z_subtoken(token, Z_MUL)) {
|
if (sub_token = Z_subtoken(token, Z_MUL)) {
|
||||||
multiplier = strtoul(sub_token, nullptr, 10);
|
multiplier = strtol(sub_token, nullptr, 10);
|
||||||
}
|
}
|
||||||
// look for divider
|
// look for divider
|
||||||
else if (sub_token = Z_subtoken(token, Z_DIV)) {
|
else if (sub_token = Z_subtoken(token, Z_DIV)) {
|
||||||
multiplier = - strtoul(sub_token, nullptr, 10); // negative to indicate divider
|
divider = strtol(sub_token, nullptr, 10); // negative to indicate divider
|
||||||
|
}
|
||||||
|
// look for offset (base)
|
||||||
|
else if (sub_token = Z_subtoken(token, Z_OFFSET)) {
|
||||||
|
base = strtol(sub_token, nullptr, 10); // negative to indicate divider
|
||||||
}
|
}
|
||||||
// look for `manuf:HHHH`
|
// look for `manuf:HHHH`
|
||||||
else if (sub_token = Z_subtoken(token, Z_MANUF)) {
|
else if (sub_token = Z_subtoken(token, Z_MANUF)) {
|
||||||
|
@ -276,6 +287,8 @@ bool ZbLoad(const char *filename_raw) {
|
||||||
plugin_attr.type = type_id;
|
plugin_attr.type = type_id;
|
||||||
plugin_attr.name = name;
|
plugin_attr.name = name;
|
||||||
plugin_attr.multiplier = multiplier;
|
plugin_attr.multiplier = multiplier;
|
||||||
|
plugin_attr.divider = divider;
|
||||||
|
plugin_attr.base = base;
|
||||||
plugin_attr.manuf = manuf;
|
plugin_attr.manuf = manuf;
|
||||||
} else {
|
} else {
|
||||||
// ATTRIBUTE SYNONYM
|
// ATTRIBUTE SYNONYM
|
||||||
|
@ -290,17 +303,23 @@ bool ZbLoad(const char *filename_raw) {
|
||||||
uint16_t new_cluster_id = strtoul(tok2, &delimiter_slash2, 16);
|
uint16_t new_cluster_id = strtoul(tok2, &delimiter_slash2, 16);
|
||||||
uint16_t new_attr_id = strtoul(delimiter_slash2+1, nullptr, 16);
|
uint16_t new_attr_id = strtoul(delimiter_slash2+1, nullptr, 16);
|
||||||
int8_t multiplier = 1;
|
int8_t multiplier = 1;
|
||||||
|
int8_t divider = 1;
|
||||||
|
int16_t base = 0;
|
||||||
|
|
||||||
// ADDITIONAL ELEMENTS?
|
// ADDITIONAL ELEMENTS?
|
||||||
while (token = strtok_r(rest, ",", &rest)) {
|
while (token = strtok_r(rest, ",", &rest)) {
|
||||||
char * sub_token;
|
char * sub_token;
|
||||||
// look for multiplier
|
// look for multiplier
|
||||||
if (sub_token = Z_subtoken(token, Z_MUL)) {
|
if (sub_token = Z_subtoken(token, Z_MUL)) {
|
||||||
multiplier = strtoul(sub_token, nullptr, 10);
|
multiplier = strtol(sub_token, nullptr, 10);
|
||||||
}
|
}
|
||||||
// look for divider
|
// look for divider
|
||||||
else if (sub_token = Z_subtoken(token, Z_DIV)) {
|
else if (sub_token = Z_subtoken(token, Z_DIV)) {
|
||||||
multiplier = - strtoul(sub_token, nullptr, 10); // negative to indicate divider
|
divider = strtol(sub_token, nullptr, 10); // negative to indicate divider
|
||||||
|
}
|
||||||
|
// look for offset (base)
|
||||||
|
else if (sub_token = Z_subtoken(token, Z_OFFSET)) {
|
||||||
|
base = strtol(sub_token, nullptr, 10); // negative to indicate divider
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AddLog(LOG_LEVEL_DEBUG, "ZIG: ZbLoad unrecognized modifier '%s'", token);
|
AddLog(LOG_LEVEL_DEBUG, "ZIG: ZbLoad unrecognized modifier '%s'", token);
|
||||||
|
@ -313,6 +332,8 @@ bool ZbLoad(const char *filename_raw) {
|
||||||
syn.new_cluster = new_cluster_id;
|
syn.new_cluster = new_cluster_id;
|
||||||
syn.new_attribute = new_attr_id;
|
syn.new_attribute = new_attr_id;
|
||||||
syn.multiplier = multiplier;
|
syn.multiplier = multiplier;
|
||||||
|
syn.divider = divider;
|
||||||
|
syn.base = base;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,9 +381,15 @@ bool ZbUnload(const char *filename_raw) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// append modifiers like mul/div/manuf
|
// append modifiers like mul/div/manuf
|
||||||
void Z_AppendModifiers(char * buf, size_t buf_len, int8_t multiplier, uint16_t manuf) {
|
void Z_AppendModifiers(char * buf, size_t buf_len, int8_t multiplier, int8_t divider, int16_t base, uint16_t manuf) {
|
||||||
if (multiplier != 0 && multiplier != 1) {
|
if (multiplier != 0 && multiplier != 1) {
|
||||||
ext_snprintf_P(buf, buf_len, "%s,%s%i", buf, multiplier > 0 ? Z_MUL : Z_DIV, multiplier > 0 ? multiplier : -multiplier);
|
ext_snprintf_P(buf, buf_len, "%s,%s%i", buf, Z_MUL, multiplier);
|
||||||
|
}
|
||||||
|
if (divider != 0 && divider != 1) {
|
||||||
|
ext_snprintf_P(buf, buf_len, "%s,%s%i", buf, Z_DIV, divider);
|
||||||
|
}
|
||||||
|
if (base != 0) {
|
||||||
|
ext_snprintf_P(buf, buf_len, "%s,%s%i", buf, Z_OFFSET, base);
|
||||||
}
|
}
|
||||||
if (manuf) {
|
if (manuf) {
|
||||||
ext_snprintf_P(buf, buf_len, "%s,%s%04X", buf, Z_MANUF, manuf);
|
ext_snprintf_P(buf, buf_len, "%s,%s%04X", buf, Z_MANUF, manuf);
|
||||||
|
@ -403,12 +430,12 @@ void ZbLoadDump(void) {
|
||||||
Z_getTypeByNumber(type_str, sizeof(type_str), attr.type);
|
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, type_str);
|
||||||
}
|
}
|
||||||
Z_AppendModifiers(buf, sizeof(buf), attr.multiplier, attr.manuf);
|
Z_AppendModifiers(buf, sizeof(buf), attr.multiplier, attr.divider, attr.base, attr.manuf);
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("%s"), buf);
|
AddLog(LOG_LEVEL_INFO, PSTR("%s"), buf);
|
||||||
}
|
}
|
||||||
for (const Z_attribute_synonym & syn : tmpl.synonyms) {
|
for (const Z_attribute_synonym & syn : tmpl.synonyms) {
|
||||||
ext_snprintf_P(buf, sizeof(buf), "%04X/%04X=%04X/%04X", syn.cluster, syn.attribute, syn.new_cluster, syn.new_attribute);
|
ext_snprintf_P(buf, sizeof(buf), "%04X/%04X=%04X/%04X", syn.cluster, syn.attribute, syn.new_cluster, syn.new_attribute);
|
||||||
Z_AppendModifiers(buf, sizeof(buf), syn.multiplier, 0);
|
Z_AppendModifiers(buf, sizeof(buf), syn.multiplier, syn.divider, syn.base, 0);
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("%s"), buf);
|
AddLog(LOG_LEVEL_INFO, PSTR("%s"), buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1568,7 +1568,7 @@ void Z_AutoConfigReportingForCluster(uint16_t shortaddr, uint16_t groupaddr, uin
|
||||||
buf.add16(min_interval);
|
buf.add16(min_interval);
|
||||||
buf.add16(max_interval);
|
buf.add16(max_interval);
|
||||||
if (!Z_isDiscreteDataType(attr_matched.zigbee_type)) { // report_change is only valid for non-discrete data types (numbers)
|
if (!Z_isDiscreteDataType(attr_matched.zigbee_type)) { // report_change is only valid for non-discrete data types (numbers)
|
||||||
ZbApplyMultiplier(report_change, attr_matched.multiplier);
|
ZbApplyMultiplier(report_change, attr_matched.multiplier, attr_matched.divider, attr_matched.base);
|
||||||
// encode value
|
// encode value
|
||||||
int32_t res = encodeSingleAttribute(buf, report_change, "", attr_matched.zigbee_type);
|
int32_t res = encodeSingleAttribute(buf, report_change, "", attr_matched.zigbee_type);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
|
|
@ -222,15 +222,15 @@ void zigbeeZCLSendCmd(class ZCLFrame &zcl) {
|
||||||
// Special encoding for multiplier:
|
// Special encoding for multiplier:
|
||||||
// multiplier == 0: ignore
|
// multiplier == 0: ignore
|
||||||
// multiplier == 1: ignore
|
// multiplier == 1: ignore
|
||||||
// multiplier > 0: divide by the multiplier
|
void ZbApplyMultiplier(double &val_d, int8_t multiplier, int8_t divider, int8_t base) {
|
||||||
// multiplier < 0: multiply by the -multiplier (positive)
|
|
||||||
void ZbApplyMultiplier(double &val_d, int8_t multiplier) {
|
|
||||||
if ((0 != multiplier) && (1 != multiplier)) {
|
if ((0 != multiplier) && (1 != multiplier)) {
|
||||||
if (multiplier > 0) { // inverse of decoding
|
val_d = val_d * multiplier;
|
||||||
val_d = val_d / multiplier;
|
|
||||||
} else {
|
|
||||||
val_d = val_d * (-multiplier);
|
|
||||||
}
|
}
|
||||||
|
if ((0 != divider) && (1 != divider)) {
|
||||||
|
val_d = val_d / divider;
|
||||||
|
}
|
||||||
|
if (0 != base) {
|
||||||
|
val_d = val_d + base;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,8 +242,8 @@ bool ZbTuyaWrite(SBuffer & buf, const Z_attribute & attr) {
|
||||||
const char * val_str = attr.getStr();
|
const char * val_str = attr.getStr();
|
||||||
|
|
||||||
if (attr.key_is_str || attr.key_is_cmd) { return false; } // couldn't find attr if so skip
|
if (attr.key_is_str || attr.key_is_cmd) { return false; } // couldn't find attr if so skip
|
||||||
if (attr.isNum() && (1 != attr.attr_multiplier)) {
|
if (attr.isNum()) {
|
||||||
ZbApplyMultiplier(val_d, attr.attr_multiplier);
|
ZbApplyMultiplier(val_d, attr.attr_multiplier, attr.attr_divider, 0);
|
||||||
}
|
}
|
||||||
uint32_t u32 = val_d;
|
uint32_t u32 = val_d;
|
||||||
int32_t i32 = val_d;
|
int32_t i32 = val_d;
|
||||||
|
@ -301,8 +301,8 @@ bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_stat
|
||||||
const char * val_str = attr.getStr();
|
const char * val_str = attr.getStr();
|
||||||
|
|
||||||
if (attr.key_is_str && attr.key_is_cmd) { return false; } // couldn't find attr if so skip
|
if (attr.key_is_str && attr.key_is_cmd) { return false; } // couldn't find attr if so skip
|
||||||
if (attr.isNum() && (1 != attr.attr_multiplier)) {
|
if (attr.isNum()) {
|
||||||
ZbApplyMultiplier(val_d, attr.attr_multiplier);
|
ZbApplyMultiplier(val_d, attr.attr_multiplier, attr.attr_divider, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// push the value in the buffer
|
// push the value in the buffer
|
||||||
|
@ -421,7 +421,7 @@ void ZbSendReportWrite(class JsonParserToken val_pubwrite, class ZCLFrame & zcl)
|
||||||
if (val_attr_rc) {
|
if (val_attr_rc) {
|
||||||
val_d = val_attr_rc.getFloat();
|
val_d = val_attr_rc.getFloat();
|
||||||
val_str = val_attr_rc.getStr();
|
val_str = val_attr_rc.getStr();
|
||||||
ZbApplyMultiplier(val_d, attr.attr_multiplier);
|
ZbApplyMultiplier(val_d, attr.attr_multiplier, attr.attr_divider, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// read TimeoutPeriod
|
// read TimeoutPeriod
|
||||||
|
|
|
@ -254,15 +254,16 @@ extern "C" {
|
||||||
|
|
||||||
extern const be_ctypes_structure_t be_zigbee_zcl_attribute_struct = {
|
extern const be_ctypes_structure_t be_zigbee_zcl_attribute_struct = {
|
||||||
sizeof(Z_attribute), /* size in bytes */
|
sizeof(Z_attribute), /* size in bytes */
|
||||||
8, /* number of elements */
|
9, /* number of elements */
|
||||||
nullptr,
|
nullptr,
|
||||||
(const be_ctypes_structure_item_t[8]) {
|
(const be_ctypes_structure_item_t[9]) {
|
||||||
{ "_attr_id", offsetof(Z_attribute, attr_id), 0, 0, ctypes_u16, 0 },
|
{ "_attr_id", offsetof(Z_attribute, attr_id), 0, 0, ctypes_u16, 0 },
|
||||||
{ "_cluster", offsetof(Z_attribute, cluster), 0, 0, ctypes_u16, 0 },
|
{ "_cluster", offsetof(Z_attribute, cluster), 0, 0, ctypes_u16, 0 },
|
||||||
{ "_cmd", offsetof(Z_attribute, attr_id), 0, 0, ctypes_u8, 0 }, // low 8 bits of attr_id
|
{ "_cmd", offsetof(Z_attribute, attr_id), 0, 0, ctypes_u8, 0 }, // low 8 bits of attr_id
|
||||||
{ "_direction", offsetof(Z_attribute, attr_id) + 1, 0, 0, ctypes_u8, 0 }, // high 8 bits of attr_id
|
{ "_direction", offsetof(Z_attribute, attr_id) + 1, 0, 0, ctypes_u8, 0 }, // high 8 bits of attr_id
|
||||||
{ "_iscmd", offsetof(Z_attribute, key_is_cmd), 0, 0, ctypes_u8, 0 },
|
{ "_iscmd", offsetof(Z_attribute, key_is_cmd), 0, 0, ctypes_u8, 0 },
|
||||||
{ "attr_multiplier", offsetof(Z_attribute, attr_multiplier), 0, 0, ctypes_i8, 0 },
|
{ "attr_multiplier", offsetof(Z_attribute, attr_multiplier), 0, 0, ctypes_i8, 0 },
|
||||||
|
{ "attr_divider", offsetof(Z_attribute, attr_divider), 0, 0, ctypes_i8, 0 },
|
||||||
{ "attr_type", offsetof(Z_attribute, attr_type), 0, 0, ctypes_u8, 0 },
|
{ "attr_type", offsetof(Z_attribute, attr_type), 0, 0, ctypes_u8, 0 },
|
||||||
// { "key", offsetof(Z_attribute, key), 0, 0, ctypes_ptr32, 0 },
|
// { "key", offsetof(Z_attribute, key), 0, 0, ctypes_ptr32, 0 },
|
||||||
// { "key_is_pmem", offsetof(Z_attribute, key_is_pmem), 0, 0, ctypes_u8, 0 },
|
// { "key_is_pmem", offsetof(Z_attribute, key_is_pmem), 0, 0, ctypes_u8, 0 },
|
||||||
|
|
Loading…
Reference in New Issue