Time based climate automation (weekdays/weekend)

The following is a consolidated version of all three automations. I think I understood the purpose of the binary_sensor but if I didn’t then it will require adjustments.

alias: example
description: ''
trigger:
  - id: 'weekday'
    platform: time
    at:
      - '06:00'
      - '08:00'
      - '15:00'
      - '20:00'
      - '22:00'
  - id: 'weekend'
    platform: time
    at:
      - '08:00'
      - '21:00'
      - '22:00'
  - id: 'override'
    platform: state
    entity_id: binary_sensor.tuer_balkon_onoff
    to: 'off'
    for: '00:01:00'
  - id: 'disable'
    platform: state
    entity_id: binary_sensor.tuer_balkon_onoff
    to: 'on'
    for: '00:02:00'
condition: []
action:
  - choose:
      - conditions:
          - "{{ trigger.id == ['weekday', 'override'] }}"
          - "{{ 1 <= now().isoweekday() <= 5 }}"
          - "{{ is_state('binary_sensor.tuer_balkon_onoff', 'off') }}"
        sequence:
          - variables:
              schedule:
                6: 17
                8: 24
                15: 20
                20: 22
                22: 20
                24: 17
          - service: climate.set_temperature
            target:
              entity_id: climate.thermostat_kueche
            data:
              hvac_mode: 'heat'
              temperature: "{{ schedule.get(schedule.keys() | select('>', now().hour) | first, 21) }}"

      - conditions:
          - "{{ trigger.id in ['weekend', 'override'] }}"
          - "{{ now().isoweekday() in [6,7]  }}"
          - "{{ is_state('binary_sensor.tuer_balkon_onoff', 'off') }}"
        sequence:
          - variables:
              schedule:
                8: 17
                21: 24
                22: 20
                24: 17
          - service: climate.set_temperature
            target:
              entity_id: climate.thermostat_kueche
            data:
              hvac_mode: 'heat'
              temperature: "{{ schedule.get(schedule.keys() | select('>', now().hour) | first, 21) }}"

      - conditions:
          - "{{ trigger.id == 'disable' }}"
        sequence:
          - service: climate.turn_off
            target:
              entity_id: climate.thermostat_kueche
    default: []
mode: single

It has four triggers:

  1. Weekday schedule
  2. Weekend schedule
  3. Override when the binary_sensor is off for 1 minute
  4. Disable when the binary_sensor is on for 2 minutes

The choose has three choices where the first two corresponds to one of the first three triggers and the last choice is for the fourth trigger.


EDIT

I overlooked to mention that because this is a single automation, it cannot do what your third automation does and that’s to turn off the first two automations (because it would be turning itself off in this case). What it does instead is to have the weekday/weekend triggers check if the binary_sensor is off before setting the thermostat’s target temperature. If it’s on then the scheduled operation isn’t performed.

@123 suppose you wanted to use input_numbers for the temperature, Would the code here

          - variables:
              schedule:
                6: 17
                8: 24
                15: 20
                20: 22
                22: 20
                24: 17

then be changed to:

          - variables:
              schedule:
                6: {{ input_numbers.temp1 }}
                8: {{ input_numbers.temp2 }}
                15: {{ input_numbers.temp3 }}
                20: {{ input_numbers.temp4 }}
                22: {{ input_numbers.temp5 }}
                24: {{ input_numbers.temp6 }}

Try it; be sure to wrap the template in quotes and remove the last s in input_numbers.

I just noticed an edge case as I was testing. If the times are the same in weekday and weekend it will always take the first. So for 08:00 and 22:00 it will take weekday and not run.

1 Like

Good point; I overlooked that important detail. It effectively prevents consolidating the weekday and weekend schedules into one automation if both have common hours. EDIT I was too hasty when I wrote that; I now believe it can be done. I’ll post it tomorrow.

Dual version

It’s fairly easy to split the consolidated version into two separate automations, each handling its own schedule. The disabling logic can go in either one; I put it in the first automation.

alias: weekday schedule
description: ''
trigger:
  - id: 'weekday'
    platform: time
    at:
      - '06:00'
      - '08:00'
      - '15:00'
      - '20:00'
      - '22:00'
  - id: 'override'
    platform: state
    entity_id: binary_sensor.tuer_balkon_onoff
    to: 'off'
    for: '00:01:00'
  - id: 'disable'
    platform: state
    entity_id: binary_sensor.tuer_balkon_onoff
    to: 'on'
    for: '00:02:00'
