diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 5ee54afa7..9c8d258de 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -8,6 +8,7 @@ - Add command ``HumOffset -10.0 .. 10.0`` to set global humidity sensor offset (#7934) - Add Zigbee support for Hue emulation by Stefan Hadinger - Add Dew Point to Temperature and Humidity sensors +- Change Zigbee simplification of devices probing, saving Flash and memory ### 8.1.0.10 20200227 diff --git a/tasmota/xdrv_23_zigbee_0_constants.ino b/tasmota/xdrv_23_zigbee_0_constants.ino index c49f914b4..63d851c04 100644 --- a/tasmota/xdrv_23_zigbee_0_constants.ino +++ b/tasmota/xdrv_23_zigbee_0_constants.ino @@ -388,9 +388,6 @@ enum ZCL_Global_Commands { #define ZF(s) static const char ZS_ ## s[] PROGMEM = #s; #define Z(s) ZS_ ## s -const uint16_t Z_ProfileIds[] PROGMEM = { 0x0104, 0x0109, 0xA10E, 0xC05E }; -const char Z_ProfileNames[] PROGMEM = "ZigBee Home Automation|ZigBee Smart Energy|ZigBee Green Power|ZigBee Light Link"; - typedef struct Z_StatusLine { uint32_t status; // no need to use uint8_t since it uses 32 bits anyways const char * status_msg; diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index c7167e090..0cbe9a507 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -28,14 +28,14 @@ const uint16_t kZigbeeSaveDelaySeconds = ZIGBEE_SAVE_DELAY_SECONDS; // wait f typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); +const size_t endpoints_max = 8; // we limit to 8 endpoints + typedef struct Z_Device { uint64_t longaddr; // 0x00 means unspecified char * manufacturerId; char * modelId; char * friendlyName; - std::vector endpoints; // encoded as high 16 bits is endpoint, low 16 bits is ProfileId - std::vector clusters_in; // encoded as high 16 bits is endpoint, low 16 bits is cluster number - std::vector clusters_out; // encoded as high 16 bits is endpoint, low 16 bits is cluster number + uint8_t endpoints[endpoints_max]; // static array to limit memory consumption, list of endpoints until 0x00 or end of array // json buffer used for attribute reporting DynamicJsonBuffer *json_buffer; JsonObject *json; @@ -81,7 +81,6 @@ typedef struct Z_Deferred { // - shortaddr is unique if not null // - longaddr is unique if not null // - shortaddr and longaddr cannot be both null -// - clusters_in and clusters_out containt only endpoints listed in endpoints class Z_Devices { public: Z_Devices() {}; @@ -98,20 +97,17 @@ public: uint64_t getDeviceLongAddr(uint16_t shortaddr) const; + uint8_t findFirstEndpoint(uint16_t shortaddr) const; + // Add new device, provide ShortAddr and optional longAddr // If it is already registered, update information, otherwise create the entry void updateDevice(uint16_t shortaddr, uint64_t longaddr = 0); // Add an endpoint to a device - void addEndoint(uint16_t shortaddr, uint8_t endpoint); - - // Add endpoint profile - void addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t profileId); + void addEndpoint(uint16_t shortaddr, uint8_t endpoint); // Add cluster - void addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out); - - uint8_t findClusterEndpointIn(uint16_t shortaddr, uint16_t cluster); + void addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster); void setManufId(uint16_t shortaddr, const char * str); void setModelId(uint16_t shortaddr, const char * str); @@ -175,8 +171,6 @@ public: private: std::vector _devices = {}; std::vector _deferred = {}; // list of deferred calls - // std::vector _devices = std::vector(4); - // std::vector _deferred = std::vector(4); // list of deferred calls uint32_t _saveTimer = 0; uint8_t _seqNumber = 0; // global seqNumber if device is unknown @@ -186,9 +180,6 @@ private: template < typename T> static int32_t findEndpointInVector(const std::vector & vecOfElements, uint8_t element); - // find the first endpoint match for a cluster - static int32_t findClusterEndpoint(const std::vector & vecOfElements, uint16_t element); - Z_Device & getShortAddr(uint16_t shortaddr); // find Device from shortAddr, creates it if does not exist const Z_Device & getShortAddrConst(uint16_t shortaddr) const ; // find Device from shortAddr, creates it if does not exist Z_Device & getLongAddr(uint64_t longaddr); // find Device from shortAddr, creates it if does not exist @@ -226,31 +217,13 @@ int32_t Z_Devices::findEndpointInVector(const std::vector & vecOfElements, u int32_t found = 0; for (auto &elem : vecOfElements) { - if ( ((elem >> 16) & 0xFF) == element) { return found; } + if (elem == element) { return found; } found++; } return -1; } -// -// Find the first endpoint match for a cluster, whether in or out -// Clusters are stored in the format 0x00EECCCC (EE=endpoint, CCCC=cluster number) -// In: -// _devices.clusters_in or _devices.clusters_out -// cluster number looked for -// Out: -// Index of found Endpoint_Cluster number, or -1 if not found -// -int32_t Z_Devices::findClusterEndpoint(const std::vector & vecOfElements, uint16_t cluster) { - int32_t found = 0; - for (auto &elem : vecOfElements) { - if ((elem & 0xFFFF) == cluster) { return found; } - found++; - } - return -1; -} - // // Create a new Z_Device entry in _devices. Only to be called if you are sure that no // entry with same shortaddr or longaddr exists. @@ -263,9 +236,7 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { nullptr, // ManufId nullptr, // DeviceId nullptr, // FriendlyName - std::vector(), // at least one endpoint - std::vector(), // try not to allocate if not needed - std::vector(), // try not to allocate if not needed + { 0, 0, 0, 0, 0, 0, 0, 0 }, // endpoints nullptr, nullptr, shortaddr, 0, // seqNumber @@ -293,13 +264,6 @@ void Z_Devices::freeDeviceEntry(Z_Device *device) { free(device); } -void Z_Devices::shrinkToFit(uint16_t shortaddr) { - Z_Device & device = getShortAddr(shortaddr); - device.endpoints.shrink_to_fit(); - device.clusters_in.shrink_to_fit(); - device.clusters_out.shrink_to_fit(); -} - // // Scan all devices to find a corresponding shortaddr // Looks info device.shortaddr entry @@ -489,67 +453,31 @@ void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) { // // Add an endpoint to a shortaddr // -void Z_Devices::addEndoint(uint16_t shortaddr, uint8_t endpoint) { +void Z_Devices::addEndpoint(uint16_t shortaddr, uint8_t endpoint) { if (!shortaddr) { return; } if (0x00 == endpoint) { return; } - uint32_t ep_profile = (endpoint << 16); Z_Device &device = getShortAddr(shortaddr); if (&device == nullptr) { return; } // don't crash if not found - if (findEndpointInVector(device.endpoints, endpoint) < 0) { - device.endpoints.push_back(ep_profile); - dirty(); - } -} -void Z_Devices::addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t profileId) { - if (!shortaddr) { return; } - if (0x00 == endpoint) { return; } - uint32_t ep_profile = (endpoint << 16) | profileId; - Z_Device &device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } // don't crash if not found - int32_t found = findEndpointInVector(device.endpoints, endpoint); - if (found < 0) { - device.endpoints.push_back(ep_profile); - dirty(); - } else { - if (device.endpoints[found] != ep_profile) { - device.endpoints[found] = ep_profile; + for (uint32_t i = 0; i < endpoints_max; i++) { + if (endpoint == device.endpoints[i]) { + return; // endpoint already there + } + if (0 == device.endpoints[i]) { + device.endpoints[i] = endpoint; dirty(); + return; } } } -void Z_Devices::addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out) { - if (!shortaddr) { return; } - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } // don't crash if not found - uint32_t ep_cluster = (endpoint << 16) | cluster; - if (!out) { - if (!findInVector(device.clusters_in, ep_cluster)) { - device.clusters_in.push_back(ep_cluster); - dirty(); - } - } else { // out - if (!findInVector(device.clusters_out, ep_cluster)) { - device.clusters_out.push_back(ep_cluster); - dirty(); - } - } -} +// Find the first endpoint of the device +uint8_t Z_Devices::findFirstEndpoint(uint16_t shortaddr) const { + int32_t found = findShortAddr(shortaddr); + if (found < 0) return 0; // avoid creating an entry if the device was never seen + const Z_Device &device = devicesAt(found); -// Look for the best endpoint match to send a command for a specific Cluster ID -// return 0x00 if none found -uint8_t Z_Devices::findClusterEndpointIn(uint16_t shortaddr, uint16_t cluster){ - int32_t short_found = findShortAddr(shortaddr); - if (short_found < 0) return 0; // avoid creating an entry if the device was never seen - Z_Device &device = getShortAddr(shortaddr); - if (&device == nullptr) { return 0; } // don't crash if not found - int32_t found = findClusterEndpoint(device.clusters_in, cluster); - if (found >= 0) { - return (device.clusters_in[found] >> 16) & 0xFF; - } else { - return 0; - } + return device.endpoints[0]; // returns 0x00 if no endpoint } void Z_Devices::setManufId(uint16_t shortaddr, const char * str) { @@ -1069,58 +997,13 @@ String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { if (device.manufacturerId) { dev[F("Manufacturer")] = device.manufacturerId; } - } - - // If dump_mode == 2, dump a lot more details - if (3 <= dump_mode) { - JsonObject& dev_endpoints = dev.createNestedObject(F("Endpoints")); - for (std::vector::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) { - uint32_t ep_profile = *ite; - uint8_t endpoint = (ep_profile >> 16) & 0xFF; - uint16_t profileId = ep_profile & 0xFFFF; + JsonArray& dev_endpoints = dev.createNestedArray(F("Endpoints")); + for (uint32_t i = 0; i < endpoints_max; i++) { + uint8_t endpoint = device.endpoints[i]; + if (0x00 == endpoint) { break; } snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); - JsonObject& ep = dev_endpoints.createNestedObject(hex); - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), profileId); - ep[F("ProfileId")] = hex; - - int32_t found = -1; - for (uint32_t i = 0; i < sizeof(Z_ProfileIds) / sizeof(Z_ProfileIds[0]); i++) { - if (pgm_read_word(&Z_ProfileIds[i]) == profileId) { - found = i; - break; - } - } - if (found > 0) { - GetTextIndexed(hex, sizeof(hex), found, Z_ProfileNames); - ep[F("ProfileIdName")] = hex; - } - - ep.createNestedArray(F("ClustersIn")); - ep.createNestedArray(F("ClustersOut")); - } - - for (std::vector::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) { - uint16_t cluster = *itc & 0xFFFF; - uint8_t endpoint = (*itc >> 16) & 0xFF; - - snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); - JsonArray &cluster_arr = dev_endpoints[hex][F("ClustersIn")]; - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster); - cluster_arr.add(hex); - } - - for (std::vector::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) { - uint16_t cluster = *itc & 0xFFFF; - uint8_t endpoint = (*itc >> 16) & 0xFF; - - snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); - JsonArray &cluster_arr = dev_endpoints[hex][F("ClustersOut")]; - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster); - cluster_arr.add(hex); + dev_endpoints.add(hex); } } } diff --git a/tasmota/xdrv_23_zigbee_4_persistence.ino b/tasmota/xdrv_23_zigbee_4_persistence.ino index b85b296b1..d7b0d0f59 100644 --- a/tasmota/xdrv_23_zigbee_4_persistence.ino +++ b/tasmota/xdrv_23_zigbee_4_persistence.ino @@ -108,37 +108,25 @@ class SBuffer hibernateDevice(const struct Z_Device &device) { buf.add8(0x00); // overall length, will be updated later buf.add16(device.shortaddr); buf.add64(device.longaddr); - uint32_t endpoints = device.endpoints.size(); - if (endpoints > 254) { endpoints = 254; } - buf.add8(endpoints); + + uint32_t endpoints_count = 0; + for (endpoints_count = 0; endpoints_count < endpoints_max; endpoints_count++) { + if (0x00 == device.endpoints[endpoints_count]) { break; } + } + + buf.add8(endpoints_count); // iterate on endpoints - for (std::vector::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) { - uint32_t ep_profile = *ite; - uint8_t endpoint = (ep_profile >> 16) & 0xFF; - uint16_t profileId = ep_profile & 0xFFFF; + for (uint32_t i = 0; i < endpoints_max; i++) { + uint8_t endpoint = device.endpoints[i]; + if (0x00 == endpoint) { break; } // stop buf.add8(endpoint); - buf.add16(profileId); - for (std::vector::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) { - uint16_t cluster = *itc & 0xFFFF; - uint8_t c_endpoint = (*itc >> 16) & 0xFF; + buf.add16(0x0000); // profile_id, not used anymore - if (endpoint == c_endpoint) { - uint8_t clusterCode = toClusterCode(cluster); - if (0xFF != clusterCode) { buf.add8(clusterCode); } - } - } + // removed clusters_in buf.add8(0xFF); // end of endpoint marker - for (std::vector::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) { - uint16_t cluster = *itc & 0xFFFF; - uint8_t c_endpoint = (*itc >> 16) & 0xFF; - - if (endpoint == c_endpoint) { - uint8_t clusterCode = toClusterCode(cluster); - if (0xFF != clusterCode) { buf.add8(clusterCode); } - } - } + // no more storage of clusters_out buf.add8(0xFF); // end of endpoint marker } @@ -235,22 +223,21 @@ void hydrateDevices(const SBuffer &buf) { for (uint32_t j = 0; j < endpoints; j++) { uint8_t ep = buf_d.get8(d++); uint16_t ep_profile = buf_d.get16(d); d += 2; - zigbee_devices.addEndointProfile(shortaddr, ep, ep_profile); + zigbee_devices.addEndpoint(shortaddr, ep); // in clusters while (d < dev_record_len) { // safe guard against overflow uint8_t ep_cluster = buf_d.get8(d++); if (0xFF == ep_cluster) { break; } // end of block - zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), false); + // ignore } // out clusters while (d < dev_record_len) { // safe guard against overflow uint8_t ep_cluster = buf_d.get8(d++); if (0xFF == ep_cluster) { break; } // end of block - zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), true); + // ignore } } - zigbee_devices.shrinkToFit(shortaddr); //AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Device 0x%04X Memory3.shrink = %d"), shortaddr, ESP.getFreeHeap()); // parse 3 strings diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index b7c5829ac..12bb658ec 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -549,6 +549,7 @@ ZF(ZCLVersion) ZF(AppVersion) ZF(StackVersion) ZF(HWVersion) ZF(Manufacturer) ZF ZF(DateCode) ZF(PowerSource) ZF(SWBuildID) ZF(Power) ZF(SwitchType) ZF(Dimmer) ZF(MainsVoltage) ZF(MainsFrequency) ZF(BatteryVoltage) ZF(BatteryPercentage) ZF(CurrentTemperature) ZF(MinTempExperienced) ZF(MaxTempExperienced) ZF(OverTempTotalDwell) +ZF(SceneCount) ZF(CurrentScene) ZF(CurrentGroup) ZF(SceneValid) ZF(AlarmCount) ZF(Time) ZF(TimeStatus) ZF(TimeZone) ZF(DstStart) ZF(DstEnd) ZF(DstShift) ZF(StandardTime) ZF(LocalTime) ZF(LastSetTime) ZF(ValidUntilTime) @@ -660,6 +661,13 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0002, 0x0002, Z(MaxTempExperienced), &Z_Copy }, { 0x0002, 0x0003, Z(OverTempTotalDwell), &Z_Copy }, + // Scenes cluster + { 0x0005, 0x0000, Z(SceneCount), &Z_Copy }, + { 0x0005, 0x0001, Z(CurrentScene), &Z_Copy }, + { 0x0005, 0x0002, Z(CurrentGroup), &Z_Copy }, + { 0x0005, 0x0003, Z(SceneValid), &Z_Copy }, + //{ 0x0005, 0x0004, Z(NameSupport), &Z_Copy }, + // On/off cluster { 0x0006, 0x0000, Z(Power), &Z_Copy }, { 0x0006, 0x8000, Z(Power), &Z_Copy }, // See 7280 @@ -933,7 +941,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0405, 0x0000, Z(Humidity), &Z_FloatDiv100 }, // Humidity { 0x0405, 0x0001, Z(HumidityMinMeasuredValue), &Z_Copy }, // { 0x0405, 0x0002, Z(HumidityMaxMeasuredValue), &Z_Copy }, // - { 0x0405, 0x0003, Z(HumidityTolerance), &Z_Copy }, // + { 0x0405, 0x0003, "HumidityTolerance", &Z_Copy }, // { 0x0405, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Occupancy Sensing cluster diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 299021693..8d756c95d 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -127,7 +127,7 @@ const Z_CommandConverter Z_Commands[] PROGMEM = { { Z(RemoveScene), 0x0005, 0x02, 0x82, Z(xxyyyyzz) }, // xx = status, yyyy = group id, zz = scene id { Z(RemoveAllScenes),0x0005, 0x03, 0x82, Z(xxyyyy) }, // xx = status, yyyy = group id { Z(StoreScene), 0x0005, 0x04, 0x82, Z(xxyyyyzz) }, // xx = status, yyyy = group id, zz = scene id - { Z(GetSceneMembership),0x0005, 0x06, 0x82, Z() }, // specific + { Z(GetSceneMembership),0x0005, 0x06, 0x82,Z(xxyyzzzz) }, // specific }; #define ZLE(x) ((x) & 0xFF), ((x) >> 8) // Little Endian @@ -289,7 +289,7 @@ void sendHueUpdate(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uin if (z_cat >= 0) { uint8_t endpoint = 0; if (!groupaddr) { - endpoint = zigbee_devices.findClusterEndpointIn(shortaddr, cluster); + endpoint = zigbee_devices.findFirstEndpoint(shortaddr); } if ((endpoint) || (groupaddr)) { // send only if we know the endpoint zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, z_cat, 0 /* value */, &Z_ReadAttrCallback); @@ -395,7 +395,33 @@ void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, boo for (uint32_t i = 0; i < xyz.y; i++) { arr.add(payload.get16(2 + 2*i)); } - //arr.add(xyz.z); + } else if ((cluster == 0x0005) && ((cmd == 0x00) || (cmd == 0x02) || (cmd == 0x03))) { + // AddScene or RemoveScene or StoreScene + json[command_name2 + F("Status")] = xyz.x; + json[command_name2 + F("StatusMsg")] = getZigbeeStatusMessage(xyz.x); + json[F("GroupId")] = xyz.y; + json[F("SceneId")] = xyz.z; + } else if ((cluster == 0x0005) && (cmd == 0x01)) { + // ViewScene + json[command_name2 + F("Status")] = xyz.x; + json[command_name2 + F("StatusMsg")] = getZigbeeStatusMessage(xyz.x); + json[F("GroupId")] = xyz.y; + json[F("SceneId")] = xyz.z; + String scene_payload = json[attrid_str]; + json[F("ScenePayload")] = scene_payload.substring(8); // remove first 8 characters + } else if ((cluster == 0x0005) && (cmd == 0x03)) { + // RemoveAllScenes + json[command_name2 + F("Status")] = xyz.x; + json[command_name2 + F("StatusMsg")] = getZigbeeStatusMessage(xyz.x); + json[F("GroupId")] = xyz.y; + } else if ((cluster == 0x0005) && (cmd == 0x06)) { + // GetSceneMembership + json[command_name2 + F("Status")] = xyz.x; + json[command_name2 + F("StatusMsg")] = getZigbeeStatusMessage(xyz.x); + json[F("Capacity")] = xyz.y; + json[F("GroupId")] = xyz.z; + String scene_payload = json[attrid_str]; + json[F("ScenePayload")] = scene_payload.substring(8); // remove first 8 characters } } else { if (0 == xyz.x_type) { diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index e503c9449..1ca3c3b29 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -190,20 +190,6 @@ void Z_SendActiveEpReq(uint16_t shortaddr) { Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq)); - - // uint8_t NodeDescReq[] = { Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, - // Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; - - //ZigbeeZNPSend(NodeDescReq, sizeof(NodeDescReq)); Not sure this is useful -} - -// Send ZDO_SIMPLE_DESC_REQ to get full list of supported Clusters for a specific endpoint -void Z_SendSimpleDescReq(uint16_t shortaddr, uint8_t endpoint) { - uint8_t SimpleDescReq[] = { Z_SREQ | Z_ZDO, ZDO_SIMPLE_DESC_REQ, // 2504 - Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr), - endpoint }; - - ZigbeeZNPSend(SimpleDescReq, sizeof(SimpleDescReq)); } const char* Z_DeviceType[] = { "Coordinator", "Router", "End Device", "Unknown" }; @@ -248,13 +234,8 @@ int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { uint8_t activeEpCount = buf.get8(7); uint8_t* activeEpList = (uint8_t*) buf.charptr(8); - for (uint32_t i = 0; i < activeEpCount; i++) { - zigbee_devices.addEndoint(nwkAddr, activeEpList[i]); - } - - for (uint32_t i = 0; i < activeEpCount; i++) { - Z_SendSimpleDescReq(nwkAddr, activeEpList[i]); + zigbee_devices.addEndpoint(nwkAddr, activeEpList[i]); } Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" @@ -292,56 +273,6 @@ void Z_SendAFInfoRequest(uint16_t shortaddr, uint8_t endpoint, uint16_t clusteri ZigbeeZNPSend(buf.getBuffer(), buf.len()); } - -int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf) { - // Received ZDO_SIMPLE_DESC_RSP - Z_ShortAddress srcAddr = buf.get16(2); - uint8_t status = buf.get8(4); - Z_ShortAddress nwkAddr = buf.get16(5); - uint8_t lenDescriptor = buf.get8(7); - uint8_t endpoint = buf.get8(8); - uint16_t profileId = buf.get16(9); // The profile Id for this endpoint. - uint16_t deviceId = buf.get16(11); // The Device Description Id for this endpoint. - uint8_t deviceVersion = buf.get8(13); // 0 – Version 1.00 - uint8_t numInCluster = buf.get8(14); - uint8_t numOutCluster = buf.get8(15 + numInCluster*2); - - if (0 == status) { - zigbee_devices.addEndointProfile(nwkAddr, endpoint, profileId); - for (uint32_t i = 0; i < numInCluster; i++) { - zigbee_devices.addCluster(nwkAddr, endpoint, buf.get16(15 + i*2), false); - } - for (uint32_t i = 0; i < numOutCluster; i++) { - zigbee_devices.addCluster(nwkAddr, endpoint, buf.get16(16 + numInCluster*2 + i*2), true); - } - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"Endpoint\":\"0x%02X\"" - ",\"ProfileId\":\"0x%04X\",\"DeviceId\":\"0x%04X\",\"DeviceVersion\":%d" - "\"InClusters\":["), - ZIGBEE_STATUS_SIMPLE_DESC, endpoint, - profileId, deviceId, deviceVersion); - for (uint32_t i = 0; i < numInCluster; i++) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(15 + i*2)); - } - ResponseAppend_P(PSTR("],\"OutClusters\":[")); - for (uint32_t i = 0; i < numOutCluster; i++) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(16 + numInCluster*2 + i*2)); - } - ResponseAppend_P(PSTR("]}}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - - uint8_t cluster = zigbee_devices.findClusterEndpointIn(nwkAddr, 0x0000); - if (cluster) { - Z_SendAFInfoRequest(nwkAddr, cluster, 0x0000, 0x01); // TODO, do we need tarnsacId counter? - } - } - return -1; -} - int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { uint8_t status = buf.get8(2); Z_IEEEAddress ieeeAddr = buf.get64(3); @@ -353,14 +284,6 @@ int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { zigbee_devices.updateDevice(nwkAddr, ieeeAddr); char hex[20]; Uint64toHex(ieeeAddr, hex, 64); - // Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - // "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - // "}}"), - // ZIGBEE_STATUS_DEVICE_IEEE, hex, nwkAddr - // ); - - // MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - // XdrvRulesProcess(); // Ping response const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); if (friendlyName) { @@ -417,7 +340,9 @@ int32_t Z_DataConfirm(int32_t res, const class SBuffer &buf) { char status_message[32]; if (status) { // only report errors - strncpy_P(status_message, (const char*) getZigbeeStatusMessage(status), sizeof(status_message)); + const char * statm = (const char*) getZigbeeStatusMessage(status); + if (nullptr == statm) { statm = PSTR(""); } + strncpy_P(status_message, statm, sizeof(status_message)); status_message[sizeof(status_message)-1] = 0; // truncate if needed, strlcpy is safer but strlcpy_P does not exist Response_P(PSTR("{\"" D_JSON_ZIGBEE_CONFIRM "\":{\"" D_CMND_ZIGBEE_ENDPOINT "\":%d" @@ -442,7 +367,7 @@ int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { char hex[20]; Uint64toHex(ieeeAddr, hex, 64); Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" ",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"), ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr, (capabilities & 0x04) ? "true" : "false", @@ -467,7 +392,7 @@ int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) { char hex[20]; Uint64toHex(ieeeAddr, hex, 64); Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" ",\"ParentNetwork\":\"0x%04X\"}}"), ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw ); @@ -600,7 +525,6 @@ const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_PERMITJOIN_OPEN_XX, &Z_ReceivePermitJoinStatus }, { AREQ_ZDO_NODEDESCRSP, &Z_ReceiveNodeDesc }, { AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp }, - { AREQ_ZDO_SIMPLEDESCRSP, &Z_ReceiveSimpleDesc }, { AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr }, { AREQ_ZDO_BIND_RSP, &Z_BindRsp }, }; @@ -635,24 +559,21 @@ int32_t Z_Query_Bulbs(uint8_t value) { if (0 <= device.bulbtype) { uint16_t cluster; - uint8_t endpoint; + uint8_t endpoint = zigbee_devices.findFirstEndpoint(device.shortaddr); cluster = 0x0006; - endpoint = zigbee_devices.findClusterEndpointIn(device.shortaddr, cluster); if (endpoint) { // send only if we know the endpoint zigbee_devices.setTimer(device.shortaddr, 0 /* groupaddr */, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); wait_ms += inter_message_ms; } cluster = 0x0008; - endpoint = zigbee_devices.findClusterEndpointIn(device.shortaddr, cluster); if (endpoint) { // send only if we know the endpoint zigbee_devices.setTimer(device.shortaddr, 0 /* groupaddr */, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); wait_ms += inter_message_ms; } cluster = 0x0300; - endpoint = zigbee_devices.findClusterEndpointIn(device.shortaddr, cluster); if (endpoint) { // send only if we know the endpoint zigbee_devices.setTimer(device.shortaddr, 0 /* groupaddr */, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); wait_ms += inter_message_ms; diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 743af73a3..e90782a8c 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -394,7 +394,7 @@ void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, if ((0 == endpoint) && (shortaddr)) { // endpoint is not specified, let's try to find it from shortAddr, unless it's a group address - endpoint = zigbee_devices.findClusterEndpointIn(shortaddr, cluster); + endpoint = zigbee_devices.findFirstEndpoint(shortaddr); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: shortaddr 0x%04X, groupaddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"), @@ -847,7 +847,7 @@ void CmndZbRead(void) { } if ((0 == endpoint) && (device)) { // try to compute the endpoint - endpoint = zigbee_devices.findClusterEndpointIn(device, cluster); + endpoint = zigbee_devices.findFirstEndpoint(device); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); } if (groupaddr) {