Together these led me to believe that I should be able to write a trigger like the one in the simple example automation below. Basically, my understanding from the docs is that an event trigger may specify an event_data field, whose contents must match against the contents of the data field of a candidate event in order for the trigger to fire. The data of state_changed events consists of three fields: entity_id, old_state, and new_state. The latter two are state objects, which themselves contain a variety of fields, and in this case I want to match on the value of the domain field of the old_state object.
In my testing, however, this automation never triggers, even though I can confirm elsewhere that a personâs state has changed (e.g. from âHomeâ to âAwayâ). Does anybody know what Iâm doing wrong?
I believe I could rewrite this as an unconditional event trigger (no event_data field) with a separate condition (probably a template) that examines the domain of the old_state, but it would seem kind of wasteful to trigger on every single state_changed event, no? And in any case, I would still like to understand why this event_data-based approach doesnât work; if it doesnât work by design, then perhaps the documentation could be improved to clarify this. Or more likely Iâm just being dumb! Thanks for any pointers!
alias: "Notify: person changed zone"
description: ""
trigger:
- platform: event
event_type: state_changed
event_data:
old_state:
domain: person
variables:
name: "{{event.data.old_state.name}}"
whence: "{{event.data.old_state.state}}"
whither: "{{event.data.new_state.state}}"
condition: []
action:
- service: notify.notify
data:
title: "{{name}} is on the move."
message: "{{name}} has moved from {{whence}} to {{whither}}."
mode: single
Go to Developer Tools > Events, enter state_changed in âEvent to subscribe toâ then click 'Start Listening '.
Various events will scroll by and, based on the results from my system, domain is not present in old_state or new_state. That explains why the Event Trigger you created never triggers.
Thanks, @Taras! That must explain it. Is the documentation incorrect, then? Regarding the state_changed event type, it says:
It contains the entity identifier and both the new_state and old_state of the entity as state objects.
And then the documentation for âState Objectsâ quite clearly says:
state.domain: Domain of the entity. Example: light.
If the new_state and old_state fields of the state_changed event type are actually only partial state objects, I feel like the documentation should say so, and furthermore list which subset of fields will actually be present.
Or perhaps itâs a bug that state.domain, state.object_id, and other documented fields are not being populated in the state objects?
Or, perhaps itâs the case that some of the fields in the âState Objectsâ documentation are âoptionalâ and not guaranteed to be present on all states? If so then I feel like that documentation could be better about highlighting which fields are optional, and furthermore what sorts of states might be expected to have them and which not. Itâs all pretty confusing right now unless you go and sniff events empirically, which is kind of inconvenient to do for things like person state (I guess I would have to walk down the street or something while subscribing to âstate_changedâ in the dev tools on my phone).
EDIT: I suppose a fourth possibility is that some of those documented state fields are only present on state objects as returned by the states() function inside a template, which I donât think I can use in the event_data field of my event trigger. That, too, should be documented if so, i.e., which fields are actually present in the raw state data, and which are âderivedâ and only present in the objects returned by states() when evaluating a template. Or perhaps the implementation of the event trigger platform should be updated to include the âfullâ state object as returned by states() when testing usersâ event_data fields.
Iâd be happy to take a crack at improving the docs myself if it were clear what the actual intention is.
It took some digging but I tracked down the author and date of that specific section of the documentation indicating old_state and new_state contain state objects.
Maybe it was correct at the time but today this is what I see:
event_type: state_changed
data:
entity_id: sensor.dishwasher_energy_power
old_state:
entity_id: sensor.dishwasher_energy_power
state: "11"
attributes:
state_class: none
unit_of_measurement: W
device_class: power
friendly_name: dishwasher ENERGY Power
last_changed: "2022-12-12T16:46:13.220469+00:00"
last_updated: "2022-12-12T16:46:13.220469+00:00"
context:
id: 01GM3KNM74FFPHEFK0SVJCEB23
parent_id: null
user_id: null
If we compare it to a State Objectâs properties (as per its documentation), it doesnât include the following:
domain
object_id
name
So it appears to contain most, but not all, of a State Objectâs properties.
Effectively, the reply I posted above solves the problem: it didnât trigger because thereâs no domain property.
Feel free to refine the documentation. Whatever changes you make will be vetted by a developer. If thereâs any question about the need for the modification, you can point them to this topic.
Cool, thanks for digging . I wonder whatâs best⌠to document the partial subset of properties, or to actually change the behavior of the state_changed event type to include all properties?
For anyone else trying to do this (trigger based on the domain of the entity whose state changed), hereâs what worked for me.
trigger:
- platform: event
event_type: state_changed
condition:
- condition: template
value_template: >-
{{trigger.event.data.entity_id.startswith('person.') and
trigger.event.data.old_state is not none}}
Unfortunately it seems to be unavoidable that the trigger will fire on all state changes in the system, and itâs also unfortunate that the only way to test the domain of the entity is by using startswith(...) on the entity_id string
How many person entities do you have and does the quantity change often?
If the answer is ânot many and noâ then just list the entities in a State Trigger.
Yes, that is a good point. Originally I had hoped to avoid hard coding the list of entities by triggering on domain, but since thatâs not possible, itâs probably best to go with a State Trigger that hard codes the entities.
It is not clear from the documentation for the State Trigger (or mentioned at all!) that I could access state objects corresponding to the previous and new states (analogous to old_state and new_state in the state_changed event type), but by checking traces empirically I determined that these are in fact available as trigger.from_state and trigger.to_state.
Here is a worked example that functions for me, without triggering on every single state change in the system
alias: "WIP: Notify when person moves"
description: ""
trigger:
- platform: state
entity_id:
- person.yours_truly
- person.my_better_half
to: null
condition:
- condition: template
value_template: >-
{{trigger.from_state is not none and trigger.from_state.state !=
trigger.to_state.state}}
action:
- service: notify.notify
data:
title: "{{state_attr(trigger.entity_id, 'friendly_name')}} is on the move."
message: >-
{{state_attr(trigger.entity_id, 'friendly_name')}} has moved from
{{trigger.from_state.state}} to {{trigger.to_state.state}}.
enabled: true
mode: queued
FYI
You can reference the entityâs friendly_name directly from the tiggervariable like this:
action:
- service: notify.notify
data:
title: "{{ trigger.to_state.name }} is on the move."
message: >-
{{ trigger.to_state.name }} has moved from
{{ trigger.from_state.state }} to {{ trigger.to_state.state }}.
Same problem here. In that case with the âupdateâ domain. There are a bunch of update entities. To do an automation that enumerate all the update entities is difficult, especially considering that new update entities appear every month.
I have the following automation that is actually working well:
alias: ActualizaciĂłn Update Disponible
description: >-
Comprueba si hay una nueva versiĂłn de alguna de las entidades de tipo Update.
Mejorar cuando se pueda para que el trigger no se active en cada cambio de
estado
trigger:
- platform: event
event_type: state_changed
condition:
- condition: template
value_template: >-
{{ trigger.event.data.new_state.domain == 'update' and
trigger.event.data.new_state.state == "on" and
trigger.event.data.old_state.state == "off" }}
action:
- service: notify.telegram_casa
data:
message: >-
đĄ ActualizaciĂłn disponible: {% if
trigger.event.data.new_state.attributes['title'] is none %} {{
trigger.event.data.new_state.attributes['friendly_name'] | replace('_',
' ') }} {% else %} {{ trigger.event.data.new_state.attributes['title'] |
replace('_', ' ') }} {% endif %} -> {{
trigger.event.data.new_state.attributes['latest_version'] }}
mode: parallel
max: 50
But I think its performance would be greatly improved if we can have the âdomainâ attribute in state objects, as documentation âsaysâ.
I know. I have this automation temporarily until we have a better way to do it. It would be great adding the âdomainâ attribute to the state objects.
Yeah, but i canât use it in the trigger of an event automation :frowning. Or at least I donât know how
It sure would be nice if we couldâŚ
Trigger off event state_changed when it matches a device_class or some other attribute of the states! Something likeâŚ