I am trying to create an automation (or rather a set of automations most probably) that would handle the following scenario.
SETUP
I have a heater, which can have the following states:
Confort
Eco
Frost protection
Off
The heater’s state can be updated through any of the three following actions:
A schedule pilots this heater and changes the states following a timetable.
We change the heater’s state manually.
When we open the window, a contact sensor triggers an automation that switches the heater off. We want the heater to be switched back to the correct state, which is not necessarily the one on which it was when the window got opened.
SCENARIO
And the last bit is where it becomes complicated : when either the scheduler changes the heater state or this state is changed manually, how can the automation know this new state to which it has to update the heater when we close the window.
Here is a concrete example:
The heater is on “Confort”.
It is 7:55 am, and I open the window to air the room. My automation switches the heater to “Off”.
It is 8 am, and the scheduler switches the heater to “Eco” => I don’t what this to happen! I want this target state to be kept somewhere, and the heater to stay on “Off” because the window is still opened.
It is 8:02 am, and close the window, and I want the heater to be set on “Eco” as scheduled, not on “Confort” as it was before I opened the window.
CONSTRAINTS
The scheduler and the manual state change must manipulate the entity state directly => I don’t want (/it is not workable) to have a complicated setup that would require to use an intermediate state holder instead of the actual entity state. It is not feasible on the scheduler, and would require to do tricks and adjustments that would be easy to get lost into and forget about how it all works out in the future.
THEORETICAL SOLUTION
The following solution would work:
A first automation triggers when the window is opened, and:
Takes the current state of the heater and puts its value in a helper (Text? Dropdown?).
Changes the state of the heater to “Off”.
A second automation triggers when the window is closed, and:
Sets the heater’s state to the value that was kept in the helper.
A third automation triggers when the state of the heater changes, and if the change has neither been made by first automations, nor by the second, nor by this automation itself, it:
Takes the changed state of the heater and updates the helper with this value.
Changes the state of the heater to “Off”.
CHALLENGE
The challenge lies in the “if the change has neither been made by first automations, nor by the second, nor by this automation itself”.
I know this information is available in the log book as shown in the screenshot below, but I could not find a way to access the logs from an automation in an “if” condition to get this information.
Aha! Great stuff! I could not find correspondence of the parent_id’s value in any of the automation data (even in the id in the automation.yaml file is different) so I could not say for sure it was indeed related to an automation.
Thanks for the tip ! I will implement a solution and post the results.
I looked at the automation traces : the parent_id changes at each execution even though the same automation is the trigger. So in your proposition, the EXAMPLE_parent_id1 will be different every time. Hence it cannot be added to the code for comparaison.
I would need a way to identify the automation the parent_id represents, and I have not found a way yet.
For the time being, as a degraded solution, I can check parent_id to know if an automation (any automation) has triggered the change in state. Luckily I have no other automations than the three I mentionned that do that for the time being, but when this ceases to be the case, it will not work anymore.
Anyone has a clue on how to link the parent_id to the specific automation?
Based on your tests, this post, and some tests of my own, I think the following should work for the other two automations:
condition:
- alias: Continue if not triggered by self or other automations
condition: template
value_template: |
{% set automations = ['automation.EXAMPLE_1', 'automation.EXAMPLE_2'] %}
{% set others = expand(automations) | map(attribute='context.id') | list %}
{{ trigger.to_state.context.id not in others }}
As mentioned in the last post of the linked thread, a 100% reliable way to avoid self-triggering other than setting the mode to single is proving more elusive.
I read the last post you mentioned and I am thinking : one could possibly use the last_changed or last_updated state attributes to sort out the mode issue. Will look into it.
But, depending on the rest of the automation, that’s not exactly the same a making it unable to trigger itself and it would throttle all trigger sources/contexts.
Interesting… I was talking about the last_changed or last_updated attributes on the trigger.to_state state object and did not even think to the this state object… This one opens some new possibilities. Will dig.