模板

模板(也称为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_OPENCOVER_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 语法进行模板化。

所有 Lambda 调用

参考文档