Binary sensor for a calender event (google calendar)

  • google calendar
  • The appointment is called “Schulfrei”
  • The appointment is the whole day

One Sensor sensor should be on when it’s today and one sensor should be on when it’s tommorow (24h offeset)

I tried this one

{% if is_state_attr('calendar.mygooglecalendar', 'message', "Schulfrei") %}
          true
        {% else %}
          false
        {% endif %}

But it shows that the event is active at the moment, but there is no appointment today?

If your calendar can reasonably be expected to have overlapping/coincident events you should not base your sensor on the state of the calendar entity, you will need to use a trigger-based template binary sensor and the calendar.get_events service.

Example template binary sensor

Example 2

This means i have to put this whole template into the configuration yaml to get the sensor?

Looks complicated, it was so easy for my caldav calender

 - platform: caldav
    url: url
    username: "user"
    password: "pass"
    custom_calendars:
      - name: "Schulfrei"
        calendar: "name"
        search: "Schulfrei"

No.
it means you create a template sensor -

template:
  - trigger:
      - platform: time_pattern
        minutes: "/5"
    action:
      - service: calendar.get_events
        data:
          duration:
            hours: 48
          target:
            entity_id: calendar.googlecalendar
          response_variable: agenda
     binary_sensor:
       - name: Event Today
         state: >-
           # your code here

Thanks I insert this in the configuration.yaml:

template:
  - trigger:
      - platform: time
        at: "00:01:00"
    action:
      - service: calendar.get_events
        data:
          start_date_time: "{{ today_at() }}"
          end_date_time: "{{ today_at('23:59:00') }}"
        target:
          entity_id: calendar.xyz
        response_variable: agenda
    binary_sensor:
      - name: Schulfrei xyz Heute
        state: |-
          {% set search_term = "Schulfrei" %}
          {{ agenda['calendar.xyz'].events 
          | selectattr('summary', 'search', search_term) | list | count > 0 }}
  - trigger:
      - platform: time
        at: "00:01:00"
    action:
      - service: calendar.get_events
        data:
          start_date_time: "{{ today_at() + timedelta(days= 1)}}"
          end_date_time: "{{ today_at('23:59:00') + timedelta(days= 1) }}"
        target:
          entity_id: calendar.xyz
        response_variable: agenda
    binary_sensor:
      - name: Schulfrei xyz Morgen
        state: |-
          {% set search_term = "Schulfrei" %}
          {{ agenda['calendar.xyz'].events 
          | selectattr('summary', 'search', search_term) | list | count > 0 }}

OK - but, if the second calendar is the same calendar - you don’t need to use a second trigger and second service call.

template:
  - trigger:
      - platform: time
        at: "00:01:00"
    action:
      - service: calendar.get_events
        data:
          start_date_time: "{{ today_at() }}"
          end_date_time: "{{ today_at('23:59:00') }}"
        target:
          entity_id: calendar.xyz
        response_variable: agenda
    binary_sensor:
      - name: Schulfrei xyz Heute
        state: |-
          {% set search_term = "Schulfrei" %}
          {{ agenda['calendar.xyz'].events 
          | selectattr('summary', 'search', search_term) | list | count > 0 }}
      - name: Schulfrei xyz Morgen
        state: |-
          {% set search_term = "Schulfrei" %}
          {{ agenda['calendar.xyz'].events 
          | selectattr('summary', 'search', search_term) | list | count > 0 }}

Would be nice beeing able to shorten the code, the problem is, that with your solution both sensor would give the same state.
I need different Start/end Times.

I’m working on that now :wink:

OK here it is:

template:
  - trigger:
      - platform: time
        at: "00:01:00"
    action:
      - service: calendar.get_events
        data:
          start_date_time: "{{ today_at() }}"
          duration:
            hours: 50
        target:
          entity_id: calendar.xyz
        response_variable: agenda
    binary_sensor:
      - name: Schulfrei xyz Heute
        state: |-
          {% set search_term = "Schulfrei" %}
          {% set d = today_at()|as_timestamp|timestamp_custom("%Y-%m-%d") %}
          {{ agenda['calendar.xyz'].events 
          | selectattr('summary', 'search', search_term) | selectattr('start','eq',d) | list | count > 0 }}
      - name: Schulfrei xyz Morgen
        state: |-
          {% set search_term = "Schulfrei" %}
          {% set d = (today_at() + timedelta(days=1))|as_timestamp|timestamp_custom("%Y-%m-%d") %}
          {{ agenda['calendar.xyz'].events 
          | selectattr('summary', 'search', search_term) | selectattr('start','eq',d) | list | count > 0 }}

Is it not necessary insert times in today_at() ?

No, it defaults to midnight ( “00:00:00” ) if you leave it empty.

And midnight → midnight of the same day is not zero?

And the duration is necessary now?

Duration just makes it easier to say I want events within this many hours of the start time, rather than having to code another template for the end time.

So we are saying start at 00:00:00 - using today_at() is doing the same as

now().replace(hour=0,minute=0,second=0)

and fetch events within 50 hours of the start time.

okay, then the duration should be 24 hours?

No, because you want to detect events tomorrow too - since you are doing a sensor of an event that is today and a sensor for an event tomorrow.

but the duration of today is 24h and the duration of tommorow is 24 h :thinking:

Good point, that’s what late night coding does for you.
It doesn’t really matter with the code I posted though, because we are matching the date of today and the date of tomorrow, there could be 7 days worth of events, it will still only match today and tomorrow.