Best Practices Organize YAMLs

I have been enjoying home assistant for the past year or so, but I haven’t necessarily kept up with all of the new “best” ways to do things.

Mainly, the question is about the format of templates and sensors. I know that there is a legacy way and a new way, and that we dont necessarily have to migrate, but I’m having issues growing my platform when I have examples of both going on, and I want to embark on a cleanup migration process to get things squeaky clean.

I am pasting some of my files down below… can someone suggest the “best” way to organize my custom sensors and yaml files so I can future proof myself to stay organized?

Right now, my configuration.yaml looks like this:

default_config:

homeassistant:
  customize: !include customize.yaml
  currency: USD
 
# Load frontend themes from the themes folder
frontend:
  themes: !include_dir_merge_named themes

# Text-to-speech
tts:
  - platform: google_translate

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
template: !include_dir_merge_list templates/
sensor: !include sensors.yaml

generic_hygrostat:
  - name: Bedroom Humidity
    humidifier: input_boolean.humidifier_call_switch
    target_sensor: sensor.bedroom_temp_humidity
    target_humidity: 50
    dry_tolerance: 5
    wet_tolerance: 5
    device_class: "humidifier"
    min_cycle_duration:
      seconds: 5

geo_location:
  - platform: usgs_earthquakes_feed
    feed_type: "past_hour_m45_earthquakes"
    radius: 6300
    minimum_magnitude: 4.5
    latitude: 17.00000
    longitude: -30.00000
    
notify:
- name: txt_dad
  platform: smtp
  server: smtp.gmail.com
  port: 587
  timeout: 15
  encryption: starttls
  sender: ****redacted****
  username: ****redacted****
  password: ****redacted****
  recipient: 
    - ****redacted**** 
  sender_name: ****redacted****

I think one of the first things that confuses me, is that I have template: ~include_dir_merge_list templates/ as well as sensor: !include sensors.yaml.

In sensors.yaml, I have:

- platform: history_stats
  type: time
  name: Garage Doors Open Today
  entity_id: binary_sensor.garage_any_door_open
  state: "on"
  start: "{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}"
  end: "{{ now() }}"
- platform: template
  sensors:
    sun_window_ang_similarity:
      friendly_name: Sun-window angular similarity
      unit_of_measurement: "degrees"
      value_template: >
        {% set deg2rad = pi/180 %}

        {% set sun_azi = state_attr('sun.sun', 'azimuth') | int %}
        {% set sun_ele = state_attr('sun.sun', 'elevation') | int %}

        {% set sun_x = cos(sun_azi*deg2rad)*cos(sun_ele*deg2rad) %}
        {% set sun_y = sin(sun_azi*deg2rad)*cos(sun_ele*deg2rad) %}
        {% set sun_z = sin(sun_ele*deg2rad) %}

        {% set win_azi = 232.68 %}
        {% set win_ele = 0 %}

        {% set win_x = cos(win_azi*deg2rad)*cos(win_ele*deg2rad) %}
        {% set win_y = sin(win_azi*deg2rad)*cos(win_ele*deg2rad) %}
        {% set win_z = sin(win_ele*deg2rad) %}

        {% set dot = sun_x*win_x + sun_y*win_y + sun_z*win_z %}
        {% set norm_win = sqrt(win_x**2 + win_y**2 + win_z**2) %}
        {% set norm_sun = sqrt(sun_x**2 + sun_y**2 + sun_z**2) %}
        {% set cos_sim = dot/(norm_win*norm_sun) %}

        {% set ang_sim = 1 - acos(cos_sim)/pi %}
        {{ ((cos_sim * 100) | round(0)) if (sun_ele > 5 and cos_sim > 0 ) else 0 }}

In templates/sensor.yaml I have:

