From 13763f55a68361c13e81b56b279cdb0d798c76b3 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 22 Feb 2020 20:53:55 +0100 Subject: [PATCH] Fix Zigbee auto-increment transaction number (#7757) --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 1 + tasmota/xdrv_23_zigbee_1_headers.ino | 2 +- tasmota/xdrv_23_zigbee_3_devices.ino | 23 ++++++++++++++++++++++- tasmota/xdrv_23_zigbee_6_commands.ino | 2 +- tasmota/xdrv_23_zigbee_8_parsers.ino | 2 ++ tasmota/xdrv_23_zigbee_9_impl.ino | 9 +++++---- 7 files changed, 33 insertions(+), 7 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 465bcde8f..c8cf0ab3a 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,6 +5,7 @@ - Revert most wifi connectivity changes introduced in 8.1.0.5 (#7746, #7602, #7621) - Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) - Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) +- Fix Zigbee auto-increment transaction number (#7757) ### 8.1.0.8 20200212 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 00cda53b4..c7930e79b 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -489,6 +489,7 @@ #define D_CMND_ZIGBEE_FORGET "Forget" #define D_CMND_ZIGBEE_SAVE "Save" #define D_CMND_ZIGBEE_LINKQUALITY "LinkQuality" + #define D_CMND_ZIGBEE_ENDPOINT "Endpoint" #define D_CMND_ZIGBEE_READ "Read" #define D_CMND_ZIGBEE_SEND "Send" #define D_JSON_ZIGBEE_ZCL_SENT "ZbZCLSent" diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino index 101d5703d..0bc592266 100644 --- a/tasmota/xdrv_23_zigbee_1_headers.ino +++ b/tasmota/xdrv_23_zigbee_1_headers.ino @@ -21,7 +21,7 @@ // contains some definitions for functions used before their declarations -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp = true, uint8_t transacId = 1); +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId); // Get an JSON attribute, with case insensitive key search diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index 4814bdb8a..78c192cc1 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -49,6 +49,8 @@ typedef struct Z_Device { // json buffer used for attribute reporting DynamicJsonBuffer *json_buffer; JsonObject *json; + // sequence number for Zigbee frames + uint8_t seqNumber; } Z_Device; // All devices are stored in a Vector @@ -96,6 +98,9 @@ public: // device just seen on the network, update the lastSeen field void updateLastSeen(uint16_t shortaddr); + // get next sequence number for (increment at each all) + uint8_t getNextSeqNumber(uint16_t shortaddr); + // Dump json String dump(uint32_t dump_mode, uint16_t status_shortaddr = 0) const; @@ -133,6 +138,7 @@ public: private: std::vector _devices = {}; uint32_t _saveTimer = 0; + uint8_t _seqNumber = 0; // global seqNumber if device is unknown template < typename T> static bool findInVector(const std::vector & vecOfElements, const T & element); @@ -226,7 +232,9 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { std::vector(), 0,0,0,0, nullptr, - nullptr, nullptr }; + nullptr, nullptr, + 0, // seqNumber + }; device.json_buffer = new DynamicJsonBuffer(); _devices.push_back(device); dirty(); @@ -532,6 +540,19 @@ void Z_Devices::updateLastSeen(uint16_t shortaddr) { _updateLastSeen(device); } +// get the next sequance number for the device, or use the global seq number if device is unknown +uint8_t Z_Devices::getNextSeqNumber(uint16_t shortaddr) { + int32_t short_found = findShortAddr(shortaddr); + if (short_found >= 0) { + Z_Device &device = getShortAddr(shortaddr); + device.seqNumber += 1; + return device.seqNumber; + } else { + _seqNumber += 1; + return _seqNumber; + } +} + // Per device timers // // Reset the timer for a specific device diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 073ab8e4c..9d6f38b95 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -78,7 +78,7 @@ int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoi break; } if (attrs) { - ZigbeeZCLSend(shortaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false /* we do want a response */); + ZigbeeZCLSend(shortaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(shortaddr)); } } diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 668f85471..7d84124ed 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -451,6 +451,8 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":%s}"), srcaddr, msg.c_str()); zcl_received.postProcessAttributes(srcaddr, json); + // Add Endpoint + json[F(D_CMND_ZIGBEE_ENDPOINT)] = srcendpoint; // Add linkquality json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 6ea08c4ac..eccfc56be 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -344,7 +344,7 @@ void ZigbeeZNPSend(const uint8_t *msg, size_t len) { ToHex_P(msg, len, hex_char, sizeof(hex_char))); } -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp, uint8_t transacId) { +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId) { SBuffer buf(25+len); buf.add8(Z_SREQ | Z_AF); // 24 buf.add8(AF_DATA_REQUEST); // 01 @@ -357,7 +357,7 @@ void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8 buf.add8(0x1E); // 1E radius buf.add8(3 + len); - buf.add8((disableDefResp ? 0x10 : 0x00) | (clusterSpecific ? 0x01 : 0x00)); // Frame Control Field + buf.add8((needResponse ? 0x00 : 0x10) | (clusterSpecific ? 0x01 : 0x00)); // Frame Control Field buf.add8(transacId); // Transaction Sequance Number buf.add8(cmdId); if (len > 0) { @@ -438,7 +438,7 @@ void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { } // everything is good, we can send the command - ZigbeeZCLSend(dstAddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len()); + ZigbeeZCLSend(dstAddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len(), false, zigbee_devices.getNextSeqNumber(dstAddr)); // now set the timer, if any, to read back the state later if (clusterSpecific) { zigbeeSetCommandTimer(dstAddr, cluster, endpoint); @@ -469,6 +469,7 @@ void CmndZbSend(void) { uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint String cmd_str = ""; // the actual low-level command, either specified or computed + // parse JSON const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); if (nullptr != &val_device) { device = zigbee_devices.parseDeviceParam(val_device.as()); @@ -729,7 +730,7 @@ void CmndZbRead(void) { } if ((0 != endpoint) && (attrs_len > 0)) { - ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false /* we do want a response */); + ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(device)); ResponseCmndDone(); } else { ResponseCmndChar("Missing parameters");