How do I trigger based on a substring of a bunch of sensors?

I know this seems crazy, but I’ve been spending hours on this without success.

I’m looking for a way to look for the string “batt” in an http api-sensor state and then fire a trigger based on that.
Here’s what I think is probably the closest to correct, but still doesn’t work:

  - alias: Device battery low
    trigger:
      platform: state
      entity_id: group.raw_sensors
    condition:
      - condition: template
        value_template: >
          {{'batt' in trigger.to_state.state}}

I think this one above doesn’t work because the group is acting more like a binary sensor and going “on” or “off” instead of a variable with the state of the sensor.

I also tried something like this:

  - alias: Device battery low
    trigger:
      platform: template
      value_template: >
        {% set found = 0 %}
        {% for state in states.sensor %}
          {% if 'batt' in state.state %}
            {% set found = 1 %}
          {% endif %}
        {% endfor %}
        {{ found == 1 }}

but it doesn’t seem to be getting into the trigger.

Any ideas?

How does the HTTP API-sensor data look like?

I have a 433Mhz battery powered temperature/humidity sensor, the battery level is being put in the device attributes. I created a virtual sensor for it:
sensors.yaml

- platform: template
  sensors:
    tx320_sk_battery:
      value_template: '{% if states.sensor.slaapkamer.attributes["Battery numeric"] | float == 9.0 %}Vol{% else %}Leeg{% endif %}'
      friendly_name: 'Cresta slaapkamer batterij'
      entity_id: sensor.slaapkamer

022.cresta_slaapkamer_battery_low.yaml

alias: 022 - Cresta slaapkamer low battery
trigger:
  - platform: state
    entity_id: sensor.tx320_sk_battery
    from: 'Vol'
    to: 'Leeg'
action:
- service: notify.telegram_f
  data:
    title: Batterijmelding - 
    message: Batterij van de Cresta TX320 in de slaapkamer begint leeg te raken!

customization.yaml

`sensor.tx320_sk_battery:`
`  hidden: true`

Excuse my Dutch, vol = full, leeg = empty.
The batterylevel attribute is 9 when battery is full and 0 (or not 9) when (almost) empty.

