跳转到内容

替换

ESPHome 有一种强大的方式来减少配置文件中的重复:替换。 使用替换,您可以为所有同类节点提供单个通用源文件,并根据需要替换表达式。

substitutions:
bme280_temperature_offset: "-1.0"
sensor:
- platform: bme280_i2c
temperature:
name: BME280 温度
filters:
- offset: ${bme280_temperature_offset}

在顶级 substitutions 部分,您可以根据需要放置任意数量的键值对。在验证您的配置之前,ESPHome 将自动用其值替换所有出现的替换。替换的语法基于 bash 并区分大小写:$substitution_key${substitution_key}(相同)。

替换变量可以是任何有效的 YAML 类型,例如:

substitutions:
device:
name: 厨房空调
port: 12
enabled: true
color: "黄色"
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 表达式和过滤器可以在 ${ ... } 语法中使用。

所有替换变量都可以在 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: |
高 DPI ${high_dpi and "已启用" or "已禁用"}。
binary_sensor:
- platform: gpio
name: 引脚 ${sensor_pin.number} 上的二值传感器
pin: ${sensor_pin}

请注意,在其他项目中,Jinja 使用 {{ ... }} 语法作为表达式分隔符。 在 ESPHome 中,我们将 Jinja 配置为使用 ${...} 代替,因此它与现有的替换语法相同,并避免与 Home Assistant 自己使用 Jinja 冲突。

要了解可以使用哪些类型的表达式和过滤器,请参阅 Jinja 表达式 文档。

除了 Jinja 的原生运算符如 +-*/、… Python 的 math 库作为模块暴露:

substitutions:
x: 20
y: 50
lvgl:
widgets:
- label:
x: $x
y: $y
text: 距离是 ${math.sqrt(x*x+y*y)}。

要查看有哪些数学函数可用,请参阅 Python math 库 文档。

除了 Jinja 表达式,ESPHome 还支持许多可在替换中使用的内置函数。

  • ord 返回给定字符的 Unicode 码点。示例:ord("A") == 65
  • chr 返回给定 Unicode 码点的字符。示例:chr(65) == "A"
  • len 返回字符串的长度。示例:len("Hello") == 5

您可以通过在任何值之前使用 !literal 标签来防止 ESPHome 替换变量或处理 Jinja:

substitutions:
value: "测试值"
lvgl:
widgets:
- label:
text: !literal "这是一个 ${value}"

在上面的示例中,text 属性的值将是,字面上的,这是一个 ${value}

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: 2

on-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

您可以通过添加带有参数 KEYVALUE-s 开关从命令行定义或覆盖替换。这将覆盖替换 KEY 并为其分配值 VALUE。此开关可以多次包含。考虑以下 example.yaml 文件:

substitutions:
name: my_default_name
esphome:
name: $name

…以及以下命令:

Terminal window
esphome -s name my_device01 config example.yaml

您将获得类似以下的输出:

substitutions:
name: my_device01
esphome:
name: my_device01
# ...

命令行替换优先于配置文件中的替换。这可用于创建通用的”模板”配置文件(如上面的 example.yaml),可由多个设备使用,利用命令行提供的替换。

此外,您可以使用 YAML 插入运算符 << 语法创建一个多个节点继承的 YAML 文件:

# 在 common.yaml 中
esphome:
name: $devicename
# ...
sensor:
- platform: dht
# ...
temperature:
name: 温度
humidity:
name: 湿度
# 在 nodemcu1.yaml 中
substitutions:
devicename: nodemcu1
<<: !include common.yaml

TIP

要从仪表板隐藏这些基础文件,您可以

  • 将它们放在子目录中(仪表板仅显示顶级目录中的文件)
  • 在文件名前加上点,如 .base.yaml