模板
模板(也称为lambda)允许你在 ESPHome 中几乎做任何事情。例如,如果你想要只在某个复杂公式评估为真时执行某个自动化,你可以使用模板。让我们先看一个例子:
binary_sensor:
- platform: gpio
name: "Cover End Stop"
id: top_end_stop
cover:
- platform: template
name: Living Room Cover
lambda: !lambda |-
if (id(top_end_stop).state) {
return COVER_OPEN;
} else {
return COVER_CLOSED;
}
这里发生了什么?首先,我们定义了一个二进制传感器(特别注意使用 id: top_end_stop
),然后定义了一个
模板覆盖。(如果你是 Home Assistant 的新手,‘覆盖’类似于百叶窗、卷帘或车库门。)模板覆盖的状态由模板或 “lambda” 控制。在 lambda 中,你只是在编写 C++ 代码,因此使用 lambda 而不是 Home Assistant 的 “模板” 术语来避免混淆。无论如何,不要因为看到 “C++” 就害怕 lambda —— 编写 lambda 并不难!这里有一些基础知识:
首先,你可能已经想知道 lambda: !lambda |-
部分的含义是什么。!lambda
告诉 ESPHome 以下块应该是 lambda 或 C++ 代码的解释。注意,在这里,lambda:
键实际上会隐式地将以下块作为 lambda,因此在这种情况下,你也可以写成 lambda: |-
。
接下来,有奇怪的 |-
字符组合。这告诉 YAML 解析器将以下缩进块视为纯文本。没有它,YAML 解析器会尝试将以下块作为 YAML 键(如 cover:
)等读取。 (你可能还见过类似的变体,如 >-
或只是 |
或 >
。这些不同风格在处理空白时有轻微差异,但为了我们的目的,我们可以忽略这一点)。
使用 if (...) { ... } else { ... }
我们创建了一个条件。这实际上意味着如果第一个括号内的东西评估为 true
,则执行第一个块(在这种情况下是 return COVER_OPEN;
,否则评估第二个块。return ...;
使代码块返回值给模板。在这种情况下,我们返回 COVER_OPEN
或 COVER_CLOSED
来指示覆盖关闭或打开。
最后,id(...)
是一个辅助函数,使 ESPHome 获取具有指定 ID 的对象(你可以在其他地方定义,如 top_end_stop
),并允许你直接调用 ESPHome 的许多 API。例如,这里我们使用 .state
获取当前终端状态,并使用它来构建覆盖状态。
ℹ️ Note
ESPHome 不会检查你输入的 lambda 表达式的有效性,并将它们盲目地复制到生成的 C++ 代码中。如果编译失败或 lambda 出现其他问题,最好查看生成的 C++ 源文件<NODE_NAME>/src/main.cpp
。
✅ Tip
要在 lambda 中存储在执行之间保持其值的本地变量,你可以像示例中那样创建
static
变量。这里,变量num_executions
每次执行 lambda 时都会增加 1,并记录当前值。lambda: |- static int num_executions = 0; ESP_LOGD("main", "I am at execution number %d", num_executions); num_executions += 1;
模板操作
ESPHome 允许你模板自动化中使用的操作的大多数参数。例如,如果你有一个灯,并在按下按钮时将其设置为预定义颜色,你可以这样做:
on_press:
then:
- light.turn_on:
id: some_light_id
transition_length: 0.5s
red: 0.8
green: 1.0
blue: !lambda |-
// 传感器输出值从 0 到 100。灯光颜色的蓝色部分将由传感器值决定。
return id(some_sensor).state / 100.0;
当你在文档中看到某个操作的标签为 “templatable” 时,它就像这个例子一样,可以使用上面描述/显示的 lambda 语法进行模板化。