模板
模板(也称为 lambda)允许你在 ESPHome 中执行几乎任何操作。例如,如果你只想在某个复杂公式评估为 true 时才执行某个自动化,你可以使用模板来实现。让我们先看一个例子:
binary_sensor: - platform: gpio name: "Cover End Stop" id: top_end_stopcover: - 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 的新手,“cover”指的是像百叶窗、卷帘门或车库门之类的东西。)模板遮帘的状态由模板或”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 的其他功能未按预期工作,最好的办法是查看 <NODE_NAME>/src/main.cpp 下生成的 C++ 源文件。
TIP
要在 lambda 中存储跨执行保持值的局部变量,你可以创建 static 变量,如下例所示。此处,变量 num_executions 在每次执行 lambda 时递增一,并记录当前值。
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 |- // The sensor outputs values from 0 to 100. The blue // part of the light color will be determined by the sensor value. return id(some_sensor).state / 100.0;当你在某个动作的文档中看到”templatable”(可模板化)标签时,表示该参数可以像本例一样使用上述 lambda 语法进行模板化。