From 6cba04e6e07b6c0bc5af9fe9be81daf89190432d Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 22 Nov 2020 16:07:09 +0100 Subject: [PATCH] Zigbee better support for attribute Reachable --- tasmota/xdrv_23_zigbee_2_devices.ino | 3 ++ tasmota/xdrv_23_zigbee_2a_devices_impl.ino | 9 ++++++ tasmota/xdrv_23_zigbee_6_commands.ino | 4 +++ tasmota/xdrv_23_zigbee_8_parsers.ino | 33 +++++++++++++++++----- tasmota/xdrv_23_zigbee_A_impl.ino | 3 ++ 5 files changed, 45 insertions(+), 7 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index 4c66bff95..597c2d607 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -832,6 +832,9 @@ public: bool isHueBulbHidden(uint16_t shortaddr) const ; Z_Data_Light & getLight(uint16_t shortaddr); + // device is reachable + void deviceWasReached(uint16_t shortaddr); + // Timers void resetTimersForDevice(uint16_t shortaddr, uint16_t groupaddr, uint8_t category, uint16_t cluster = 0xFFFF, uint8_t endpoint = 0xFF); void setTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func); diff --git a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino b/tasmota/xdrv_23_zigbee_2a_devices_impl.ino index 006e7c76d..59ad6b6f5 100644 --- a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino +++ b/tasmota/xdrv_23_zigbee_2a_devices_impl.ino @@ -320,6 +320,15 @@ void Z_Device::setLastSeenNow(void) { last_seen = Rtc.utc_time; } +void Z_Devices::deviceWasReached(uint16_t shortaddr) { + // since we just receveived data from the device, it is reachable + zigbee_devices.resetTimersForDevice(shortaddr, 0 /* groupaddr */, Z_CAT_REACHABILITY); // remove any reachability timer already there + Z_Device & device = findShortAddr(shortaddr); + if (device.valid()) { + device.setReachable(true); // mark device as reachable + } +} + // 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) { Z_Device & device = findShortAddr(shortaddr); diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index b5f0296da..7f16a9997 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -200,6 +200,10 @@ void Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster void Z_Unreachable(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { if (BAD_SHORTADDR != shortaddr) { zigbee_devices.getShortAddr(shortaddr).setReachable(false); // mark device as reachable + Z_attribute_list attr_list; + attr_list.addAttribute(F("Reachable")).setBool(false); // "Reachable":false + // Z_postProcessAttributes(shortaddr, endpoint, attr_list); // make sure all is updated accordingly + zigbee_devices.jsonPublishNow(shortaddr, attr_list); } } diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 620bb1ed6..81cdfee4b 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -537,6 +537,8 @@ int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { uint8_t* activeEpList = (uint8_t*) buf.charptr(4); #endif + // device is reachable + zigbee_devices.deviceWasReached(nwkAddr); for (uint32_t i = 0; i < activeEpCount; i++) { uint8_t ep = activeEpList[i]; zigbee_devices.getShortAddr(nwkAddr).addEndpoint(ep); @@ -660,6 +662,9 @@ int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf) { #endif if (0 == status) { + // device is reachable + zigbee_devices.deviceWasReached(nwkAddr); + if (!Settings.flag4.zb_disable_autobind) { Z_AutoBindDefer(nwkAddr, endpoint, buf, numInIndex, numInCluster, numOutIndex, numOutCluster); } @@ -709,6 +714,7 @@ int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { if (0 == status) { // SUCCESS zigbee_devices.updateDevice(nwkAddr, ieeeAddr); + zigbee_devices.deviceWasReached(nwkAddr); char hex[20]; Uint64toHex(ieeeAddr, hex, 64); // Ping response @@ -825,6 +831,8 @@ int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { #endif zigbee_devices.updateDevice(nwkAddr, ieeeAddr); + // device is reachable + zigbee_devices.deviceWasReached(nwkAddr); char hex[20]; Uint64toHex(ieeeAddr, hex, 64); @@ -855,6 +863,8 @@ int32_t ZNP_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) { Z_ShortAddress parentNw = buf.get16(12); zigbee_devices.updateDevice(srcAddr, ieeeAddr); + // device is reachable + zigbee_devices.deviceWasReached(srcAddr); char hex[20]; Uint64toHex(ieeeAddr, hex, 64); @@ -883,6 +893,9 @@ int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) { String msg = getZDPStatusMessage(status); #endif // USE_ZIGBEE_EZSP + // device is reachable + zigbee_devices.deviceWasReached(nwkAddr); + const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), nwkAddr); @@ -913,6 +926,9 @@ int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf) { String msg = getZDPStatusMessage(status); #endif // USE_ZIGBEE_EZSP + // device is reachable + zigbee_devices.deviceWasReached(nwkAddr); + const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); Response_P(PSTR("{\"" D_JSON_ZIGBEE_UNBIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), nwkAddr); @@ -949,6 +965,9 @@ int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) { const size_t prefix_len = 4; #endif // USE_ZIGBEE_EZSP + // device is reachable + zigbee_devices.deviceWasReached(shortaddr); + const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr); Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND_STATE "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), shortaddr); @@ -1057,6 +1076,9 @@ int32_t Z_MgmtLqiRsp(int32_t res, const class SBuffer &buf) { const size_t prefix_len = 4; #endif // USE_ZIGBEE_EZSP + // device is reachable + zigbee_devices.deviceWasReached(shortaddr); + const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr); Response_P(PSTR("{\"" D_JSON_ZIGBEE_MAP "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), shortaddr); @@ -1135,6 +1157,9 @@ int32_t EZ_ParentAnnceRsp(int32_t res, const class SBuffer &buf, bool rsp) { prefix_len = 1; } + // device is reachable + zigbee_devices.deviceWasReached(shortaddr); + const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr); Response_P(PSTR("{\"" D_JSON_ZIGBEE_PARENT "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), shortaddr); @@ -1478,6 +1503,7 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) { if (device.valid()) { device.setLQI(linkquality != 0xFF ? linkquality : 0xFE); // EFR32 has a different scale for LQI device.setLastSeenNow(); + zigbee_devices.deviceWasReached(srcaddr); } char shortaddr[8]; @@ -1524,12 +1550,6 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) { zcl_received.generateCallBacks(attr_list); // set deferred callbacks, ex: Occupancy Z_postProcessAttributes(srcaddr, zcl_received.getSrcEndpoint(), attr_list); - // since we just receveived data from the device, it is reachable - zigbee_devices.resetTimersForDevice(srcaddr, 0 /* groupaddr */, Z_CAT_REACHABILITY); // remove any reachability timer already there - if (device.valid()) { - device.setReachable(true); // mark device as reachable - } - if (defer_attributes) { // Prepare for publish if (zigbee_devices.jsonIsConflict(srcaddr, attr_list)) { @@ -1545,7 +1565,6 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) { } } - #ifdef USE_ZIGBEE_EZSP /*********************************************************************************************\ diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index e73a71567..8df3acbf9 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -1044,6 +1044,9 @@ void CmndZbProbeOrPing(boolean probe) { uint16_t shortaddr = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true).shortaddr; if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } + // set a timer for Reachable - 2s default value + zigbee_devices.setTimer(shortaddr, 0, Z_CAT_REACHABILITY_TIMEOUT, 0, 0, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable); + // everything is good, we can send the command Z_SendIEEEAddrReq(shortaddr); if (probe) {