Trouble with template, returns none in blueprint, works great in the template tester

I have added a template in a blueprint

{{ ((strptime(states(next_t), "%H:%M:%S")).replace(day=now().day, year=now().year, month=now().month, hour=strptime(states(next_t), "%H:%M:%S").hour - retry_t | int)).time() }}

With next_t being a variable that stores the selected input from the time helpers and retry_t does the same with number helpers.

When I try it with in the Developer/Template environment with the helpers added manually, it works flawlessly. However, when I use it in a blueprint, it says that a value was expected but got none.

The full blueprint here

blueprint:
  name: HVAC Daily Schedule, local version
  description: Set the target HVAC temperature based on its mode.
  domain: automation
  input:
    climate_id:
      name: Thermostat
      description: The thermostat to control.
      selector:
        entity:
          domain: climate
          multiple: false
    cooling_temp:
      name: Cool Set Point
      description: The target temperature when cooling.
      selector:
        entity:
          domain: input_number
          multiple: false
      #selector:
        #number:
          #min: 0.0
          #max: 100.0
          #step: 1.0
          #mode: slider
          #unit_of_measurement: "°C"
    heating_temp:
      name: Heat Set Point
      description: The target temperature when heating.
      selector:
        entity:
          domain: input_number
          multiple: false
      #selector:
        #number:
          #min: 0.0
          #max: 100.0
          #step: 1.0
          #mode: slider
          #unit_of_measurement: "°C"
    set_temp:
      name: Current selected temperature
      description: The input that stores the currently selected temperature
      selector:
        entity:
          domain: input_number
          multiple: false
    set_mode:
      name: Current selected climate mode
      description: The input that stores the currently selected climate mode
      selector:
        entity:
          domain: input_select
          multiple: false
    at_time:
      name: Time
      description: The time to update this device
      selector:
        entity:
          domain: input_datetime
      # selector:
      #  time: {}
    next_time:
      name: Next schedule
      description: The next scheduled time of this automation. If this is e.g. \"Daytime\" then you should select \"Nighttime\" here.
      selector:
        entity:
          domain: input_datetime    
    retry_timeout:
      name: Retry timeout
      #description: How many hours before the selected next schedule the automation times out
      description: When the automation times out.
      #selector:
      # time: {}
      #selector:
      #  number:
      #    min: 1.0
      #    max: 4.0
      #    step: 1.0
      #    mode: slider
      #    unit_of_measurement: "Hours"
      selector:
        time: {}
    on_monday:
      name: Monday
      default: true
      selector:
        boolean: {}
    on_tuesday:
      name: Tuesday
      default: true
      selector:
        boolean: {}
    on_wednesday:
      name: Wednesday
      default: true
      selector:
        boolean: {}
    on_thursday:
      name: Thursday
      default: true
      selector:
        boolean: {}
    on_friday:
      name: Friday
      default: true
      selector:
        boolean: {}
    on_saturday:
      name: Saturday
      default: true
      selector:
        boolean: {}
    on_sunday:
      name: Sunday
      default: true
      selector:
        boolean: {}
  source_url: http://localhost
variables:
  weekly_schedule:
  - !input on_monday
  - !input on_tuesday
  - !input on_wednesday
  - !input on_thursday
  - !input on_friday
  - !input on_saturday
  - !input on_sunday
  heating_t: !input heating_temp
  cooling_t: !input cooling_temp
  current_m: !input climate_id
  next_t: !input next_time
  retry_t: !input retry_timeout
trigger:
- platform: time
  at: !input at_time
condition:
- condition: template
  value_template: '{{ weekly_schedule[now().weekday()] }}'
