YAML not valid unless I duplicate 'template' key?

I’m refactoring my old template code to the new syntax, in the process I thought I would then combine duplicate template: blocks into one…but it then gives a TON of errors trying to reload.

Anyone able to tell why this might be?

Specifically I tried to remove the line:

template:
  - trigger:

to just

  - trigger:

which I assumed would go with the previous template block. But then I get LOADS of errors all over the place in the logfile.

Working code, with duplicate template:

input_boolean:
  # This will be a "fan on" to keep the fan running 24x7
  downstairs_hvac_fan_on_manual_hold:
    name: Downstairs HVAC Fan On Manual Hold
    icon: hass:fan



template:

  - sensor:

      - default_entity_id: sensor.downstairs_hvac_fan_status
        name: "Downstairs HVAC Fan Status"
        #entity_id: sensor.time
        state: >-
          {{ state_attr('climate.downstairs_thermostat','fan_state').split(' ').0 }}

      - name: Downstairs HVAC Fan Mode Preference
        icon: hass:fan
        state: >-
          {% set fan_on = is_state('group.downstairs_hvac_fan_on_conditions','on') %}
          {% set fan_circ = is_state('group.downstairs_hvac_fan_circ_conditions','on') %}
          {% set fan_force_auto = is_state('group.downstairs_hvac_fan_force_auto_conditions','on') %}
          {% if fan_on and (not fan_force_auto) %}
            Low
          {% elif fan_circ and (not fan_force_auto) %}
            Circulation
          {% else %}
            Auto low
          {% endif %}



  - binary_sensor:

      - default_entity_id: binary_sensor.downstairs_hvac_fan_idle_cycle
        name: "Downstairs HVAC Fan Idle Cycle"
        delay_on: '04:00:00'
        delay_off: >
          {{ 0 if is_state('binary_sensor.downstairs_hvac_fan_idle_cycle','unknown') else '02:00:00' }}
        state: >-
          {{ is_state('sensor.downstairs_hvac_fan_status','Idle') and
             is_state('binary_sensor.downstairs_hvac_fan_idle_cycle','off') }}

      - default_entity_id: binary_sensor.downstairs_hvac_fan_manual_on
        name: "Downstairs HVAC Fan Manual On"
        delay_on: '00:01:00'
        delay_off: >
          {{ 0 if is_state('binary_sensor.downstairs_hvac_fan_manual_on','unknown') else '01:00:00' }}
        state: >-
          {{ state_attr('climate.downstairs_thermostat','fan_mode') == 'Low' and
             is_state('group.downstairs_hvac_fan_on_conditions','off') }}

      - default_entity_id: binary_sensor.main_floor_high_temp_difference
        name: "Main Floor High Temp Difference"
        delay_on: >
          {{ 0 if is_state('binary_sensor.main_floor_high_temp_difference','unknown') else '00:05:00' }}
        delay_off: >
          {{ 0 if is_state('binary_sensor.main_floor_high_temp_difference','unknown') else '00:10:00' }}
        state: >-
          {{ (states('sensor.main_floor_max_temperature')|float(-999) - states('sensor.main_floor_min_temperature')|float(999)) > 4 }}

      - default_entity_id: binary_sensor.basement_rooms_high_temp_difference
        name: "Basement Rooms High Temp Difference"
        delay_on: >
          {{ 0 if is_state('binary_sensor.basement_rooms_high_temp_difference','unknown') else '00:05:00' }}
        delay_off: >
          {{ 0 if is_state('binary_sensor.basement_rooms_high_temp_difference','unknown') else '00:10:00' }}
        state: >-
          {{ (states('sensor.basement_rooms_max_temperature')|float(-999) - states('sensor.basement_rooms_min_temperature')|float(999)) > 3 }}

      - default_entity_id: binary_sensor.basement_main_floor_high_temp_difference
        name: "Basement Main Floor High Temp Difference"
        delay_on: >
          {{ 0 if is_state('binary_sensor.basement_main_floor_high_temp_difference','unknown') else '00:05:00' }}
        delay_off: >
          {{ 0 if is_state('binary_sensor.basement_main_floor_high_temp_difference','unknown') else '00:10:00' }}
        state: >-
          {{ states('sensor.main_floor_average_temperature')|float('NAN') != 'NAN' and states('sensor.basement_rooms_average_temperature')|float('NAN') != 'NAN' and
             (states('sensor.main_floor_average_temperature')|float(0) - states('sensor.basement_rooms_average_temperature')|float(0)) | abs > 3 }}

      - default_entity_id: binary_sensor.downstairs_set_temp_near_outside_temp
        name: "Downstairs Set Temp Near Outside Temp"
        delay_on: >
          {{ 0 if is_state('binary_sensor.downstairs_set_temp_near_outside_temp','unknown') else '00:05:00' }}
        delay_off: >
          {{ 0 if is_state('binary_sensor.downstairs_set_temp_near_outside_temp','unknown') else '00:10:00' }}
        state: >-
          {{ states('sensor.outside_rear_sensor_age')|int(9999) < 1800 and
             (states('sensor.outside_rear_temperature')|float(999) - states('sensor.downstairs_hvac_set_temp_cooling')|float(-999)) < 5 and
             (states('sensor.outside_rear_temperature')|float(-999) - states('sensor.downstairs_hvac_set_temp_heating')|float(999)) > -5 }}

      - default_entity_id: binary_sensor.downstairs_can_do_passive_cooling
        name: "Downstairs Can Do Passive Cooling"
        delay_on: >
          {{ 0 if is_state('binary_sensor.downstairs_can_do_passive_cooling','unknown') else '00:05:00' }}
        delay_off: >
          {{ 0 if is_state('binary_sensor.downstairs_can_do_passive_cooling','unknown') else '00:10:00' }}
        state: >-
          {{ states('sensor.outside_rear_sensor_age')|int(9999) < 1800 and
             states('sensor.outside_rear_temperature')|float(999) < states('sensor.main_floor_average_temperature')|float(-999) and
             states('sensor.main_floor_average_temperature')|float(-999) > ((states('sensor.downstairs_hvac_set_temp_heating')|float(999) + (states('sensor.downstairs_hvac_set_temp_cooling')|float(999)*2))/3) }}

      - default_entity_id: binary_sensor.downstairs_can_do_passive_heating
        name: "Downstairs Can Do Passive Heating"
        delay_on: >
          {{ 0 if is_state('binary_sensor.downstairs_can_do_passive_heating','unknown') else '00:05:00' }}
        delay_off: >
          {{ 0 if is_state('binary_sensor.downstairs_can_do_passive_heating','unknown') else '00:10:00' }}
        state: >-
          {{ states('sensor.outside_rear_sensor_age')|int(9999) < 1800 and
             states('sensor.outside_rear_temperature')|float(-999) > states('sensor.main_floor_average_temperature')|float(999) and
             states('sensor.main_floor_average_temperature')|float(999) < (((states('sensor.downstairs_hvac_set_temp_heating')|float(-999)*2) + states('sensor.downstairs_hvac_set_temp_cooling')|float(-999))/3) }}

      - default_entity_id: binary_sensor.downstairs_door_open_recently
        name: "Downstairs Door Open Recently"
        delay_on: >
          {{ 0 if is_state('binary_sensor.downstairs_door_open_recently','unknown') else '00:00:10' }}
        delay_off: >
          {{ 0 if is_state('binary_sensor.downstairs_door_open_recently','unknown') else '00:30:00' }}
        state: >-
          {{ is_state('binary_sensor.back_door','on') or
             is_state('binary_sensor.front_door','on') or
             is_state('binary_sensor.basement_door','on') }}

      - default_entity_id: binary_sensor.downstairs_humidifier_run_fan
        name: "Downstairs Humidifier Run Fan"
        delay_on: '00:15:00'
        delay_off: >
          {{ 0 if is_state('binary_sensor.downstairs_humidifier_run_fan','unknown') else '00:00:30' }}
        state: >-
          {{ is_state('binary_sensor.downstairs_hvac_humidifier_running','on') and
             states('sensor.indoor_projected_night_humidity') | float(999) < 50.0 and
             states('sensor.outdoor_humidity_coming_inside') | float(999) < 60.0 and
             states('sensor.downstairs_hvac_zone_average_humidity') | float(999) < 45.0 and
             states('sensor.downstairs_hvac_zone_max_humidity') | float(999) < 48.0 }}

      - default_entity_id: binary_sensor.downstairs_dehumidifier_run_fan
        name: "Downstairs Dehumidifier Run Fan"
        # delay_on: '00:00:00'
        delay_off: >
          {{ 0 if is_state('binary_sensor.downstairs_dehumidifier_run_fan','unknown') else '00:10:00' }}
        state: >-
          {{ is_state('binary_sensor.basement_dehumidifier_running','on') and
             states('sensor.downstairs_hvac_zone_max_humidity') | float(999) > 50.0 }}

      - default_entity_id: binary_sensor.downstairs_bathroom_exhaust_fan_on
        name: "Downstairs Bathroom Exhaust Fan On"
        delay_on: >
          {{ 0 if is_state('binary_sensor.downstairs_bathroom_exhaust_fan_on','unknown') else '00:01:00' }}
        delay_off: >
          {{ 0 if is_state('binary_sensor.downstairs_bathroom_exhaust_fan_on','unknown') else '00:05:00' }}
        state: >-
          {{  is_state('switch.basement_bath_exhaust_fan','on') }}

      - default_entity_id: binary_sensor.downstairs_hvac_fan_tou_peak_auto
        name: "Downstairs HVAC Fan TOU Peak Auto"
        value_template: >-
          {{  is_state('binary_sensor.dominion_power_tou_peak','on') and is_state('input_boolean.downstairs_hvac_severe_weather_mode','off') }} 


