It's time to fix Aqara battery bug

You mean for the device “lumi.weather”, the battery level is not updated ?
If I m right it’s updated every hour with the periodic report ?

For information, IDK what you are doing with DDF, but deconz load DDF only at start, so if you delete it after deconz running, it will be not updated.

Yes, it does not change. For none of those devices (while all others including Aqara do). Even for one or two I replaced the battery meanwhile.

OK thanks. I‘m gonna try reloading the deCONZ addon/container and see if it changes something.

It does not change, but what is the actual value ? 0 ? (and the previous one)
On my side I have one with a 92% value.

Remember the value used is taken from the periodic report, not the value you can see in the GUI (and idk if this one is good)

        {
          "name": "config/battery",
          "parse": {"fn": "xiaomi:special", "at": "0xff01", "idx": "0x01", "script": "xiaomi_battery.js"}
        },

The values differ (e. g. 88 %, 72 % etc.) but they are frozen (not changing) for at least two weeks.

Reloaded deCONZ now (which by the way also brought new diagnostics entity „duration“ for the Aqara motion sensors) and I will monitor battery values the next days.

At least when now selecting „Edit DDF“ the default DDF opens. A good sign.

All sensors got battery value updates meanwhile. Restarting deCONZ to get rid of a deleted DDF seems to have done the trick.

Following up on this: I see similar behavior for Aqara illuminance sensors (lumi.sen_ill.mgl01): they went down to 0 % regularly - especially those which run for a longer time now (almost 3 years!).

