mirror of
https://github.com/arendst/Tasmota.git
synced 2025-04-25 07:17:16 +00:00
Zigbee report unprocessed attributes
This commit is contained in:
parent
af039838b6
commit
eb65038b6c
@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file.
|
||||
- IRremoteESP8266 library from v2.8.2 to v2.8.3
|
||||
- Tasmota Core32 from 2.0.4.1 to 2.0.5
|
||||
- IRremoteESP8266 library from v2.8.3 to v2.8.4
|
||||
- Zigbee report unprocessed attributes
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -34,8 +34,9 @@ class zcl_attribute : zcl_attribute_ntv
|
||||
var v = self._cmd
|
||||
return ((v != 0xFF) && self._iscmd) ? v : nil
|
||||
elif k == "direction"
|
||||
var v = self._direction
|
||||
return ((v != 0xFF) && self._iscmd) ? (v & 0x01) : nil
|
||||
return self._direction
|
||||
elif k == "cmd_general"
|
||||
return self._cmd_general
|
||||
elif k == "val"
|
||||
var v = self._get_val()
|
||||
if isinstance(v, bytes)
|
||||
@ -69,13 +70,13 @@ class zcl_attribute : zcl_attribute_ntv
|
||||
else
|
||||
self._cmd = v
|
||||
self._iscmd = 1
|
||||
if self._direction == 0xFF # default direction
|
||||
self._direction = 0
|
||||
end
|
||||
# if self._direction == 0xFF # default direction
|
||||
# self._direction = 0
|
||||
# end
|
||||
end
|
||||
elif k == "direction"
|
||||
if v == nil
|
||||
self._direction = 0xFF
|
||||
self._direction = 0
|
||||
else
|
||||
self._direction = v ? 0x01 : 0x00
|
||||
self._iscmd = 1
|
||||
@ -117,7 +118,7 @@ class zcl_attribute : zcl_attribute_ntv
|
||||
s += "+" + str(self.key_suffix)
|
||||
end
|
||||
elif (self.cluster != nil) && (self.cmd != nil) && (self.direction != nil)
|
||||
s = string.format("%04X%s%02X", self.cluster, self.direction ? "<" : "!" ,self.cmd)
|
||||
s = string.format("%04X%s%02X", self.cluster, self.direction ? "?" : "!" ,self.cmd)
|
||||
if self.key_suffix > 1
|
||||
s += "+" + str(self.key_suffix)
|
||||
end
|
||||
|
@ -80,7 +80,7 @@ be_local_closure(zcl_attribute_key_tostring, /* name */
|
||||
/* K10 */ be_nested_str_weak(cmd),
|
||||
/* K11 */ be_nested_str_weak(direction),
|
||||
/* K12 */ be_nested_str_weak(_X2504X_X25s_X2502X),
|
||||
/* K13 */ be_nested_str_weak(_X3C),
|
||||
/* K13 */ be_nested_str_weak(_X3F),
|
||||
/* K14 */ be_nested_str_weak(_X21),
|
||||
}),
|
||||
be_str_weak(key_tostring),
|
||||
@ -185,8 +185,8 @@ be_local_closure(zcl_attribute_setmember, /* name */
|
||||
/* K6 */ be_nested_str_weak(cmd),
|
||||
/* K7 */ be_nested_str_weak(_cmd),
|
||||
/* K8 */ be_const_int(1),
|
||||
/* K9 */ be_nested_str_weak(_direction),
|
||||
/* K10 */ be_nested_str_weak(direction),
|
||||
/* K9 */ be_nested_str_weak(direction),
|
||||
/* K10 */ be_nested_str_weak(_direction),
|
||||
/* K11 */ be_nested_str_weak(val),
|
||||
/* K12 */ be_nested_str_weak(_set_val),
|
||||
/* K13 */ be_nested_str_weak(key),
|
||||
@ -195,7 +195,7 @@ be_local_closure(zcl_attribute_setmember, /* name */
|
||||
}),
|
||||
be_str_weak(setmember),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[72]) { /* code */
|
||||
( &(const binstruction[66]) { /* code */
|
||||
0x1C0C0300, // 0000 EQ R3 R1 K0
|
||||
0x780E0007, // 0001 JMPF R3 #000A
|
||||
0x4C0C0000, // 0002 LDNIL R3
|
||||
@ -205,7 +205,7 @@ be_local_closure(zcl_attribute_setmember, /* name */
|
||||
0x90020203, // 0006 SETMBR R0 K1 R3
|
||||
0x70020000, // 0007 JMP #0009
|
||||
0x90020202, // 0008 SETMBR R0 K1 R2
|
||||
0x7002003C, // 0009 JMP #0047
|
||||
0x70020036, // 0009 JMP #0041
|
||||
0x1C0C0302, // 000A EQ R3 R1 K2
|
||||
0x780E0008, // 000B JMPF R3 #0015
|
||||
0x4C0C0000, // 000C LDNIL R3
|
||||
@ -216,58 +216,52 @@ be_local_closure(zcl_attribute_setmember, /* name */
|
||||
0x70020001, // 0011 JMP #0014
|
||||
0x90020602, // 0012 SETMBR R0 K3 R2
|
||||
0x90020905, // 0013 SETMBR R0 K4 K5
|
||||
0x70020031, // 0014 JMP #0047
|
||||
0x7002002B, // 0014 JMP #0041
|
||||
0x1C0C0306, // 0015 EQ R3 R1 K6
|
||||
0x780E000D, // 0016 JMPF R3 #0025
|
||||
0x780E0008, // 0016 JMPF R3 #0020
|
||||
0x4C0C0000, // 0017 LDNIL R3
|
||||
0x1C0C0403, // 0018 EQ R3 R2 R3
|
||||
0x780E0002, // 0019 JMPF R3 #001D
|
||||
0x540E00FE, // 001A LDINT R3 255
|
||||
0x90020E03, // 001B SETMBR R0 K7 R3
|
||||
0x70020006, // 001C JMP #0024
|
||||
0x70020001, // 001C JMP #001F
|
||||
0x90020E02, // 001D SETMBR R0 K7 R2
|
||||
0x90020908, // 001E SETMBR R0 K4 K8
|
||||
0x880C0109, // 001F GETMBR R3 R0 K9
|
||||
0x541200FE, // 0020 LDINT R4 255
|
||||
0x1C0C0604, // 0021 EQ R3 R3 R4
|
||||
0x780E0000, // 0022 JMPF R3 #0024
|
||||
0x90021305, // 0023 SETMBR R0 K9 K5
|
||||
0x70020021, // 0024 JMP #0047
|
||||
0x1C0C030A, // 0025 EQ R3 R1 K10
|
||||
0x780E000C, // 0026 JMPF R3 #0034
|
||||
0x4C0C0000, // 0027 LDNIL R3
|
||||
0x1C0C0403, // 0028 EQ R3 R2 R3
|
||||
0x780E0002, // 0029 JMPF R3 #002D
|
||||
0x540E00FE, // 002A LDINT R3 255
|
||||
0x90021203, // 002B SETMBR R0 K9 R3
|
||||
0x70020005, // 002C JMP #0033
|
||||
0x780A0001, // 002D JMPF R2 #0030
|
||||
0x580C0008, // 002E LDCONST R3 K8
|
||||
0x70020000, // 002F JMP #0031
|
||||
0x580C0005, // 0030 LDCONST R3 K5
|
||||
0x90021203, // 0031 SETMBR R0 K9 R3
|
||||
0x90020908, // 0032 SETMBR R0 K4 K8
|
||||
0x70020012, // 0033 JMP #0047
|
||||
0x1C0C030B, // 0034 EQ R3 R1 K11
|
||||
0x70020020, // 001F JMP #0041
|
||||
0x1C0C0309, // 0020 EQ R3 R1 K9
|
||||
0x780E000B, // 0021 JMPF R3 #002E
|
||||
0x4C0C0000, // 0022 LDNIL R3
|
||||
0x1C0C0403, // 0023 EQ R3 R2 R3
|
||||
0x780E0001, // 0024 JMPF R3 #0027
|
||||
0x90021505, // 0025 SETMBR R0 K10 K5
|
||||
0x70020005, // 0026 JMP #002D
|
||||
0x780A0001, // 0027 JMPF R2 #002A
|
||||
0x580C0008, // 0028 LDCONST R3 K8
|
||||
0x70020000, // 0029 JMP #002B
|
||||
0x580C0005, // 002A LDCONST R3 K5
|
||||
0x90021403, // 002B SETMBR R0 K10 R3
|
||||
0x90020908, // 002C SETMBR R0 K4 K8
|
||||
0x70020012, // 002D JMP #0041
|
||||
0x1C0C030B, // 002E EQ R3 R1 K11
|
||||
0x780E0003, // 002F JMPF R3 #0034
|
||||
0x8C0C010C, // 0030 GETMET R3 R0 K12
|
||||
0x5C140400, // 0031 MOVE R5 R2
|
||||
0x7C0C0400, // 0032 CALL R3 2
|
||||
0x7002000C, // 0033 JMP #0041
|
||||
0x1C0C030D, // 0034 EQ R3 R1 K13
|
||||
0x780E0003, // 0035 JMPF R3 #003A
|
||||
0x8C0C010C, // 0036 GETMET R3 R0 K12
|
||||
0x8C0C010E, // 0036 GETMET R3 R0 K14
|
||||
0x5C140400, // 0037 MOVE R5 R2
|
||||
0x7C0C0400, // 0038 CALL R3 2
|
||||
0x7002000C, // 0039 JMP #0047
|
||||
0x1C0C030D, // 003A EQ R3 R1 K13
|
||||
0x780E0003, // 003B JMPF R3 #0040
|
||||
0x8C0C010E, // 003C GETMET R3 R0 K14
|
||||
0x5C140400, // 003D MOVE R5 R2
|
||||
0x7C0C0400, // 003E CALL R3 2
|
||||
0x70020006, // 003F JMP #0047
|
||||
0x600C0003, // 0040 GETGBL R3 G3
|
||||
0x5C100000, // 0041 MOVE R4 R0
|
||||
0x7C0C0200, // 0042 CALL R3 1
|
||||
0x8C0C070F, // 0043 GETMET R3 R3 K15
|
||||
0x5C140200, // 0044 MOVE R5 R1
|
||||
0x5C180400, // 0045 MOVE R6 R2
|
||||
0x7C0C0600, // 0046 CALL R3 3
|
||||
0x80000000, // 0047 RET 0
|
||||
0x70020006, // 0039 JMP #0041
|
||||
0x600C0003, // 003A GETGBL R3 G3
|
||||
0x5C100000, // 003B MOVE R4 R0
|
||||
0x7C0C0200, // 003C CALL R3 1
|
||||
0x8C0C070F, // 003D GETMET R3 R3 K15
|
||||
0x5C140200, // 003E MOVE R5 R1
|
||||
0x5C180400, // 003F MOVE R6 R2
|
||||
0x7C0C0600, // 0040 CALL R3 3
|
||||
0x80000000, // 0041 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
@ -447,7 +441,7 @@ be_local_closure(zcl_attribute_member, /* name */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[16]) { /* constants */
|
||||
( &(const bvalue[17]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(cluster),
|
||||
/* K1 */ be_nested_str_weak(_cluster),
|
||||
/* K2 */ be_nested_str_weak(attr_id),
|
||||
@ -457,17 +451,18 @@ be_local_closure(zcl_attribute_member, /* name */
|
||||
/* K6 */ be_nested_str_weak(_cmd),
|
||||
/* K7 */ be_nested_str_weak(direction),
|
||||
/* K8 */ be_nested_str_weak(_direction),
|
||||
/* K9 */ be_const_int(1),
|
||||
/* K10 */ be_nested_str_weak(val),
|
||||
/* K11 */ be_nested_str_weak(_get_val),
|
||||
/* K12 */ be_nested_str_weak(tohex),
|
||||
/* K13 */ be_nested_str_weak(key),
|
||||
/* K14 */ be_nested_str_weak(_get_key),
|
||||
/* K15 */ be_nested_str_weak(member),
|
||||
/* K9 */ be_nested_str_weak(cmd_general),
|
||||
/* K10 */ be_nested_str_weak(_cmd_general),
|
||||
/* K11 */ be_nested_str_weak(val),
|
||||
/* K12 */ be_nested_str_weak(_get_val),
|
||||
/* K13 */ be_nested_str_weak(tohex),
|
||||
/* K14 */ be_nested_str_weak(key),
|
||||
/* K15 */ be_nested_str_weak(_get_key),
|
||||
/* K16 */ be_nested_str_weak(member),
|
||||
}),
|
||||
be_str_weak(member),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[78]) { /* code */
|
||||
( &(const binstruction[75]) { /* code */
|
||||
0x1C080300, // 0000 EQ R2 R1 K0
|
||||
0x780A0008, // 0001 JMPF R2 #000B
|
||||
0x88080101, // 0002 GETMBR R2 R0 K1
|
||||
@ -478,7 +473,7 @@ be_local_closure(zcl_attribute_member, /* name */
|
||||
0x70020000, // 0007 JMP #0009
|
||||
0x4C0C0000, // 0008 LDNIL R3
|
||||
0x80040600, // 0009 RET 1 R3
|
||||
0x70020041, // 000A JMP #004D
|
||||
0x7002003E, // 000A JMP #004A
|
||||
0x1C080302, // 000B EQ R2 R1 K2
|
||||
0x780A000A, // 000C JMPF R2 #0018
|
||||
0x88080103, // 000D GETMBR R2 R0 K3
|
||||
@ -491,7 +486,7 @@ be_local_closure(zcl_attribute_member, /* name */
|
||||
0x70020000, // 0014 JMP #0016
|
||||
0x4C0C0000, // 0015 LDNIL R3
|
||||
0x80040600, // 0016 RET 1 R3
|
||||
0x70020034, // 0017 JMP #004D
|
||||
0x70020031, // 0017 JMP #004A
|
||||
0x1C080305, // 0018 EQ R2 R1 K5
|
||||
0x780A000A, // 0019 JMPF R2 #0025
|
||||
0x88080106, // 001A GETMBR R2 R0 K6
|
||||
@ -504,48 +499,45 @@ be_local_closure(zcl_attribute_member, /* name */
|
||||
0x70020000, // 0021 JMP #0023
|
||||
0x4C0C0000, // 0022 LDNIL R3
|
||||
0x80040600, // 0023 RET 1 R3
|
||||
0x70020027, // 0024 JMP #004D
|
||||
0x70020024, // 0024 JMP #004A
|
||||
0x1C080307, // 0025 EQ R2 R1 K7
|
||||
0x780A000A, // 0026 JMPF R2 #0032
|
||||
0x780A0002, // 0026 JMPF R2 #002A
|
||||
0x88080108, // 0027 GETMBR R2 R0 K8
|
||||
0x540E00FE, // 0028 LDINT R3 255
|
||||
0x200C0403, // 0029 NE R3 R2 R3
|
||||
0x780E0003, // 002A JMPF R3 #002F
|
||||
0x880C0104, // 002B GETMBR R3 R0 K4
|
||||
0x780E0001, // 002C JMPF R3 #002F
|
||||
0x2C0C0509, // 002D AND R3 R2 K9
|
||||
0x70020000, // 002E JMP #0030
|
||||
0x4C0C0000, // 002F LDNIL R3
|
||||
0x80040600, // 0030 RET 1 R3
|
||||
0x7002001A, // 0031 JMP #004D
|
||||
0x1C08030A, // 0032 EQ R2 R1 K10
|
||||
0x780A000B, // 0033 JMPF R2 #0040
|
||||
0x8C08010B, // 0034 GETMET R2 R0 K11
|
||||
0x7C080200, // 0035 CALL R2 1
|
||||
0x600C000F, // 0036 GETGBL R3 G15
|
||||
0x5C100400, // 0037 MOVE R4 R2
|
||||
0x60140015, // 0038 GETGBL R5 G21
|
||||
0x7C0C0400, // 0039 CALL R3 2
|
||||
0x780E0002, // 003A JMPF R3 #003E
|
||||
0x8C0C050C, // 003B GETMET R3 R2 K12
|
||||
0x7C0C0200, // 003C CALL R3 1
|
||||
0x5C080600, // 003D MOVE R2 R3
|
||||
0x80040400, // 003E RET 1 R2
|
||||
0x7002000C, // 003F JMP #004D
|
||||
0x1C08030D, // 0040 EQ R2 R1 K13
|
||||
0x780A0003, // 0041 JMPF R2 #0046
|
||||
0x8C08010E, // 0042 GETMET R2 R0 K14
|
||||
0x7C080200, // 0043 CALL R2 1
|
||||
0x80040400, // 0044 RET 1 R2
|
||||
0x70020006, // 0045 JMP #004D
|
||||
0x60080003, // 0046 GETGBL R2 G3
|
||||
0x5C0C0000, // 0047 MOVE R3 R0
|
||||
0x7C080200, // 0048 CALL R2 1
|
||||
0x8C08050F, // 0049 GETMET R2 R2 K15
|
||||
0x5C100200, // 004A MOVE R4 R1
|
||||
0x7C080400, // 004B CALL R2 2
|
||||
0x80040400, // 004C RET 1 R2
|
||||
0x80000000, // 004D RET 0
|
||||
0x80040400, // 0028 RET 1 R2
|
||||
0x7002001F, // 0029 JMP #004A
|
||||
0x1C080309, // 002A EQ R2 R1 K9
|
||||
0x780A0002, // 002B JMPF R2 #002F
|
||||
0x8808010A, // 002C GETMBR R2 R0 K10
|
||||
0x80040400, // 002D RET 1 R2
|
||||
0x7002001A, // 002E JMP #004A
|
||||
0x1C08030B, // 002F EQ R2 R1 K11
|
||||
0x780A000B, // 0030 JMPF R2 #003D
|
||||
0x8C08010C, // 0031 GETMET R2 R0 K12
|
||||
0x7C080200, // 0032 CALL R2 1
|
||||
0x600C000F, // 0033 GETGBL R3 G15
|
||||
0x5C100400, // 0034 MOVE R4 R2
|
||||
0x60140015, // 0035 GETGBL R5 G21
|
||||
0x7C0C0400, // 0036 CALL R3 2
|
||||
0x780E0002, // 0037 JMPF R3 #003B
|
||||
0x8C0C050D, // 0038 GETMET R3 R2 K13
|
||||
0x7C0C0200, // 0039 CALL R3 1
|
||||
0x5C080600, // 003A MOVE R2 R3
|
||||
0x80040400, // 003B RET 1 R2
|
||||
0x7002000C, // 003C JMP #004A
|
||||
0x1C08030E, // 003D EQ R2 R1 K14
|
||||
0x780A0003, // 003E JMPF R2 #0043
|
||||
0x8C08010F, // 003F GETMET R2 R0 K15
|
||||
0x7C080200, // 0040 CALL R2 1
|
||||
0x80040400, // 0041 RET 1 R2
|
||||
0x70020006, // 0042 JMP #004A
|
||||
0x60080003, // 0043 GETGBL R2 G3
|
||||
0x5C0C0000, // 0044 MOVE R3 R0
|
||||
0x7C080200, // 0045 CALL R2 1
|
||||
0x8C080510, // 0046 GETMET R2 R2 K16
|
||||
0x5C100200, // 0047 MOVE R4 R1
|
||||
0x7C080400, // 0048 CALL R2 2
|
||||
0x80040400, // 0049 RET 1 R2
|
||||
0x80000000, // 004A RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -107,7 +107,8 @@ public:
|
||||
bool key_is_pmem; // is the string in progmem, so we don't need to make a copy
|
||||
bool val_str_raw; // if val is String, it is raw JSON and should not be escaped
|
||||
bool key_is_cmd; // if command, cmd_id is the low 8 bits of attr_id.
|
||||
// The high 8 bits are `0` command sent to device or `1` command received from device
|
||||
// Bit #8 is `0` command sent to device or `1` command received from device
|
||||
// Bit #9 is `0` command is cluster specific, or `1` general_command
|
||||
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)
|
||||
int8_t attr_multiplier; // [opt] multiplier for attribute, defaults to 0x01 (no change)
|
||||
@ -161,7 +162,7 @@ public:
|
||||
void setKeyName(const char * _key, const char * _key2);
|
||||
|
||||
void setKeyId(uint16_t cluster, uint16_t attr_id);
|
||||
void setCmdId(uint16_t cluster, uint8_t cmd_id, bool direction);
|
||||
void setCmdId(uint16_t cluster, uint8_t cmd_id, bool direction, bool cmd_general);
|
||||
|
||||
// Setters
|
||||
void setNone(void);
|
||||
@ -209,7 +210,7 @@ public:
|
||||
|
||||
bool equalsKey(const Z_attribute & attr2, bool ignore_key_suffix = false) const;
|
||||
bool equalsId(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) const;
|
||||
bool equalsCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix = 0) const;
|
||||
bool equalsCmd(uint16_t cluster, uint8_t cmd_id, bool direction, bool cmd_general, uint8_t suffix = 0) const;
|
||||
bool equalsKey(const char * name, uint8_t suffix = 0) const;
|
||||
bool equalsVal(const Z_attribute & attr2) const;
|
||||
bool equals(const Z_attribute & attr2) const;
|
||||
@ -272,7 +273,7 @@ public:
|
||||
Z_attribute & addAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0);
|
||||
|
||||
// ZCL command
|
||||
Z_attribute & addAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix = 0);
|
||||
Z_attribute & addAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, bool cmd_general, uint8_t suffix = 0);
|
||||
|
||||
// Add attribute to the list, given name
|
||||
Z_attribute & addAttribute(const char * name, bool pmem = false, uint8_t suffix = 0);
|
||||
@ -293,15 +294,15 @@ public:
|
||||
|
||||
// find if attribute with same key already exists, return null if not found
|
||||
const Z_attribute * findAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) const;
|
||||
const Z_attribute * findAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix = 0) const;
|
||||
const Z_attribute * findAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, bool cmd_general, uint8_t suffix = 0) const;
|
||||
const Z_attribute * findAttribute(const char * name, uint8_t suffix = 0) const;
|
||||
const Z_attribute * findAttribute(const Z_attribute &attr) const; // suffix always count here
|
||||
// non-const variants
|
||||
inline Z_attribute * findAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) {
|
||||
return (Z_attribute*) ((const Z_attribute_list*)this)->findAttribute(cluster, attr_id, suffix);
|
||||
}
|
||||
inline Z_attribute * findAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix = 0) {
|
||||
return (Z_attribute*) ((const Z_attribute_list*)this)->findAttributeCmd(cluster, cmd_id, direction, suffix);
|
||||
inline Z_attribute * findAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, bool cmd_general, uint8_t suffix = 0) {
|
||||
return (Z_attribute*) ((const Z_attribute_list*)this)->findAttributeCmd(cluster, cmd_id, direction, cmd_general, suffix);
|
||||
}
|
||||
inline Z_attribute * findAttribute(const char * name, uint8_t suffix = 0) {
|
||||
return (Z_attribute*) (((const Z_attribute_list*)this)->findAttribute(name, suffix));
|
||||
@ -317,7 +318,7 @@ public:
|
||||
// if suffix == 0, we don't care and find the first match
|
||||
Z_attribute & findOrCreateAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0);
|
||||
Z_attribute & findOrCreateAttribute(const char * name, uint8_t suffix = 0);
|
||||
Z_attribute & findOrCreateCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix = 0);
|
||||
Z_attribute & findOrCreateCmd(uint16_t cluster, uint8_t cmd_id, bool direction, bool cmd_general, uint8_t suffix = 0);
|
||||
// always care about suffix
|
||||
Z_attribute & findOrCreateAttribute(const Z_attribute &attr);
|
||||
// replace attribute with new value, suffix does care
|
||||
@ -381,11 +382,11 @@ void Z_attribute::setKeyId(uint16_t _cluster, uint16_t _attr_id) {
|
||||
key_is_cmd = false;
|
||||
}
|
||||
|
||||
void Z_attribute::setCmdId(uint16_t _cluster, uint8_t _cmd_id, bool direction) {
|
||||
void Z_attribute::setCmdId(uint16_t _cluster, uint8_t _cmd_id, bool direction, bool cmd_general) {
|
||||
freeKey();
|
||||
key_is_str = false;
|
||||
cluster = _cluster;
|
||||
attr_id = _cmd_id | (direction ? 0x100 : 0x000);
|
||||
attr_id = _cmd_id | (direction ? 0x100 : 0x000) | (cmd_general ? 0x200 : 0x000);
|
||||
key_is_cmd = true;
|
||||
}
|
||||
|
||||
@ -570,9 +571,9 @@ bool Z_attribute::equalsId(uint16_t _cluster, uint16_t _attr_id, uint8_t suffix)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Z_attribute::equalsCmd(uint16_t _cluster, uint8_t _cmd_id, bool _direction, uint8_t suffix) const {
|
||||
bool Z_attribute::equalsCmd(uint16_t _cluster, uint8_t _cmd_id, bool _direction, bool cmd_general, uint8_t suffix) const {
|
||||
if (!key_is_cmd ||key_is_str) { return false; }
|
||||
uint16_t _attr_id = _cmd_id | (_direction ? 0x100 : 0x000);
|
||||
uint16_t _attr_id = _cmd_id | (_direction ? 0x100 : 0x000) | (cmd_general ? 0x200 : 0x000);
|
||||
if ((this->cluster == _cluster) && (this->attr_id == _attr_id) && (!this->key_is_cmd)) {
|
||||
if (suffix) {
|
||||
if (key_suffix == suffix) { return true; }
|
||||
@ -636,8 +637,10 @@ String Z_attribute::toString(bool prefix_comma) const {
|
||||
snprintf_P(attr_name, sizeof(attr_name), PSTR("%04X/%04X"), this->cluster, this->attr_id);
|
||||
} else { // cmd
|
||||
bool direction = (this->attr_id & 0x100);
|
||||
bool cmd_general = (this->attr_id & 0x200);
|
||||
uint8_t cmd_id = this->attr_id & 0xFF;
|
||||
snprintf_P(attr_name, sizeof(attr_name), PSTR("%04X%c%02X"), this->cluster, direction ? '<' : '!', cmd_id);
|
||||
char cmd_char = cmd_general ? (direction ? '^' : '_') : (direction ? '?' : '!');
|
||||
snprintf_P(attr_name, sizeof(attr_name), PSTR("%04X%c%02X"), this->cluster, cmd_char, cmd_id);
|
||||
}
|
||||
res += attr_name;
|
||||
if (key_suffix > 1) {
|
||||
@ -808,10 +811,10 @@ Z_attribute & Z_attribute_list::addAttribute(uint16_t cluster, uint16_t attr_id,
|
||||
}
|
||||
|
||||
// add a cluster/cmd_id attribute at the end of the list
|
||||
Z_attribute & Z_attribute_list::addAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix) {
|
||||
Z_attribute & Z_attribute_list::addAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, bool cmd_general, uint8_t suffix) {
|
||||
Z_attribute & attr = addToLast();
|
||||
attr.cluster = cluster;
|
||||
attr.attr_id = cmd_id | (direction ? 0x100 : 0);
|
||||
attr.attr_id = cmd_id | (direction ? 0x100 : 0) | (cmd_general ? 0x200 : 0x000);
|
||||
attr.key_is_cmd = true;
|
||||
if (!suffix) { attr.key_suffix = countAttribute(attr.cluster, attr.attr_id); }
|
||||
else { attr.key_suffix = suffix; }
|
||||
@ -884,7 +887,7 @@ const Z_attribute * Z_attribute_list::findAttribute(const Z_attribute &attr) con
|
||||
} else if (!attr.key_is_cmd) {
|
||||
return findAttribute(attr.cluster, attr.attr_id, suffix);
|
||||
} else {
|
||||
return findAttributeCmd(attr.cluster, attr.attr_id & 0xFF, attr.attr_id & 0x100 ? true : false, suffix);
|
||||
return findAttributeCmd(attr.cluster, attr.attr_id & 0xFF, attr.attr_id & 0x100 ? true : false, attr.attr_id & 0x200 ? true : false, suffix);
|
||||
}
|
||||
}
|
||||
|
||||
@ -902,9 +905,9 @@ size_t Z_attribute_list::countAttribute(uint16_t cluster, uint16_t attr_id) cons
|
||||
return count;
|
||||
}
|
||||
|
||||
const Z_attribute * Z_attribute_list::findAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix) const {
|
||||
const Z_attribute * Z_attribute_list::findAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, bool cmd_general, uint8_t suffix) const {
|
||||
for (const auto & attr : *this) {
|
||||
if (attr.equalsCmd(cluster, cmd_id, direction, suffix)) { return &attr; }
|
||||
if (attr.equalsCmd(cluster, cmd_id, direction, cmd_general, suffix)) { return &attr; }
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -915,9 +918,9 @@ Z_attribute & Z_attribute_list::findOrCreateAttribute(uint16_t cluster, uint16_t
|
||||
return found ? *found : addAttribute(cluster, attr_id, suffix);
|
||||
}
|
||||
|
||||
Z_attribute & Z_attribute_list::findOrCreateCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix) {
|
||||
Z_attribute * found = findAttributeCmd(cluster, cmd_id, direction, suffix);
|
||||
return found ? *found : addAttributeCmd(cluster, cmd_id, direction, suffix);
|
||||
Z_attribute & Z_attribute_list::findOrCreateCmd(uint16_t cluster, uint8_t cmd_id, bool direction, bool cmd_general, uint8_t suffix) {
|
||||
Z_attribute * found = findAttributeCmd(cluster, cmd_id, direction, cmd_general, suffix);
|
||||
return found ? *found : addAttributeCmd(cluster, cmd_id, direction, cmd_general, suffix);
|
||||
}
|
||||
|
||||
const Z_attribute * Z_attribute_list::findAttribute(const char * name, uint8_t suffix) const {
|
||||
@ -943,7 +946,7 @@ Z_attribute & Z_attribute_list::findOrCreateAttribute(const char * name, uint8_t
|
||||
Z_attribute & Z_attribute_list::findOrCreateAttribute(const Z_attribute &attr) {
|
||||
Z_attribute & ret = attr.key_is_str ? findOrCreateAttribute(attr.key, attr.key_suffix)
|
||||
: attr.key_is_cmd ?
|
||||
findOrCreateCmd(attr.cluster, attr.attr_id & 0xFF, attr.attr_id & 0x100 ? true : false, attr.key_suffix)
|
||||
findOrCreateCmd(attr.cluster, attr.attr_id & 0xFF, attr.attr_id & 0x100 ? true : false, attr.attr_id & 0x200 ? true : false, attr.key_suffix)
|
||||
: findOrCreateAttribute(attr.cluster, attr.attr_id, attr.key_suffix);
|
||||
ret.key_suffix = attr.key_suffix;
|
||||
return ret;
|
||||
|
@ -112,6 +112,7 @@ public:
|
||||
_linkquality(linkquality), _securityuse(securityuse), _seqnumber(seqnumber)
|
||||
{
|
||||
_frame_control.d8 = frame_control;
|
||||
direction = _frame_control.b.direction;
|
||||
clusterSpecific = (_frame_control.b.frame_type != 0);
|
||||
needResponse = !_frame_control.b.disable_def_resp;
|
||||
payload.addBuffer(buf, buf_len);
|
||||
@ -131,7 +132,7 @@ public:
|
||||
srcendpoint, dstendpoint, _wasbroadcast,
|
||||
_linkquality, _securityuse, _seqnumber,
|
||||
_frame_control,
|
||||
_frame_control.b.frame_type, _frame_control.b.direction, _frame_control.b.disable_def_resp,
|
||||
_frame_control.b.frame_type, direction, _frame_control.b.disable_def_resp,
|
||||
manuf, transactseq, cmd,
|
||||
&payload);
|
||||
if (Settings->flag3.tuya_serial_mqtt_publish) {
|
||||
@ -165,9 +166,8 @@ public:
|
||||
return zcl_frame;
|
||||
}
|
||||
|
||||
bool isClusterSpecificCommand(void) {
|
||||
return _frame_control.b.frame_type & 1;
|
||||
}
|
||||
bool isClusterSpecificCommand(void) const { return _frame_control.b.frame_type & 1; }
|
||||
uint8_t getDirection(void) const { return direction; }
|
||||
|
||||
// parsers for received messages
|
||||
void parseReportAttributes(Z_attribute_list& attr_list);
|
||||
@ -1127,10 +1127,10 @@ void ZCLFrame::parseClusterSpecificCommand(Z_attribute_list& attr_list) {
|
||||
device.debounce_transact = transactseq;
|
||||
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, USE_ZIGBEE_DEBOUNCE_COMMANDS, 0 /*clusterid*/, srcendpoint, Z_CAT_DEBOUNCE_CMD, 0, &Z_ResetDebounce);
|
||||
|
||||
convertClusterSpecific(attr_list, cluster, cmd, _frame_control.b.direction, shortaddr, srcendpoint, payload);
|
||||
convertClusterSpecific(attr_list, cluster, cmd, direction, shortaddr, srcendpoint, payload);
|
||||
if (!Settings->flag5.zb_disable_autoquery) {
|
||||
// read attributes unless disabled
|
||||
if (!_frame_control.b.direction) { // only handle server->client (i.e. device->coordinator)
|
||||
if (!direction) { // only handle server->client (i.e. device->coordinator)
|
||||
if (_wasbroadcast) { // only update for broadcast messages since we don't see unicast from device to device and we wouldn't know the target
|
||||
sendHueUpdate(BAD_SHORTADDR, groupaddr, cluster);
|
||||
}
|
||||
|
@ -347,9 +347,9 @@ void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster,
|
||||
// Format: "0001!06": "00" = "<cluster>!<cmd>": "<payload>" for commands to devices
|
||||
// Format: "0004<00": "00" = "<cluster><<cmd>": "<payload>" for commands to devices
|
||||
// char attrid_str[12];
|
||||
// snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '<' : '!', cmd);
|
||||
// snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '?' : '!', cmd);
|
||||
// Z_attribute & attr_raw = attr_list.addAttribute(attrid_str);
|
||||
Z_attribute & attr_raw = attr_list.addAttributeCmd(cluster, cmd, direction);
|
||||
Z_attribute & attr_raw = attr_list.addAttributeCmd(cluster, cmd, direction, false /* cluster specific */);
|
||||
attr_raw.setBuf(payload, 0, payload.len());
|
||||
|
||||
// TODO Berry encode command
|
||||
|
@ -1698,36 +1698,56 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) {
|
||||
attr_list.group_id = groupid;
|
||||
}
|
||||
|
||||
if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_DEFAULT_RESPONSE == zcl_received.getCmdId())) {
|
||||
zcl_received.parseResponse(); // Zigbee general "Default Response", publish ZbResponse message
|
||||
// uint8_t cmdid = zcl_received.getCmdId();
|
||||
bool cmd_ignore = false; // ignore the command in later processing
|
||||
|
||||
if (zcl_received.isClusterSpecificCommand()) {
|
||||
// Cluster-specific command
|
||||
zcl_received.parseClusterSpecificCommand(attr_list);
|
||||
Z_Query_Battery(srcaddr); // do battery auto-probing when receiving commands
|
||||
} else {
|
||||
// Build the ZbReceive list
|
||||
if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId() || ZCL_WRITE_ATTRIBUTES == zcl_received.getCmdId())) {
|
||||
zcl_received.parseReportAttributes(attr_list); // Zigbee report attributes from sensors
|
||||
// General cluster command
|
||||
switch (zcl_received.getCmdId()) {
|
||||
case ZCL_DEFAULT_RESPONSE:
|
||||
zcl_received.parseResponse(); // Zigbee general "Default Response", publish ZbResponse message
|
||||
cmd_ignore = true;
|
||||
break;
|
||||
case ZCL_REPORT_ATTRIBUTES:
|
||||
case ZCL_WRITE_ATTRIBUTES:
|
||||
zcl_received.parseReportAttributes(attr_list); // Zigbee report attributes from sensors
|
||||
|
||||
// since we receive a sensor value, and the device is still awake,
|
||||
// try to read the battery value
|
||||
if (clusterid != 0x0001) { // avoid sending Battery probe if we already received info from cluster 0x0001
|
||||
Z_Query_Battery(srcaddr);
|
||||
}
|
||||
if (clusterid && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { defer_attributes = true; } // don't defer system Cluster=0 messages or Write Attribute
|
||||
} else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES_RESPONSE == zcl_received.getCmdId())) {
|
||||
zcl_received.parseReadAttributesResponse(attr_list);
|
||||
if (clusterid) { defer_attributes = true; } // don't defer system Cluster=0 messages
|
||||
} else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES == zcl_received.getCmdId())) {
|
||||
zcl_received.parseReadAttributes(srcaddr, attr_list);
|
||||
// never defer read_attributes, so the auto-responder can send response back on a per cluster basis
|
||||
} else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_REPORTING_CONFIGURATION_RESPONSE == zcl_received.getCmdId())) {
|
||||
zcl_received.parseReadConfigAttributes(srcaddr, attr_list);
|
||||
} else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_CONFIGURE_REPORTING_RESPONSE == zcl_received.getCmdId())) {
|
||||
zcl_received.parseConfigAttributes(srcaddr, attr_list);
|
||||
} else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_WRITE_ATTRIBUTES_RESPONSE == zcl_received.getCmdId())) {
|
||||
zcl_received.parseWriteAttributesResponse(attr_list);
|
||||
} else if (zcl_received.isClusterSpecificCommand()) {
|
||||
zcl_received.parseClusterSpecificCommand(attr_list);
|
||||
Z_Query_Battery(srcaddr); // do battery auto-probing when receiving commands
|
||||
// since we receive a sensor value, and the device is still awake,
|
||||
// try to read the battery value
|
||||
if (clusterid != 0x0001) { // avoid sending Battery probe if we already received info from cluster 0x0001
|
||||
Z_Query_Battery(srcaddr);
|
||||
}
|
||||
if (clusterid && zcl_received.getCmdId() == ZCL_REPORT_ATTRIBUTES) { defer_attributes = true; } // defer attributes reporting except for cluster 0x0000 or Write Attribute
|
||||
break;
|
||||
case ZCL_READ_ATTRIBUTES_RESPONSE:
|
||||
zcl_received.parseReadAttributesResponse(attr_list);
|
||||
if (clusterid) { defer_attributes = true; } // defer attributes reporting except for cluster 0x0000
|
||||
break;
|
||||
case ZCL_READ_ATTRIBUTES:
|
||||
zcl_received.parseReadAttributes(srcaddr, attr_list);
|
||||
// never defer read_attributes, so the auto-responder can send response back on a per cluster basis
|
||||
break;
|
||||
case ZCL_READ_REPORTING_CONFIGURATION_RESPONSE:
|
||||
zcl_received.parseReadConfigAttributes(srcaddr, attr_list);
|
||||
break;
|
||||
case ZCL_CONFIGURE_REPORTING_RESPONSE:
|
||||
zcl_received.parseConfigAttributes(srcaddr, attr_list);
|
||||
break;
|
||||
case ZCL_WRITE_ATTRIBUTES_RESPONSE:
|
||||
zcl_received.parseWriteAttributesResponse(attr_list);
|
||||
break;
|
||||
default:
|
||||
attr_list.addAttributeCmd(clusterid, zcl_received.getCmdId(), zcl_received.getDirection(), true /* general command */).setBuf(zcl_received.payload, 0, zcl_received.payload.len());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// unless attributes are ignored, post-process and publish them
|
||||
if (!cmd_ignore) {
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":{%s}}"), srcaddr, attr_list.toString(false, false).c_str()); // don't include battery
|
||||
|
||||
#ifdef USE_BERRY
|
||||
|
@ -556,6 +556,11 @@ void ZbSendSend(class JsonParserToken val_cmd, ZCLFrame & zcl) {
|
||||
// Now parse the string to extract cluster, command, and payload
|
||||
// Parse 'cmd' in the form "AAAA_BB/CCCCCCCC" or "AAAA!BB/CCCCCCCC"
|
||||
// where AAAA is the cluster number, BB the command number, CCCC... the payload
|
||||
// Possible delimiters:
|
||||
// "AAAA_BB/...": general cluster, sent to device (direction == 0)
|
||||
// "AAAA^BB/...": general cluster, recevied from device (direction == 1)
|
||||
// "AAAA!BB/...": cluster specific, sent to device (direction == 0)
|
||||
// "AAAA?BB/...": cluster specific, recevied from device (direction == 1)
|
||||
// First delimiter is '_' for a global command, or '!' for a cluster specific command
|
||||
const char * data = val_cmd.getStr();
|
||||
uint16_t local_cluster_id = parseHex(&data, 4);
|
||||
@ -569,8 +574,9 @@ void ZbSendSend(class JsonParserToken val_cmd, ZCLFrame & zcl) {
|
||||
}
|
||||
|
||||
// delimiter
|
||||
if (('_' == *data) || ('!' == *data)) {
|
||||
if ('_' == *data) { zcl.clusterSpecific = false; }
|
||||
if (('_' == *data) || ('^' == *data) || ('!' == *data) || ('?' == *data)) {
|
||||
if ('_' == *data || '^' == *data) { zcl.clusterSpecific = false; }
|
||||
if ('^' == *data || '?' == *data) { zcl.direction = true; }
|
||||
data++;
|
||||
} else {
|
||||
ResponseCmndChar_P(PSTR(D_ZIGBEE_WRONG_DELIMITER));
|
||||
|
@ -254,13 +254,14 @@ extern "C" {
|
||||
|
||||
extern const be_ctypes_structure_t be_zigbee_zcl_attribute_struct = {
|
||||
sizeof(Z_attribute), /* size in bytes */
|
||||
9, /* number of elements */
|
||||
10, /* number of elements */
|
||||
nullptr,
|
||||
(const be_ctypes_structure_item_t[9]) {
|
||||
(const be_ctypes_structure_item_t[10]) {
|
||||
{ "_attr_id", offsetof(Z_attribute, attr_id), 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
|
||||
{ "_direction", offsetof(Z_attribute, attr_id) + 1, 0, 0, ctypes_u8, 0 }, // high 8 bits of attr_id
|
||||
{ "_cmd_general", offsetof(Z_attribute, attr_id) + 1, 1, 1, ctypes_u8, 0 }, // bit #1 of byte+1
|
||||
{ "_direction", offsetof(Z_attribute, attr_id) + 1, 0, 1, ctypes_u8, 0 }, // bit #0 of byte+1
|
||||
{ "_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_divider", offsetof(Z_attribute, attr_divider), 0, 0, ctypes_i8, 0 },
|
||||
|
Loading…
x
Reference in New Issue
Block a user