template:
  - trigger:
      - platform: state
        id: "cooling"
        entity_id: sensor.downstairs_hvac_status
        to: 'cooling'
      - platform: state
        id: "cooling_idle"
        entity_id: sensor.downstairs_hvac_status
        from: 'cooling'
        to: 'idle'
        for: '00:05:00'
      - platform: homeassistant
        id: "ha_start"
        event: start
    binary_sensor:
      - name: "Downstairs HVAC Cooling Idle Fan Delay"
        state: >-
          {% if  trigger.id == "cooling" %}
            True
          {% else %}
            False
          {% endif %}


group:

  downstairs_hvac_fan_on_conditions:
    name: "Downstairs HVAC Fan On Conditions"
    entities:
      - binary_sensor.main_floor_high_temp_difference
      - binary_sensor.basement_rooms_high_temp_difference
      - binary_sensor.basement_main_floor_high_temp_difference
      #- binary_sensor.downstairs_can_do_passive_cooling
      #- binary_sensor.downstairs_can_do_passive_heating
      - binary_sensor.downstairs_hvac_fan_manual_on
      #- binary_sensor.downstairs_door_open_recently
      - binary_sensor.downstairs_humidifier_run_fan
      - binary_sensor.downstairs_dehumidifier_run_fan
      - binary_sensor.downstairs_bathroom_exhaust_fan_on
      - input_boolean.downstairs_hvac_fan_on_manual_hold
      - input_boolean.downstairs_hvac_severe_weather_mode

  downstairs_hvac_fan_circ_conditions:
    name: "Downstairs HVAC Fan Circ Conditions"
    entities:
      - binary_sensor.downstairs_hvac_fan_idle_cycle
      #- binary_sensor.downstairs_set_temp_near_outside_temp

  downstairs_hvac_fan_force_auto_conditions:
    name: "Downstairs HVAC Fan Force Auto Conditions"
    entities:
      - binary_sensor.downstairs_hvac_cooling_idle_fan_delay
      - binary_sensor.downstairs_hvac_fan_tou_peak_auto

