with post7 I get error:
Action binary_sensor.set_state not found
this part works and shows me all the event there are for today:
data:
start_date_time: ‘{{ now().replace(hour=0, minute=0, second=0) }}’
end_date_time: ‘{{ now().replace(hour=23, minute=59, second=59) }}’
target:
entity_id: calendar.CALENDARNAME
response_variable: agenda
action: calendar.get_events
There is no action binary_sensor.set_state
in the trigger-based template sensor configuration I posted.
Where did you place the configuration? It should go either in your configuration.yaml
file under the template:
key or in the templates.yaml
file (without the template:
at the top) if you have that folder set up. Also, be aware that it only has a time trigger, so the binary sensor’s state will be “unknown” until it is triggered. You can add other triggers if you want to be able to trigger it manually.
Sorry for my stupidity.
I have now added the code to configuration.yaml file (I thought it should be part of automation.yaml).
So I have added the code, and now what?
What should happen? What should I see where?
How does this takes care of operning the blinds at 10.30 when there is a calendar event?
I’m missing this link in this part…
Ok, so I made some adjustments to my code which triggers the Boolean state:
alias: Update Event ROOM Boolean
description: >-
Update input.boolean event_ROOM to "on" or "off" based on Google Calendar
events.
trigger:
- platform: time
at: "04:30:00"
condition: []
action:
- data:
start_date_time: "{{ now().replace(hour=0, minute=0, second=0, microsecond=0) }}"
end_date_time: "{{ now().replace(hour=23, minute=59, second=59, microsecond=999999) }}"
target:
entity_id: calendar.CALENDARNAME
response_variable: agenda
action: calendar.get_events
- variables:
event_messages:
- Zomervakantie
- Herfstvakantie
- Kerstvakantie
- Eerste Kerstdag
- Tweede Kerstdag
- Studiedag
- Eerste Paasdag
- Tweede Paasdag
- Hemelvaartsdag
- Eerste Pinksterdag
- Tweede Pinksterdag
events: "{{ agenda['calendar.CALENDARNAME']['events'] }}"
matching_events: >
{% set matching = events | selectattr('summary', 'in', event_messages) |
map(attribute='summary') | list %} {% if matching %}
{{ matching | join(', ') }}
{% else %}
No matching events for today.
{% endif %}
- data:
message: >
Debugging Information: - Event Messages: {{ event_messages | join(', ')
}} - Events: {{ events | map(attribute='summary') | join(', ') }} -
Matching Events: {{ matching_events }}
level: info
action: system_log.write
- choose:
- conditions:
- condition: template
value_template: "{{ matching_events != 'No matching events for today.' }}"
sequence:
- target:
entity_id: input_boolean.event_ROOM
action: input_boolean.turn_on
data: {}
- conditions:
- condition: template
value_template: "{{ matching_events == 'No matching events for today.' }}"
sequence:
- target:
entity_id: input_boolean.event_ROOM
action: input_boolean.turn_off
data: {}
mode: single
This is the code to update the boolean state based on calendar event.
The code now also sets boolean state to Off when there is no predefined event_message.
The code also states which event_message is the trigger for the boolean to be set to “On”, this can be seen in the tracing of the automation.
Next step is to redefine the automation to open the blinds based on the boolean state.
Going to look for an alternate way for the waits and delays. The chance is small that there is a reload or restart during the wait/delay action, but just in case to be sure.
I reviewed and adjusted the code to:
trigger:
- platform: time
at: '07:30:00'
- platform: time
at: '10:30:00'
- platform: state
entity_id: sun.sun
from: below_horizon
to: above_horizon
condition: []
action:
- choose:
- conditions:
- condition: time
weekday:
- mon
- tue
- wed
- thu
- fri
- condition: state
entity_id: input_boolean.event_ROOM
state: 'off'
- condition: template
value_template: |
{% if now().strftime('%H:%M') == '07:30' %}
{% if is_state('sun.sun', 'above_horizon') %}
true
{% else %}
false
{% endif %}
{% else %}
false
{% endif %}
sequence:
- target:
entity_id: cover.blinds_ROOM
action: cover.open_cover
- conditions:
- condition: time
weekday:
- sat
- sun
- condition: state
entity_id: input_boolean.event_ROOM
state: 'off'
- condition: template
value_template: |
{% if now().strftime('%H:%M') == '10:30' %}
{% if is_state('sun.sun', 'above_horizon') %}
true
{% else %}
false
{% endif %}
{% else %}
false
{% endif %}
sequence:
- target:
entity_id: cover.blinds_ROOM
action: cover.open_cover
- conditions:
- condition: state
entity_id: input_boolean.event_ROOM
state: 'on'
- condition: template
value_template: |
{% if now().strftime('%H:%M') == '10:30' %}
{% if is_state('sun.sun', 'above_horizon') %}
true
{% else %}
false
{% endif %}
{% else %}
false
{% endif %}
sequence:
- target:
entity_id: cover.blinds_ROOM
action: cover.open_cover
mode: single
By using this code I avoid using wait or delay templates.
First, don’t get down on yourself… Home Assistant is designed to be powerful and flexible. The price we all pay for that is that it has a steep learning curve and there are usually at least 4 ways to do anything.
If you have not done so since adding the sensor configuration, restart Home Assistant so the Template integration is fully loaded.
You should now have a new binary_sensor
entity. If you used the configuration I posted above it will be binary_sensor.is_it_a_holiday
.
You can use it either directly as a condition in your blinds’ automations, or you can use them in the automations that set the states of the input boolean helpers for each room.
Example Automation for rooms that celebrate all holidays
alias: Update Event ROOM Boolean (all holidays)
description: >-
Update input.boolean event_ROOM to "on" or "off" based on Google Calendar events.
trigger:
- platform: state
entity_id: binary_sensor.is_it_a_holiday
to:
- "on"
- "off"
from:
- "on"
- "off"
condition: []
action:
- action: input_boolean.turn_{{ trigger.to_state.state }}
target:
entity_id: input_boolean.event_ROOM
data: {}
mode: single
Example Automation for a room that celebrate select holidays
alias: Update Event ROOM Boolean (Selected Holidays)
description: >-
Update input.boolean event_ROOM to "on" or "off" based on Google Calendar events.
trigger:
- platform: state
entity_id: binary_sensor.is_it_a_holiday
attribute: holiday_title
condition: []
action:
- if:
- alias: Set to 'off' if not a Holiday
condition: template
value_template: "{{ trigger.to_state.state == 'off' }}"
then:
- action: input_boolean.turn_off
data: {}
target:
entity_id: input_boolean.event_ROOM
else:
- variables:
holiday: "{{trigger.to_state.attributes.holiday_title}}"
this_room_celebrates:
- Eerste Kerstdag
- Tweede Kerstdag
- Studiedag Sophie
- Eerste Paasdag
new_state: |
{{ 'on' if holiday in this_room_celebrates else 'off' }}
- action: input_boolean.turn_{{ new_state }}
target:
entity_id: input_boolean.event_ROOM
data: {}
mode: single
The blinds automation you posted looks like it should work fine. There are a couple templates that might be able to be streamlined… but these are only minimally more efficient. If the way you have it makes more sense to you, don’t worry about making these changes.
Streamlining Explanations
- I would define the time as a variable at the top of the action block. Since it will likely be checked a few times, it’s more efficient to run the calculation just once. This can also help prevent false negatives if your machine is running a slow at that particular moment and
now()
spills over to the next minute before you get to the final condition that checks it.
...
action:
- variables:
time: "{{ now().strftime('%H:%M') }}"
....
- If you are actually in the Netherlands the following template can be simplified significantly because the latest sunrise in the country is around 08:53.
{% if now().strftime('%H:%M') == '10:30' %}
{% if is_state('sun.sun', 'above_horizon') %}
true
{% else %}
false
{% endif %}
{% else %}
false
{% endif %}
If the first if
is true, the second will always be true. Combined it with the time
variable show above, the template can just be:
{{ time == '10:30' }}
- Along similar lines, the template for the earlier time can only return
true
if the two ifs are both true:
{% if now().strftime('%H:%M') == '07:30' %}
{% if is_state('sun.sun', 'above_horizon') %}
true
{% else %}
false
{% endif %}
{% else %}
false
{% endif %}
Using the time
variable with and
, it can be compacted to:
{{ time == '07:30' and is_state('sun.sun', 'above_horizon') }}
Here’s how those changes would look in the sample you posted:
Example Blinds Automation
trigger:
- platform: time
at: ‘07:30:00’ - platform: time
at: ‘10:30:00’ - platform: state
entity_id: sun.sun
from: below_horizon
to: above_horizon
condition:
action: - variables:
time: “{{ now().strftime(‘%H:%M’) }}” - choose:
- conditions:
- condition: time
weekday:- mon
- tue
- wed
- thu
- fri
- condition: state
entity_id: input_boolean.event_ROOM
state: ‘off’ - condition: template
value_template: |
{{ time == ‘07:30’ and is_state(‘sun.sun’, ‘above_horizon’) }}
sequence: - target:
entity_id: cover.blinds_ROOM
action: cover.open_cover
- condition: time
- conditions:
- condition: time
weekday:- sat
- sun
- condition: state
entity_id: input_boolean.event_ROOM
state: ‘off’ - condition: template
value_template: “{{ time == ‘10:30’ }}”
sequence: - target:
entity_id: cover.blinds_ROOM
action: cover.open_cover
- condition: time
- conditions:
- condition: state
entity_id: input_boolean.event_ROOM
state: ‘on’ - condition: template
value_template: “{{ time == ‘10:30’ }}”
sequence: - target:
entity_id: cover.blinds_ROOM
action: cover.open_cover
mode: single
- condition: state
- conditions:
Thanks for these words, Sometimes it’s just difficult to find the right way for something, there are a lot of possibilities, no not all are pratical to use.
I added the code to config.yamla few days ago and restarted HA, I could see a binary sensor was created/available.
I Now understand how to set this up, thanks.
The blinds automation you posted looks like it should work fine. There are a couple templates that might be able to be streamlined… but these are only minimally more efficient. If the way you have it makes more sense to you, don’t worry about making these changes.
Since the automation I now have it all works like I would like, I’m carefully to apply new code at this moment.
This part I will implement, thanks for this simplification!