How to trigger automation by device_class?

Hello there, I already post a similar message to create a feature about that on this post. But I post here too if one or you having a smart work around to answer to my need.

Need : With the minimum configuration, I’d like to trigger my automation smarter than listing all my entities in my automation or creating a manual group for them.

To be the most flexible, I really want to NOT creating a manual group with my entities.

The user experience might be : I’ve got a new motion sensor entity. I put it in an area. And it could be trigger by my automation.

A quick example to show how it could be implemented :

WHEN motion is trigger…
THEN turn on the light of the motion_device’s area.

- id: 'turn_on_light'
  mode: single
  alias: 'Turn on light'
  description: ''
  trigger:
    - platform: template
      value_template: "{{ states.binary_sensor | rejectattr('attributes.device_class', 'undefined') | selectattr('attributes.device_class', 'eq', 'motion') | selectattr('state', 'eq', 'on') | list }}"
  condition: []
  action:
    - service: light.turn_on
      target:
        area_id: "{{ area_id(target.entity_id) }}"

Any idear ?

Thanks a lot,
Lou_Juicy

1 Like

Whenever any entity in the system changes state a state_changed event is fired. That event has all the data you need to determine if it is associated with a motion sensor you care about. You can use an event trigger, together with an appropriate condition that checks the event trigger variable, to fire your automation.

Note that all other triggers are basically just useful “shortcuts” to an event trigger. If none of the other existing triggers work easily for a given situation, you can always fall back on the event trigger.

So, e.g., you might do something like this:

- trigger:
  - platform: event
    event_type: state_changed
  condition:
  - >
    {{ trigger.event.data.new_state is not none and
       trigger.event.data.new_state.domain == 'binary_sensor' and
       trigger.event.data.new_state.attributes.device_class | default('') == 'motion' and
       trigger.event.data.new_state.state == 'on' }}
  action:
  - service: light.turn_on
    target:
      area_id: "{{ area_id(trigger.event.data.entity_id) }}"
3 Likes

Given your experience with the internals of automations, perhaps you can help me understand the performance and efficiency impact (if any) of monitoring every state_changed event.

My understanding is that an automation is considered “triggered” (i.e. its last_triggered value is updated) only when it processes both its trigger and condition (and it evaluates to true). However, even if the condition is not met (i.e. it’s false), processing takes place to evaluate it. Given a busy trigger, like one that monitors every state_changed event, it means the condition will be processed frequently.

Can you speculate if there would be any performance improvement between what you proposed and the Feature Request for a State Trigger with a device_class option? In other words, if most of the processing occurs in the trigger, as opposed to the condition, is that better for efficiency and performance or is it too close to call?

For example, one thing that comes to mind is that if the trigger never executes then no trace is generated.

1 Like

As you probably know, I stepped away from HA for a quite a while since I worked on the automation/scripting internals. A LOT of changes have happened since then in regard to optimizing triggers. And the entire tracing infrastructure was added as well. So, I’m not as familiar with the details as I once was.

But, yes, I’d say that a specialized trigger that considers the value of the device_class attribute would be more efficient than what I suggested above. It may have to run as often but eliminating the need to evaluate a template on each iteration could be the biggest difference. Or, like you say, avoiding causing a trace event could also make a big difference.

The way I look at it, though, is a relatively compact automation that can do the work of potentially many other automations (using more “traditional” triggers/techniques) is a win, especially if doing it another way is difficult to implement. I generally don’t worry too much about performance; but then again, I don’t have a particular busy system myself.

2 Likes

The absence of your valuable experience was noticed; we missed you Phil! I hope your hiatus was not due to anything unfortunate and was just a well-deserved break. Welcome back!

Thanks! Mostly just got busy. Then when that died down so much had changed it was a bit overwhelming to try and jump back in. :wink: I probably won’t do quite as much anymore, especially with core stuff. But I did just do an overhaul on the life360 integration, which will be part of 2022.7.0. Hopefully that isn’t a disaster. :sweat_smile:

1 Like

It looks very promising ! Thanks a lot for the code and especially for the explanation ! I’ll implement it asap to see if there is performance issue.

I’m trying to move my dump HA configuration for a more plug n play configuration that could allow me to trigger / select my entities by their job instead of their entity_id.

All new template method like area_entities help me a lot to do it but I’v already see some performance issues with my bad implementation for templates.

For example, previously, when I was trying to detect motion in an area, then I expanded all area’s entities before to filter them by device_class.

{{ expand(area_entities('area')) | selectattr('domain', 'eq', 'binary_sensor') | selectattr('attributes.device_class', 'eq', 'motion') | selectattr('state', 'eq', 'on') | list }}

Now, I filter them first then, I extended them.

{{ expand(area_entities('area') | select('match', 'binary_sensor.')) | selectattr('attributes.device_class', 'eq', 'motion') | selectattr('state', 'eq', 'on') | list | length }}

It looks obvious when I write It now but so hard to understand with the classic HA documentation.

Maybe I’ll had to learn developer documentation first to understand basic concepts like you explain it on your first post.

Again thanks a lot for your help both of you !
Lou_Juicy