condition: []
action:
  - choose:
      - conditions:
          - "{{ trigger.id == ['weekday', 'override'] }}"
          - "{{ 1 <= now().isoweekday() <= 5 }}"
          - "{{ is_state('binary_sensor.tuer_balkon_onoff', 'off') }}"
        sequence:
          - variables:
              schedule:
                6: 17
                8: 24
                15: 20
                20: 22
                22: 20
                24: 17
          - service: climate.set_temperature
            target:
              entity_id: climate.thermostat_kueche
            data:
              hvac_mode: 'heat'
              temperature: "{{ schedule.get(schedule.keys() | select('>', now().hour) | first, 21) }}"
      - conditions: "{{ trigger.id == 'disable' }}"
        sequence:
          - service: climate.turn_off
            target:
              entity_id: climate.thermostat_kueche
    default: []
mode: single
alias: weekend schedule
description: ''
trigger:
  - id: 'weekend'
    platform: time
    at:
      - '08:00'
      - '21:00'
      - '22:00'
  - id: 'override'
    platform: state
    entity_id: binary_sensor.tuer_balkon_onoff
    to: 'off'
    for: '00:01:00'
condition: []
action:
  - choose:
      - conditions:
          - "{{ now().isoweekday() in [6,7]  }}"
          - "{{ is_state('binary_sensor.tuer_balkon_onoff', 'off') }}"
        sequence:
          - variables:
              schedule:
                8: 17
                21: 24
                22: 20
                24: 17
          - service: climate.set_temperature
            target:
              entity_id: climate.thermostat_kueche
            data:
              hvac_mode: 'heat'
              temperature: "{{ schedule.get(schedule.keys() | select('>', now().hour) | first, 21) }}"
    default: []
mode: single

As promised, here’s the revised version. It’s more compact than the previous version I posted and can handle a scheduled hour that’s common to both the weekday and weekend schedules.

alias: example
description: ''
trigger:
  - id: 'schedule'
    platform: time
    at:
      - '06:00'
      - '08:00'
      - '15:00'
      - '20:00'
      - '21:00'
      - '22:00'
  - id: 'override'
    platform: state
    entity_id: binary_sensor.tuer_balkon_onoff
    to: 'off'
    for: '00:01:00'
  - id: 'disable'
    platform: state
    entity_id: binary_sensor.tuer_balkon_onoff
    to: 'on'
    for: '00:02:00'
condition: []
action:
  - choose:
      - conditions:
          - "{{ trigger.id != 'disable' }}"
          - "{{ is_state('binary_sensor.tuer_balkon_onoff', 'off') }}"
        sequence:
          - variables:
              weekday:
                6: 17
                8: 24
                15: 20
                20: 22
                22: 20
                24: 17
              weekend:
                8: 17
                21: 24
                22: 20
                24: 17
              schedule: "{{ weekday if 1 <= now().isoweekday() <= 5 else weekend }}"
          - service: climate.set_temperature
            target:
              entity_id: climate.thermostat_kueche
            data:
              hvac_mode: 'heat'
              temperature: "{{ schedule.get(schedule.keys() | select('>', now().hour) | first, 21) }}"
      - conditions:
          - "{{ trigger.id == 'disable' }}"
        sequence:
          - service: climate.turn_off
            target:
              entity_id: climate.thermostat_kueche
    default: []
mode: single
1 Like

Thanks Taras - that looks good. And that’s what I mean with “some magic” - the “script” part of it. And I like the “input.number” part from @AllHailJ.

Two points:

  1. in the first condition

should be
- "{{ trigger.id != 'override' }}".

  1. I´ve got an error message
Error rendering data template: TypeError: '>' not supported between instances of 'str' and 'int'

and the only data template part is in
temperature: "{{ schedule.get(schedule.keys() | select('>', now().hour) | first, 21) }}"

You know where the problem is? And another question: What does this line mean?

And after all there are still some questions:

  1. What happens if the door is open and a schedule time is on time?
  2. What happens if the door will be closed (after one minute)? Which temperature will be choosen?
  3. What happens if it the time from 8 to 15 somebody changed the temp manually? When will the temp adjusted?