Can we eliminate those 0 % reportings for that hardware too (like we did in Ignore invalid Aqara -100 temperature by amelchio · Pull Request #6723 · dresden-elektronik/deconz-rest-plugin · GitHub)?

Sure, do you know the “bad value” ?
The problem is this DDf use a JS script, so a change in this file will impact all device that use it, so better to create a new one for this device

Use Instead

if (measuredValue > 0 && measuredValue < 0xffff) {

Thinking about this a second time resulted in: maybe I misunderstood something.

  1. Aqara multi sensor (temperature, pressure etc.): had -100 ° values for temperature sensor. Sorted out by filtering those on a DDF level.
  2. Aqara illuminance sensor: it’s not the actual illuminance sensor (like it was the temperature sensor of the other Aqara device at #1), but the battery sensor falling to 0 % regularly for no obvious reason (as shown in It's time to fix Aqara battery bug - #41 by bcutter).

So if I/one would filter `battery: 0 % to be ignored", would that actually be a solution? Because, well… the battery at some day could really be empty, so reported as 0 % (never seen that, as all Aqara devices die way before, usually at 70 to at best 60 %).

Ha ? so you have the problem on the battery too ? Not the luminance ?
So it’s exactly the same code.

Did you read my last post? If I suppress 0 %, what happens if the battery actually is at 0 %? :slight_smile:

You will have the previous value, the one before the 0 value. And like you I never see a 0 value for battery, the device die before.

1 Like

OK, that sound’s good. Now I need a working custom DDF to test this. I’m (still) not really into DDF-ing.

a) Can you give me a kick-start?
b) Do you think this might be helpful for others too (or an individual/custom corner case) so it should make its way into deCONZ?

In the end it’s another workaround for the unreliable Aqara sensor firmware. -100° here, 0 % battery life there…

a) What is your OS ? (You have probably already say it, but I don’t remember all the post).
You can edit fastly the original DDF, or create a new one with the change in the user folder (I will give you the DDF)

b) IDK, on my side I don’t have the issue, and it’s not a common issue for me (I can be wrong), but you can sumbit a PR, we will see other devs decision.

I don’t think it would be allowed. Generally, you dont want to change values other than up/downscaling.

Well, you remember we filtered out the -100 degrees values (see earlier posts in this topic)? :slight_smile:

Using HA OS. I know from earlier custom DDFs how and where to store them so they are persistent (not overwritten on addon/deCONZ container update).

It’s only I have no idea what the content of the DDF should be to suppress/ignore the 0 % value only for the battery values for the „lumi.sen_ill.mgl01“ device.

Yes, but that’s different opposed to the battery percentage. Mine seem to work okay.

Ah OK. Why is it different? Because you’ve seen this (-100 °) with your sensors too? So following that logic now there are two options for the battery values:

  • my Aqara illuminance sensors are the only one in the world behaving like that
  • yours are the only one working perfectly meaning never sending 0 % for some time before switching back

Both cases are very likely not true and therefore not a no-go for a PR to deliver the fix to others. But TBH, once I have a custom DDF with the great help of @Smanar, I will test it for a while. If it works for me, fine. If others don’t need it, fine too :slight_smile:

1 Like

I never had the -100 degree one. Also, as its out its range (-20 as minimal temp, Aqara Temperature and Humidity Sensor T1 - Aqara UK Shop) it can be ignored.

I think i’ve seen the battery on lower than 70%.

IDK, he is right, on my side I never had 0 value for battery, so using a filter for them is an idea to test.

It’s only I have no idea what the content of the DDF should be to suppress/ignore the 0 % value only for the battery values for the „lumi.sen_ill.mgl01“ device

Can try this DDF, based on https://github.com/dresden-elektronik/deconz-rest-plugin/blob/master/devices/xiaomi/xiaomi_gzcgq01lm_light_sensor.json

{
  "schema": "devcap1.schema.json",
  "doc:path": "xiaomi/xiaomi_gzcgq01lm_light_sensor.md",
  "doc:hdr": "Light sensor GZCGQ01LM",
  "manufacturername": ["$MF_XIAOMI", "$MF_LUMI"],
  "modelid": ["lumi.sen_ill.mgl01", "lumi.sen_ill.mgl01"],
  "vendor": "Xiaomi",
  "product": "Mijia Light Sensor GZCGQ01LM",
  "status": "Gold",
  "md:known_issues": [ ],
  "sleeper": true,
  "subdevices": [
    {
      "type": "$TYPE_LIGHT_LEVEL_SENSOR",
      "restapi": "/sensors",
      "uuid": [
        "$address.ext",
        "0x01",
        "0x0400"
      ],
      "fingerprint": {
        "profile": "0x0104",
        "device": "0x0106",
        "endpoint": "0x01",
        "in": [
          "0x0001",
          "0x0400"
        ]
      },
      "items": [
        {
          "name": "attr/lastseen"
        },
        {
          "name": "attr/manufacturername"
        },
        {
          "name": "attr/modelid",
          "awake": true
        },
        {
          "name": "attr/name"
        },
        {
          "name": "attr/swversion",
          "awake": true,
          "parse": {
            "at": "0x00f7",
            "ep": 1,
            "fn": "xiaomi:special",
            "idx": "0x08",
            "script": "xiaomi_swversion.js"
          },
          "read": {
            "fn": "none"
          }
        },
        {
          "name": "attr/type"
        },
        {
          "name": "attr/uniqueid"
        },
        {
          "name": "config/on"
        },
        {
          "name": "config/battery",
          "awake": true,
          "parse": {
            "at": "0x00f7",
            "ep": 1,
            "fn": "xiaomi:special",
            "idx": "0x01",
            "eval": "const vmin = 2700; const vmax = 3000; const v = Math.max(vmin, Math.min(Attr.val, vmax)); const bat = Math.round(((v - vmin) / (vmax - vmin)) * 100); if (bat>0){Item.val = Math.max(0, Math.min(bat, 100));}"
          }
        },
        {
          "name": "config/reachable"
        },
        {
          "name": "config/tholddark"
        },
        {
          "name": "config/tholdoffset"
        },
        {
          "name": "state/lightlevel",
          "parse": {
            "at": "0x0000",
            "cl": "0x0400",
            "ep": 1,
            "script": "../generic/illuminance_cluster/sml_light_level.js"
          }
        },
        {
          "name": "state/dark"
        },
        {
          "name": "state/daylight"
        },
        {
          "name": "state/lux"
        },
        {
          "name": "state/lastupdated"
        }
      ],
      "example": {
        "config": {
          "battery": 100,
          "on": true,
          "reachable": true,
          "tholddark": 12000,
          "tholdoffset": 7000
        },
        "ep": 1,
        "etag": "761fff5a33ee73a8b9e4ec2e8ee5dac2",
        "lastseen": "2021-01-13T12:07Z",
        "manufacturername": "XIAOMI",
        "modelid": "lumi.sen_ill.mgl01",
        "name": "Light Sensor",
        "state": {
          "dark": false,
          "daylight": false,
          "lastupdated": "2021-01-13T12:07:27.511",
          "lightlevel": 13425,
          "lux": 22
        },
        "swversion": "0.0.0_0027",
        "type": "ZHALightLevel",
        "uniqueid": "04:cf:8c:df:3c:7f:1f:80-01-0400"
      }
    }
  ],
  "bindings": [
    {
      "bind": "unicast",
      "src.ep": 1,
      "cl": "0x0400",
      "report": [
        {
          "at": "0x0000",
          "dt": "0x21",
          "min": 10,
          "max": 3600,
          "change": "0x0064"
        }
      ]
    }
  ]
}

The magic is here


        {
          "name": "config/battery",
          "awake": true,
          "parse": {
            "at": "0x00f7",
            "ep": 1,
            "fn": "xiaomi:special",
            "idx": "0x01",
            "eval": "const vmin = 2700; const vmax = 3000; const v = Math.max(vmin, Math.min(Attr.val, vmax)); const bat = Math.round(((v - vmin) / (vmax - vmin)) * 100); if (bat>0){Item.val = Math.max(0, Math.min(bat, 100));}"
          }
        },

And what would this “magic” part needs to look like to efficiently filter the unwanted 0 (zero) values?