automation:

  - alias: "Downstairs HVAC Set Fan Mode"
    trigger:
      - platform: state
        entity_id: sensor.downstairs_hvac_fan_mode_preference 
        for: '00:00:05'
      - platform: state
        entity_id: climate.downstairs_thermostat
        to: 'heat_cool'
        for: '00:00:05'
    condition:
      - condition: state
        entity_id: climate.downstairs_thermostat
        state: 'heat_cool'
    action:
      - service: climate.set_fan_mode
        data:
          entity_id: climate.downstairs_thermostat
          fan_mode: "{{ states('sensor.downstairs_hvac_fan_mode_preference') }}"

  - alias: "Downstairs HVAC Set Fan Off"
    trigger:
      - platform: state
        entity_id: climate.downstairs_thermostat
        to: 'off'
    action:
      - service: climate.set_fan_mode
        data:
          entity_id: climate.downstairs_thermostat
          fan_mode: "Auto low"

#  - alias: "Downstairs Thermostat Fan Cycle On"
#    trigger:
#      - platform: state
#        entity_id: group.downstairs_hvac_fan_on_conditions
#        to: 'on'
#      - platform: state
#        entity_id: climate.downstairs_thermostat
#        to: 'heat_cool'
#      - platform: state
#        entity_id: sensor.downstairs_hvac_daily_cycle
#      - platform: state
#        entity_id: sensor.downstairs_hvac_status
#        from: 'cooling'
#        to: 'idle'
#        for: '00:05:00'
#    condition:
#      - condition: state
#        entity_id: group.downstairs_hvac_fan_on_conditions
#        state: 'on'
#      - condition: state
#        entity_id: climate.downstairs_thermostat
#        state: 'heat_cool'
#    action:
#      - service: climate.set_fan_mode
#        data:
#          entity_id: climate.downstairs_thermostat
#          fan_mode: "Low"
#
#  - alias: "Downstairs Thermostat Fan Cycle Circ"
#    trigger:
#      - platform: state
#        entity_id: group.downstairs_hvac_fan_on_conditions
#        to: 'off'
#      - platform: state
#        entity_id: group.downstairs_hvac_fan_circ_conditions
#        to: 'on'
#      - platform: state
#        entity_id: sensor.downstairs_hvac_fan_status
#        to: 'Running'
#        for:
#          hours: 1
#      - platform: state
#        entity_id: climate.downstairs_thermostat
#        to: 'heat_cool'
#      - platform: state
#        entity_id: sensor.downstairs_hvac_daily_cycle
#      - platform: state
#        entity_id: sensor.downstairs_hvac_status
#        from: 'cooling'
#        to: 'idle'
#        for: '00:10:00'
#    condition:
#      - condition: state
#        entity_id: group.downstairs_hvac_fan_on_conditions
#        state: 'off'
#      - condition: state
#        entity_id: group.downstairs_hvac_fan_circ_conditions
#        state: 'on'
#      - condition: state
#        entity_id: climate.downstairs_thermostat
#        state: 'heat_cool'
#    action:
#      - service: climate.set_fan_mode
#        data:
#          entity_id: climate.downstairs_thermostat
#          fan_mode: "Circulation"
#
#  - alias: "Downstairs Thermostat Fan Cycle Off"
#    trigger:
#      - platform: state
#        entity_id: group.downstairs_hvac_fan_on_conditions
#        to: 'off'
#      - platform: state
#        entity_id: group.downstairs_hvac_fan_circ_conditions
#        to: 'off'
#      - platform: state
#        entity_id: sensor.downstairs_hvac_fan_status
#        to: 'Running'
#        for:
#          hours: 1
#      - platform: state
#        entity_id: climate.downstairs_thermostat
#        to: 'heat_cool'
#      - platform: state
#        entity_id: sensor.downstairs_hvac_daily_cycle
#      - platform: state
#        entity_id: sensor.downstairs_hvac_status
#        from: 'cooling'
#        to: 'idle'
#    condition:
#      - condition: or
#        conditions:
#          - condition: template
#            value_template: '{{ trigger.from_state.state == "cooling" and trigger.to_state.state == "idle" }}'
#          - condition: and
#            conditions:
#              - condition: state
#                entity_id: group.downstairs_hvac_fan_on_conditions
#                state: 'off'
#              - condition: state
#                entity_id: group.downstairs_hvac_fan_circ_conditions
#                state: 'off'
#      - condition: state
#        entity_id: climate.downstairs_thermostat
#        state: 'heat_cool'
#    action:
#      - service: climate.set_fan_mode
#        data:
#          entity_id: climate.downstairs_thermostat
#          fan_mode: "Auto low"

