From c9c948e567159fe11aef980779ab6b11b02c6948 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 21 Dec 2020 12:13:57 +0100 Subject: [PATCH] Zigbee improved CIE handling --- tasmota/xdrv_23_zigbee_2_devices.ino | 2 + tasmota/xdrv_23_zigbee_5_converters.ino | 25 +++++++---- tasmota/xdrv_23_zigbee_8_parsers.ino | 56 ++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index 8532e5da8..c319bb26f 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -847,6 +847,8 @@ typedef enum Z_Def_Category { Z_CAT_BIND, // send auto-binding to coordinator Z_CAT_CONFIG_ATTR, // send a config attribute reporting request Z_CAT_READ_ATTRIBUTE, // read a single attribute + Z_CAT_CIE_ATTRIBUTE, // write CIE address + Z_CAT_CIE_ENROLL, // enroll CIE zone } Z_Def_Category; const uint32_t Z_CAT_REACHABILITY_TIMEOUT = 2000; // 1000 ms or 1s diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 074c44ec6..174871c44 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -779,8 +779,9 @@ public: void parseReadAttributesResponse(Z_attribute_list& attr_list); void parseReadConfigAttributes(Z_attribute_list& attr_list); void parseConfigAttributes(Z_attribute_list& attr_list); + void parseWriteAttributesResponse(Z_attribute_list& attr_list); void parseResponse(void); - void parseResponseOld(void); + void parseResponse_inner(uint8_t cmd, bool cluster_specific, uint8_t status); void parseClusterSpecificCommand(Z_attribute_list& attr_list); // synthetic attributes converters @@ -1467,6 +1468,11 @@ void ZCLFrame::parseConfigAttributes(Z_attribute_list& attr_list) { attr_1.setStrRaw(attr_config_list.toString(true).c_str()); } +// ZCL_WRITE_ATTRIBUTES_RESPONSE +void ZCLFrame::parseWriteAttributesResponse(Z_attribute_list& attr_list) { + parseResponse_inner(ZCL_WRITE_ATTRIBUTES_RESPONSE, false, _payload.get8(0)); +} + // ZCL_READ_REPORTING_CONFIGURATION_RESPONSE void ZCLFrame::parseReadConfigAttributes(Z_attribute_list& attr_list) { uint32_t i = 0; @@ -1554,12 +1560,8 @@ void ZCLFrame::parseReadAttributesResponse(Z_attribute_list& attr_list) { } } -// ZCL_DEFAULT_RESPONSE -void ZCLFrame::parseResponse(void) { - if (_payload.len() < 2) { return; } // wrong format - uint8_t cmd = _payload.get8(0); - uint8_t status = _payload.get8(1); +void ZCLFrame::parseResponse_inner(uint8_t cmd, bool cluster_specific, uint8_t status) { Z_attribute_list attr_list; // "Device" @@ -1572,7 +1574,7 @@ void ZCLFrame::parseResponse(void) { attr_list.addAttributePMEM(PSTR(D_JSON_ZIGBEE_NAME)).setStr(friendlyName); } // "Command" - snprintf_P(s, sizeof(s), PSTR("%04X!%02X"), _cluster_id, cmd); + snprintf_P(s, sizeof(s), PSTR("%04X%c%02X"), _cluster_id, cluster_specific ? '!' : '_', cmd); attr_list.addAttributePMEM(PSTR(D_JSON_ZIGBEE_CMD)).setStr(s); // "Status" attr_list.addAttributePMEM(PSTR(D_JSON_ZIGBEE_STATUS)).setUInt(status); @@ -1591,6 +1593,15 @@ void ZCLFrame::parseResponse(void) { MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); } +// ZCL_DEFAULT_RESPONSE +void ZCLFrame::parseResponse(void) { + if (_payload.len() < 2) { return; } // wrong format + uint8_t cmd = _payload.get8(0); + uint8_t status = _payload.get8(1); + + parseResponse_inner(cmd, true, status); +} + // Parse non-normalized attributes void ZCLFrame::parseClusterSpecificCommand(Z_attribute_list& attr_list) { convertClusterSpecific(attr_list, _cluster_id, _cmd_id, _frame_control.b.direction, _srcaddr, _srcendpoint, _payload); diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 5d92458de..32709c7dc 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -652,6 +652,8 @@ void Z_AutoBindDefer(uint16_t shortaddr, uint8_t endpoint, const SBuffer &buf, if (bitRead(cluster_map, Z_ClusterToCxBinding(0x0500))) { // send a read command to cluster 0x0500, attribute 0x0001 (ZoneType) - to read the type of sensor zigbee_devices.queueTimer(shortaddr, 0 /* groupaddr */, 2000, 0x0500, endpoint, Z_CAT_READ_ATTRIBUTE, 0x0001, &Z_SendSingleAttributeRead); + zigbee_devices.queueTimer(shortaddr, 0 /* groupaddr */, 2000, 0x0500, endpoint, Z_CAT_CIE_ATTRIBUTE, 0 /* value */, &Z_WriteCIEAddress); + zigbee_devices.queueTimer(shortaddr, 0 /* groupaddr */, 2000, 0x0500, endpoint, Z_CAT_CIE_ENROLL, 1 /* zone */, &Z_SendCIEZoneEnrollResponse); } // enqueue bind requests @@ -1346,7 +1348,7 @@ void Z_SendDeviceInfoRequest(uint16_t shortaddr) { } // -// Send sing attribute read request in Timer +// Send single attribute read request in Timer // void Z_SendSingleAttributeRead(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr); @@ -1367,6 +1369,56 @@ void Z_SendSingleAttributeRead(uint16_t shortaddr, uint16_t groupaddr, uint16_t })); } +// +// Write CIE address +// +void Z_WriteCIEAddress(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr); + SBuffer buf(12); + buf.add16(0x0010); // attribute 0x0010 + buf.add8(ZEUI64); + buf.add64(localIEEEAddr); + + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Writing CIE address")); + ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ + shortaddr, + 0x0000, /* group */ + 0x0500 /*cluster*/, + endpoint, + ZCL_WRITE_ATTRIBUTES, + 0x0000, /* manuf */ + false /* not cluster specific */, + true /* response */, + false /* discover route */, + transacid, /* zcl transaction id */ + buf.getBuffer(), buf.len() + })); +} + + +// +// Write CIE address +// +void Z_SendCIEZoneEnrollResponse(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr); + uint8_t EnrollRSP[2] = { 0x00 /* Sucess */, Z_B0(value) /* ZoneID */ }; + + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Sending Enroll Zone %d"), Z_B0(value)); + ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ + shortaddr, + 0x0000, /* group */ + 0x0500 /*cluster*/, + endpoint, + 0x00, // Zone Enroll Response + 0x0000, /* manuf */ + true /* cluster specific */, + true /* response */, + false /* discover route */, + transacid, /* zcl transaction id */ + EnrollRSP, sizeof(EnrollRSP) + })); +} + // // Auto-bind some clusters to the coordinator's endpoint 0x01 // @@ -1600,6 +1652,8 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) { zcl_received.parseReadConfigAttributes(attr_list); } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_CONFIGURE_REPORTING_RESPONSE == zcl_received.getCmdId())) { zcl_received.parseConfigAttributes(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); }