Répartir le fichier configuration.yaml en plusieurs fichiers

Ceci est une traduction de la documentation : Splitting up the configuration - Home Assistant

Pour approfondir vos connaissances, n’hésitez pas à lire le tutoriel de @McFly :


Introduction

Vous utilisez Home Assistant depuis un certain temps déjà et votre fichier configuration.yaml devient incompréhensible, ou tout simplement, vous voulez commencer avec l’approche distribué de ce fichier. Voici comment commencer scinder le configuration.yaml en morceaux plus compréhensibles (lire : pour les humains).

Tout d’abord, plusieurs membres de la communauté ont nettoyé (lire : sans clés/mots de passe API, etc.) les versions de leurs configurations disponibles pour consultation, vous pouvez en voir la liste ici, et certains membres de HACF disponible dans la Awesome List disponible ici.

Avant de vous jeter dessus, prenez le temps de lire ce qui suit. Ça facilitera la compréhension, surtout quand il n’y a pas de commentaire (assez explicite) dans les fichiers.

Maintenant, malgré le fait que nous allons découper le fichier configuration.yaml dans les explications plus bas, ce fichier va dans tous les cas continuer à exister, bien que sous forme bien moins encombrante, voir presque complètement dénudé.

Dans cette version plus légère, nous aurons encore besoin de ce que l’on pourrait appeler le code principal (exemple) :

homeassistant:
  # Name of the location where Home Assistant is running
  name: "My Home Assistant Instance"
  # Location required to calculate the time the sun rises and sets
  latitude: 37
  longitude: -121
  # 'metric' for Metric, 'imperial' for Imperial
  unit_system: imperial
  # Pick yours from here: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
  time_zone: "America/Los_Angeles"
  customize: !include customize.yaml

Notez que chaque ligne après homeassistant: est indentée de deux (2) espaces. Comme les fichiers de configuration de Home Assistant sont basés sur le langage YAML, l’indentation et l’espacement sont importants. Notez également que l’entrée apparemment étrange après customize:

!include nomdefichier.yaml est la déclaration qui indique à Home Assistant d’insérer le contenu de nomdefichier.yaml à ce moment-là. C’est ainsi que nous allons pouvoir décomposer un fichier monolithique et difficile à lire (lorsqu’il devient volumineux) en morceaux plus faciles à gérer.

Maintenant, avant de commencer à répartir les différents composants, examinons les autres intégrations (dans notre exemple) qui resteront dans le fichier de base :

history:
frontend:
logbook:
http:
  api_password: "ImNotTelling!"

ifttt:
  key: ["nope"]

wink:
  access_token: ["wouldn't you"]
  refresh_token: ["like to know"]

zwave:
  usb_path: "/dev/ttyUSB0"
  config_path: "/usr/local/share/python-openzwave/config"
  polling_interval: 10000

mqtt:
  broker: 127.0.0.1

Comme pour le code principal, l’indentation fait la différence. Les en-têtes d’intégration (par exemple : mqtt:) doivent être alignés à gauche (sans indentation), et les paramètres (tel que : broker:) doivent être indentés de deux (2) espaces.

Notez qu’il est techniquement possible de séparer ces intégrations de ce fichier. A vous de mesurer les avantages/inconvénients pour de si petites et " uniques" intégrations.
Vous remarquerez également le symbole # (dièse). Il débute une ligne de commentaire, dans la mesure où ce qui suit sur la même ligne ne sera pas interprété. Cela améliore la lisibilité du fichier, permet de désactiver des fonctionnalités ou de laisser une explication sur ce qui l’entoure.

Supposons désormais qu’un fichier vierge ait été créé dans le répertoire de configuration de Home Assistant pour chacun des éléments suivants :

automation.yaml
zone.yaml
sensor.yaml
switch.yaml
device_tracker.yaml
customize.yaml

automation.yaml contiendra tous les détails d’intégration de l’automatisation. zone.yaml contiendra les détails d’intégration de la zone, etc. Ces fichiers peuvent être nommés de la façon que vous désirez, mais leur donner des noms correspondant à leur fonction facilitera le suivi, et le partage avec les autres membres (aussi bien pour avoir de l’aide que pour aider quelqu’un d’autre).