As far as I could tell, removing the second template line should work. What are some of the errors you get?

Looks like you’re using packages, just noting it.

Ya that file should only have one (the first) template: in it, otherwise looks ok to me. What errors are you getting when you remove the second one?

Edit: Oops, a little slow here :wink:

@Edwin_D @HappyCadaver yes, I’m using packages, makes it easier for me to make my configuration grouped by capability and modular (duplicate, remove, share) without having it tangled with other capabilities.

They moved the logfile so its now hard to grep/filter, but when I remove the duplicate template line I get a TON of seemingly unrelated errors suddenly appear.

This isn’t the only file I have like this, I’ve got a few where I used trigger-templates that have the same strange issue.

Here’s the log commenting out the 2nd #template

line 159 errors here because of value_template isn’t an allowed option wthin a templae binary_sensor … it likely must read “state:” ?

And perhaps that lead to the point where it stumbles across the following duplicated “template:” ?

If these are template sensors that you manually migrated to the new format then it is a shame that you did not use the custom migration tool available or used the migrated yml provided by the repair that HA must have given. These contain vital bits that are required to make sure the new versions are an exact drop in replacement for the old one. Not using those mean you may risk that the entity id changes and automations break because of it.

OH! I thought I had caught all those…good eye!

That’s odd that everything seemed to be working perfectly without throwing errors when I had the second template key instead of throwing an error.