I think that is also the way to go for you, extract the value from the sensor with some [Jinja](http://jinja.pocoo.org/docs/dev/templates/) magic and put the batterylevel in a virtual sensor, which you can then use in automation rules.

Thank you for the reply - I am able to use a virtual sensor to get the battery info out but if I have many many of them that is what I am trying to do without listed each one in a separate automation. Is there a way to add them all to one automation?

I don’t know, my best bet would be something with those Jinja templates i mentioned.

Maybe you should look into the for function in jinja. I can’t check right now but maybe you could just iterate over all sensors of this group. I don’t know if you can get all sensors of a group but if so you could iterate over them.

Cheers

Sorry, but do you have any more info on how to access groups? I’ve been looking in the docs and the code and can’t find a reference. Any way to iterate or get access to group entities?

Sure. Just take a look at the groups in your developer console under “states” there you can see that each group has an attribute named “entity_id” You should be able to iterate over that or you could iterate over all states and just check if they are in that field of the group.

In Jinja the for loop looks like this:

  action:
    - service: notify.janis_handy_telegram
      data_template:
        title: "[ALERT][Homeassistant] "
        message: >-
          {%- for state in states.sensor if state.entity_id == trigger.entity_id -%}
            {{ state.attributes.friendly_name }} is down.
          {%- endfor -%}

I hope this helps.

Cheers

2 Likes

Thanks for the additional info. I also found a loose reference that the entity_ids are in the group attributes, so here’s what I have come up with so far:

{%- for state in states.group if state.entity_id == 'group.raw_sensors' %}
    {% for sstate in states.sensor if sstate.entity_id in state.attributes.entity_id %}
        {{ 'batt' in sstate.state }}
    {% endfor %}
{%- endfor -%}

I do wish there was a more direct way of accessing the group by name without iterating over all of them. If anyone knows of a way, please let me know.

Now, I should be able to come up with a template trigger based on this at some point. I’ll need to spend just a bit more time figuring out what a trigger would look like - I think it needs to return ‘true’ or ‘false’ based on the loops above, but I’m still unclear how template triggers work, am I correct that the template get executed for EVERY component state change?

1 Like

Yes you are correct. That is also why you should really only use template triggers as a last resort. You should at least build a if block around your core template which check the “trigger.entity_id” for your group.Also you could use the states function like “states.group.raw_sensors” This way you would not have to iterate over the groups.

Cheers

PS: Yes the template trigger has to return true or false

So after much trial and error, this is what I settled on, quite different than what I had originally:

trigger:
  platform: template
  value_template: >
    {% for sstate in states.sensor if sstate.entity_id in states.group.raw_sensors.attributes.entity_id and 'batt' in sstate.state %}
      {% if loop.first %}
        {{true}}
      {% endif %}
    {% else %}
      {{false}}
    {% endfor %}

If you see anything wierd with this, please let me know. Thanks for all your help.

I’m not sure about this. But this would trigger EVERYTIME a state changed…ANY state that is.

Cheers

Maybe try somethin like this to get to only trigger on state changes from the group:

trigger:
  platform: template
  value_template: >
    {% for sstate in states.sensor if sstate.entity_id in states.group.raw_sensors.attributes.entity_id and 'batt' in sstate.state and trigger.entity_id in states.group.raw_sensors.attributes.entity_id %}
      {% if loop.first %}
        {{true}}
      {% endif %}
    {% else %}
      {{false}}
    {% endfor %}
2 Likes

I’m a bit new to jinja templates, but I’m learning and this post was extremely helpful for me as I’m trying to do something similar. I have a group of battery sensors (12 actually) and the thought of creating 12 different automations to alert on a low battery made me cringe.

I was able to use the template console in the developer tools to get me close, but I think I have a misunderstanding of how the automation triggers work.

Using your example I was able to piece together the following automation (I used 70 as a test because I have a couple of devices lower than 70%):

batteries:
  name: Battery Levels
  entities:
    - sensor.living_room_4in1_battery
    - sensor.master_bed_4in1_battery
    - sensor.office_4in1_battery
    - sensor.front_door_battery
    - sensor.garage_back_door_battery
    - sensor.garage_laundry_door_battery
    - sensor.kitchen_glassdoor_battery
    - sensor.master_bed_door_battery
    - sensor.master_bed_glassdoor_battery
    - sensor.nw_garage_door_battery
    - sensor.se_garage_door_battery
    - sensor.maibox_battery

# ---------------------------------- # 
- alias: Low Battery Notification
  trigger:
    - platform: template
      value_template: >
        {% for state in states.sensor
          if trigger.entity_id in states.group.batteries.attributes.entity_id
            and state.entity_id in states.group.batteries.attributes.entity_id
              and state.state | int < 70 %}
            {% if loop.first %}
              {{true}}
            {% endif %}
          {% else %}
            {{false}}
        {% endfor %}
  action:
    - service: notify.all
      data_template:
        message: >
          {{ trigger.from_state.attributes.friendly_name }} needs new batteries.

I’m not sure if the message data_template is correct or not, but I would at least figure I would see the automation get triggered in the logs if that was the problem. Is there a way to somehow test for trigger.entity_id in the template developer tools?

1 Like

Sadly I do not know of any way to test the trigger.entity_id in the developer tools on the Web frontend.

Cheers

@jceloria Hi, did you ever get this to work?

Unfortunately not yet, I’m also in the middle of switching employment so I haven’t had a lot of time to work on it.

Reviving a old thread, I just tested this out and it seems to work okay at least with the first device it finds (it would be great to get notifications for all devices that are found below the threshold, but I can live with this). I’d like to post what I have to keep me honest and to make sure I’m not doing something stupid. Any other suggestions are greatly appreciated.

  # Send a notification if a zwave device battery is low
  - alias: Low Battery Notification
    hide_entity: True
    trigger:
      - platform: template
        value_template: >
          {% for zwave in states.zwave if zwave.attributes.battery_level %}
            {%- if zwave.attributes.battery_level | int < 70 -%}
              {{true}}
            {%- endif -%}
          {%- endfor -%}
    action:
      - service: notify.pushover
        data_template:
          data:
            sound: spacealarm
            priority: 1
          message: >
            {{ trigger.to_state.attributes.friendly_name }} needs new batteries.