I can assure you that saying ‘abracadabra’ didn’t make the “script part” materialize for me.

That changes my understanding of the binary_sensor’s purpose. Can you explain what role this binary_sensor plays with regards to the schedule?

That error message implies the variables in the example I posted have been altered. In the example, the key-values pairs (in weekend and weekday) are both integers (the error message is indicating one of them is a string).

Ah OK. Let me say it this way: It’s hard too “read” the script part for me and creating such code for me is doing magic :).

That’s easy: It’s a sensor that detect “door is open” and if the door is longer open than 2 minutes the thermostate should turned off and under no circumstances it should turned on. If the door is closed (“off”) for one minute the thermostate should turned on and the regarding temperature for the time slot should be set.

Hmm, I just copied your code. But I will check. Thanks.

That’s how I assumed it should work so I advise that you do not make the change you suggested.

The only change I would make is to rename override to enable to make it clearer that the scheduled operation is being re-enabled (after having been disabled by the open door).

Oh, I think I found it: I created an automation with gui and pasted the code in the integrated yaml editor but after saving the code will be transformed. Now I created a fake automation and paste the code directly into the yaml and it seams to work.

You´re right - I´ve overseen the “!=” as “if not”.

The Automation Editor has a habit of reformatting YAML according to its rules. Sometimes this reformatting changes the meaning of the data and results in a broken automation.

I found a thread that talks about tuples

{% set schedule = {4:20, 6:21, 8:20, 10:19 12:20 22:17, 24:17} %}
{% set key = schedule.keys() | list %}
{% set value = schedule.values() | list %}
{% set hour = now().hour %}
{{ hour }}
{{ value[key.index(hour)] }}
{{ schedule[hour] }}

You can change {{ value[key.index(hour)] }} to {{ value[key.index(8)] }} or {{schedule[8]}}and it will show in the developer the second half of the tuple 20.

Hope this helps with your understanding

@AllHailJ Is that an answer to me? I can’t do anything with that, sorry :).

Could you please say something to that. What does it mean?

“Take from the list of scheduled times the line which contains a number which is bigger than the current hour …” - if I read it right, but what comes after that?

It was for you. Use developer tools and you can cut and paste into templates and see how tuples work.

Ah - understood. Thanks!

I can get the array to be dynamic in the developers tools

{% set s_wk = 
   {state_attr('input_datetime.sp1_wk', 'hour'): states('input_number.t1_wk'), 
   state_attr('input_datetime.sp2_wk', 'hour'): states('input_number.t2_wk'), 
   state_attr('input_datetime.sp3_wk', 'hour'): states('input_number.t3_wk'),
   state_attr('input_datetime.sp4_wk', 'hour'): states('input_number.t4_wk'),
   state_attr('input_datetime.sp5_wk', 'hour'): states('input_number.t5_wk')} %}
{% set s_wknd =
   {state_attr('input_datetime.sp1_wknd', 'hour'): states('input_number.t1_wknd'),
   state_attr('input_datetime.sp2_wknd', 'hour'): states('input_number.t2_wknd'), 
   state_attr('input_datetime.sp3_wknd', 'hour'): states('input_number.t3_wknd'), 
   state_attr('input_datetime.sp4_wknd', 'hour'): states('input_number.t4_wknd'),
   state_attr('input_datetime.sp5_wknd', 'hour'): states('input_number.t5_wknd')} %}
{% set hour = now().hour %}
{{ hour }}
{{s_wk[19]}}
{{s_wknd[20]}}

And here is screen shot from developer tools

but I can’t get it to work in the automation.

