From 0604fac3bc7ab90c4595846b46d336b790f3ea76 Mon Sep 17 00:00:00 2001 From: valentin richard Date: Sat, 12 Apr 2025 19:12:32 +0200 Subject: [PATCH] fix(zigbee): fix `convertTuyaSpecificCluster` datapoint parser -> support multiple data points in the same payload. (#23247) Co-authored-by: valentin --- .gitignore | 3 ++ .../xdrv_23_zigbee_6_0_commands.ino | 35 ++++++++++++++----- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 820b5a561..e6b5050b7 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,9 @@ lib/libesp32/berry/berry *.bak *.code-workspace +## IntelliJ ###### +.idea + ## Python virtual environments for Platformio ## venv .venv diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_0_commands.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_0_commands.ino index 53ca8f223..d9270b0d3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_0_commands.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_0_commands.ino @@ -602,19 +602,38 @@ static void replyTuyaTime( uint16_t cluster, uint16_t shortaddr, uint8_t dstendp bool convertTuyaSpecificCluster(class Z_attribute_list &attr_list, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &buf) { if ((1 == cmd) || (2 == cmd)) { // attribute report or attribute response - // uint16_t seq_number = buf.get16BigEndian(0) - uint8_t dpid = buf.get8(2); // dpid from Tuya documentation - uint8_t attr_type = buf.get8(3); // data type from Tuya documentation - uint16_t len = buf.get16BigEndian(4); - // create a synthetic attribute with id 'dpid' - Z_attribute & attr = attr_list.addAttribute(cluster, (attr_type << 8) | dpid); - parseSingleTuyaAttribute(attr, buf, 6, len, attr_type); - return true; // true = remove the original Tuya attribute + uint16_t read_index = 0; // position in the buffer + // uint16_t seq_number = buf.get16BigEndian(read_index); // seq + read_index += 2; + + // continue while we can read at least 4 bytes: the dpid (u8), the type (u8), and the length (u16) + while ((read_index + 4) <= buf.len()) { + uint8_t dpid = buf.get8(read_index); // dpid + read_index++; + uint8_t attr_type = buf.get8(read_index); // data type + read_index++; + uint16_t len = buf.get16BigEndian(read_index); + read_index += 2; + + // ensures we may read at least `len` bytes, if not, the payload is malformed. + if ((read_index + len) > buf.len()) { + break; + } + + // create a synthetic attribute with id 'dpid' + Z_attribute & attr = attr_list.addAttribute(cluster, (attr_type << 8) | dpid); + parseSingleTuyaAttribute(attr, buf, read_index, len, attr_type); + read_index += len; + } + + return true; // true = remove the original Tuya attribute } + if (0x24 == cmd) { replyTuyaTime(cluster, shortaddr, srcendpoint); return true; } + return false; }