Merge pull request #16567 from s-hadinger/zigbee_fix_attr_write

Fix zigbee attribute writes and configuration
This commit is contained in:
s-hadinger 2022-09-18 19:39:53 +02:00 committed by GitHub
commit 67239431f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 17 deletions

View File

@ -278,10 +278,12 @@ uint8_t toPercentageCR2032(uint32_t voltage) {
// Adds to buf:
// - n bytes: value (typically between 1 and 4 bytes, or bigger for strings)
// returns number of bytes of attribute, or <0 if error
// If the value is `NAN`, the value encoded is the "zigbee invalid value"
int32_t encodeSingleAttribute(SBuffer &buf, double val_d, const char *val_str, uint8_t attrtype) {
uint32_t len = Z_getDatatypeLen(attrtype); // pre-compute length, overloaded for variable length attributes
uint32_t u32 = val_d;
int32_t i32 = val_d;
bool nan = isnan(val_d);
uint32_t u32 = nan ? 0xFFFFFFFF : roundf(val_d);
int32_t i32 = roundf(val_d);
float f32 = val_d;
switch (attrtype) {
@ -315,13 +317,13 @@ int32_t encodeSingleAttribute(SBuffer &buf, double val_d, const char *val_str, u
// signed 8
case Zint8: // int8
buf.add8(i32);
buf.add8(nan ? 0x80 : i32);
break;
case Zint16: // int16
buf.add16(i32);
buf.add16(nan ? 0x8000 : i32);
break;
case Zint32: // int32
buf.add32(i32);
buf.add32(nan ? 0x80000000 : i32);
break;
case Zsingle: // float

View File

@ -1594,7 +1594,7 @@ void Z_AutoConfigReportingForCluster(uint16_t shortaddr, uint16_t groupaddr, uin
buf.add16(min_interval);
buf.add16(max_interval);
if (!Z_isDiscreteDataType(attr_matched.zigbee_type)) { // report_change is only valid for non-discrete data types (numbers)
ZbApplyMultiplier(report_change, attr_matched.multiplier, attr_matched.divider, attr_matched.base);
ZbApplyMultiplierForWrites(report_change, attr_matched.multiplier, attr_matched.divider, attr_matched.base);
// encode value
int32_t res = encodeSingleAttribute(buf, report_change, "", attr_matched.zigbee_type);
if (res < 0) {

View File

@ -219,18 +219,20 @@ void zigbeeZCLSendCmd(class ZCLFrame &zcl) {
// Definitive doc for Tuya protocol:
// https://developer.tuya.com/en/docs/iot-device-dev/tuya-zigbee-universal-docking-access-standard?id=K9ik6zvofpzql#subtitle-6-Private%20cluster
// Special encoding for multiplier:
// Special encoding for multiplier when sending writes or reportable attributes,
// I.e. multipliers and dividers are inversed
// multiplier == 0: ignore
// multiplier == 1: ignore
void ZbApplyMultiplier(double &val_d, int8_t multiplier, int8_t divider, int8_t base) {
void ZbApplyMultiplierForWrites(double &val_d, int8_t multiplier, int8_t divider, int8_t base) {
if (0 != base) {
val_d = val_d - base;
}
if ((0 != multiplier) && (1 != multiplier)) {
val_d = val_d * multiplier;
val_d = val_d / multiplier;
}
if ((0 != divider) && (1 != divider)) {
val_d = val_d / divider;
}
if (0 != base) {
val_d = val_d + base;
val_d = val_d * divider;
}
}
@ -243,7 +245,7 @@ bool ZbTuyaWrite(SBuffer & buf, const Z_attribute & attr) {
if (attr.key_is_str || attr.key_is_cmd) { return false; } // couldn't find attr if so skip
if (attr.isNum()) {
ZbApplyMultiplier(val_d, attr.attr_multiplier, attr.attr_divider, 0);
ZbApplyMultiplierForWrites(val_d, attr.attr_multiplier, attr.attr_divider, 0);
}
uint32_t u32 = val_d;
int32_t i32 = val_d;
@ -302,7 +304,7 @@ bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_stat
if (attr.key_is_str && attr.key_is_cmd) { return false; } // couldn't find attr if so skip
if (attr.isNum()) {
ZbApplyMultiplier(val_d, attr.attr_multiplier, attr.attr_divider, 0);
ZbApplyMultiplierForWrites(val_d, attr.attr_multiplier, attr.attr_divider, 0);
}
// push the value in the buffer
@ -419,9 +421,14 @@ void ZbSendReportWrite(class JsonParserToken val_pubwrite, class ZCLFrame & zcl)
// read ReportableChange
JsonParserToken val_attr_rc = attr_config[PSTR("ReportableChange")];
if (val_attr_rc) {
val_d = val_attr_rc.getFloat();
// If value is `null` then we send 0xFFFF for invalid value
val_str = val_attr_rc.getStr();
ZbApplyMultiplier(val_d, attr.attr_multiplier, attr.attr_divider, 0);
if (!val_attr_rc.isNull()) {
val_d = val_attr_rc.getFloat();
ZbApplyMultiplierForWrites(val_d, attr.attr_multiplier, attr.attr_divider, 0);
} else {
val_d = NAN;
}
}
// read TimeoutPeriod