action:
  - if:
      - condition: and
        conditions:
          - condition: time
            before: !input "retry_timeout"
            #before: '{{ ((strptime(states(next_t), "%H:%M:%S")).replace(day=now().day, year=now().year, month=now().month, hour=strptime(states(next_t), "%H:%M:%S").hour - retry_t | int)).time() }}'
          - condition: state
            entity_id: !input "climate_id"
            state: unavailable
    then:
      - repeat:
          until:
            condition:
              - condition: time
                before: !input "retry_timeout"
                #before: '{{ ((strptime(states(next_t), "%H:%M:%S")).replace(day=now().day, year=now().year, month=now().month, hour=strptime(states(next_t), "%H:%M:%S").hour - retry_t | int)).time() }}'
          sequence:
            - if:
                condition:
                  - condition: state
                    entity_id: !input "climate_id"
                    state: unavailable
              then:
                - delay: 00:01:00
              else:
                - choose:
                    - conditions:
                      - condition: state
                        entity_id: !input "climate_id"
                        state: heat
                      sequence:
                        - service: climate.set_temperature
                          entity_id: !input "climate_id"
                          data: 
                            temperature: '{{ states(heating_t) | float }}'
                        - service: input_number.set_value
                          entity_id: !input "set_temp"
                          data:
                            value: '{{ states(heating_t) | float }}'
                        - service: input_select.select_option
                          entity_id: !input "set_mode"
                          data:
                            option: '{{ states(current_m) }}'
                    - conditions:
                      - condition: state
                        entity_id: !input "climate_id"
                        state: cool
                      sequence:
                        - service: climate.set_temperature
                          entity_id: !input "climate_id"
                          data:
                            temperature: '{{ states(cooling_t) | float }}'
                        - service: input_number.set_value
                          entity_id: !input "set_temp"
                          data:
                            value: '{{ states(cooling_t) | float }}'
                        - service: input_select.select_option
                          entity_id: !input "set_mode"
                          data:
                            option: '{{ states(current_m) }}'                            
    else:
      if:
        - condition: and
          conditions:
          - condition: time
            before: !input "retry_timeout"
            #before: '{{ ((strptime(states(next_t), "%H:%M:%S")).replace(day=now().day, year=now().year, month=now().month, hour=strptime(states(next_t), "%H:%M:%S").hour - retry_t | int)).time() }}'
          - not:
              - condition: state
                entity_id: !input "climate_id"
                state: unavailable
      then:
        - choose:
            - conditions:
              - condition: state
                entity_id: !input "climate_id"
                state: heat
              sequence:
                - service: climate.set_temperature
                  entity_id: !input "climate_id"
                  data:
                    temperature: '{{ states(heating_t) | float }}'
                - service: input_number.set_value
                  entity_id: !input "set_temp"
                  data:
                    value: '{{ states(heating_t) | float }}'
                - service: input_select.select_option
                  entity_id: !input "set_mode"
                  data:
                    option: '{{ states(current_m) }}'                    
            - conditions:
              - condition: state
                entity_id: !input "climate_id"
                state: cool
              sequence:
                - service: climate.set_temperature
                  entity_id: !input "climate_id"
                  data:
                    temperature: '{{ states(cooling_t) | float }}'
                - service: input_number.set_value
                  entity_id: !input "set_temp"
                  data:
                    value: '{{ states(cooling_t) | float }}'
                - service: input_select.select_option
                  entity_id: !input "set_mode"
                  data:
                    option: '{{ states(current_m) }}'                     
      else:
        - stop: Still unavailable
mode: single

If there’s a better way to achieve what I’m trying to do (subtract from time) I’m very interested as it’s very clunky. I know it’s a bit convoluted, I thought that by converting time to datetime it would handle rollovers i.e. 00:00:00 - 1 would become 23:00:00 but it just became -1 and therefore an invalid time so it’s more than needed.

A Time Condition’s before option doesn’t support templates. It supports time as a string, input_datetime, or sensor (whose device_class is timestamp).

Reference: Time Condition

Re-design it to use a Template Condition.

I see.

I redesigned it with the following code, which seems to work.

I’m new to both templates and python, so if you spot any error, it would be greatly appreciated.

