Binary sensor that triggers if any battery level goes beyond a threshold (broken in 2022.09)

Before updating from 2022.07 to 2022.09, I had this binary sensor (that I use to trigger an alert) working perfectly, for years:

  - platform: template
    sensors:
      low_battery_in_sensor_pool:
        device_class: battery
        value_template: > 
          {{ (states.sensor
            | selectattr('attributes.device_class', 'eq', 'battery')
            | map(attribute='state')
            | reject('in', ['unknown', 'unavailable', 'discharging'])
            | map('int', -1) | select('<', 20)
            | select('>=', 0)
            | list | count) > 1
          }}

After the update to 2022.09, this no longer works, I noticed that dozens of unrelated entities now get selected by “selectattr”, they seem to now have a device_class of “battery” (could be a zwavejs2mqtt problem), and their value is 0% (hence, they trigger my template sensor and I am getting useless notifications), for example:

image

Anyways - I thought that instead of selecting the “sensors” based on device_class, a workaround could be to select based on entity_id string matching, I’d like to select all the sensors whose entity_id ends with “_battery_level”. It seems this would cover all sensors I’m interested on (zwave door sensors, PIRs, sirens, flood sensors). This is what I do in the UI, where I use a “batter-state-card” that matches based on “*_battery_level”

is there a way to re-write the selectattr based on partial string matching?

          {{ (states.sensor
            | selectattr('attributes.device_class', 'defined') 
            | selectattr('attributes.device_class', 'eq', 'battery')
            | map(attribute='state')
            | reject('in', ['unknown', 'unavailable', 'discharging'])
            | map('int', -1) | select('<', 20)
            | select('>=', 0)
            | list | count) > 1
          }}

Thanks @petro for the fast response! I just tested this, unfortunately the binary sensor is still active

I edited the orignal post to show more details of the problem I’m having

Device Class indeed seems to be defined and set to “battery” in a bunch of unrelated entities. They are all zwave entities. This might be a problem of zwavejs2mqtt which I also had to upgrade (I am now using 7.1 - docker container)

Is there a way to do the “selection” based on sub string matching with the entity_id?

You can use regex.

selectattr("entity_id", "search", "(battery)")

Thanks @tom_l , this solution worked exactly as expected, using “(_battery_level)” as regex

Thanks for sharing !
I have implemented this to tell me if a device has low battery (below 10%):

  - binary_sensor:
      - name: "Device With Low Battery Detected"
        unique_id: "Device With Low Battery Detected"
        state: >-
          {{ (states.sensor
            | selectattr('attributes.device_class', 'defined') 
            | selectattr("entity_id", "search", "(battery)")
            | map(attribute='state')
            | reject('in', ['unknown', 'unavailable', 'discharging'])
            | map('int', -1) | select('<', 10)
            | select('>=', 0)
            | list | count > 0)
          }}

BUT… I would like to also include in the logic devices reporting ‘low’ (instead of a %).
I have tried several methods without success. Any guidance is appreciated.