You can nowadays - you need to declare a variable in the trigger. In the actions
you can use the choose
based on that variable.
Thank you @AllHailJ, I certainly would like to make use of templates in my automatons but I am a beginner and most of what you have shared here is way over my head.
automation:
trigger:
- platform: sun
event: sunrise
variables:
state: 'on'
- platform: sun
event: sunrise
offset: "01:30:00"
variables:
state: 'on'
- platform: sun
event: sunrise
offset: "02:00:00"
variables:
state: 'on'
- platform: sun
event: sunrise
offset: "03:30:00"
variables:
state: 'on'
- platform: sun
event: sunrise
offset: "00:30:00"
variables:
state: 'off'
- platform: sun
event: sunrise
offset: "02:00:00"
variables:
state: 'off'
- platform: sun
event: sunrise
offset: "02:30:00"
variables:
state: 'off'
- platform: sun
event: sunrise
offset: "04:00:00"
variables:
state: 'off'
action:
- choose:
- conditions: {{ state == 'on' }}
sequence:
- service: light.turn_on
target:
- entity_id: light.room_plant
default:
- service: light.turn_off
target:
- entity_id: light.room_plant
The offests had a couple errors… you can also use trigger variables to define the service without needing to use a Choose action.
- alias: 100 - Test Lights
id: Test Lights
initial_state: true
trigger:
- platform: sun
event: sunrise
id: 'on'
- platform: sun
event: sunrise
offset: "01:30:00"
id: 'on'
- platform: sun
event: sunrise
offset: "03:00:00"
id: 'on'
- platform: sun
event: sunrise
offset: "04:30:00"
id: 'on'
- platform: sun
event: sunrise
offset: "01:00:00"
id: 'off'
- platform: sun
event: sunrise
offset: "02:30:00"
id: 'off'
- platform: sun
event: sunrise
offset: "04:00:00"
id: 'off'
- platform: sun
event: sunrise
offset: "05:30:00"
id: 'off'
conditions: []
action:
- service: light.turn_{{trigger.id}}
target:
- entity_id: light.room_plant
mode: single
Thank you @Didgeridrew, I saw them and was correcting for it in my automation. But you bet me to it. And thank you so much for the extra - using trigger ids.
Create a Template Binary Sensor called binary_sensor.plant_light
. It’s computed state represents when the light should be on
or off
.
template:
- binary_sensor:
- name: 'Plant Light'
state: >
{% set sr = today_at((state_attr('sun.sun', 'next_rising') | as_datetime | as_local).strftime('%H:%M')) %}
{{ sr <= now() < sr + timedelta(hours=1) or
sr + timedelta(hours=1.5) <= now() < sr + timedelta(hours=2.5) or
sr + timedelta(hours=3) <= now() < sr + timedelta(hours=4) or
sr + timedelta(hours=4.5) <= now() < sr + timedelta(hours=5.5) }}
Create an automation that is triggered by the state-changes of binary_sensor.plant_light
or a restart.
alias: Control Plant Lights
trigger:
- platform: state
entity_id: binary_sensor.plant_light
to:
- 'on'
- 'off'
- platform: homeassistant
event: start
condition: []
action:
- service: "light.turn_{{ states('binary_sensor.plant_light') }}"
target:
entity_id:
- light.your_first_plant_light
- light.your_second_plant_light
- light.your_third_plant_light
NOTE
-
The reason the State Trigger explicitly specifies the desired
to
states is because a Template Binary Sensor can potentially have anunknown
state and we don’t want to trigger on that. -
There are other things that can be done to make the automation even more robust but this should meet your requirements (including the ability to survive a restart and set the lights to the correct state).
EDIT
Correction. Added missing action:
statement.
Thank you so much @123, With just one read I couldn’t wrap my head around this. But I am going to read again and try to implement this as this is the ideal solution I want.
@123 If it dies, reboots or reloads the automation after sunrise then the next rising will be tomorrows sunrise. You can use sun2 and get around this problem.
Another elegant solution BTW!
Yes and it will also happen immediately after sunrise time has passed because, as you pointed out, sun.sun
’s next_rising
attribute will be computed for the next day. However, the first line of the template ensures the datetime object, that represents sunrise, contains today’s date (meaning today’s date but with tomorrow’s sunrise time … which for most purposes is sufficient because the difference is minor). This ensures the time comparisons employing now()
work correctly.
Thanks for educating me on that - I understand now. It’s also why I like sun2 as you get a sensor.sunrise
that is always today.
As it should be IMHO but, due to reasons lost in history, sun.sun’s attributes behave like they do. FWIW, I’ve seen commentary by the development team that sun.sun
ought to be re-engineered (more along the line’s of pnbruckner’s sun2 component) but the concern is it would be a major breaking change.
I assume you mean the template because the rest of it is straightforward (a simple automation triggered by either a binary_sensor or a restart).
The first line of the template simply creates a variable named sr
representing sunrise. Its value is sunrise time represented as a datetime object.
The remainder of the template determines in which of the four time ranges the current time is in. each time range represents when the light should be on.
Current time is between sunrise and sunrise + 1 hour OR
Current time is between sunrise + 1.5 hours and sunrise + 2.5 hours OR
Current time is between sunrise + 3 hours and sunrise + 4 hours OR
Current time is between sunrise + 4.5 hours and sunrise + 5.5 hours
- If the current time is within any of the four time ranges, the binary_sensor’s state is
on
. - If the current time is not within any of the four time ranges, the binary_sensor’s state is
off
.
Thank you very much @123, it started making sense now. I will try to implement it and post back here.
I get a configuration formatting error that says:
bad indentation of a mapping entry at line 11, column 3:
- service: "light.turn_{{ states …
Could someone help me figure out how to fix it?
That’s my fault; I overlooked to include the action:
statement in the original example. I have updated the example above.
Simply add action:
on a separate line after the condition.
I don’t know what I am doing wrong here but the automation is not working for me. The light (switch.socket_plant_light_one) wouldn’t turn on even if the trace shows its turned on. This is what I have as configuration.
In the debug trace I have an error related to mobile app that’s a fault I made.
In /config/templates.yaml:
- binary_sensor:
- name: 'Plant Light One Timer'
state: >
{% set sun_rise = today_at((state_attr('sun.sun', 'next_rising') | as_datetime | as_local).strftime('%H:%M')) %}
{{ sun_rise <= now() < sun_rise + timedelta(hours=1) or
sun_rise + timedelta(hours=1.5) <= now() < sun_rise + timedelta(hours=2.5) or
sun_rise + timedelta(hours=3) <= now() < sun_rise + timedelta(hours=4) or
sun_rise + timedelta(hours=4.5) <= now() < sun_rise + timedelta(hours=5.5) }}
In /config/automations/routines/light/plant-light-one-timer.yaml
- id: 'plant_light_one_timer'
alias: Control Plant Light One
trigger:
- platform: state
entity_id: binary_sensor.plant_light_one_timer
to:
- 'on'
- 'off'
- platform: homeassistant
event: start
condition: []
action:
- service: "light.turn_{{ states('binary_sensor.plant_light_one_timer') }}"
target:
entity_id:
- switch.socket_plant_light_one
- service: notify.mobile_app_aruns_iphone
data:
title: "Plant Light One Alerts"
message: "Plant light one turned {{ states('binary_sensor.plant_light_one_timer') }}"
data:
group: "plantlight-notification-group"
- service: notify.alexa_media
data:
message: >-
Plant Light One turned {{ states('binary_sensor.plant_light_one_timer') }}
target:
- media_player.echo_main_bedroom
data:
type: announce
I get these messages in trace:
Restarting homeassistant gives me this:
I realized my silly mistake. In my case it should be switch.turn_on|off
NOT light.turn_on|off
action:
- service: "switch.turn_{{ states('binary_sensor.plant_light_one_timer') }}"
target:
entity_id:
- switch.socket_plant_light_one
As you have discovered, if you use a service call meant for light
entities then the entity_id
should contain light
entities. Similarly, a service call for switch
entities requires switches.
For future reference, if you need a service call to turn on a mix of entity types, you can use homeassistant.turn_on
.
If you wish, you can use script variables to streamline the automation a little bit:
- id: 'plant_light_one_timer'
alias: Control Plant Light One
trigger:
- platform: state
entity_id: binary_sensor.plant_light_one_timer
to:
- 'on'
- 'off'
- platform: homeassistant
event: start
condition: []
action:
- variables:
t1: "{{ states('binary_sensor.plant_light_one_timer') }}"
msg: "Plant light one turned {{ t1 }}"
- service: "switch.turn_{{ t1 }}"
target:
entity_id:
- switch.socket_plant_light_one
- service: notify.mobile_app_aruns_iphone
data:
title: "Plant Light One Alerts"
message: "{{ msg }}"
data:
group: "plantlight-notification-group"
- service: notify.alexa_media
data:
message: "{{ msg }}"
target:
- media_player.echo_main_bedroom
data:
type: announce
Even after making the changes above the light/socket doesn’t turn on.
- id: 'plant_light_test'
alias: Plant light Test
trigger:
- platform: state
entity_id: binary_sensor.plant_light_test
to:
- 'on'
- 'off'
- platform: homeassistant
event: start
condition: []
action:
- service: "switch.turn_{{ states('binary_sensor.plant_light_test') }}"
target:
entity_id:
- switch.socket_plant_light_one
I made a change in the binary sensor condition to reflect the time now for testing purpose as below:
- binary_sensor:
- name: 'Plant Light Test'
state: >
{% set sr = today_at((state_attr('sun.sun', 'next_rising') | as_datetime | as_local).strftime('%H:%M')) %}
{{ sr <= now() < sr + timedelta(hours=1) or
sr + timedelta(hours=1.5) <= now() < sr + timedelta(hours=2.5) or
sr + timedelta(hours=3) <= now() < sr + timedelta(hours=4) or
sr + timedelta(hours=4.5) <= now() < sr + timedelta(hours=5.5) or
sr + timedelta(hours=10.5) <= now() < sr + timedelta(hours=11.5) }}