blueprint:
  name: HVAC Daily Schedule, local version
  description: Set the target HVAC temperature based on its mode.
  domain: automation
  input:
    climate_id:
      name: Thermostat
      description: The thermostat to control.
      selector:
        entity:
          domain: climate
          multiple: false
    cooling_temp:
      name: Cool Set Point
      description: The target temperature when cooling.
      selector:
        entity:
          domain: input_number
          multiple: false
    heating_temp:
      name: Heat Set Point
      description: The target temperature when heating.
      selector:
        entity:
          domain: input_number
          multiple: false
    set_temp:
      name: Current selected temperature
      description: The input that stores the currently selected temperature
      selector:
        entity:
          domain: input_number
          multiple: false
    set_mode:
      name: Current selected climate mode
      description: The input that stores the currently selected climate mode
      selector:
        entity:
          domain: input_select
          multiple: false
    at_time:
      name: Time
      description: The time to update this device
      selector:
        entity:
          domain: input_datetime
    next_time:
      name: Next schedule
      description: The next scheduled time of this automation. If this is e.g. \"Daytime\" then you should select \"Nighttime\" here.
      selector:
        entity:
          domain: input_datetime    
    retry_timeout:
      name: Retry timeout offset
      description: How many hours before the selected next schedule the automation times out
      selector:
        number:
          min: 1.0
          max: 4.0
          step: 1.0
          mode: slider
          unit_of_measurement: "Hours"
    on_monday:
      name: Monday
      default: true
      selector:
        boolean: {}
    on_tuesday:
      name: Tuesday
      default: true
      selector:
        boolean: {}
    on_wednesday:
      name: Wednesday
      default: true
      selector:
        boolean: {}
    on_thursday:
      name: Thursday
      default: true
      selector:
        boolean: {}
    on_friday:
      name: Friday
      default: true
      selector:
        boolean: {}
    on_saturday:
      name: Saturday
      default: true
      selector:
        boolean: {}
    on_sunday:
      name: Sunday
      default: true
      selector:
        boolean: {}
  source_url: http://localhost
variables:
  weekly_schedule:
  - !input on_monday
  - !input on_tuesday
  - !input on_wednesday
  - !input on_thursday
  - !input on_friday
  - !input on_saturday
  - !input on_sunday
  heating_t: !input heating_temp
  cooling_t: !input cooling_temp
  current_m: !input climate_id
  next_t: !input next_time
  retry_t: !input retry_timeout
trigger:
- platform: time
  at: !input at_time
condition:
- condition: template
  value_template: '{{ weekly_schedule[now().weekday()] }}'
