From 4af6b7d5404f5e47f92a3416aadbec52e0de3330 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 28 Jun 2020 17:53:59 +0200 Subject: [PATCH] Moved LQI to Zigbee devices --- tasmota/xdrv_23_zigbee_2_devices.ino | 38 +++++++++++++++++++++ tasmota/xdrv_23_zigbee_5_converters.ino | 41 ++++++++++------------- tasmota/xdrv_23_zigbee_8_parsers.ino | 2 +- tasmota/xdrv_23_zigbee_A_impl.ino | 44 ++----------------------- 4 files changed, 60 insertions(+), 65 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index 23a9343d4..991646d06 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -71,6 +71,8 @@ typedef struct Z_Device { uint16_t ct; // last CT: 153-500 uint16_t hue; // last Hue: 0..359 uint16_t x, y; // last color [x,y] + uint8_t linkquality; // lqi from last message, 0xFF means unknown + uint8_t batterypercentx2;// battery percentage x 2 (0..200), 0xFF means unknwon } Z_Device; /*********************************************************************************************\ @@ -147,6 +149,10 @@ public: const char * getModelId(uint16_t shortaddr) const; const char * getManufacturerId(uint16_t shortaddr) const; void setReachable(uint16_t shortaddr, bool reachable); + void setLQI(uint16_t shortaddr, uint8_t lqi); + uint8_t getLQI(uint16_t shortaddr) const; + void setBatteryPercentx2(uint16_t shortaddr, uint8_t bpx2); + uint8_t getBatteryPercentx2(uint16_t shortaddr) const; // get next sequence number for (increment at each all) uint8_t getNextSeqNumber(uint16_t shortaddr); @@ -294,6 +300,8 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { 200, // ct 0, // hue 0, 0, // x, y + 0xFF, // lqi, 0xFF = unknown + 0xFF // battery percentage x 2, 0xFF means unknown }; device_alloc->json_buffer = new DynamicJsonBuffer(16); @@ -619,6 +627,36 @@ void Z_Devices::setReachable(uint16_t shortaddr, bool reachable) { bitWrite(device.power, 7, reachable); } +void Z_Devices::setLQI(uint16_t shortaddr, uint8_t lqi) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } // don't crash if not found + device.linkquality = lqi; +} + +uint8_t Z_Devices::getLQI(uint16_t shortaddr) const { + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + return device.linkquality; + } + return 0xFF; +} + +void Z_Devices::setBatteryPercentx2(uint16_t shortaddr, uint8_t bpx2) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } // don't crash if not found + device.batterypercentx2 = bpx2; +} + +uint8_t Z_Devices::getBatteryPercentx2(uint16_t shortaddr) const { + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + return device.batterypercentx2; + } + return 0xFF; +} + // 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); diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 4835306a5..9488918b3 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -128,6 +128,7 @@ enum Z_ConvOperators { Z_AqaraSensor, // decode prioprietary Aqara Sensor message Z_AqaraVibration, // decode Aqara vibration modes Z_AqaraCube, // decode Aqara cube + Z_BatteryPercentage, // memorize Battery Percentage in RAM }; ZF(ZCLVersion) ZF(AppVersion) ZF(StackVersion) ZF(HWVersion) ZF(Manufacturer) ZF(ModelId) @@ -238,7 +239,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zuint16, Cx0001, 0x0000, Z(MainsVoltage), 1, Z_Nop }, { Zuint8, Cx0001, 0x0001, Z(MainsFrequency), 1, Z_Nop }, { Zuint8, Cx0001, 0x0020, Z(BatteryVoltage), -10,Z_Nop }, // divide by 10 - { Zuint8, Cx0001, 0x0021, Z(BatteryPercentage), -2, Z_Nop }, // divide by 2 + { Zuint8, Cx0001, 0x0021, Z(BatteryPercentage), -2, Z_BatteryPercentage }, // divide by 2 // Device Temperature Configuration cluster { Zint16, Cx0002, 0x0000, Z(CurrentTemperature), 1, Z_Nop }, @@ -1176,16 +1177,19 @@ void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { // ====================================================================== // Record Manuf int32_t Z_ManufKeepFunc(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = value; zigbee_devices.setManufId(shortaddr, value.as()); return 1; } -// +// Record ModelId int32_t Z_ModelKeepFunc(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = value; zigbee_devices.setModelId(shortaddr, value.as()); return 1; } +// Record BatteryPercentage +int32_t Z_BatteryPercentageKeepFunc(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + zigbee_devices.setBatteryPercentx2(shortaddr, value.as()); + return 1; +} // Add pressure unit int32_t Z_AddPressureUnitFunc(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { @@ -1193,22 +1197,6 @@ int32_t Z_AddPressureUnitFunc(const class ZCLFrame *zcl, uint16_t shortaddr, Jso return 0; // keep original key } -// Convert int to float and divide by 100 -int32_t Z_FloatDiv100Func(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = ((float)value) / 100.0f; - return 1; // remove original key -} -// Convert int to float and divide by 10 -int32_t Z_FloatDiv10Func(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = ((float)value) / 10.0f; - return 1; // remove original key -} -// Convert int to float and divide by 10 -int32_t Z_FloatDiv2Func(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = ((float)value) / 2.0f; - return 1; // remove original key -} - // Publish a message for `"Occupancy":0` when the timer expired int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { DynamicJsonBuffer jsonBuffer; @@ -1219,8 +1207,6 @@ int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t clu // Aqara Cube int32_t Z_AqaraCubeFunc(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = value; // copy the original value - const char * modelId_c = zigbee_devices.getModelId(shortaddr); // null if unknown String modelId((char*) modelId_c); @@ -1353,7 +1339,13 @@ int32_t Z_AqaraSensorFunc(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObj json.remove(tmp); bool translated = false; // were we able to translate to a known format? if (0x01 == attrid) { - json[F(D_JSON_VOLTAGE)] = val / 1000.0f; + float batteryvoltage = val / 1000.0f; + json[F("BatteryVoltage")] = batteryvoltage; + uint8_t batterypercentage = toPercentageCR2032(val); + json[F("BatteryPercentage")] = batterypercentage; + zigbee_devices.setBatteryPercentx2(shortaddr, batterypercentage * 2); + // deprecated + json[F(D_JSON_VOLTAGE)] = batteryvoltage; json[F("Battery")] = toPercentageCR2032(val); } else if ((nullptr != modelId) && (0 == zcl->getManufCode())) { translated = true; @@ -1431,6 +1423,9 @@ int32_t Z_ApplyConverter(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObje case Z_AqaraCube: func = &Z_AqaraCubeFunc; break; + case Z_BatteryPercentage: + func = &Z_BatteryPercentageKeepFunc; + break; }; if (func) { diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 5699801d8..548c09a25 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -758,7 +758,7 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { timestamp); zcl_received.log(); - ZdSetLinkQuality(srcaddr, linkquality); + zigbee_devices.setLQI(srcaddr, linkquality); char shortaddr[8]; snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index 935257e8e..489aece50 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -1068,44 +1068,6 @@ void CmndZbConfig(void) { hex_precfgkey_l, hex_precfgkey_h); } -/*********************************************************************************************\ - * Database of linkqualities - there must be a better way to implement this ... -\*********************************************************************************************/ - -const uint8_t MAX_ZBRECORDS = 16; - -typedef struct Z_DevRecord_t { - uint16_t shortaddr; - uint8_t linkquality; -} Z_DevRecord_t; - -Z_DevRecord_t Z_DevRecord[MAX_ZBRECORDS]; -uint8_t Z_DevIndex = 0; - -void ZdSetLinkQuality(uint16_t shortaddr, uint8_t linkquality) { - if (Z_DevIndex < MAX_ZBRECORDS -1) { - uint32_t i; - for (i = 0; i < Z_DevIndex; i++) { - if (shortaddr == Z_DevRecord[i].shortaddr) { - Z_DevRecord[i].linkquality = linkquality; - return; - } - } - Z_DevRecord[i].shortaddr = shortaddr; - Z_DevRecord[i].linkquality = linkquality; - Z_DevIndex++; - } -} - -uint8_t ZdGetLinkQuality(uint16_t shortaddr) { - for (uint32_t i = 0; i < Z_DevIndex; i++) { - if (shortaddr == Z_DevRecord[i].shortaddr) { - return Z_DevRecord[i].linkquality; - } - } - return 0; -} - /*********************************************************************************************\ * Presentation \*********************************************************************************************/ @@ -1128,9 +1090,9 @@ void ZigbeeShow(bool json) name = spart1; } snprintf_P(spart2, sizeof(spart2), PSTR("-")); - uint8_t lq = ZdGetLinkQuality(shortaddr); - if (lq) { - snprintf_P(spart2, sizeof(spart2), PSTR("%d"), lq); + uint8_t lqi = zigbee_devices.getLQI(shortaddr); + if (0xFF != lqi) { + snprintf_P(spart2, sizeof(spart2), PSTR("%d"), lqi); } WSContentSend_PD(PSTR("{s}%s{m}LQI %s{e}"), name, spart2);