Here comes the step by step details
1. Get the historical values:
Basically I use an sql sensor like this:
- platform: sql
queries:
- name: light_entities_historically_on1
query: "select group_concat(st.entity_id, ', ') as _out from states st
inner join (
select max(state_id) as max_id, entity_id from states
where last_updated < datetime('now','-7 days') and
entity_id in ('light.gaestevaerelse',
'light.hue_color_lamp_1',
'light.sofa1spot',
'light.sofa2spot',
'light.hue_color_lamp_2',
'light.hyggespot',
'light.standerlampe',
'light.dagligdtue_pendel',
'light.alrumspisebord',
'light.kokkenbord1')
group by entity_id) m_st
on st.state_id = m_st.max_id
where state = 'on'"
column: "_out"
This sensor returns those of the specifies entities that where on for exactly 7 days ago.
The output is one string holding a list of entities like this.
light.alrumspisebord, light.dagligdtue_pendel, light.hue_color_lamp_1, light.hue_color_lamp_2, light.kokkenbord1, light.sofa1spot, light.sofa2spot
I would have preferred that this sensor was defined generic that simply returns the entities that must be toggled, without the need of specifying exactly which entities to include, but due to:
- The sql sensor does not support templates and hence dynamic SQL queries
- A limitation in the sensor state value size that may not exceed 255 characters, ottherwise the sensor will fail.
Therefor I had to identify and select the entities to be included and group these to make sure that the maximum output (list of these entities with spaces and comas, as shown above) does not exceed 255 characters.
This resulted in defining 4 sensors:
- light_entities_historically_on1
- light_entities_historically_on2
- light_entities_historically_off1
- light_entities_historically_off2
Note You must adjust these to include the names of your entities to be included in the simulation and based on the number /length of the names of these entities you might need to define more or fewer sensors.
These are always up-to-date and hold of entities that where on and off for, the period i selected which is ,7 days, ago.
2. Define a helper that can be used to turn simulation on/off:
3. Define a binary sensor that determines when to activate the simulation:
I could have done that based on the helper I just defined, but I want to include another factor that the simulation is only activated if no body is home, so I defined these two binary sensor
- platform: template
sensors:
anybody_home:
device_class: presence
value_template: >
{{ is_state('person.ghassan','my_home') or
is_state('person.anne','my_home')}}
- platform: template
sensors:
activate_vacation_light:
device_class: presence
value_template: >
{{ is_state('binary_sensor.anybody_home','off') and
is_state('input_boolean.vacation_light','on') }}
Note that I donât use the default âhomeâ zone as this is not adjustable and covers a larger area, which some might think is ok, but I preferred to define another zone âmy_homeâ which is much smaller and covers only my property, this makes the detection of whether any body is home, much more precise.
So, the binary sensor activate_vacation_light is true if input_boolean.vacation_light helper is turned on, and no body is home.
4. Make the automation:
Here is my automation
alias: vacation light
description: ''
trigger:
- platform: time_pattern
minutes: /10
condition:
- condition: state
entity_id: binary_sensor.activate_vacation_light
state: 'on'
action:
- service: light.toggle
data:
entity_id: >-
{%- for device in states.light | selectattr('entity_id','in', target_on
) |selectattr('state','in','off') | map(attribute="entity_id") | list +
states.light | selectattr('entity_id','in', target_off ) |selectattr('state','in','on') | map(attribute="entity_id") | list %}
{%- if not loop.first %}, {% endif %}{{device}}
{%- endfor %}
variables:
was_on1: '{{ states(''sensor.light_entities_historically_on1'') }}'
was_on2: '{{ states(''sensor.light_entities_historically_on2'') }}'
was_off1: '{{ states(''sensor.light_entities_historically_off1'') }}'
was_off2: '{{ states(''sensor.light_entities_historically_off2'') }}'
target_on: ( '{{was_on1}}' + ', ' + '{{ was_on2 }}' ).split(', ')
target_off: ( '{{was_off1}}' + ', ' + '{{ was_off2 }}' ).split(', ')
mode: single
And here is some explanation:
-
The automation is triggered every 10 minutes:
- You can adjust this to the precision period you like
-
The action is only performed if activate_vacation_light explained above, is true
-
Variables are defined to simplify the action:
-
target_on combines the values from light_entities_historically_on1 & light_entities_historically_on2 into one total list of entities that where on. Similarly for target_off.
-
The action toggles light entities that:
- currently are on and are in the target_off list
- and those that currently are off and are in the target_on list
And that is it.
This works perfectly for me
If the SQL sensor gets more flexible in the future, I would love to make this more generic without the need of specifying the entities and worrying about the sensor size. Then the code can be used by every one without the need to change anything
Hope you get inspired and you are interested giving it a try.
Please let me know if you have any questions or challenges getting this to work