action:
  - if:
      - condition:
          - condition: template
            value_template: >
              {% set next = strptime(states(next_t), "%H:%M:%S") %}
              {% set tmpNow = now() %}
              {% set now = strptime("00:00:00", "%H:%M:%S").replace(hour=tmpNow.hour, minute=tmpNow.minute) %}
              {% set offset = retry_t | int %}
              {% set endtime = next - timedelta(hours=offset) %}
              
              {% if (endtime < now) %}
              {% set dayOffset = 1 %}
              {% else %}
              {% set dayOffset = 0 %}
              {% endif %}
              
              {% set endtime = endtime + timedelta(days=dayOffset) %}
              
              {{ now <= endtime }}
          - condition: state
            entity_id: !input "climate_id"
            state: unavailable
    then:
      - repeat:
          until:
          # - condition: time
          #   before: !input "retry_timeout"
          - condition: template
            value_template: >
              {% set next = strptime(states(next_t), "%H:%M:%S") %}
              {% set tmpNow = now() %}
              {% set now = strptime("00:00:00", "%H:%M:%S").replace(hour=tmpNow.hour, minute=tmpNow.minute) %}
              {% set offset = retry_t | int %}
              {% set endtime = next - timedelta(hours=offset) %}
              
              {% if (endtime < now) %}
              {% set dayOffset = 1 %}
              {% else %}
              {% set dayOffset = 0 %}
              {% endif %}
              
              {% set endtime = endtime + timedelta(days=dayOffset) %}
              
              {{ now >= endtime }}
          sequence:
            - if:
                condition:
                  - condition: state
                    entity_id: !input "climate_id"
                    state: unavailable
              then:
                - delay: 00:01:00
              else:
                - choose:
                    - conditions:
                      - condition: state
                        entity_id: !input "climate_id"
                        state: heat
                      sequence:
                        - service: climate.set_temperature
                          entity_id: !input "climate_id"
                          data: 
                            temperature: '{{ states(heating_t) | float }}'
                        - service: input_number.set_value
                          entity_id: !input "set_temp"
                          data:
                            value: '{{ states(heating_t) | float }}'
                        - service: input_select.select_option
                          entity_id: !input "set_mode"
                          data:
                            option: '{{ states(current_m) }}'
                    - conditions:
                      - condition: state
                        entity_id: !input "climate_id"
                        state: cool
                      sequence:
                        - service: climate.set_temperature
                          entity_id: !input "climate_id"
                          data:
                            temperature: '{{ states(cooling_t) | float }}'
                        - service: input_number.set_value
                          entity_id: !input "set_temp"
                          data:
                            value: '{{ states(cooling_t) | float }}'
                        - service: input_select.select_option
                          entity_id: !input "set_mode"
                          data:
                            option: '{{ states(current_m) }}'
                - stop: Completed
    else:
      if:
        - condition: and
          conditions:
          # - condition: time
          #   before: !input "retry_timeout"
          - condition: template
            value_template: >
              {% set next = strptime(states(next_t), "%H:%M:%S") %}
              {% set tmpNow = now() %}
              {% set now = strptime("00:00:00", "%H:%M:%S").replace(hour=tmpNow.hour, minute=tmpNow.minute) %}
              {% set offset = retry_t | int %}
              {% set endtime = next - timedelta(hours=offset) %}
              
              {% if (endtime < now) %}
              {% set dayOffset = 1 %}
              {% else %}
              {% set dayOffset = 0 %}
              {% endif %}
              
              {% set endtime = endtime + timedelta(days=dayOffset) %}
              
              {{ now <= endtime }}
          - not:
              - condition: state
                entity_id: !input "climate_id"
                state: unavailable
      then:
        - choose:
            - conditions:
              - condition: state
                entity_id: !input "climate_id"
                state: heat
              sequence:
                - service: climate.set_temperature
                  entity_id: !input "climate_id"
                  data:
                    temperature: '{{ states(heating_t) | float }}'
                - service: input_number.set_value
                  entity_id: !input "set_temp"
                  data:
                    value: '{{ states(heating_t) | float }}'
                - service: input_select.select_option
                  entity_id: !input "set_mode"
                  data:
                    option: '{{ states(current_m) }}'                    
            - conditions:
              - condition: state
                entity_id: !input "climate_id"
                state: cool
              sequence:
                - service: climate.set_temperature
                  entity_id: !input "climate_id"
                  data:
                    temperature: '{{ states(cooling_t) | float }}'
                - service: input_number.set_value
                  entity_id: !input "set_temp"
                  data:
                    value: '{{ states(cooling_t) | float }}'
                - service: input_select.select_option
                  entity_id: !input "set_mode"
                  data:
                    option: '{{ states(current_m) }}'                     
      else:
        - stop: Still unavailable
mode: single
1 Like

Looks good. The Template Condition uses the current day now().workday() as an index value to check weekly_schedule which is a list of booleans.


Please consider marking my post above with the Solution tag. It will automatically place a check-mark next to the topic’s title which signals to other users that this topic has been resolved. This helps users find answers to similar questions.

For more information about the Solution tag, refer to guideline 21 in the FAQ.