Maybe if the logfile had not been removed it’d be easier to filter for specific things among the million warnings that get printed as stuff initializes (because of course while they’re initializing many things will be unknown!)

Changing the value_template to state fixed my issue!

The “repair” is utterly useless. There’s like 300+ “repairs” and they are seemingly random with no way to sort/filter to make it sensible, preferring to group by domain rather than capability (same stupid issue as most of the GUI managed stuff) which means I would have to spend days clicking thru to manually figure out grouping. I can do it by hand faster than I can hunt for which of the 300+ “repairs” are relevant to each package file.

I’m not aware of this “custom migration tool” you speak of.

It is marked as the solution of the post explaining the need for the migration:

Hadn’t seen that back when the repairs first showed up.

But it also doesn’t sound useful:

A folder will be generated inside your configuration. This folder will be named migrated_templates and it will contain mutliple files. Each file will be a domain and it will contain all templates in that domain.

So basically I would then have to manually hunt down and rebuild every one of my package files because they’d be de-package-ified. It sounds like that tool was written by someone who has no concept of software design, maintenance, encapsulation, or object oriented design but just writes everything as spaghetti-code in one big mess.

And it also doesn’t say what happens to all my verbose comments spread thru my YAML packages - some of which are ASCII-art flow charts to help follow design plans:

Then each of those “major” inputs is its own separate YAML package file encapsulating the relevant information for that capability. And each of them uses a mixture of templates, input_numbers, input_booleans, automations, and possibly other integrations to accomplish the sub-objectives.

If I want to remove a functionality (e.g. feels-like offset) I just take the 1 value out of the sum in the main file and remove the relevant YAML file. I would not want that mixed in with (for example) the templates that track status of my power station.

The tool cannot see the original organization of the files you had. So scuffing the person doing his utmost to prevent work for you (more than 300 hours spent by him) isn’t helpful either. You either accept all the effort he put in to doing as much as he could, or you do it all manually and end up here with all the mistakes you made while doing it.

Doing some cut and paste to redistribute the data in the migrated file isn’t nearly as hard as making all the required changes manually imho.

The new format has been around for years, personally I converted all of them over time. Of the hundreds of template sensors I had none to fix. You still have a couple of months left to fix things.

4 Likes

It was incredibly useful. They were all done in chunks and all I had to do was move the relevant stuff back to the right package…

Took me 20 minutes to do 164 sensors. It saved me from having to think about any of them. One was legit broke but the break was obvious and easily fixed, I reported it to Petro and I believe current version of the tool even avoids the issue I had.

3 Likes

Curious how many packages you have?

I’ve got nearly 200 of them across 24 major areas (e.g. “lighting”, “hvac”, “temp & humidity”, “laundry”, “pets”, etc). Some of which are generated by other scripts so I can quickly update replacing RTL-433 sensors if the ID changes or sensor is replaced.

And I’m not sure how many templates it is thru that, some are single ones others are many in one file.

I hate to think how long it’d take me to hunt down every individual template to put it back in the correct area one at a time, whether its copy-paste thru the UI or from a script that garbles it into spaghetti code.

Those 164 are spread across about 16 packages. Some more some less.

Look it spits out a text file. Each of the items in the file are arranged in order they’re processed. So guess what that means if you start with two folders open. One - the source file two your tree of targets. It went…

Copy.

Oh that’s this file…

Open, Replace, Save, Reload template. Next.

I got to about 15-30 seconds per file near the end.

Yours would just be more files. Personally I don’t break my subsystems down to the level you do but the procedure is no different… And I bet you can ID which file a sensor goes in on sight. If you can’t, I’d offer yoou organization may be too complex.

You have six months to do it deprication doesn’t mean it goes away now. Either way there is a tool it works very well if you’re interested in even looking at it.