跳转到内容

ESPHome 中的 YAML 配置

ESPHome 配置文件使用 YAML,这是一种人类友好的数据序列化标准。本页面解释了标准 YAML 特性和 ESPHome 特定的扩展。

YAML 的设计目标是易于阅读和编辑,但也可能令人沮丧,特别是在缩进方面。YAML 是 JSON 的超集,JSON 语法可以在 YAML 文件中使用。

ESPHome YAML 文件中配置块的顺序通常不重要,因为在任何验证或处理之前会读取全部内容。

  • 注释: # 后的任何文本都是注释。
  • 标量: 字符串、数字、布尔值。
  • 序列: 项目列表,使用 -[ ... ]
  • 映射: 键值对,使用 key: value{ ... }
  • 锚点和别名: 使用 &anchor*alias 重用 YAML 块。
  • 多行字符串: 使用 |> 处理多行文本。

YAML 注释是 # 符号后的任何文本,延伸到行尾。如果需要在字符串中包含 # 字符,必须将其放在引号内。

示例:

# 这是一个注释
foo:
bar: 3 # 这是另一个注释
text: "# 可以包含在字符串中"

YAML 标量是任何不包含冒号 (:) 的值。它可以是字符串、数字、布尔值或 null。

字符串用双引号 (") 或单引号 (') 括起。标准转义序列(如换行符 \n 和 Unicode 码点)仅在双引号内被转换。字符串也可以是不带引号的字符序列,且不是有效的数字或布尔值,例如 23times 即使不加引号也会被视为字符串。字符串也可以是多行的,使用 |>

布尔值是 truefalse,不区分大小写。ESPHome 还将其他字符串映射为布尔值:

  • yesonenable 映射为 true
  • nooffdisable 映射为 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"

第一种情况没有额外缩进,而第二种情况有,这可能看起来很奇怪。区别在于第一种情况的序列项本身是一个映射,键为 platformname,而第二种情况的序列项是键 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” 是映射中的一个键,其值是另一个映射。第二个映射有键 platformpinnamedevice_classunit_of_measurementaccuracy_decimalsstate_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 的元数据,但第二个传感器覆盖了 pinname 值。

YAML 以几种不同的方式支持多行字符串。

用双引号 (") 或单引号 (') 括起的字符串可以跨行。注意事项:

  • 后续行上的前导空格被忽略;
  • 可以通过留空行来插入换行符;
  • \n 这样的转义序列仅在双引号内被转换;

一般而言,下面描述的块字符串比引号多行字符串更可取。

示例:

sensor: # 此传感器的名称将是 "Sensor Name"
- platform: template
name: "Sensor
Name"

块字符串是由特殊字符序列引入的多行字符串,所有缩进大于引入字符串的键的后续行都被视为字符串的一部分。块字符串标记有三个部分:

  • 块样式指示符(|>)(必需)
  • 截断指示符(-+)(可选)
  • 缩进值(数字,可选)

块样式控制如何处理嵌入的换行符 - 当使用 |(字面)样式时,嵌入的换行符被保留,而当使用 >(折叠)样式时,嵌入的换行符被折叠成单个空格。

截断指示符控制字符串末尾的处理方式:

  • 无截断指示符:以单个换行符结束字符串
  • -:删除所有尾随换行符;
  • +:保留所有尾随换行符。

缩进值指定在每行开头插入多少空格。它是可选的,默认缩进将从第一行文本推断,因此通常不需要使用它。

在 ESPHome 中,您最常使用 |- 样式,它将保留内部换行符并删除尾随换行符。

示例:

multiline_string: |-
这是一个跨多行的
字符串。内部换行符
将被保留,尾随换行符将被删除。
some_other_key: # 这不是字符串的一部分

ESPHome 在标准 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: 特性允许您定义可在整个配置中引用的可重用值。有关完整详情,请参阅替换

  • 在此位置插入另一个 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: 特性允许您定义可重用且可能是部分的配置,这些配置可以包含在您的主配置中。数据与主配置合并,主配置中的值优先于包数据中的值。

有关更多详情,请参阅

任何以点 (.) 开头的顶级配置键将被忽略,不会包含在最终配置中。这主要用于定义不属于配置的锚点。

.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"

隐藏键名并不重要,实际上可以只是一个点,但建议使用更具描述性的名称。

在 ESPHome 配置文件中,可以嵌入 lambda,即在运行时评估的 C++ 代码块,用于提供动态值和实现 YAML 中无法实现的逻辑。使用 !lambda 标签定义 lambda。有关更多信息,请参阅模板