Splitting config for template:

Great :slight_smile: That’s exactly what I was looking for.

You see, the problem is that my configuration.yaml is not so big yet to split it into entities. But not-so-small that it needs some logical splitting.

Packages will exactly solve this until my configuration gets sufficiently big.

Thanks a lot.

My experience:

  1. Add this into “configuration.yaml”:
  packages: !include_dir_named conf
  1. Create a “conf” folder in the config dir.

  2. Create ANY tree structure in the “conf” folder:
    image
    where each subfolder may have other subfolders and so on.

  3. Inside any folder (let it be “network/net/asus_ac68u”, for example) create as many yaml files as you want.

  4. Every yaml file may have “sensor”, “template”, “input_boolean”, “automation”, “customize” etc sections (surely one same section per one file, i.e. one “sensor”, one “customize” etc).

The main idea is to structure a config by tasks (network devices, persons, weather, home climat, etc) - instead of piling all template sensors in one file.

Unfortunately, there is one limitation - you must use unique filenames.
I.e. you cannot have several “test.yaml” files in different folders - have to rename them to “test_router.yaml”, “test_waterpump.yaml” etc.
Created this issue, missed a moment when it was closed.

Also, if you want to exclude some functionality (like “got rid of this router”) - just remove the whole “router xxx” folder form the structure. Alternatively - rename all yaml files in this folder, replace “yaml” extension by something llike “disabled” (I use “dis”).
If you have several HA installation (apartment, country house, test setup, …) and some router is moved from one place to another - just move it’s particular folder into another installation.

Secrets may also be stored on several levels (local secrets, global secrets).

A similar approach may be used for Lovelace (dashboards, views, decluttering- (described here), button-card-templates & a brand new config-template-card global vars).

10 Likes

What am I missing? My sensors never show up in states!

this is what I did using your expamples.

made a folder templates, in it folder sensors and binary_sensors in those folders I placed yaml files with a sensor for instance, when I make a typo in them or leave out the word sensor: I get an error when i update template entites so ha looks in those files, that works some how

vb:

configuration. yaml

template:
  - sensor: !include_dir_merge_list templates/sensors/
  - binary_sensor: !include_dir_merge_list templates/binary_sensors/

in directory config/templates/sensors - file verbruik.yaml

# template sensor:

sensor:
-   name: "waterverbruik looptijd"
    unique_id: '8775766800'
    unit_of_measurement: "sec"
    value_template: >
        {% set t = this.state if states('input_boolean.kraan_aan_uit') == 'off' else now().timestamp() - states.input_boolean.kraan_aan_uit.last_changed.timestamp() %}
        {{ t | round(2, 'common') }}

I used names with and without “” that did not matter, problem is HA does not register nor use those sensors I defined ???

het origineel is dit.

- platform: template
    sensors:
        duree_ecoulement_eau_principale:
          friendly_name: Durée d'écoulement de l'eau principale
          unit_of_measurement: "sec"
          value_template: >
            {% set t = this.state if states('input_boolean.eau_principale_on_off') == 'off' else now().timestamp() - states.input_boolean.eau_principale_on_off.last_changed.timestamp() %}
            {{ t | round(2, 'common') }}

Please

  1. You need to remove the “sensor:” line from the top of the file.

  2. You are mixing up configuration syntax. The new style templates use “state:” instead of “value_template:”.

Check the dics to see the differences.

yes, found that out… had to use state.
plus I could not use !include_dir_merge_list it would not work had to use – template: !include templates.yaml.
Why I do not know but had to, could not leave out sensor: at the top of the file, it would not work.

TY

I actually found a way to have the flat structure I wanted in the initial post.

configuration.yaml:

template: !include templates.yaml

templates.yaml:

- binary_sensor: !include template_binary_sensors.yaml

- sensor: !include template_sensors.yaml

#################################################################
# Triggered Sensors
#################################################################

- trigger:
    - platform: etc...
3 Likes

Personally, I find it easiest to break everything into folders and then have files in each folder for what they do.

template: !include_dir_merge_list template

e.g. file

Check my proposal.
It allows to split per functionality, not per particular types.

1 Like

EDIT: Oh nevermind, you’re not saying as a feature request. My bad, that’s what you’re using

Yes, this config split I have been using for 2 years, very flexible and structural.

hey, i think is what im trying to do, are you abel to post a screenshot of how you set this up??

This is what im trying to achieve?

