Moved LQI to Zigbee devices

This commit is contained in:
Stephan Hadinger 2020-06-28 17:53:59 +02:00
parent 609b0309fa
commit 4af6b7d540
4 changed files with 60 additions and 65 deletions

View File

@ -71,6 +71,8 @@ typedef struct Z_Device {
uint16_t ct; // last CT: 153-500 uint16_t ct; // last CT: 153-500
uint16_t hue; // last Hue: 0..359 uint16_t hue; // last Hue: 0..359
uint16_t x, y; // last color [x,y] 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; } Z_Device;
/*********************************************************************************************\ /*********************************************************************************************\
@ -147,6 +149,10 @@ public:
const char * getModelId(uint16_t shortaddr) const; const char * getModelId(uint16_t shortaddr) const;
const char * getManufacturerId(uint16_t shortaddr) const; const char * getManufacturerId(uint16_t shortaddr) const;
void setReachable(uint16_t shortaddr, bool reachable); 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) // get next sequence number for (increment at each all)
uint8_t getNextSeqNumber(uint16_t shortaddr); uint8_t getNextSeqNumber(uint16_t shortaddr);
@ -294,6 +300,8 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) {
200, // ct 200, // ct
0, // hue 0, // hue
0, 0, // x, y 0, 0, // x, y
0xFF, // lqi, 0xFF = unknown
0xFF // battery percentage x 2, 0xFF means unknown
}; };
device_alloc->json_buffer = new DynamicJsonBuffer(16); 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); 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 // 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) { uint8_t Z_Devices::getNextSeqNumber(uint16_t shortaddr) {
int32_t short_found = findShortAddr(shortaddr); int32_t short_found = findShortAddr(shortaddr);

View File

@ -128,6 +128,7 @@ enum Z_ConvOperators {
Z_AqaraSensor, // decode prioprietary Aqara Sensor message Z_AqaraSensor, // decode prioprietary Aqara Sensor message
Z_AqaraVibration, // decode Aqara vibration modes Z_AqaraVibration, // decode Aqara vibration modes
Z_AqaraCube, // decode Aqara cube Z_AqaraCube, // decode Aqara cube
Z_BatteryPercentage, // memorize Battery Percentage in RAM
}; };
ZF(ZCLVersion) ZF(AppVersion) ZF(StackVersion) ZF(HWVersion) ZF(Manufacturer) ZF(ModelId) 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 }, { Zuint16, Cx0001, 0x0000, Z(MainsVoltage), 1, Z_Nop },
{ Zuint8, Cx0001, 0x0001, Z(MainsFrequency), 1, Z_Nop }, { Zuint8, Cx0001, 0x0001, Z(MainsFrequency), 1, Z_Nop },
{ Zuint8, Cx0001, 0x0020, Z(BatteryVoltage), -10,Z_Nop }, // divide by 10 { 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 // Device Temperature Configuration cluster
{ Zint16, Cx0002, 0x0000, Z(CurrentTemperature), 1, Z_Nop }, { Zint16, Cx0002, 0x0000, Z(CurrentTemperature), 1, Z_Nop },
@ -1176,16 +1177,19 @@ void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) {
// ====================================================================== // ======================================================================
// Record Manuf // 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) { 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<const char*>()); zigbee_devices.setManufId(shortaddr, value.as<const char*>());
return 1; 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) { 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<const char*>()); zigbee_devices.setModelId(shortaddr, value.as<const char*>());
return 1; 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<uint8_t>());
return 1;
}
// Add pressure unit // 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) { 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 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 // 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) { int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) {
DynamicJsonBuffer jsonBuffer; DynamicJsonBuffer jsonBuffer;
@ -1219,8 +1207,6 @@ int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t clu
// Aqara Cube // 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) { 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 const char * modelId_c = zigbee_devices.getModelId(shortaddr); // null if unknown
String modelId((char*) modelId_c); String modelId((char*) modelId_c);
@ -1353,7 +1339,13 @@ int32_t Z_AqaraSensorFunc(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObj
json.remove(tmp); json.remove(tmp);
bool translated = false; // were we able to translate to a known format? bool translated = false; // were we able to translate to a known format?
if (0x01 == attrid) { 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); json[F("Battery")] = toPercentageCR2032(val);
} else if ((nullptr != modelId) && (0 == zcl->getManufCode())) { } else if ((nullptr != modelId) && (0 == zcl->getManufCode())) {
translated = true; translated = true;
@ -1431,6 +1423,9 @@ int32_t Z_ApplyConverter(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObje
case Z_AqaraCube: case Z_AqaraCube:
func = &Z_AqaraCubeFunc; func = &Z_AqaraCubeFunc;
break; break;
case Z_BatteryPercentage:
func = &Z_BatteryPercentageKeepFunc;
break;
}; };
if (func) { if (func) {

View File

@ -758,7 +758,7 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) {
timestamp); timestamp);
zcl_received.log(); zcl_received.log();
ZdSetLinkQuality(srcaddr, linkquality); zigbee_devices.setLQI(srcaddr, linkquality);
char shortaddr[8]; char shortaddr[8];
snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr);

View File

@ -1068,44 +1068,6 @@ void CmndZbConfig(void) {
hex_precfgkey_l, hex_precfgkey_h); 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 * Presentation
\*********************************************************************************************/ \*********************************************************************************************/
@ -1128,9 +1090,9 @@ void ZigbeeShow(bool json)
name = spart1; name = spart1;
} }
snprintf_P(spart2, sizeof(spart2), PSTR("-")); snprintf_P(spart2, sizeof(spart2), PSTR("-"));
uint8_t lq = ZdGetLinkQuality(shortaddr); uint8_t lqi = zigbee_devices.getLQI(shortaddr);
if (lq) { if (0xFF != lqi) {
snprintf_P(spart2, sizeof(spart2), PSTR("%d"), lq); snprintf_P(spart2, sizeof(spart2), PSTR("%d"), lqi);
} }
WSContentSend_PD(PSTR("{s}%s{m}LQI %s{e}"), name, spart2); WSContentSend_PD(PSTR("{s}%s{m}LQI %s{e}"), name, spart2);