YAML 配置文件中的 ESPHome
概述
ESPHome 配置文件使用 YAML,这是一种人类友好的数据序列化标准。本页面解释了标准 YAML 功能和 ESPHome 特有的扩展。
YAML 设计为易于阅读和编辑,但在处理缩进时也可能令人沮丧。YAML 是 JSON 的超集,因此 JSON 语法可以用于 YAML 文件。
ESPHome YAML 文件中的配置块的顺序通常不重要,因为整个内容将在任何验证或处理之前被读取。
标准YAML功能
- 注释: 任何以
#
开头的文本都是注释。 - 标量: 字符串、数字、布尔值。
- 序列: 列表项,使用
-
或[ ... ]
。 - 映射: 键值对,使用
key: value
或{ ... }
。 - 锚点和别名: 使用
&anchor
和*alias
重用 YAML 块。 - 多行字符串: 使用
|
或>
表示多行文本。
注释
YAML 注释是任何以 #
符号开头的文本,延伸到行尾。如果你需要在字符串中包含 #
字符,它必须出现在引号内。
示例:
# 这是一个注释
foo:
bar: 3 # 这是另一个注释
text: "# 可以包含在字符串中"
标量
YAML 标量是任何不包含冒号(:
)的值。它可以是字符串、数字、布尔值或空值。
字符串用双引号("
)或单引号('
)括起来。标准转义序列(如换行符 \n
和 Unicode 代码点)仅在双引号内被转换。字符串也可以是非引号的字符序列,它不是有效的数字或布尔值,例如 23times
即使未加引号也会被视为字符串。字符串也可以是多行的,使用 |
或 >
。
布尔值是 true
或 false
,不区分大小写。ESPHome 还将其他字符串映射到布尔值:
yes
、on
和enable
映射为true
。no
、off
和disable
映射为false
。
数值是整数或浮点数。在 ESPHome 中,在大多数需要数字的地方,它也可以写为包含整数或浮点数的字符串,这将自动转换。
示例:
esp8266:
board: esp8285 # esp8285 是一个字符串
restore_from_flash: true # 布尔值
web_server:
port: 80 # 整数值
序列
YAML 序列是一个列表(或数组),使用 -
或 [ ... ]
。项可以是标量、序列或映射。每个序列项使用 -
标志,而 JSON 风格的 [ ... ]
可以在一行中,或跨多行。
示例:
# JSON 风格
data_pins: [48, 47, 39, 40]
# YAML 风格
data_pins:
- 48
- 47
- 39
- 40
sensors:
# 一系列传感器,每个都是映射
- platform: gpio
name: "Temperature 1"
pin: GPIO32
- platform: gpio
name: "Temperature 2"
pin: GPIO33
YAML 格式的序列有时会让人困惑 - 考虑以下示例:
- platform: gpio
name: "Temperature 1"
- label:
text: "Temperature 1"
看起来第一个例子中没有额外的缩进,而第二个例子中有。区别在于第一个例子中的序列项本身是一个映射,有 platform
和 name
键,而第二个例子中的序列项是一个键 label
,其值为一个映射,键为 text
,值为 "Temperature 1"
。将这些重写为 JSON 格式可以更清楚地理解:
- {
"platform": "gpio",
"name": "Temperature 1"
}
- {
"label": {
"text": "Temperature 1"
}
}
一个有用的经验法则是,无论序列项以冒号结尾的地方,其值必须是映射,而不是标量,因此它需要进一步缩进来表示后续行,这个例子是错误的,并且会抛出两个错误:
- label: # 会抛出错误 "expected a dictionary"
text: "Temperature 1" # 错误!应该缩进。会抛出错误 "text is an invalid option for ..."
映射
YAML 映射是一系列键值对,使用 key: value
或 { ... }
。键可以是任何有效的 YAML 标量(尽管它们通常会被限制为预定义集中的字符串),而值可以是任何有效的 YAML 标量、列表或映射。映射也可以称为字典、关联数组或哈希表。单个映射中使用的键必须是唯一的。
示例:
sensor:
platform: gpio
pin: GPIO32
name: "Temperature 1"
device_class: temperature
unit_of_measurement: "°C"
accuracy_decimals: 1
state_class: measurement
在上面的示例中,“sensor”是一个映射中的键,其值是另一个映射。第二个映射有 platform
、pin
、name
、device_class
、unit_of_measurement
、accuracy_decimals
和 state_class
键。
当映射值是一个序列时,它应该在键之后缩进,但 YAML 在缩进错误方面很宽容,例如:
widgets:
- label:
text: Temperature 1
- label:
text: Temperature 2
注意,序列标记 -
在映射键 widgets
下 不 缩进。这在技术上是不正确的,但 YAML 解析器会正确解释。建议你坚持正确的格式,但如果你在 YAML 文件中看到这种情况,要知道它确实有效 - 它在复杂的配置中限制缩进深度时非常有用。
锚点、别名和覆盖值
YAML 锚点(&anchor
)和别名(*alias
)允许你定义一个配置块并在其他地方重用它。这对于重复元数据字段特别有用。
你还可以在合并时覆盖特定值,使用 <<: *anchor
:
sensor:
- &common_adc
pin: GPIO32
platform: adc
name: "Temperature 1"
device_class: temperature
unit_of_measurement: "°C"
accuracy_decimals: 1
state_class: measurement
- <<: *common_adc
pin: GPIO33
name: "Temperature 2"
在这个示例中,两个传感器共享 common_adc
的元数据,但第二个传感器覆盖了 pin
和 name
值。
多行字符串
YAML 支持多种格式的多行字符串。
引用多行字符串
用双引号("
)或单引号('
)引用的字符串可以跨多行。注意:
- 后续行的前导空白被忽略;
- 可以通过留空行插入换行符;
- 转义序列如
\n
仅在双引号内被转换;
通常来说,下面描述的块字符串比引用的多行字符串更可取。
示例:
sensor: # 这个传感器的名称将是 "Sensor Name"
- platform: template
name: "Sensor
Name"
块字符串
块字符串是以特殊字符序列引入的多行字符串,后续所有缩进大于引入字符串的键的行都被视为字符串的一部分。 块字符串标记有三部分:
- 块风格指示器(
|
或>
)(必需) - 塞切指示器(
-
或+
)(可选) - 缩进值(一个数字,可选)
块风格控制嵌入换行符的处理方式 - 使用 |
(字面)风格时,嵌入换行符被保留,而使用 >
(折叠)风格时,嵌入换行符被折叠成一个空格。
塞切指示器控制字符串末尾的处理方式:
- 无塞切指示器:以单个换行符结束字符串
-
:删除所有尾随换行符;+
:保留所有尾随换行符。
缩进值指定每行开头要插入多少空格。它是可选的,默认缩进将根据文本的第一行猜测,因此通常不需要使用它。
在 ESPHome 中,你通常使用 |-
风格,它将保留内部换行符并删除尾随换行符。
示例:
multiline_string: |-
这是一个跨多行分割的字符串。内部换行符将被保留,尾随换行符将被删除。
some_other_key: # 这不是字符串的一部分
ESPHome YAML 扩展
ESPHome 在标准 YAML 中添加了几个非标准但非常有用的功能:
密码和 secrets.yaml
文件
!secret
标签允许你引用存储在单独的 secrets.yaml
文件中的敏感值(如密码或 API 密钥)。当你希望能够在分发配置文件时而不泄露你的秘密时,这特别有帮助。
ℹ️ Important
为了保护你的秘密,secrets.yaml
文件不应提交到 git 或任何其他版本控制系统。
示例:
wifi:
ssid: "MyWiFi"
password: !secret wifi_password
并在你的 secrets.yaml
中:
wifi_password: my_super_secret_password
秘密文件必须只包含键到标量值的平面映射。
替换
substitutions:
功能允许你定义可在整个配置中引用的可重用值。有关详细信息,请参阅 Substitutions
!include
- 在此位置插入另一个 YAML 文件的内容。
- 可以用于配置的任何级别,并在该级别进行替换。
- 除非与
packages:
(见下文)一起使用,否则插入是字面的。 - 可以在包含文件中使用替换来引用传递给
!include
的值。此类值将覆盖任何全局替换,因此全局替换可用于提供默认值。
示例:
binary_sensor:
- platform: gpio
id: button1
pin: GPIOXX
on_multi_click: !include { file: on-multi-click.yaml, vars: { id: 1 } } # 内联语法
- platform: gpio
id: button2
pin: GPIOXX
on_multi_click: !include
# 多行语法
file: on-multi-click.yaml
vars:
id: 2
包
packages:
功能允许你定义可重用且可能是部分配置,可以包含在你的主配置中。数据与主配置合并,主配置中的值优先于包数据中的值。
有关更多详细信息,请参阅 Packages。
隐藏项
任何以点(.
)开头的顶级配置键都将被忽略,并且不会包含在最终配置中。这主要用于定义不是配置一部分的锚点。
.number: &AnchorNumber # 定义一个锚点,但排除它
optimistic: true
min_value: 0
max_value: 600
step: 1
initial_value: 0
number:
- platform: template
<<: *AnchorNumber # 包含之前定义的锚点
id: "SwitchMainDelay"
name: "Main Switch Delay"
隐藏键的名称并不重要,实际上可以只是一个点,但建议使用更具描述性的名称。
Lambda
在 ESPHome 配置文件中,可以嵌入 lambda,它们是 C++ 代码块,在运行时被评估,以提供动态值并实现 YAML 中不可能实现的逻辑。lambda 使用 !lambda
标签定义。有关更多信息,请参阅 模板。