Complex blind automation

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
  1. 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') }}"
....
  1. 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' }}
  1. 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
    • 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
    • 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

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!

1 Like