Ce qui induit que le fichier configuration.yaml doit contenir les lignes suivantes :

automation: !include automation.yaml
zone: !include zone.yaml
sensor: !include sensor.yaml
switch: !include switch.yaml
device_tracker: !include device_tracker.yaml

Attention, l’imbrication des !include (le fait d’avoir un !include dans un fichier qui est lui-même !include) ne fonctionnera pas. Vous pouvez cependant avoir plusieurs !include de haut niveau pour une intégration donnée, si vous donnez un label différent à chacun d’entre eux, par exemple :

light:
- platform: group
  name: "Bedside Lights"
  entities:
    - light.left_bedside_light
    - light.right_bedside_light

# define more light groups in a separate file
light groups: !include light-groups.yaml

# define some light switch mappings in a different file
light switches: !include light-switches.yaml

Avec !include light-groups.yaml pouvant ressembler à ceci :

- platform: group
  name: "Outside Lights"
  entities:
    - light.porch_lights
    - light.patio_lights

Et !include light-switches.yaml à cela :

- platform: switch
  name: "Patio Lights"
  entity_id: switch.patio_lights

- platform: switch
  name: "Floor Lamp"
  entity_id: switch.floor_lamp_plug

Très bien, nous avons donc les intégrations uniques et les déclarations d’inclusion dans le fichier de base, mais que peut-on mettre dans ces fichiers supplémentaires ?
Regardons un exemple issu de la documentation officielle d’Home Assistant, device_tracker.yaml :

- platform: owntracks
- platform: nmap_tracker
  
  home_interval: 3
  hosts: 192.168.2.0/24

  track_new_devices: true
  interval_seconds: 40
  consider_home: 120

Ce petit exemple illustre le fonctionnement des fichiers fractionnés. Dans ce cas, nous commençons avec deux entrées de suivi de périphérique (owntracks et nmap). Ces fichiers suivent le « style 1 », c’est-à-dire une entrée de tête alignée entièrement à gauche (- platform: owntracks) suivie des entrées de paramètres indentées de deux espaces.

Voici un autre exemple de configuration, avec une sonde (sensor) plus complexe :

### sensor.yaml
### METEOBRIDGE #############################################
- platform: tcp
  name: "Outdoor Temp (Meteobridge)"
  host: 192.168.2.82
  timeout: 6
  payload: "Content-type: text/xml; charset=UTF-8\n\n"
  value_template: "{{value.split (' ')[2]}}"
  unit: C
- platform: tcp
  name: "Outdoor Humidity (Meteobridge)"
  host: 192.168.2.82
  port: 5556
  timeout: 6
  payload: "Content-type: text/xml; charset=UTF-8\n\n"
  value_template: "{{value.split (' ')[3]}}"
  unit: Percent

#### STEAM FRIENDS ##################################
- platform: steam_online
  api_key: ["not telling"]
  accounts:
      - 76561198012067051

#### TIME/DATE ##################################
- platform: time_date
  display_options:
      - "time"
      - "date"
- platform: worldclock
  time_zone: Etc/UTC
  name: "UTC"
- platform: worldclock
  time_zone: America/New_York
  name: "Ann Arbor"

Vous remarquerez que cet exemple comprend une section de paramètres secondaires (sous la section STEAM) ainsi qu’un meilleur exemple de la façon dont les commentaires peuvent être utilisés pour décomposer les fichiers en sections.

Si vous avez des problèmes, consultez le fichier home-assistant.log dans le répertoire de configuration ainsi que vos indentations. Si malgré tout, ça ne fonctionne pas, n’hésitez pas à poser vos questions sur ce forum ou sur Discord.

Débogage de plusieurs fichiers de configuration

Si vous disposez de nombreux fichiers de configuration, le script check_config vous permet de voir comment Home Assistant les interprète. Ces commandes sont utilisables via l’add-on SSH & Web Terminal :

  • Lister tous les fichiers chargés : hass --script check_config --files
  • Visualisation de la configuration d’un composant : hass --script check_config --info light
  • Ou la configuration de tous les composants : hass --script check_config --info all
    Vous pouvez obtenir de l’aide sur la ligne de commande en utilisant : hass --script check_config --help