You can’t nest sub folders and use an include on the sensor folder.

I think I’m missing something here.
ATM I have a few templates working in my main configuration.yaml.

I’m trying to get a duplicate going from within templates.yaml. (Name Changed of course).
It doesn’t seem to be showing up.
I asume no reboot is required as the config check reports any errors when I have templates.yaml wrong.

Mine’s very simple, so my mistake must be basic.
Did try adding - sensor to the top of the file, but that caused an error on the line where - name is.

Can anyone help.

My Configuration.yaml,

# Loads default set of integrations. Do not remove.
default_config:

# 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 templates.yaml

template:

# Calculate Inverter Power
sensor:
  - platform: template
    sensors:
      net_power:
        value_template:
          "{{ ( states('sensor.sdm220m_3_power') | float | round(1)) -
          ( states('sensor.sdm220m_2_power') | float | round(1))}}"
        unit_of_measurement: "W"
        device_class: power
        #state_class: measurement #Causes Error
        friendly_name: Inverter Net Power

  # Calculate Inverter Production
  - platform: template
    sensors:
      net_production:
        value_template:
          "{{ ( states('sensor.sdm220m_3_import_active_energy') | float | round(1)) -
          ( states('sensor.sdm220m_2_import_active_energy') | float | round(1))}}"
        unit_of_measurement: "kWh"
        device_class: energy
        #state_class: total_increasing #Causes Error
        #state_class: measurement #Causes Error
        #attributes:
        #  last_reset: "1970-01-01T00:00:00+00:00"
        friendly_name: Inverter Net Production

  # Calculate Inverter Production - Alternate Code
template:
  - sensor:
      - name: "Inverter_Production"
        unique_id: "inverter_net_prod_test"
        unit_of_measurement: "kWh"
        device_class: energy
        state_class: total_increasing
        state: >
          {{ states ('sensor.sdm220m_3_import_active_energy') | float(2) | round(2)
          - states ('sensor.sdm220m_2_import_active_energy') | float(2) | round(2)}}
        availability: >
          {{ states ('sensor.sdm220m_3_import_active_energy') | float(none) != none and
              states ('sensor.sdm220m_2_import_active_energy') | float(none) != none }}

      - name: "Inverter_Net_Power"
        unique_id: "inverter_net_power" 
        unit_of_measurement: 'W'
        device_class: power
        state_class: measurement
        state: >
            {{ states ('sensor.sdm220m_3_power') | float(2) | round(2)
            - states ('sensor.sdm220m_2_power') | float(2) | round(2)}}
        availability: >
            {{ states ('sensor.sdm220m_3_power') | float(none) != none and
                states ('sensor.sdm220m_2_power') | float(none) != none }}
#  - sensor:
      - name: "Spa Temp Req"
        unique_id: "spa_temp_req" 
        unit_of_measurement: '°C'
        device_class: temperature
        state_class: measurement
        state: >
            {{ states ('input_number.spa_set_temp') | float(1) | round(1)
            - states ('sensor.gw1100c_v2_2_0_soil_temperature_5') | float(1) | round(1)}}
        availability: >
            {{ states ('input_number.spa_set_temp') | float(none) != none and
                states ('sensor.gw1100c_v2_2_0_soil_temperature_5') | float(none) != none }}

#  - sensor:
      - name: "Spa Temp Rise"
        unique_id: "spa_temp_diff" 
        unit_of_measurement: '°C'
        device_class: temperature
        state_class: measurement
        state: >
            {{ states ('sensor.gw1100c_v2_2_0_soil_temperature_6') | float(1) | round(1)
            - states ('sensor.gw1100c_v2_2_0_soil_temperature_5') | float(1) | round(1)}}
        availability: >
            {{ states ('sensor.gw1100c_v2_2_0_soil_temperature_6') | float(none) != none and
                states ('sensor.gw1100c_v2_2_0_soil_temperature_5') | float(none) != none }}

The templates.yaml I have created,

- name: "Spa Temp Need"
  unique_id: "spa_temp_need"
  unit_of_measurement: "°C"
  device_class: temperature
  state_class: measurement
  state: >
    {{ states ('input_number.spa_set_temp') | float(1) | round(1)
    - states ('sensor.gw1100c_v2_2_0_soil_temperature_6') | float(1) | round(1)}}
  availability: >
    {{ states ('input_number.spa_set_temp') | float(none) != none and
        states ('sensor.gw1100c_v2_2_0_soil_temperature_6') | float(none) != none }}

