Multiple calendar template based automation

Good Evening,

I am trying to setup multiple automations based on two rental control calendars. The first automation should trigger two hours before the tenants arrive and the second automation should go off 30 mins before. My question is not only how to get it done but also what will be the best way going forward. My wife and I would like to keep adding our house to different platforms and if I can somehow group these two triggers will be fantastic. I created multiple binary_sensors for both calendars and my goal was to play with the trigger delay settings to wait 1:30 before the second set of actions will trigger. This code was obtained from this forum. Stumped by Template Binary Sensor! Looking for guidance

template:
# This binarary sensor will trigger every 1 minute and will define the A/C conditions before arrival
  - trigger:
      - platform: time_pattern
        minutes: /1
    binary_sensor:
      - name: "AirBnB Calendar 2 Hours Prior arrival"
        state: '{{ ((((as_timestamp(states.calendar.rental_control_airbnb.attributes.start_time) - as_timestamp(now())) / 60) | int) <= 120 and (((as_timestamp(states.calendar.rental_control_airbnb.attributes.start_time) - as_timestamp(now())) / 60) | int) > 0) }}’
	binary_sensor:
      - name: "VRBO Calendar 2 Hours Prior arrival"
        state: '{{ ((((as_timestamp(states.calendar.rental_control_vrbo.attributes.start_time) - as_timestamp(now())) / 60) | int) <= 120 and (((as_timestamp(states.calendar.rental_control_vrbo.attributes.start_time) - as_timestamp(now())) / 60) | int) > 0)}}'

I am also new to scripting and fairly new to home assistant as well. Any help will be much appreciated.

Thanks in advance.

Why not create a sensor with the datetime instead and use this in your automation directly?
That way there is no polling (which is just a waste of resources most of the time) and it will be easier to see the times things will trigger.

Hello,

Thank you for your reply.

So are you saying I should use the same code but swap it from binary_sensor to a sensor?

Regards,

Will it look something like this?

  sensor:
      - name: "AirBnB and VRBO Calendar 2 Hours Prior arrival"
        state: '{{(states.calendar.rental_control_airbnb.attributes.start_time) or (states.calendar.rental_control_vrbo.attributes.start_time)}}'
	unit_of_measurement: "Minutes"
  
  trigger:
  - platform: state
    entity_id: sensor.airbnb_and_vrbo_calendar_2_hours_prior_arrival
    to: '>120'

?

Not sure what the or does in your template.
But I assume the output of the template is a datetime like 2022-02-26 19:00:00 -ish… (You can test it in template tools)

So using a template to get the time two hours before could be:

"{{ state_attr('calendar.rental_control_airbnb', 'start_time') - timedelta(minutes=120) }}"

and this sensor should be able to be used in the automation as a time trigger on a sensor/input datetime.

Is this for a single property? If it is you can combine them into a list and a use a for loop:

template:
  - binary_sensor:
      - name: Vrbo and AirBnb 2hr prior
        state: >
          {% set starts = [
          state_attr('calendar.rental_control_airbnb', 'start_time'),
          state_attr('calendar.rental_control_vrbo', 'start_time'),
          ] |reject('eq', None)|list %}
          {% for a in starts %}
          {% set b = a|as_datetime|as_local %}
          {{ 'True' if now() >= b - timedelta(hours=2) }}
          {% endfor %}
      - name: Vrbo and AirBnb 30min prior
        state: >
          {% set starts = [
          state_attr('calendar.rental_control_airbnb', 'start_time'),
          state_attr('calendar.rental_control_vrbo', 'start_time'),
          ] |reject('eq', None)|list %}
          {% for a in starts %}
          {% set b = a|as_datetime|as_local %}
          {{ 'True' if now() >= b - timedelta(minutes=30) }}
          {% endfor %}

If you need it to cover multiple properties where both AirBnb and Vrbo could be within time one of the chosen timeframes the templates would need to be changed.

Hello @Didgeridrew

Yes, this will be for a single property. I will give that try and report back.

Thank both so much for all your help.

Regards,

Hello @Didgeridrew

The code works pretty well. Thank you!.

I was wondering if you can narrow the trigger to only happen within a time window. For example, within 2h to 2h and 10 mins. My fear is that any time I restart server management this automation will go off and may impact the tenants.

Please let me know if that makes any sense.

Thank you

Yes that is possible, just change the expression lines…

From:
{{ 'True' if now() >= b - timedelta(hours=2) }}

To:
{{ 'True' if (b - timedelta(hours=1, minutes=50) > now() >= b - timedelta(hours=2)) }}

Adding a from: off to your trigger would also help the issue if the sensor switches from “unavailable” or “unknown” to “on”.

