Automation condition for Multiple all day events in Local Calendar?

Hi,

I have a calendar with multiple all day events on the same day.

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

Thanks

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' ] }}
3 Likes

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?

repeat-until

Can you post the yaml for the whole automation so we can see how all the parts work together?

alias: Bin2 collection
description: ""
trigger:
  - platform: calendar
    event: start
    offset: "-1:53: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 }}"
                - condition: numeric_state
                  entity_id: input_boolean.emergency_switch_helper
                  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: queued
max: 10

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:

 - condition: numeric_state
                  entity_id: input_boolean.emergency_switch_helper
                  above: 0

Which correctly throws an error in the log:

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

I agree it should work as is.

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
1 Like

Thank you I will give this a try.

regarding the following problem

I see this triggers the following in the logs:

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?

Post your complete, current automation… the error message you posted does not make sense with the problem you have shown.

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.

1 Like

@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.


The black bin works as expected but brown bin goes on then off immediately. Times are slightly out as I was testing on the problematic brown bin.

I see, thanks.

In your new example above, can I double check you didn’t make a small mistake?

The trigger for “on” happens six hours before an event starts in the calendar (any event would trigger this):

  - trigger:
    - platform: calendar
      event: start
      offset: '-6:00:00'
      id: 'on'

But then in the action to retrieve the calendar events you have this:

      - 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=6) }}
            {% endif %}
          duration:
            minutes: 1  

Doesn’t this mean that it will grab all events between the following times:

  1. Start time = 1 minute after event (because we have now() + timedelta(hours=6, minutes=1) )
    and
  2. End time = 2 minutes after the event (because duration: minutes: 1 )

Is this what you meant to do?