I have the following automation where i want to find a “Blue bin collection” entry or a “Black bin collection” entry for the next day.
This works some of the time, however it seems to show only one event per day in “Developer Tools” > States for the calendar entity and therefore “Brown bin collection” is sometime present in the calendar entity State and therefore the below conditions don’t match, even though they should match the other all day event. Is there a way to find and apply these conditions below or similar to all events in my Local calendar on a particular day, in this example 3hrs before the start of the multiple all day events?
alias: Bin collection
description: ""
trigger:
- platform: calendar
event: start
offset: "-3:0:0"
entity_id: calendar.calendar
variables:
bin: " {{state_attr ( 'calendar.calendar', 'message' ) | regex_replace(find='Blue bin collection', replace='blue', ignorecase=False) | regex_replace(find='Black bin collection', replace='black', ignorecase=False) }} "
condition:
- condition: or
conditions:
- condition: state
entity_id: calendar.calendar
attribute: message
state: Blue bin collection
for:
hours: 0
minutes: 0
seconds: 0
- condition: state
entity_id: calendar.calendar
attribute: message
state: Black bin collection
enabled: true
What mode is your automation set to use? If the events both start at the same time, you need to have the automation mode set to parallel or queued to execute actions based on concurrent calendar events.
Thank you for taking the time to reply. It was in queued mode but I have now changed it to parallel to see if this makes a difference, will see how it goes.
Unfortunately parallel mode did not change the behaviour. It still only matches against what is in the state of calendar.calendar entity which has the following:
message: Blue bin collection
all_day: true
start_time: 2023-03-08 00:00:00
end_time: 2023-03-09 00:00:00
location:
description:
friendly_name: Calendar
supported_features: 7
There’s no “Brown bin collection” state entity. Even though as shown in the screenshot in my initial post it is a 2nd all day entry for today.
I added “Brown bin collection” as a condition but this did not match anything. Any pointers as to what to do would be great. It does however match for “Blue bin collection” as it is present in the developer tools > entity state for calendar.calendar
Sorry, I should have explained better… As described in the Calendar examples and Calendar trigger templates docs, your conditions need to be based on the trigger variable, the same goes for your bin variable.
alias: Bin collection
description: ""
mode: parallel
trigger:
- platform: calendar
event: start
offset: "-3:0:0"
entity_id: calendar.calendar
variables:
bin: >
{{ trigger.calendar_event.summary | regex_replace(find='Blue bin collection', replace='blue', ignorecase=False)
| regex_replace(find='Black bin collection', replace='black', ignorecase=False) }}
condition:
- condition: template
value_template: >
{{ trigger.calendar_event.summary in ['Black bin collection', 'Blue bin collection' ] }}
This works! Thank you for your input and help and i will mark your input as the solution. However I have hit a slightly different issue. Both parallel and queued modes are cancelling a loop/ repeat action in the automation when the second Brown bin collection triggers in parallel or queued with reason unknown which is not expected? Is this perhaps a bug or expected behaviour?
This seems to all be working now, I have a better grasp of trigger templates.
I am not sure if the below changes made a difference but it is working perfectly. I deleted:
Error in 'until[0]' evaluation: In 'or' (item 5 of 5): In 'numeric_state': In 'numeric_state' condition: entity input_boolean.emergency_switch_helper state 'off' cannot be processed as a number
below is the fully working automation yaml
alias: Bin collection
description: ""
trigger:
- platform: calendar
event: start
offset: "0:34:0"
entity_id: calendar.calendar
variables:
bin: " {{ trigger.calendar_event.summary | regex_replace(find='Blue bin collection', replace='blue', ignorecase=False) | regex_replace(find='Black bin collection', replace='black', ignorecase=False) | regex_replace(find='Brown bin collection', replace='brown', ignorecase=False) }} "
condition:
- condition: template
value_template: >-
{{ trigger.calendar_event.summary in ['Blue bin collection', 'Black bin
collection'] }}
action:
- parallel:
- repeat:
until:
- condition: or
conditions:
- type: is_open
condition: device
device_id: 37be57a9405a4fc690c28d8584dde3fb
entity_id: binary_sensor.front_door_contact_sensor
domain: binary_sensor
- condition: template
value_template: "{{ repeat.index == 30 }}"
enabled: true
- condition: state
entity_id: input_boolean.emergency_switch_helper
state: "on"
enabled: false
- condition: numeric_state
entity_id: automation.emergency_switch_input_helper
attribute: current
above: 0
sequence:
- service: notify.living_room_tv
data:
message: >-
Bin day tomorrow. It is {{ trigger.calendar_event.summary }}
day on {{ trigger.calendar_event.start }}
enabled: true
- delay:
hours: 0
minutes: 0
seconds: 10
milliseconds: 0
enabled: true
enabled: true
- service: notify.mobile_app
data:
message: >-
It is Bin day tomorrow. It is {{ trigger.calendar_event.summary }}
day on {{ trigger.calendar_event.start }}
data:
color: " {{ (bin) }} "
channel: Bin collection
tag: bin-collection
alert_once: true
sticky: true
enabled: true
mode: parallel
max: 10
The below condition doesn’t work (not sure why?) so disabled it but to my mind should work?
- condition: state
entity_id: input_boolean.emergency_switch_helper
state: "on"
enabled: false
but using the above helper in another automation as a trigger and monitoring attribute current does work to cancel it the repeat until/ loop until.
- condition: numeric_state
entity_id: automation.emergency_switch_input_helper
attribute: current
above: 0
That should not be necessary… Just remember that, when using until, the repeat sequence will always run at least once. If you want to avoid that, you should switch to a while based repeat.
I don’t know if you’re interested in an alternative method, but the following creates a combined message for two-bin weeks as well as supplying binary sensor entities that can be useful for dashboard cards:
Step 1: Set up trigger-based template sensors for the different bin options
Template sensors
template:
- trigger:
- platform: calendar
event: start
offset: '-6:00:00'
entity_id: calendar.calendar
id: 'on'
- platform: calendar
event: end
offset: '00:05:00'
entity_id: calendar.calendar
id: 'off'
binary_sensor:
- name: Brown Bin
state: >
{% set current = this.state | default('off') %}
{% if trigger.calendar_event.summary is search("Brown bin collection") %}
{{ trigger.id }}{% else %}{{ current }}{% endif %}
- name: Blue Bin
state: >
{% set current = this.state | default('off') %}
{% if trigger.calendar_event.summary is search("Blue bin collection") %}
{{ trigger.id }}{% else %}{{ current }}{% endif %}
- name: Black Bin
state: >
{% set current = this.state | default('off') %}
{% if trigger.calendar_event.summary is search("Black bin collection") %}
{{ trigger.id }}{% else %}{{ current }}{% endif %}
Step 2: Set up Automation
alias: Bin collection
description: ""
trigger:
- platform: calendar
event: start
offset: "-3:00:00"
entity_id: calendar.calendar
variables:
blue_or_black: "{{ trigger.calendar_event.summary in ['Blue bin collection', 'Black bin collection'] }}"
condition:
- condition: template
value_template: "{{ blue_or_black}}"
action:
- variables:
bins_on: >
{{ ['binary_sensor.blue_bin', 'binary_sensor.black_bin', 'binary_sensor.brown_bin']
| select('is_state', 'on')
| map('state_attr', 'friendly_name')
| map('replace', ' Bin', '') | map('lower') | list }}
message: >
It is Bin day tomorrow. It is {{ bins_on | join(' and ' if
bins_on|count > 1 else '') }} bin day on {{
(trigger.calendar_event.start | as_datetime).strftime("%A, %D") }}
- service: notify.mobile_app
data:
message: " {{ message }}"
data:
color: " {{ iif('blue' in bins_on, 'blue', 'black') }} "
channel: Bin collection
tag: bin-collection
alert_once: true
sticky: true
- repeat:
until:
- or:
- condition: state
entity_id: binary_sensor.front_door_contact_sensor
state: 'on'
- condition: template
value_template: "{{ repeat.index == 30 }}"
- condition: state
entity_id: input_boolean.emergency_switch_helper
state: "on"
sequence:
- service: notify.living_room_tv
data:
message: "{{ message }}"
enabled: true
- delay: 10
mode: single
Error in 'until[0]' evaluation: In 'or' (item 5 of 5): In 'numeric_state': In 'numeric_state' condition: entity input_boolean.emergency_switch_helper state 'off' cannot be processed as a number
Not sure why a helper behaves differently to other sensors devices, I can’t change the helper unless I use it in a template sensor? I don’t think i can change the helper attributes and values in the helper itself in the GUI. As it is not a device, there is no type: is_on option etc which I guess would return a numeric_state value if it existed?
You are right I had mad a mistake on another automation. Fixed it, thank you for pointing it out!. And the helper state condition does stop the repeat until loop as it should.
hello @Didgeridrew been a while since I looked into this as my automation works well (thank you for your help on this) however I noticed that using the “alternative” method (binary sensors) you suggested:
It will not keep the Brown bin collection “on”. It only seems to set it (brown bin) to “on” and keep it “on” if there is only one all day event that is called Brown bin collection. If there are multiple all day events on the same day it will only turn on and keep it on for the first listed that day which has been Blue or black bin.
I didn’t spot this anomaly as I didn’t use the sensor for the brown bin until I tried to use it and I see it turns on then off immediately. Is this a limitation/ bug?
@Didgeridrew a question for you: I like this “alternative aporoach” you suggested, because it allows alert meassages for multiple bins at once. But, In your automation, why trigger on the calendar start event again, and have to do a templated condition? You already have this information in the binary sensors. Why not just trigger the automation if any of the binary sensors turn on?
I think it might be a limitation of the trigger-based template sensor when there are essentially simultaneous triggers for 2 calendar events. Trigger-based template sensors run similarly to a script or automation in single mode, if a second trigger event happens while it is still rendering the sensors’ values the trigger will be ignored. So the problem may be highly dependent on the hardware being used and system load at the time.
Fortunately, both Calendar services and Template sensors have had significant upgrades in the 22 months since this thread started… so we can use the calendar.get_events action as part of the trigger-based sensor to query the calendar.
template:
- trigger:
- platform: calendar
event: start
offset: '-6:00:00'
entity_id: calendar.EXAMPLE
id: 'on'
- platform: calendar
event: end
offset: '00:05:00'
entity_id: calendar.EXAMPLE
id: 'off'
condition: #Optional: See Updates below
- "{{ trigger.calendar_event.all_day }}"
action:
- action: calendar.get_events
target:
entity_id: calendar.EXAMPLE
data:
start_date_time: |
{% if trigger.id == 'on' %}
{{ now() + timedelta(hours=6, minutes=1) }}
{% else %}
{{ now() - timedelta(minutes=7) }}
{% endif %}
duration:
minutes: 1
response_variable: agenda
- variables:
events: "{{ agenda['calendar.EXAMPLE']['events'] }}"
brown_bool: "{{ events | selectattr('summary', 'search', 'Brown bin collection') | list | count > 0 }}"
blue_bool: "{{ events | selectattr('summary', 'search', 'Blue bin collection') | list | count > 0 }}"
black_bool: "{{ events | selectattr('summary', 'search', 'Black bin collection') | list | count > 0 }}"
binary_sensor:
- name: Brown Bin
state: >
{% set current = this.state | default('off', 1) %}
{{ trigger.id if brown_bool else current }}
- name: Blue Bin
state: >
{% set current = this.state | default('off', 1) %}
{{ trigger.id if blue_bool else current }}
- name: Black Bin
state: >
{% set current = this.state | default('off', 1) %}
{{ trigger.id if black_bool else current }}
Because that was the trigger OP was using when they shared the full automation, and they stated they wanted to trigger 3 hours before the event (at 21:00). I think I set the binary sensors to update 6 hours before the event (at 18:00) so that the bin data would be available around the time when most people return home from work…? So, triggering when any of the binary sensors turned ‘on’ could work, but the trigger for the sensors would need to be modified to match OP’s requirements.
As with most things in HA, there are dozens of ways to set up that automation depending on the needs of the user.
Updates:
2024-01-30: Updated timedelta() value for “off” trigger.
2024-01-31: Added condition which is optional for OP’s original case, but addresses questions posed below.
@Didgeridrew and @CSP170 I was unable to reproduce any limitation/bug here. Are you sure?
When I have 2 (or even 3) simultaneous all-day events, the first version of your code appears to work fine. So, the following code correctly seems to switch on all three binary sensors for me:
template:
- trigger:
- platform: calendar
event: start
offset: '-6:00:00'
entity_id: calendar.calendar
id: 'on'
- platform: calendar
event: end
offset: '00:05:00'
entity_id: calendar.calendar
id: 'off'
binary_sensor:
- name: Brown Bin
state: >
{% set current = this.state | default('off') %}
{% if trigger.calendar_event.summary is search("Brown bin collection") %}
{{ trigger.id }}{% else %}{{ current }}{% endif %}
- name: Blue Bin
state: >
{% set current = this.state | default('off') %}
{% if trigger.calendar_event.summary is search("Blue bin collection") %}
{{ trigger.id }}{% else %}{{ current }}{% endif %}
- name: Black Bin
state: >
{% set current = this.state | default('off') %}
{% if trigger.calendar_event.summary is search("Black bin collection") %}
{{ trigger.id }}{% else %}{{ current }}{% endif %}
Nope. I can’t recall it ever being an issue for me either, but I do have vague memories of past threads with similar complaints where offsetting the events’ start times by a couple seconds solved the issue.