It looks like a deep bug inside Domoticz.
The classic Xiaomi temp/hum sensor reports the following json:
Code: Select all
{"cmd":"read_ack","model":"sensor_ht","sid":"***","short_id":***,"data":"{\"voltage\":2985,\"temperature\":\"2338\",\"humidity\":\"3801\"}"}
The Aqara temp/hum/pressure sensor reports the following json:
Code: Select all
{"cmd":"read_ack","model":"weather.v1","sid":"***","short_id":***,"data":"{\"voltage\":2955,\"temperature\":\"2485\",\"humidity\":\"2896\",\"pressure\":\"100100\"}"}
XiaomiGateway.cpp contains the following code:
Code: Select all
std::string voltage = root2["voltage"].asString();
int battery = 255;
if (voltage != "" && voltage != "3600") {
battery = ((atoi(voltage.c_str()) - 2200) / 10);
}
...
if ((name == "Xiaomi Temperature/Humidity") || (name == "Xiaomi Aqara Weather")) {
std::string temperature = root2["temperature"].asString();
std::string humidity = root2["humidity"].asString();
if (temperature != "") {
m_XiaomiGateway->InsertUpdateTemperature(sid.c_str(), "Xiaomi Temperature", temp, battery);
}
if (humidity != "") {
m_XiaomiGateway->InsertUpdateHumidity(sid.c_str(), "Xiaomi Humidity", hum, battery);
}
if (name == "Xiaomi Aqara Weather") {
std::string pressure = root2["pressure"].asString();
m_XiaomiGateway->InsertUpdatePressure(sid.c_str(), "Xiaomi Humidity", pres, battery);
}
}
Note that the battery level may be 255 if it is not set or a value around -10..110
BTW, I don't see a source of the combined Temp/Hum sensor. XiaomiGateway.cpp never called SendTempHumSensor().
All possible 3 sensors (temp, hum and pressure) must have the same battery level.
But temp always has 100%, hum, temp/hum sometimes show the correct level.
I see few bugs:
Code: Select all
void CDomoticzHardwareBase::SendTempSensor(const int NodeID, const int BatteryLevel, const float temperature, const std::string &defaultname, const int RssiLevel /* =12 */)
{
RBUF tsen;
memset(&tsen, 0, sizeof(RBUF));
tsen.TEMP.packetlength = sizeof(tsen.TEMP) - 1;
tsen.TEMP.packettype = pTypeTEMP;
...
tsen.TEMP.battery_level = BatteryLevel; // !!!
...
sDecodeRXMessage(this, (const unsigned char *)&tsen.TEMP, defaultname.c_str(), BatteryLevel);
}
It looks like BatteryLevel passed to MainWorker::DecodeRXMessage is just lost.
The field RBUF.TEMP.battery_level is declared as BYTE : 4.
I have no idea how -10, 70, 110 or 255 may be correctly converted to 4 bits field.
It looks like this field expexts a value 0..9 which means 10, 20, ..100%.
Then in
Code: Select all
void MainWorker::decode_Temp(const int HwdID, const _eHardwareTypes HwdType, const tRBUF *pResponse, _tRxMessageProcessingResult & procResult)
{
...
unsigned char BatteryLevel = 0;
if ((pResponse->TEMP.battery_level & 0x0F) == 0)
BatteryLevel = 0;
else
BatteryLevel = 100;
So the BatteryLevel is completelly lost at least for temp sensors.
I don't know how to correctly fix this bug. It is too deep and too much devices are affected.