跳转到内容

当您有许多 ESPHome 设备(或正在大规模生产和分发它们)时,一个常见的需求会浮现出来:配置模块化。您可能希望将配置拆分为通用(组)元素,将其构建成可重复使用的部分,然后可以被许多/所有设备使用。只有配置的唯一部分保留在任何给定设备的 YAML 配置文件中。

这可以通过 ESPHome 的 packages 功能实现。

包中的所有定义将以非破坏性的方式与设备的主配置合并。这允许覆盖包中包含的(部分)配置。主配置中的替换将覆盖包中同名的替换。

字典按键合并。组件列表按组件 ID(如果指定)合并。其他列表通过连接合并。所有其他配置值替换为后面的值。

ESPHome 使用 !include 从其他文件”引入”包;此功能在 !include 中描述。

packages: 键的值可以是:

  • 有效包引用的列表
  • 键到包引用的映射。使用映射时,键仅用于参考,本身没有意义。

所有格式的示例如下所示。

考虑以下示例,作者将通用配置片段(如 Wi-Fi 和 API)放入基础文件,然后在主配置中使用一些设备特定的配置进行扩展。

注意 device_base.yaml 中描述 api 组件的配置片段如何与主配置文件中的动作定义合并。

# 在 config.yaml 中
packages: # 作为列表
- !include common/wifi.yaml
- !include common/device_base.yaml
api:
actions:
- action: start_laundry
then:
- switch.turn_on: relay
# 任何额外的配置...
# 在 wifi.yaml 中
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# 在 device_base.yaml 中
esphome:
name: ${node_name}
esp32:
board: wemos_d1_mini32
logger:
api:
encryption:
key: !secret api_encryption_key

包也可以通过使用正确的配置语法从 Git 仓库加载。 替换 可以在远程包中使用,允许用户使用自己的替换值在本地覆盖它们。

NOTE

远程包中不能有 secret 查找。它们应该使用带有可选默认值的替换在打包的 YAML 中,本地设备 YAML 可以使用本地密钥中的值进行设置。

# Git 仓库示例作为映射
packages:
# 简写形式 github://username/repository/[folder/]file-path.yml[@branch-or-tag]
remote_package_shorthand: github://esphome/non-existant-repo/file1.yml@main
remote_package_files:
url: https://github.com/esphome/non-existant-repo
files: [file1.yml, file2.yml] # 可选;如果未指定,将包含所有文件
ref: main # 可选
refresh: 1d # 可选
remote_package_files2:
url: https://github.com/esphome/non-existant-repo
files:
- path: file1.yml
vars:
a: 1
b: 2
- path: file1.yml #同一文件可以用不同的 vars 指定多次。
vars:
a: 3
b: 4
- file2.yml
ref: main # 可选
refresh: 1d # 可选

对于每个包:

  • url (Required, string): 仓库的 URL。

  • path (Optional, string): 包含文件的基础公共路径。

  • username (Optional, string): 用于认证的用户名(如果需要)。

  • password (Optional, string): 用于认证的密码(如果需要)。

  • files (Required): 要包含的文件列表。可以是以下之一:

    • 文件路径列表
    • 包含 pathvars 的对象列表
  • ref (Optional, string): 从仓库拉取内容时要使用的 Git 引用。

  • refresh (Optional, Time): 仓库内容应该刷新的间隔。

由于包是使用 !include 系统合并的,可以为其提供变量。这意味着包可以用作模板,允许将复杂或重复的配置存储在包文件中,然后多次合并到配置中。

包还可以包含一个 defaults 块,为 !include 块未提供的变量提供替换。

例如,如果配置需要使用 gpio 开关平台和 time_based 盖板平台支持三个车库门,可以这样构建:

# 在 config.yaml 中
packages:
left_garage_door: !include
file: garage-door.yaml
vars:
door_name: Left
middle_garage_door: !include
file: garage-door.yaml
vars:
door_name: Middle
right_garage_door: !include
file: garage-door.yaml
vars:
door_name: Right
# 在 garage-door.yaml 中
switch:
- name: ${door_name} 车库门开关
platform: gpio
# ...

您可以根据条件包含包,或通过使用 !include 将包加载到替换变量而不是 packages 下动态选择包:

# 在 config.yaml 中
substitutions:
left_garage_door: !include
file: garage-door.yaml
vars:
door_name: Left
enable_extra_door: true
packages:
extra_door: ${ left_garage_door if enable_extra_door else {} }

上面使用 Jinja 表达式 来确定是否实际包含 left_garage_door 包。enable_extra_door 也可以从 命令行 设置。

要对包含的配置进行更改或添加额外配置,可以使用 !extend config_id,其中 config_id 是要修改的配置的 ID。

例如,要在配置之间共享的通用运行时间传感器上设置特定的更新间隔:

# 在 common.yaml 中
captive_portal:
sensor:
- platform: uptime
id: uptime_sensor
update_interval: 5min
packages:
- !include common.yaml
sensor:
- id: !extend uptime_sensor
update_interval: 10s

也支持 LVGL 样式的配置层次结构:

# 在 interface.yaml 中
lvgl:
pages:
- id: main_page
widgets:
- label:
id: title_label
text: "主页"
packages:
- !include interface.yaml
lvgl:
pages:
- id: !extend main_page
widgets:
- label:
id: !extend title_label
text: "新标题"
text_color: red

!extend 也适用于替换和 jinja:

substitutions:
switches:
- left_switch
- right_switch
- center_switch
mains_switch: 1
switch:
- platform: gpio
id: left_switch
pin: 1
- platform: gpio
id: right_switch
pin: 2
- platform: gpio
id: center_switch
pin: 3
- id: !extend ${ switches[mains_switch] }
name: "主开关"

要从包含的配置中删除现有条目,可以使用 !remove [config_id],其中 config_id 是要修改的条目的 ID。

例如,要删除配置之间共享的通用运行时间传感器:

packages:
- !include common.yaml # 见上文
sensor:
- id: !remove uptime_sensor

删除 LVGL 样式配置中的项目:

packages:
- !include interface.yaml # 见上文
lvgl:
pages:
- id: !extend main_page
widgets:
- label:
id: !remove title_label

为特定设备删除强制门户:

packages:
- !include common.yaml # 见上文
captive_portal: !remove

仅为特定设备删除属性:

packages:
common: !include common.yaml # 见上文
sensor:
- id: !extend uptime_sensor
update_interval: !remove

!remove 也适用于替换:

substitutions:
disable_reboot: true
switch:
- platform: restart
id: restart_switch
name: "客厅重启"
- id: !remove ${disable_reboot and "restart_switch"}