您使用 Home Assistant 已经有一段时间了,您的 configuration.yaml 文件已经大到让人看了想哭。或者,您只是想从一开始就采用分布式的方法。以下是如何将 configuration.yaml 拆分成更易于管理(即:人类可读)的部分。

示例配置文件供参考

首先,一些社区成员提供了他们配置的清理版本(即:不包含 API 密钥/密码)供查看。您可以在 GitHub 上的示例配置列表 中查看。

由于代码并不总是有注释,请继续阅读以详细了解配置文件的结构方式。

分析配置文件

在本节中,我们将使用一些示例配置文件,并更详细地了解它们的结构和格式。

现在您可能认为 configuration.yaml 在拆分过程中会被替换。然而,它实际上会保留下来,只是以一种更加简洁的形式。

核心配置文件

在这个精简版本中,我们仍然需要所谓的核心片段:

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, 'us_customary' for US Customary
  unit_system: us_customary
  # Pick yours from here: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
  time_zone: "America/Los_Angeles"
  customize: !include customize.yaml

缩进、包含、注释和模块化

请注意,homeassistant: 之后的每一行都缩进两个空格。由于 Home Assistant 中的配置文件基于 YAML 语言,缩进和间距很重要。还要注意 customize: 下面那个看似奇怪的条目。

!include customize.yaml 是告诉 Home Assistant 在该位置插入 customize.yaml 解析内容的语句。被包含文件的内容必须是 YAML 数据,并且在其包含位置有效。这就是我们将一个庞大且难以阅读的文件(当它变大时)拆分成更易于管理的块的方法。

现在,在我们开始拆分不同组件之前,让我们看看将保留在基础文件中的其他集成(在我们的示例中):

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

ifttt:
  key: ["nope"]

mqtt:
  sensor:
    - name: "test sensor 1"
      state_topic: "test/some_topic1"
    - name: "test sensor 2"
      state_topic: "test/some_topic2"

与核心片段一样,缩进很重要:

  • 集成标题(mqtt:)应该完全左对齐(即没有缩进)。
  • 键(sensor:)应该缩进两个空格。
  • sensor 下面的列表 - 应该再缩进两个空格,后跟一个空格。
  • mqtt 传感器列表包含两个配置,每个配置有两个键。

注释

符号(井号/磅号)表示"注释",就命令解释而言。换句话说,任何以 # 为前缀的行都会被软件忽略。它仅供人类阅读。注释允许将文件分解以提高可读性,以及在保留条目的同时关闭功能。

模块化和粒度

虽然这些集成中的某些在技术上可以移动到单独的文件中,但它们太小或是"一次性的",拆分它们是多余的。

现在,假设在 Home Assistant 配置目录中已经为以下每个创建了一个空白文件:

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

automation.yaml 将保存所有自动化集成详细信息。zone.yaml 将保存区域集成详细信息,依此类推。这些文件可以随意命名,但给它们起与其功能匹配的名称将使事情更容易跟踪。

在基础配置文件中,添加以下条目:

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

!include 语句和包用于拆分文件

嵌套 !include 语句(在被 !include 的文件中使用 !include)也可以工作。

某些集成支持多个顶级 !include 语句。这包括定义 IoT 域的集成。例如,lightswitchsensor;以及 automationscripttemplate 集成,如果您给每个集成一个不同的标签。

其他集成的配置可以使用包进行拆分。要了解更多信息,请参阅页面。

顶级键

light 平台的多个顶级键示例。

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

其中 light-groups.yaml 可能如下所示:

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

light-switches.yaml 包含:

- platform: switch
  name: "Patio Lights"
  entity_id: switch.patio_lights
  
- platform: switch
  name: "Floor Lamp"
  entity_id: switch.floor_lamp_plug

好了,现在基础文件中已经有了单个集成和 !include 语句,那么那些额外的文件里该放什么呢?

让我们看看示例中的 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

这个小例子说明了"拆分"文件是如何工作的。在这种情况下,我们从两个设备追踪器条目(owntracksnmap)开始。这些文件遵循 "样式 1",即完全左对齐的前导条目(- platform: owntracks),后跟缩进两个空格的参数条目。

