替换
ESPHome 有一种强大的方式来减少配置文件中的重复:替换。 通过替换,你可以为同一种类的节点维护一个通用的源文件,并在需要时替换相应的表达式。
substitutions: bme280_temperature_offset: "-1.0"
sensor: - platform: bme280_i2c temperature: name: BME280 Temperature filters: - offset: ${bme280_temperature_offset}在顶层的 substitutions 部分,你可以放入任意数量的键值对。在验证配置之前,ESPHome 会自动将所有出现的替换替换为其值。替换的语法基于 bash,且区分大小写:$substitution_key 或
${substitution_key}(二者相同)。
替换变量可以是任何有效的 YAML 类型,例如:
substitutions: device: name: Kitchen AC port: 12 enabled: true color: "yellow" unused_pins: [12, 23, 27]会执行两次替换,从而实现复合替换:
substitutions: foo: yellow bar_yellow_value: !secret yellow_secret bar_green_value: !secret green_secret
something: test: ${bar_${foo}_value}支持上述写法是为了向后兼容。建议从现在起使用键值字典:
substitutions: foo: yellow bar: yellow: !secret yellow_secret green: !secret green_secret
something: test: ${bar[foo]}Jinja 表达式
Section titled “Jinja 表达式”可以在 ${ ... } 语法中使用简单的 Jinja 表达式和过滤器。
所有替换变量都会通过其名称在 Jinja 表达式中可访问。
如果替换变量是键值字典,你可以用点表示法访问其成员:${ device.name },
或索引 ${ device["name"] }。
列表可以索引:${ unused_pins[2] }
substitutions: native_width: 480 native_height: 320 high_dpi: true scale: 1.5 sensor_pin: number: 3 inverted: true debug_label: width: 200 height: 20 enabled: true
display: - platform: ili9xxx dimensions: width: ${native_width * 2 if high_dpi else native_width} height: ${native_height * 2 if high_dpi else native_height}
lvgl: widgets: - label: id: debug_info hidden: ${not debug_label.enabled} width: ${ (debug_label.width * scale) | round | int } height: ${ (debug_label.height * scale) | round | int } text: | High DPI is ${high_dpi and "enabled" or "disabled"}.
binary_sensor: - platform: gpio name: Binary sensor on pin ${sensor_pin.number} pin: ${sensor_pin}请注意,在其他项目中 Jinja 使用 {{ ... }} 语法作为表达式分隔符。
在 ESPHome 中,我们已经将 Jinja 配置为使用 ${...},因此它与
现有的替换语法相同,并且可以避免与 Home Assistant 自身对 Jinja 的使用产生冲突。
要了解可以使用哪些类型的表达式和过滤器, 请参阅 Jinja 表达式 文档。
除了 Jinja 的 +、-、*、/ 等原生运算符外,Python 的 math
库作为模块暴露出来:
substitutions: x: 20 y: 50lvgl: widgets: - label: x: $x y: $y text: Distance is ${math.sqrt(x*x+y*y)}.要查看可用的数学函数,请参阅 Python math 库 文档。
除了 Jinja 表达式,ESPHome 还支持若干可在替换中使用的内置函数。
ord返回给定字符的 Unicode 码点。示例:ord("A") == 65chr返回给定 Unicode 码点对应的字符。示例:chr(65) == "A"len返回字符串的长度。示例:len("Hello") == 5
禁用 Jinja 和替换
Section titled “禁用 Jinja 和替换”你可以通过在任何值前面使用 !literal 标签来阻止 ESPHome 替换变量或处理 Jinja:
substitutions: value: "Test Value"lvgl: widgets: - label: text: !literal "This is a ${value}"在上面的示例中,text 属性的值将字面地为 This is a ${value}。
替换 !include 变量
Section titled “替换 !include 变量”ESPHome 的 !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: 2on-multi-click.yaml:
- timing: !include click-single.yaml then: - mqtt.publish: topic: ${device_name}/button${id}/status payload: single- timing: !include click-double.yaml then: - mqtt.publish: topic: ${device_name}/button${id}/status payload: double你还可以使用替换来构造要包含的文件名:
substitutions: platform: esp32
binary_sensor: - platform: gpio id: button1 pin: GPIOXX on_multi_click: !include { file: on-multi-click-${platform}.yaml, vars: { id: 1 } } - platform: gpio id: button2 pin: GPIOXX on_multi_click: !include file: on-multi-click-${platform}.yaml vars: id: 2ESPHome 会在加载文件之前展开文件名中的替换,因此上例中的 on-multi-click-${platform}.yaml
会解析为 on-multi-click-esp32.yaml。任何替换表达式——包括
Jinja 表达式——都可以使用。
你可以通过添加带有 KEY 和 VALUE 参数的 -s 开关,从命令行定义或覆盖替换。这将覆盖替换 KEY 并为其赋值 VALUE。该开关可以多次使用。考虑以下 example.yaml 文件:
substitutions: name: my_default_name
esphome: name: $name…以及以下命令:
esphome -s name my_device01 config example.yaml你将得到类似以下的输出:
substitutions: name: my_device01
esphome: name: my_device01 # ...命令行替换优先于配置文件中的替换。这可用于创建通用的
“模板” 配置文件(如上例中的 example.yaml),多个设备可以共用它们,并在命令行提供
替换。
附赠:YAML 插入运算符
Section titled “附赠:YAML 插入运算符”此外,你可以使用 YAML 插入运算符 << 语法,创建一个 YAML 文件,从中派生多个节点:
# 在 common.yaml 中esphome: name: $devicename # ...
sensor: - platform: dht # ... temperature: name: Temperature humidity: name: Humidity# 在 nodemcu1.yaml 中substitutions: devicename: nodemcu1
<<: !include common.yamlNOTE
不支持在 YAML 插入运算符(<<: !include)的 !include 文件名中使用替换。
TIP
若要从仪表板中隐藏这些基础文件,你可以
- 将它们放入子目录中(仪表板只显示顶层目录中的文件)
- 在文件名前加一个点,例如
.base.yaml