Utilisation avancée

Il existe quatre options avancées pour inclure des répertoires entiers en une seule fois. Veuillez noter que vos fichiers doivent porter l’extension de fichier .yaml, le format .yml n’est pas pris en charge.

  • !include_dir_list renvoie le contenu d’un répertoire sous forme de liste, chaque contenu de fichier étant une entrée dans la liste. Les entrées de la liste sont classées selon l’ordre alphanumérique des noms des fichiers.
  • !include_dir_named renverra le contenu d’un répertoire sous la forme d’un dictionnaire qui met en correspondance nom de fichier => contenu du fichier.
  • !include_dir_merge_list renvoie le contenu d’un répertoire sous forme de liste en fusionnant tous les fichiers (qui doivent contenir une liste) en une seule grande liste.
  • !include_dir_merge_named renverra le contenu d’un répertoire sous forme de dictionnaire en chargeant chaque fichier et en le fusionnant dans un grand dictionnaire.

Ces options fonctionnent de façon récursives. À titre d’exemple, en utilisant !include_dir_* automation, comprendra les 6 fichiers indiqués suivant :

.
└── .homeassistant
    ├── automation
    │   ├── lights
    │   │   ├── turn_light_off_bedroom.yaml
    │   │   ├── turn_light_off_lounge.yaml
    │   │   ├── turn_light_on_bedroom.yaml
    │   │   └── turn_light_on_lounge.yaml
    │   ├── say_hello.yaml
    │   └── sensors
    │       └── react.yaml
    └── configuration.yaml (non inclus)

Voir ci-dessous pour les exemples de chacune des options.

Exemple : !include_dir_list

À l’origine, seulement le fichier configuration.yaml contenant :

automation:
  - alias: "Automation 1"
    trigger:
      platform: state
      entity_id: device_tracker.iphone
      to: "home"
    action:
      service: light.turn_on
      target:
        entity_id: light.entryway
  - alias: "Automation 2"
    trigger:
      platform: state
      entity_id: device_tracker.iphone
      from: "home"
    action:
      service: light.turn_off
      target:
        entity_id: light.entryway

Avec cette option, cela devient :

  • configuration.yaml :
automation: !include_dir_list automation/presence/
  • automation/presence/automation1.yaml :
alias: "Automation 1"
trigger:
  platform: state
  entity_id: device_tracker.iphone
  to: "home"
action:
  service: light.turn_on
  target:
    entity_id: light.entryway
  • automation/presence/automation2.yaml :
alias: "Automation 2"
trigger:
  platform: state
  entity_id: device_tracker.iphone
  from: "home"
action:
  service: light.turn_off
  target:
    entity_id: light.entryway

Il est important de noter que chaque fichier ne doit contenir qu’une seule entrée lorsque vous utilisez !include_dir_list.
Il est également important de noter que si vous fractionnez un fichier après avoir ajouté -id : pour prendre en charge l’interface utilisateur d’automatisation, la ligne -id : doit être supprimée de chacun des fichiers fractionnés.

Exemple : !include_dir_named

À l’origine, seulement le fichier configuration.yaml contenant :

alexa:
  intents:
    LocateIntent:
      action:
        service: notify.pushover
        data:
          message: "Your location has been queried via Alexa."
      speech:
        type: plaintext
        text: >
          {%- for state in states.device_tracker -%}
            {%- if state.name.lower() == User.lower() -%}
              {{ state.name }} is at {{ state.state }}
            {%- endif -%}
          {%- else -%}
            I am sorry. Pootie! I do not know where {{User}} is.
          {%- endfor -%}
    WhereAreWeIntent:
      speech:
        type: plaintext
        text: >
          {%- if is_state('device_tracker.iphone', 'home') -%}
            iPhone is home.
          {%- else -%}
            iPhone is not home.
          {% endif %}

Avec cette option, cela devient :

  • configuration.yaml :
alexa:
  intents: !include_dir_named alexa/
  • alexa/LocateIntent.yaml :
action:
  service: notify.pushover
  data:
    message: "Your location has been queried via Alexa."