这个(大型)传感器配置为我们提供了另一个示例:

### 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: ""
  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: ""
  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"

您会注意到这个示例包含一个次要参数部分(在 steam 部分下),以及注释如何用于将文件分解为部分的更好示例。

以上所有内容都可以在使用包拆分文件时应用。要了解更多信息,请参阅页面。

这差不多就是全部内容了。

如果您遇到问题,请检查文件缩进并检查 Home Assistant 日志。如果所有方法都失败了,请前往我们的 Discord 聊天服务器 并提问。

调试配置文件

如果您有许多配置文件,Home Assistant 提供了一个 CLI,允许您查看它如何解析这些文件。每种安装类型在常见任务中都有自己的章节:

高级用法

我们提供四个高级选项来一次包含整个目录。请注意,您的文件必须具有 .yaml 文件扩展名;不支持 .yml

这将允许您从 .yaml 文件中 !include 具有 .yml 扩展名的文件;而这些 .yml 文件不会被以下命令本身导入。

  • !include_dir_list 将目录内容作为列表返回,每个文件内容作为列表中的一个条目。列表条目根据文件名的字母数字顺序排序。
  • !include_dir_named 将目录内容作为字典返回,映射文件名 => 文件内容。
  • !include_dir_merge_list 将目录内容作为列表返回,通过将所有文件(应该包含列表)合并为一个大列表。
  • !include_dir_merge_named 将目录内容作为字典返回,通过加载每个文件并将其合并为一个大字典。

这些操作是递归的。例如,使用 !include_dir_list automation,将包含下面显示的所有 6 个文件:

.
└── .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 (not included)

示例:!include_dir_list

configuration.yaml

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

可以转换为:

configuration.yaml

automation: !include_dir_list automation/presence/

automation/presence/automation1.yaml

alias: "Automation 1"
triggers:
  - trigger: state
    entity_id: device_tracker.iphone
    to: "home"
actions:
  - action: light.turn_on
    target:
      entity_id: light.entryway

automation/presence/automation2.yaml

alias: "Automation 2"
triggers:
  - trigger: state
    entity_id: device_tracker.iphone
    from: "home"
actions:
  - action: light.turn_off
    target:
      entity_id: light.entryway

需要注意的是,使用 !include_dir_list 时,每个文件必须只包含一个条目。

示例:!include_dir_named

configuration.yaml


alexa:
  intents:
    LocateIntent:
      actions:
        action: notify.pushover
        data:
          message: "Your location has been queried via Alexa."
      speech:
        type: plaintext
        text: >
          
            
               is at 
            
          
            I am sorry. Pootie! I do not know where  is.
          
    WhereAreWeIntent:
      speech:
        type: plaintext
        text: >
          
            iPhone is home.
          
            iPhone is not home.
          

可以转换为:

configuration.yaml

alexa:
  intents: !include_dir_named alexa/

alexa/LocateIntent.yaml


actions:
  action: notify.pushover
  data:
    message: "Your location has been queried via Alexa."
speech:
  type: plaintext
  text: >
    
      
         is at 
      
    
      I am sorry. Pootie! I do not know where  is.
    

alexa/WhereAreWeIntent.yaml


speech:
  type: plaintext
  text: >
    
      iPhone is home.
    
      iPhone is not home.
    

示例:!include_dir_merge_list

configuration.yaml

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

可以转换为:

configuration.yaml

automation: !include_dir_merge_list automation/

automation/presence.yaml

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

需要注意的是,使用 !include_dir_merge_list 时,您必须在每个文件中包含一个列表(每个列表项用连字符 [-] 表示)。每个文件可以包含一个或多个条目。

示例:!include_dir_merge_named

configuration.yaml

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

可以转换为:

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

示例:结合 !include_dir_merge_listautomations.yaml

您想以更高级的方式拆分自动化,但仍希望能够在 UI 中创建自动化? 在上面的章节中,我们介绍了嵌套 !include。下面是如何为自动化实现这一点。

使用像 manualui 这样的标签,可以在配置中使用多个键:

configuration.yaml


# My own handmade automations
automation manual: !include_dir_merge_list automations/

# Automations I create in the UI
automation ui: !include automations.yaml