- sensor:  
    - name: days_until_next_feast_of_trumpets
      device_class: duration
      state: "{{ (states('input_datetime.next_feast_of_trumpets') | as_datetime | as_local | as_timestamp - today_at() | as_timestamp) // 86400.00 }}"
      unit_of_measurement: d
    - name: days_until_next_atonement
      device_class: duration
      state: "{{ (states('input_datetime.next_day_of_atonement') | as_datetime | as_local | as_timestamp - today_at() | as_timestamp) // 86400.00 }}"
    - name: days_until_next_tabernacles
      device_class: duration
      state: "{{ (states('input_datetime.next_tabernacles') | as_datetime | as_local | as_timestamp - today_at() | as_timestamp) // 86400.00 }}"
    - name: diff_attic_vs_house
      state: >-
        {% set a = states.sensor.loft_temperature.state|float %}
        {% set lr = states.sensor.living_room_temp_temperature.state|float %}
        {% set b = states.sensor.bedroom_temp_temperature.state|float %}
        {{ [(a - lr), (a - b)] | min }}
      unit_of_measurement: °F
    - name: diff_house_rooms
      state: >-
        {% set k = states.sensor.kitchen_temp_temperature.state|float %}
        {% set lr = states.sensor.living_room_temp_temperature.state|float %}
        {% set br = states.sensor.bedroom_temp_temperature.state|float %}
        {% set g = states.sensor.kids_temp_temperature.state|float %}
        {% set o = states.sensor.office_temp_temperature.state|float %}
        {{ ([k,lr,br,g,o] | max) - ([k,lr,br,g,o] | min) }}
      unit_of_measurement: °F
    - name: diff_kids_room
      state: >-
        {% set k = states.sensor.kitchen_temp_temperature.state|float %}
        {% set lr = states.sensor.living_room_temp_temperature.state|float %}
        {% set br = states.sensor.bedroom_temp_temperature.state|float %}
        {% set g = states.sensor.kids_temp_temperature.state|float %}
        {% set o = states.sensor.office_temp_temperature.state|float %}
        {{ g - br }}
      unit_of_measurement: °F

In templates/binary_sensor.yaml I have:

- binary_sensor:
  - name: "Garage - Any Door Open"
    state: >
        {% if states('binary_sensor.garage_human_door_state') == 'on' or 
        states('binary_sensor.garage_door_mower_state') == 'on' or 
        states('binary_sensor.garage_door_middle_state') == 'on' or 
        states('binary_sensor.garage_boat_state') == 'on' %}
            true
        {% else %}
            false
        {% endif %}
    device_class: garage_door
  - name: "Kitchen Window Sun"
    state: >
        {% if (states('sensor.sun_window_ang_similarity')|float > 30) and (states('sensor.openweathermap_cloud_coverage')|float < 80) %}
            true
        {% else %}
            false
        {% endif %}
  - name: "Attic Fan Conditions"
    state: >
        {% set month = now().month | int %}
        {% set front_porch_temp = states('sensor.front_porch_temperature') | float %}
        {% set indoor_enthalpy = states('sensor.computed_indoor_moist_air_enthalpy') | float %}
        {% set outdoor_enthalpy = states('sensor.computed_outdoor_moist_air_enthalpy') | float %}
        {% set outdoor_dew_point = states('sensor.computed_outdoor_dew_point') | float %}
        {% set airnow_aqi = states('sensor.airnow_aqi') | float %}
        {% if 3 < month <= 10 and
              40.0 < front_porch_temp < 74.0 and
              (indoor_enthalpy > outdoor_enthalpy or outdoor_dew_point < 57) and
              airnow_aqi < 101 %}
            true
        {% else %}
            false
        {% endif %}

I believe that Packages are linked in the page that Tom posted above, but many people miss it… As someone who was not familiar with YAML when I started using HA, packages were much easier to wrap my head around than the other options and have proved to be easy to use and very flexible.

Thanks for the packages suggestion - I will check that out. Part of my confusion comes from the page Tom linked as seemingly identified elsewhere as “legacy” and “not recommended.” However maybe there are subtle differences here that I’m misunderstanding.

The page I linked to is not

It has nothing to do with the page you linked to.

Packages are the way to go. I have alot of packages and they work great. Each package is focused on a single functional thing and includes the templates, automations, recorder settings, etc.

Examples of things would be basement dehumidifier, living room lights, water heater, well pump,…

Other examples are a motion sensor, as I want a template that records the last time it fired, alerts if the house is in away mode, etc.

1 Like

Do you have a specific question regarding template vs. sensor? It’s hard for us to address something as nebulous as “confusion”…

The is no “best” way. One reason there are multiple ways to split the configuration is because users have personal preferences when it comes to organization. Some people like all sensors in one file, some like an individual file for each sensor, others like to cluster related entities together in a single file (as Pete described above), and so on. One of the reasons I recommend Packages is because it allows any of the organizational topologies described above.

There isn’t really anything that is “future proof”… HA is under continuous development. A number of integrations have been moved to UI-only and it’s reasonable to assume that more will be moved in the future and your configuration will be converted automatically.

A number of template entities can now be configured as Helpers. You may want to consider moving to Helpers any of your template entities that aren’t using “advanced” features like triggers, availability, or delays.

1 Like

Both tom_I and Didgeridrew are on the nail. You need to choose your own way forward.
For me in some instances/devices I use packages and for other groups of sensors I use ‘a single file’. It truly is up to you how you design your own home?

1 Like

Oooohh…I like that idea. I never thought of that.

Right now my recorder.yaml file is so long it’s hard to find anything when things change. So I know there are likely lots of stuff that need to be excluded but aren’t.

1 Like