template: appears three times in your configuration.yaml file. It should only be there once.

do you mind sharing a screenshot, im not following any of this and if i can see what you have done, it might make more sense??

It is described here

Really like this method, thanks.
I am trying to get filter sensors working and have not succeeded yet.
In my normal sensors.yaml this works:

- platform: filter
  name: "filtered unknown power"
  unique_id: filtered_unknown_power
  entity_id: sensor.unknown_power_usage
  filters:
    - filter: throttle
      window_size: 10
      precision: 0

my package yaml doesn’t like the platform version so I tried this:
the template and the mqtt parts DO work.
but the filter doesn’t it doesn’t have error messages in the editor, but it also doesn’t work.

template:
  - sensor:
      - unique_id: ecogene_discharge_trend
        attributes:
          friendly_name: EcoGene discharge trend
        state: >
          {% set rate = state_attr('binary_sensor.ecogene_trend','gradient') %}
          {{ ([rate, 0] |min)  | abs }}
        availability: >
          {{ state_attr('binary_sensor.ecogene_trend','gradient')|is_number  }}

filter:
  sensor:
    - name: "EcoGene PV current"
      entity_id: sensor.ecogene_pv_current_fast
      filters:
        - filter: time_throttle
          window_size: "00:01"
          precision: 2

mqtt:
  sensor:
    - name: "EcoGene PV current Fast"
      state_topic: "ecogene/N/b827eb5e1860/system/0/Dc/Pv/Current"
      value_template: "{{ value_json.value | float(0) | round(2) }}"
      device_class: current
      unit_of_measurement: "A"
      icon: mdi:solar-panel

After a restart I do get this error message:

Setup failed for filter: No setup or config entry setup function defined.

Thanks for any help.

Probably because you are using a wrong definition for this “filter” sensor.
Try this:

sensor:
  - platform: filter
    …
2 Likes

Any reason why one should not use packages over this?

I’ve found using a packages folder with individual yaml files per project/function/goal to be immensely easier and treating all my custom yamls like plug-ins.

For example, here’s the one for zigbee2mqtt with a variety of custom stuff (no modifications by me other than collecting it all in one place):

  • input_select
  • input_number
  • input_text
  • input_boolean
  • script
  • timer
  • mqtt
  • automation

All in one yaml file!

# Input select for Zigbee2MQTT debug level
input_select:
  zigbee2mqtt_log_level:
    name: Zigbee2MQTT Log Level
    options:
      - debug
      - info
      - warn
      - error
    initial: info
    icon: mdi:format-list-bulleted

# Input number for joining time remaining (in minutes)
input_number:
  zigbee2mqtt_join_minutes:
    name: "Zigbee2MQTT join minutes"
    initial: 2
    min: 1
    max: 5
    step: 1
    mode: slider

# Input text to input Zigbee2MQTT friendly_name for scripts
input_text:
  zigbee2mqtt_old_name:
    name: Zigbee2MQTT Old Name
    initial: ""
  zigbee2mqtt_new_name:
    name: Zigbee2MQTT New Name
    initial: ""
  zigbee2mqtt_remove:
    name: Zigbee2MQTT Remove
    initial: ""

# Input boolean to set the force remove flag for devices
input_boolean:
  zigbee2mqtt_force_remove:
    name: Zigbee2MQTT Force Remove
    initial: false
    icon: mdi:alert-remove

# Scripts for renaming & removing devices
script:
  zigbee2mqtt_rename:
    alias: Zigbee2MQTT Rename
    sequence:
      service: mqtt.publish
      data_template:
        topic: zigbee2mqtt/bridge/request/device/rename
        payload_template: >-
          {
            "from": "{{ states.input_text.zigbee2mqtt_old_name.state | string }}",
            "to": "{{ states.input_text.zigbee2mqtt_new_name.state | string }}"
          }
  zigbee2mqtt_remove:
    alias: Zigbee2MQTT Remove
    sequence:
      service: mqtt.publish
      data_template:
        topic: zigbee2mqtt/bridge/request/device/remove
        payload_template: >-
          {
            "id": "{{ states.input_text.zigbee2mqtt_remove.state | string }}",
            "force": {% if states.input_boolean.zigbee2mqtt_force_remove.state == "off" %}false{% else %}true{% endif %}
          }