Thank you! Will give a try when I get home.

Hoping one of the experienced people here can help me with my issue.

I have 5 properties on AirBnb and a calendar is generated for my cleaners to which I wish to send them a reminder TXT message 2hrs before a clean. There are multiple clean entries on the same date and same time, but the state in HA for calendar only holds one entry.

This could be the same where you have a calendar for birthdays, if 3 people had a birthday on the same day, only 1 would be notified for.

Is there any way to capture all entries for a calendar day and where the event is at the same time?

alias: Notify Vicky of clean Today
description: ''
trigger:
  - platform: calendar
    event: start
    offset: '-2:0:0'
    entity_id: calendar.vicki_YYY
condition:
  - condition: template
    value_template: >-
      {{ 'cleaning' in
      states.calendar.vicki_YYY.attributes.description.lower() }}
action:
  - if:
      - condition: template
        value_template: >-
          {{ '30c' in states.calendar.vicki_YYY.attributes.location.lower()
          }}
    then:
      - service: rest_command.websms_txt
        data:
          message_to: 64271234567
          message_text: >-
            This is a friendly reminder that you have a clean at 30c XXX Dr
            today
  - if:
      - condition: template
        value_template: >-
          {{ '30d' in states.calendar.vicki_YYY.attributes.location.lower()
          }}
    then:
      - service: rest_command.websms_txt
        data:
          message_to: 64271234567
          message_text: >-
            This is a friendly reminder that you have a clean at 30d XXX Dr
            today
  - if:
      - condition: template
        value_template: >-
          {{ '132c' in states.calendar.vicki_YYY.attributes.location.lower()
          }}
    then:
      - service: rest_command.websms_txt
        data:
          message_to: 64271234567
          message_text: >-
            This is a friendly reminder that you have a clean at 132c XXX st
            today
  - if:
      - condition: template
        value_template: >-
          {{ '30e' in states.calendar.vicki_YYY.attributes.location.lower()
          }}
    then:
      - service: rest_command.websms_txt
        data:
          message_to: 64271234567
          message_text: >-
            This is a friendly reminder that you have a clean at 30e XXX Dr
            today
mode: queued

So I decided to stagger the events to try get this working.
10:01am I have a 3hr cleaning event for the 132 Property
11:00am I have a 3hr cleaning event for 30c property
11:01am I have a 3hr cleaning event for 30d property

I had all 3 events trigger a text message to me 2hrs before the event as planned, however all said they were for 132 property. I suspect this is because of the 3hrs event, the state doesnt update until the event is completed, so because 132 property was still within the 3hr window when the other two triggered, it failed to update the property address.

Is there any way to resolve this, other than sending my cleaners a 1 minute event for cleaning each house?

Can’t you use a different calendar?
I use office 365 and I can see n number of events ahead.

That would probably make it a lot easier.

Each cleaner has a calendar; if a job is assigned to them it gets populated to their ICS.
I guess I could create a calendar per property and then an automation rule per calendar, but then I have to do that for each cleaner, so if we have 3 cleaners and 5 properties, that becomes 15 automations.

When you say you can see events ahead, so can I, but if I go to developer tools and states, to write automations, only a single state (the next event or the current event) is shown. How are you doing automations for events in the future, or can you only do it for the next or current event?

I have one entity per event in the future.

Mmm, which plugin are you using for this, is it (https://github.com/tybritten/ical-sensor-homeassistant)?
I am using the google calendar one, but happy to change to that one if you think it will work.

Secondly, what template do you use to look at for events happening in say 2hrs and generate an action?
Currently I use {{ 'cleaning' in states.calendar.vicki_YYY.attributes.description.lower() }} to confirm its a cleaning job, but would need to incorporate this to look for [0], [1], [2] etc

I then use {{ '30c' in states.calendar.vicki_YYY.attributes.location.lower() }} to confirm the address of the property so we can send an action notifying about which property the job is for.

As I said before Office 365.
Integration:

The image I posted is from my work calendar. I have another work calendar that is a copy of my normal work calendar but it shows me the details.
The work account got stricter sharing policy a few months ago, so I made a VBA code that copies my entries in my work calendar to my “personal” calendar.

In the attributes you have start and end timestamps that you can yaml with.

The “real calendar” has this:

So here we can see the description of the calendar entry, here you could probably use the same yaml.
What I think you need to do is to create one automation on each sensor.
If I recall correctly the sensors stay for the complete duration of the day, so make sure you have enough sensors added (configurable when you set it up).
There is a different version of the code posted somewhere where the minute an event has happened it’s removed and sensor 1 becomes sensor 0, sensor 2 becomes sensor 1 and so on.

I just noticed this:

So it seems you can trigger on events.