Also when working on an ecobee thermostat it would not set the temperature it you also set the hvac_mode.

  alias: Main Floor Thermostat Control Heat Control
  description: 'Set the main floor thermostat for Heat'
  trigger:
    - id: 'schedule'
      platform: time
      at:
        - input_datetime.sp1_wk
        - input_datetime.sp2_wk
        - input_datetime.sp3_wk
        - input_datetime.sp4_wk
        - input_datetime.sp5_wk
        - input_datetime.sp1_wknd
        - input_datetime.sp2_wknd
        - input_datetime.sp3_wknd
        - input_datetime.sp4_wknd
        - input_datetime.sp5_wknd
    - id: 'override'
      platform: state
      entity_id: input_boolean.thermostat_main
      to: 'on'
      for: '00:00:30'
    - id: 'disable'
      platform: state
      entity_id: input_boolean.thermostat_main
      to: 'off'
      for: '00:00:30'
  condition: []
  action:
    - choose:
        - conditions:
            - "{{ trigger.id != 'disable' }}"
            - "{{ is_state('input_boolean.thermostat_main', 'on') }}"
          sequence:
            - variables:
                weekday: 
                  1: 61
                  2: 61
                  3: 61
                  4: 61
                  5: 61
                  6: 61
                  7: 61
                  8: 68
                  9: 68
                  10: 68
                  11: 68
                  12: 68
                  13: 68
                  14: 68
                  15: 68
                  16: 68
                  17: 50
                  18: 68
                  19: 68
                  20: 68
                  21: 61
                  22: 61
                  23: 61
                  24: 61                       
                weekend:
                  1: 61
                  2: 61
                  3: 61
                  4: 61
                  5: 61
                  6: 61
                  7: 61
                  8: 68
                  9: 68
                  10: 68
                  11: 68
                  12: 68
                  13: 68
                  14: 68
                  15: 68
                  16: 68
                  17: 50
                  18: 68
                  19: 68
                  20: 68
                  21: 61
                  22: 61
                  23: 61
                  24: 61   
                schedule: "{{ weekday if now().isoweekday() in [1,2,3,4,5] else weekend }}"
            - service: climate.set_temperature
              target:
                entity_id: climate.main_floor
              data:
                temperature: "{{ schedule[now().hour] }}"
        - conditions:
            - "{{ trigger.id == 'disable' }}"
          sequence:
            - service: climate.turn_off
              target:
                entity_id: climate.main_floor
              data:
                hvac_mode: 'off'
      default: []
  mode: single

I have searched and can find nothing that helps.

Also simplified the temperature as the documentation explained that it always took the first match so this limits it to one action per hour but that was limited anyways. You can have it anywhere in the hour to trigger. I was doing the 1-24 so I could test. I have tried

sequence:
            - variables:
                weekday: 
                  - value_template: >-
                  {% {state_attr('input_datetime.sp1_wk', 'hour'): states('input_number.t1_wk'), 
                      state_attr('input_datetime.sp2_wk', 'hour'): states('input_number.t2_wk'), 
                      state_attr('input_datetime.sp3_wk', 'hour'): states('input_number.t3_wk'),
                      state_attr('input_datetime.sp4_wk', 'hour'): states('input_number.t4_wk'),
                      state_attr('input_datetime.sp5_wk', 'hour'): states('input_number.t5_wk')} %}

and get this error

Error loading /config/configuration.yaml: while scanning for the next token found character ‘%’ that cannot start any token in “/config/automations/main_floor/MainFloorThermostatControl.yaml”, line 38, column 20

I have tried this:

          sequence:
            - variables:
                weekday: 
                  - value_template: >-
                  {{ {state_attr('input_datetime.sp1_wk', 'hour'): states('input_number.t1_wk'), 
                      state_attr('input_datetime.sp2_wk', 'hour'): states('input_number.t2_wk'), 
                      state_attr('input_datetime.sp3_wk', 'hour'): states('input_number.t3_wk'),
                      state_attr('input_datetime.sp4_wk', 'hour'): states('input_number.t4_wk'),
                      state_attr('input_datetime.sp5_wk', 'hour'): states('input_number.t5_wk')} }}

and I get this error:

Error loading /config/configuration.yaml: while scanning a simple key in “/config/automations/main_floor/MainFloorThermostatControl.yaml”, line 38, column 19 could not find expected ‘:’
in “/config/automations/main_floor/MainFloorThermostatControl.yaml”, line 39, column 23

I tried this:

          sequence:
            - variables:
                weekday: 
                  - value_template: >-
                  "{{ {state_attr('input_datetime.sp1_wk', 'hour'): states('input_number.t1_wk'), 
                      state_attr('input_datetime.sp2_wk', 'hour'): states('input_number.t2_wk'), 
                      state_attr('input_datetime.sp3_wk', 'hour'): states('input_number.t3_wk'),
                      state_attr('input_datetime.sp4_wk', 'hour'): states('input_number.t4_wk'),
                      state_attr('input_datetime.sp5_wk', 'hour'): states('input_number.t5_wk')} }}"

