MQTT battery level in UI

A quick background: I’m working on supporting some door and window sensors over MQTT since the existing solutions I have found are in adequate. This may be more of a “development” issue, but I’m sticking with “configuration” since I believe the issue stems from my configuration I push to discovery.

Each device has 3 entities: state (open/closed), tamper (tampered/untampered), battery (normal/low). The three discovered configurations as seen in Device Info → MQTT Info are:

Open/Close Sensor:

unique_id: living_room_front_windows_state
name: Living Room Front Windows
device_class: window
payload_on: open
payload_off: closed
qos: 1
availability_topic: home/downstairs/living-room/front-windows/availability
payload_available: online
payload_not_available: offline
state_topic: home/downstairs/living-room/front-windows/state
device:
  identifiers:
    - 361625
    - 362446
  name: Living Room Front Windows Sensor
  model: Honeywell-Security
  suggested_area: Living Room
platform: mqtt

Battery:

unique_id: living_room_front_windows_battery
name: Living Room Front Windows battery
device_class: battery
payload_on: low
payload_off: normal
qos: 1
availability_topic: home/downstairs/living-room/front-windows/availability
payload_available: online
payload_not_available: offline
state_topic: farrington/home/living-room/front-windows/battery
device:
  identifiers:
    - 361625
    - 362446
  name: Living Room Front Windows Sensor
  model: Honeywell-Security
  suggested_area: Living Room
platform: mqtt

Tamper:

unique_id: living_room_front_windows_tamper
name: Living Room Front Windows tamper
device_class: safety
payload_on: tampered
payload_off: untampered
qos: 1
availability_topic: home/downstairs/living-room/front-windows/availability
payload_available: online
payload_not_available: offline
state_topic: home/downstairs/living-room/front-windows/tamper
device:
  identifiers:
    - 361625
    - 362446
  name: Living Room Front Windows Sensor
  model: Honeywell-Security
  suggested_area: Living Room
platform: mqtt

The Device Info page shows everything the way I would expect. I see all three entities, and it even shows the battery health as an icon on the top right of the page:


Similarly, the battery icon shows in the device listing, similar to other battery powered devices: (New users can only attach one image? Screenshot: shows my MQTT, Zigbee, and iPhone in configuration’s device listing w/ black battery icons on the right column)

Now, for what is wrong. My battery entity shows in the main Lovelace “overview” page and mobile app:
(Screenshot: shows all three entities on the room’s card).
This clutters the page and isn’t super obvious from a “health” standpoint. Compare this to the Zigbee sensor, the battery entity doesn’t show. Instead, a black battery icon similar to the one seen earlier will annotate the entities when the battery is unhealthy (Screenshot showing what I just said)

So, how do I get hass to treat the battery in a similar fashion? I looked through config options and the entity battery_level_topic attribute looked promising. However, when I specify bat_lev_t, I get:

voluptuous.error.MultipleInvalid: extra keys not allowed @ data['battery_level_topic']

Any thoughts? Thanks!

For the MQTT integration battery must be in percent. Use MQTT Explorer (great program) to see what other topics are available. If you are using something like Zwave2MQTT then look at the topics there. Sometime the auto-discovery does not pick up everything on the first try. I had this issue with my door/window sensors.

Ah. I can give that a shot. Unfortunately, I presume that means I need to “lie”, as these sensors only have a “battery ok” boolean status. I suppose just map it to 90% and 10% or something? Really odd to me that you need to force it to percentage for the Lovelace UI, but the configuration pages, etc do recognize it as a binary sensor and show a little battery with an exclamation point for the parent device. Seems like a bug.

You could make a template sensor that gives a percentage based on the binary state. You just need to find out at what voltage the unit give a battery low and at that point put a percentage up. This will only ever give you 2 (3 if you put 0% for unavailable) different percentage data points. I would say 100% for ‘normal’ and then calculate the % for the low by dividing the voltage at which low is triggered by the max battery voltage.
Did you verify that there are not more sensor that are not currently exposed to HA?

I’ll do something like that for now, but probably not as methodological. The sensors aren’t all homogeneous anyway.
By “more sensors not currently exposed”, do you mean any more parameters for a device? I also report availability based on “last seen” (timeout since last occurrence of an an event or heartbeat). That works fine

If your sensors are Zwave and you use something like Zwave2MQTT then I have seen attributes in Zwave2MQTT that do not get added to HA. Do you use Zwave2MQTT; if so look at the sensors there and are there any attributes not in HA at this time? Have you used MQTT Explorer to see everything that goes into MQTT?

I do use zwavejs2mqtt, but not for these sensors. These are Honeywell 345MHz devices that I listen to with a SDR and pump events to MQTT with some Python that I’m about to publish to GitHub.

For fun, I disabled the WS interface in zwavejs2mqtt and went straight to MQTT Discovery and gave it a test run with a battery powered Z Wave device. Sure enough, the sensor battery level entity doesn’t show in Lovelace as a distinct entity, but the binary_sensor battery low entity does. So, this is consistent with my observed behavior, and my MQTT client’s discovery messages are not different than the zwavejs2mqtt ones in any significant way.

That leads me to this conclusion: Lovelace UI is inconsistent. The device view (e.g: /config/devices/device/BLAH) and device listing (/config/devices/dashboard) show the battery low icon for a device’s related binary_sensor battery (when low), and they show the battery level icon for a device’s related sensor battery. This seems like the expected behavior. However, on a Lovelace card, it only squashes the battery for sensor battery levels and not for binary_sensor battery low.

I could use a sensor instead and lie about percentage. But, that doesn’t seem right to me from a semantic standpoint,and requires a bit of refactoring. In my opinion, the cards should consider both sensor and binary_sensor battery device_types equivalently.

I hacked my code to use a sensor type battery instead of a binary_sensor type. In addition, I pushed low battery levels onto zwavejs2mqtt battery topics.

  1. Yes, using sensor instead of binary_sensor makes the the battery entities automatically disappear from the Lovelace cards. I still argue that this is an unexpected inconsistency and should be seen as a bug.
  2. The battery icons continue to show in the device details and device listing regardless of sensor or binary_sensor. Setting the value to 1% results in the battery warning icon with an exclamation point. This is good and expected.
  3. The battery icons never show adjacent to the related device in the Lovelace cards. Maybe I’m going crazy, but I could swear I’ve seen black right-aligned battery warnings on the Lovelace entity rows for my Zigbee (ZHA) devices.