# Timer for joining time remaining (254 sec)
timer:
  zigbee_permit_join:
    name: Time remaining
    duration: 254

mqtt:
  sensor:
    # Sensor for monitoring the bridge state
    - name: Zigbee2MQTT Bridge state
      unique_id: zigbee2mqtt_bridge_state_sensor
      state_topic: "zigbee2mqtt/bridge/state"
      value_template: "{{ value_json.state }}"
      icon: mdi:router-wireless
    # Sensor for Showing the Zigbee2MQTT Version
    - name: Zigbee2MQTT Version
      unique_id: zigbee2mqtt_version_sensor
      state_topic: "zigbee2mqtt/bridge/info"
      value_template: "{{ value_json.version }}"
      icon: mdi:zigbee
    # Sensor for Showing the Coordinator Version
    - name: Zigbee2MQTT Coordinator Version
      unique_id: zigbee2mqtt_coordinator_version_sensor
      state_topic: "zigbee2mqtt/bridge/info"
      value_template: "{{ value_json.coordinator.meta.revision }}"
      icon: mdi:chip
    - name: Zigbee2mqtt Networkmap
      unique_id: zigbee2mqtt_networkmap_sensor
      # if you change base_topic of Zigbee2mqtt, change state_topic accordingly
      state_topic: zigbee2mqtt/bridge/networkmap/raw
      value_template: >-
        {{ now().strftime('%Y-%m-%d %H:%M:%S') }}
      # again, if you change base_topic of Zigbee2mqtt, change json_attributes_topic accordingly
      json_attributes_topic: zigbee2mqtt/bridge/networkmap/raw
    
  # Switch for enabling joining
  switch:
    - name: "Zigbee2MQTT Main join"
      unique_id: zigbee2mqtt_main_join_switch
      state_topic: "zigbee2mqtt/bridge/info"
      value_template: '{{ value_json.permit_join | lower }}'
      command_topic: "zigbee2mqtt/bridge/request/permit_join"
      payload_on: "true"
      payload_off: "false"

automation:
  # Automation for sending MQTT message on input select change
  - alias: Zigbee2MQTT Log Level
    initial_state: 'On'
    trigger:
      platform: state
      entity_id: input_select.zigbee2mqtt_log_level
    action:
      - service: mqtt.publish
        data:
          payload_template: "{{ states('input_select.zigbee2mqtt_log_level') }}"
          topic: zigbee2mqtt/bridge/request/config/log_level
  # Automation to start timer when enable join is turned on
  - id: zigbee_join_enabled
    alias: Zigbee Join Enabled
    trigger:
      platform: state
      entity_id: switch.zigbee2mqtt_main_join
      to: 'On'
    action:
      service: timer.start
      entity_id: timer.zigbee_permit_join
      data_template:
        duration: "{{ '00:0%i:00' % (states('input_number.zigbee2mqtt_join_minutes') | int ) }}"
  # Automation to stop timer when switch turned off and turn off switch when timer finished
  - id: zigbee_join_disabled
    alias: Zigbee Join Disabled
    trigger:
      - platform: event
        event_type: timer.finished
        event_data:
          entity_id: timer.zigbee_permit_join
      - platform: state
        entity_id: switch.zigbee2mqtt_main_join
        to: "off"
    action:
      - service: timer.cancel
        data:
          entity_id: timer.zigbee_permit_join
      - service: switch.turn_off
        entity_id: switch.zigbee2mqtt_main_join
  - id: "zigbee2mqtt_create_notification_on_successful_interview"
    alias: Zigbee Device Joined Notification
    trigger:
      platform: mqtt
      topic: 'zigbee2mqtt/bridge/event'
    condition:
      condition: template
      value_template: '{{trigger.payload_json.type == "device_interview" and trigger.payload_json.data.status == "successful" and trigger.payload_json.data.supported}}'
    action:
      - service: persistent_notification.create
        data_template:
          title: Device joined the Zigbee2MQTT network
          message: "Name: {{trigger.payload_json.data.friendly_name}},
                    Vendor: {{trigger.payload_json.data.definition.vendor}},
                    Model: {{trigger.payload_json.data.definition.model}},
                    Description: {{trigger.payload_json.data.definition.description}}"

Edit:

My configuration.yaml has this line added to it:

homeassistant:
  packages: !include_dir_named packages

Tip: in case you want to “disable” a yaml file, just rename it from example.yaml to example.yml. That’s what I’ve done and it works out quite well.

See above.