and got this error

Error loading /config/configuration.yaml: while scanning a simple key in “/config/automations/main_floor/MainFloorThermostatControl.yaml”, line 38, column 19 could not find expected ‘:’
in “/config/automations/main_floor/MainFloorThermostatControl.yaml”, line 42, column 101

And I have tried this:

          sequence:
            - variables:
                weekday: 
                  - value_template: >-
                  "{{ {state_attr('input_datetime.sp1_wk', 'hour') ~ ':' ~ states('input_number.t1_wk'), 
                      state_attr('input_datetime.sp2_wk', 'hour') ~ ':' ~ states('input_number.t2_wk'), 
                      state_attr('input_datetime.sp3_wk', 'hour') ~ ':' ~ states('input_number.t3_wk'),
                      state_attr('input_datetime.sp4_wk', 'hour') ~ ':' ~states('input_number.t4_wk'),
                      state_attr('input_datetime.sp5_wk', 'hour') ~ ':' ~ states('input_number.t5_wk')} }}"

And I get this error:

Error loading /config/configuration.yaml: while scanning a simple key in “/config/automations/main_floor/MainFloorThermostatControl.yaml”, line 38, column 19 could not find expected ‘:’
in “/config/automations/main_floor/MainFloorThermostatControl.yaml”, line 42, column 108

and lastly I tried this:

          sequence:
            - variables:
                weekday: 
                  - value_template: 
                    {{state_attr('input_datetime.sp1_wk', 'hour') }} : {{states('input_number.t1_wk')}}
                    {{state_attr('input_datetime.sp2_wk', 'hour') }} : {{states('input_number.t2_wk')}} 
                    {{state_attr('input_datetime.sp3_wk', 'hour') }} : {{states('input_number.t3_wk')}}
                    {{state_attr('input_datetime.sp4_wk', 'hour') }} : {{states('input_number.t4_wk')}}
                    {{state_attr('input_datetime.sp5_wk', 'hour') }} : {{states('input_number.t5_wk')}}

Error loading /config/configuration.yaml: while parsing a flow mapping in “/config/automations/main_floor/MainFloorThermostatControl.yaml”, line 38, column 22 expected ‘,’ or ‘}’, but got ‘’
in “/config/automations/main_floor/MainFloorThermostatControl.yaml”, line 38, column 65

and I tried it with quotes and a comma

          sequence:
            - variables:
                weekday: 
                  - value_template: 
                    "{{state_attr('input_datetime.sp1_wk', 'hour') }}" : "{{states('input_number.t1_wk')}}",
                    "{{state_attr('input_datetime.sp2_wk', 'hour') }}" : "{{states('input_number.t2_wk')}}",
                    "{{state_attr('input_datetime.sp3_wk', 'hour') }}" : "{{states('input_number.t3_wk')}}",
                    "{{state_attr('input_datetime.sp4_wk', 'hour') }}" : "{{states('input_number.t4_wk')}}",
                    "{{state_attr('input_datetime.sp5_wk', 'hour') }}" : "{{states('input_number.t5_wk')}}"

this passed the configuration validation

variables:
  weekday:
    - value_template: ''
      '{{state_attr(''input_datetime.sp1_wk'', ''hour'') }}': '{{states(''input_number.t1_wk'')}}'
      '{{state_attr(''input_datetime.sp2_wk'', ''hour'') }}': '{{states(''input_number.t2_wk'')}}'
      '{{state_attr(''input_datetime.sp3_wk'', ''hour'') }}': '{{states(''input_number.t3_wk'')}}'
      '{{state_attr(''input_datetime.sp4_wk'', ''hour'') }}': '{{states(''input_number.t4_wk'')}}'
      '{{state_attr(''input_datetime.sp5_wk'', ''hour'') }}': '{{states(''input_number.t5_wk'')}}'

but when executed got this:

Took the value_template out and same issue . The thermostat never set and when I do it with numbers it works.

Any guidance ???

Most of the error messages are related to a incorrect indentation. However, even if you fix the indentation, it will still fail because you are using a Jinja2template to generate YAML and that won’t work.

YAML is processed first and then Jinja2 is processed.

You will need to define the dictionaries in JSON format (not YAML) within the temperature option (in the climate.set_temperature service call).