speech:
  type: plaintext
  text: >
    {%- for state in states.device_tracker -%}
      {%- if state.name.lower() == User.lower() -%}
        {{ state.name }} is at {{ state.state }}
      {%- endif -%}
    {%- else -%}
      I am sorry. Pootie! I do not know where {{User}} is.
    {%- endfor -%}
  • alexa/WhereAreWeIntent.yaml :
speech:
  type: plaintext
  text: >
    {%- if is_state('device_tracker.iphone', 'home') -%}
      iPhone is home.
    {%- else -%}
      iPhone is not home.
    {% endif %}

Exemple !include_dir_merge_list

À l’origine, seulement le fichier configuration.yaml contenant :

automation:
  - alias: "Automation 1"
    trigger:
      - platform: state
        entity_id: device_tracker.iphone
        to: "home"
    action:
      - service: light.turn_on
        target:
          entity_id: light.entryway
  - alias: "Automation 2"
    trigger:
      - platform: state
        entity_id: device_tracker.iphone
        from: "home"
    action:
      - service: light.turn_off
        target:
          entity_id: light.entryway

Avec cette option, cela devient :

  • configuration.yaml :
automation: !include_dir_merge_list automation/
  • automation/presence.yaml :
- alias: "Automation 1"
  trigger:
    - platform: state
      entity_id: device_tracker.iphone
      to: "home"
  action:
    - service: light.turn_on
      target:
        entity_id: light.entryway
- alias: "Automation 2"
  trigger:
    - platform: state
      entity_id: device_tracker.iphone
      from: "home"
  action:
    - service: light.turn_off
      target:
        entity_id: light.entryway

Il est important de noter que lorsque vous utilisez !include_dir_merge_list, vous devez inclure une liste dans chaque fichier (chaque élément de la liste est désigné par un trait d’union [-]). Et que chaque fichier peut contenir une ou plusieurs entrées.

Exemple : !include_dir_merge_named

À l’origine, seulement le fichier configuration.yaml contenant :

group:
  bedroom:
    name: "Bedroom"
    entities:
      - light.bedroom_lamp
      - light.bedroom_overhead
  hallway:
    name: "Hallway"
    entities:
      - light.hallway
      - thermostat.home
  front_yard:
    name: "Front Yard"
    entities:
      - light.front_porch
      - light.security
      - light.pathway
      - sensor.mailbox
      - camera.front_porch

Avec cette option, cela devient :

  • configuration.yaml :
group: !include_dir_merge_named group/
  • group/interior.yaml :
bedroom:
  name: "Bedroom"
  entities:
    - light.bedroom_lamp
    - light.bedroom_overhead
hallway:
  name: "Hallway"
  entities:
    - light.hallway
    - thermostat.home
  • group/exterior.yaml :
front_yard:
  name: "Front Yard"
  entities:
    - light.front_porch
    - light.security
    - light.pathway
    - sensor.mailbox
    - camera.front_porch

Exemple : combiner !include_dir_merge_list avec automations.yaml

Vous voulez passer à l’étape avancée et diviser vos automatismes, mais vous voulez quand même pouvoir créer des automatismes depuis l’interface graphique ?
Comme indiqué plus haut, il est possible d’imbriquer les includes. Voici comment nous pouvons faire cela pour les automatismes.

L’utilisation d’étiquettes comme manual ou ui permet d’utiliser plusieurs clés dans la configuration :
configuration.yaml :

# automations faites à la main
automation manual: !include_dir_merge_list automations/

# automations créées via l’interface graphique
automation ui: !include automations.yaml

MAJ 12/05/2021 : pour correspondre à la mise à jour de la documentaiton (n° commit : 2a083a8)

Super post. Mériterait de le mettre dans les tutoriels officiel. Un petit mot sur les packages ?
Actuellement je ne regroupe plus par fichier automation: Script: … mais plutôt par projet via les packages. L’avantage est de trouver au même endroit toutes les sensors, automation script … du projet.

1 J'aime

C’est déjà dans #decouverte-de-home-assistant:upside_down_face:

Non car ici c’est la traduction :fr: de la documentation concernant la configuration partagée.

La méthode package est abordé dans ce tutoriel : Organisation du fichier configuration.yaml

C’est dans la partie utilisation avancée de cette documentation.
Ainsi, que dans le tuto de @McFly cité par @Clemalex