跳转到内容

原生 API 组件

ESPHome 原生 API 用于与客户端直接通信,采用高度优化的网络协议。目前,只有 ESPHome 工具、Home Assistant 和 ioBroker 使用此原生 API。

在 ESPHome 配置中添加 api: 行后,您可以进入 Home Assistant Web 界面,在”配置”面板中导航到”集成”页面。然后等待 ESPHome 设备出现在已发现部分(可能需要最多 5 分钟),或者通过在集成概览中选择”ESPHome”并在”主机”字段中输入”<NODE_NAME>.local”或设备的 IP 地址来手动添加设备。

ESPHome 原生 API 基于使用协议缓冲区的自定义 TCP 协议。您可以在以下位置找到协议数据结构定义:api.proto 实现此协议的 Python 库是 aioesphomeapi

NOTE

Actions 以前称为 Services。ESPHome 按照 Home Assistant 的命名进行了更改,但将继续支持使用 serviceshomeassistant.service 的 YAML 配置。 文档中将只提及 Actions

# 示例配置项
api:
# 带有更多选项的示例
api:
port: 6053
batch_delay: 50ms # 为实时应用降低延迟
listen_backlog: 2 # 允许队列中有 2 个待处理连接
max_connections: 6 # 允许最多 6 个同时连接
max_send_queue: 10 # 每个连接在断开前最大排队消息数
encryption:
key: "YOUR_ENCRYPTION_KEY_HERE"
reboot_timeout: 30min
  • port (Optional, int): API 服务器运行的端口。默认为 6053

  • listen_backlog (Optional, int): 监听队列中待处理连接的最大数量。必须在 1 到 10 之间。 ESP8266/RP2040 默认为 1,ESP32 和其他平台默认为 4。较低的值使用较少内存,但在高峰期可能会拒绝连接。

  • max_connections (Optional, int): 允许的最大同时 API 连接数。必须在 1 到 20 之间。 ESP8266/RP2040 默认为 4,ESP32 和其他平台默认为 8。每个连接大约使用 500-1000 字节的 RAM。

    NOTE

    每个 API 连接在连接时大约消耗 500-1000 字节的 RAM。ESP8266 和 RP2040 设备可用内存有限(ESP8266 启动后通常有约 40KB 的可用 RAM,但配置传感器和其他组件后可能降至 20KB 以下;RP2040 使用 LWIP 原始套接字,具有类似限制),因此请注意不要将此值设置过高,否则可能导致内存不足崩溃。 默认值旨在平衡内存使用与允许多个同时连接的需求。

  • max_send_queue (Optional, int): 每个连接在断开前可以排队发送的最大消息数。必须在 1 到 64 之间。 默认值:

    • ESP8266/RP2040 为 5
    • ESP32/BK72xx/LN882x/nRF52/RTL87xx 为 8
    • host 平台为 16

    这可以防止客户端缓慢或网络停滞时的内存耗尽。 每个排队消息大约使用 8-12 字节的开销加上消息大小。

    NOTE

    当连接的发送队列已满时,设备将记录错误并断开该客户端以防止内存不足崩溃。 缓慢的客户端、导致重试的 WiFi 连接不良或网络拥塞可能会触发此问题。如果合法客户端被断开,请增加此值,但要注意嵌入式设备的内存限制。

  • encryption (Optional): 如果存在,将为 API 启用加密。使用加密有助于保护 运行 ESPHome 的设备与连接的客户端之间的通信安全。

    • key (Optional, string): 用作加密密钥的 32 字节 base64 编码字符串。如果未提供, 密钥可以在运行时设置,但在设置之前不会使用加密

      如果您需要密钥,可以使用下面的密钥;每次加载此页面时,您的浏览器都会随机生成:

NOTE

即将推出的 Home Assistant 版本将支持动态配置加密密钥。

TIP

有关包括 API 加密最佳实践在内的全面安全指南,请参阅 安全最佳实践 指南。

  • actions (Optional, list): 用户定义的动作列表。参见 用户定义动作
  • batch_delay (Optional, Time): 批量处理多个状态更新消息的延迟时间, 以减少网络开销。较低的值会更快发送更新,但使用更多网络数据包, 而较高的值可以更高效地批量处理,但会增加延迟。必须在 0ms65535ms (65.535 秒)之间。默认为 100ms

NOTE

设置 batch_delay: 0ms 可启用状态更新的立即发送模式。这对于 需要实时响应的应用程序很有用,例如 IR 遥控二进制传感器,其中必须保留 快速的 ON→OFF 转换。但是,这会增加网络流量,并可能影响 有许多快速变化传感器时的 WiFi 性能。仅在必要时使用此设置。

  • custom_services (Optional, boolean): 为使用 C++ CustomAPIDevice 类的外部组件启用自定义 API 服务的编译。仅当外部组件通过原生 API 注册自己的服务时才需要。默认为 false

  • homeassistant_services (Optional, boolean): 为使用 C++ CustomAPIDevice::call_homeassistant_service()CustomAPIDevice::fire_homeassistant_event() 方法的外部组件启用 Home Assistant 服务调用支持的编译。当使用 homeassistant.servicehomeassistant.event 动作,或 homeassistant 平台的 number 或 switch 组件时会自动启用。仅当外部组件在不使用内置动作的情况下调用 Home Assistant 服务时才需要手动设置。默认为 false

  • homeassistant_states (Optional, boolean): 为使用 C++ CustomAPIDevice::subscribe_homeassistant_state() 方法的外部组件启用 Home Assistant 状态订阅支持的编译。当使用任何 homeassistant 平台组件(sensor、binary_sensor、text_sensor、switch 或 number)时会自动启用。仅当外部组件在不使用内置组件的情况下订阅 Home Assistant 状态时才需要手动设置。默认为 false

  • reboot_timeout (Optional, Time): 当没有客户端连接到 API 时,等待重新启动的时间。这是必需的,因为有时底层 ESP 函数报告 ESP 已连接到网络,但实际上并非如此 - 只有完全重启才能修复。 可以通过设置为 0s 来禁用。默认为 15min

  • id (Optional, ID): 手动指定用于代码生成的 ID。

  • on_client_connected (Optional, Action): 当客户端 连接到 API 时执行的自动化。参见 on_client_connected 触发器

  • on_client_disconnected (Optional, Action): 当客户端 从 API 断开时执行的自动化。参见 on_client_disconnected 触发器

在使用以下任何动作之前,您需要告诉 Home Assistant 允许您的设备执行动作。

NOTE

从 ESPHome 2025.10.0 开始,您可以配置动作以使用 capture_responseon_successon_error 接收和处理来自 Home Assistant 的响应。有关详细信息,请参阅 动作响应处理

在您的 Home Assistant 实例上打开 ESPHome 集成页面:

打开您的 Home Assistant 实例并显示 ESPHome 集成。

然后:

  1. 在设备列表中找到您的设备

  2. 点击其旁边的”配置”按钮

  3. 勾选”允许设备执行 Home Assistant 动作”复选框

  4. 然后点击”提交”

NOTE

请务必按照上述说明告诉 Home Assistant 允许您的设备执行动作。

使用原生 API 与 Home Assistant 时,您可以直接从 ESPHome 自动化在 Home Assistant 事件总线中创建事件。

# 在某个触发器中
on_...:
# 简单示例
- homeassistant.event:
event: esphome.button_pressed
data:
message: 按钮被按下
  • event (Required, string): 要创建的事件 - 必须以 esphome. 开头

  • data (Optional, mapping): 随事件传递的可选静态数据。

  • data_template (Optional, mapping): 随事件传递的可选模板数据。 这将在 Home Assistant 端使用 Home Assistant 的模板引擎进行评估。

  • variables (Optional, mapping): 可在 data_template 中使用的可选变量。 值为 lambdas,将在发送请求前进行评估。

NOTE

请务必按照上述说明告诉 Home Assistant 允许您的设备执行动作。

使用原生 API 与 Home Assistant 时,您可以直接从 ESPHome 自动化执行 Home Assistant 动作。

# 在某个触发器中
on_...:
# 简单示例
- homeassistant.action:
action: notify.html5
data:
message: 按钮被按下
# 带模板和变量
- homeassistant.action:
action: notify.html5
data:
title: 新湿度
data_template:
message: 湿度为 {{ my_variable }}%。
variables:
my_variable: |-
return id(my_sensor).state;
  • action (Required, string): 要执行的 Home Assistant 动作

  • data (Optional, mapping): 执行动作时使用的可选静态数据。

  • data_template (Optional, mapping): 执行动作时使用的可选模板数据。 这将在 Home Assistant 端使用 Home Assistant 的模板引擎进行评估。

  • variables (Optional, mapping): 可在 data_template 中使用的可选变量。 值为 lambdas,将在发送请求前进行评估。

  • capture_response (Optional, boolean): 启用从 Home Assistant 动作调用捕获响应。 启用时,必须配置 on_success。默认为 false

  • response_template (Optional, templatable, string): 用于处理 动作响应数据的可选 Jinja 模板。此模板在 Home Assistant 端使用 Home Assistant 的模板引擎进行评估。 需要 capture_response: true

  • on_success (Optional, Automation): 当 Home Assistant 动作 调用成功时执行的可选自动化。当 capture_response: true 时,响应数据可作为类型为 JsonObjectConstresponse 变量使用。 参见 动作响应处理

  • on_error (Optional, Automation): 当 Home Assistant 动作 调用失败时执行的可选自动化。参见 动作响应处理

不支持数据结构,但您可以在 Home Assistant 中创建脚本并以简单格式传递所有参数。

# Home Assistant 配置
script:
...
set_light_rgb:
alias: 'ESPHome RGB 灯设置'
sequence:
- action: light.turn_on
data_template:
entity_id: '{{ light_name }}'
rgb_color:
- '{{ red }}'
- '{{ green }}'
- '{{ blue }}'

然后,在 ESPHome 中:

# 在某个触发器中
on_...:
- homeassistant.action:
action: script.set_light_rgb
data:
light_name: 'my_light'
red: '255'
green: '199'
blue: '71'

NOTE

动作响应处理在 ESPHome 2025.10.0 及更高版本中可用。

您可以配置动作以接收和处理来自 Home Assistant 的响应。这实现了双向通信,ESPHome 不仅可以调用 Home Assistant 动作,还可以处理其响应。

使用 on_successon_error 响应动作完成:

on_...:
- homeassistant.action:
action: light.toggle
data:
entity_id: light.demo_light
on_success:
- logger.log: "已切换演示灯"
on_error:
- logger.log: "切换演示灯失败"

要捕获和处理动作的响应数据,设置 capture_response: true。启用时,必须配置 on_success, 响应数据可作为名为 responseJsonObjectConst 变量使用。

# 示例:获取天气预报并解析 JSON 响应
on_...:
- homeassistant.action:
action: weather.get_forecasts
data:
entity_id: weather.forecast_home
type: hourly
capture_response: true
on_success:
- lambda: |-
JsonObjectConst next_hour = response["response"]["weather.forecast_home"]["forecast"][0];
float next_temperature = next_hour["temperature"].as<float>();
ESP_LOGI("weather", "下一小时温度: %.1f", next_temperature);

使用 response_template 通过 Home Assistant 的 Jinja 模板引擎从复杂响应中提取和格式化数据。 这需要 capture_response: true

# 示例:使用模板提取温度
on_...:
- homeassistant.action:
action: weather.get_forecasts
data:
entity_id: weather.forecast_home
type: hourly
capture_response: true
response_template: "{{ response['weather.forecast_home']['forecast'][0]['temperature'] }}"
on_success:
- lambda: |-
float temperature = response["response"].as<float>();
ESP_LOGI("weather", "下一小时温度: %.1f", temperature);

当使用 response_template 时,处理后的结果可在 response["response"] 中使用。

NOTE

请务必按照上述说明告诉 Home Assistant 允许您的设备进行动作调用。

使用原生 API 与 Home Assistant 时,您可以直接从 ESPHome 自动化将 tag_scanned 推送到 Home Assistant。

# 在某个触发器中
on_...:
# 简单示例
- homeassistant.tag_scanned: some-tag
  • tag (Required, templatable, string): 扫描标签的 ID

每当客户端连接到 API 时,此触发器就会激活。从该触发器内调用的动作可以使用两个类型为 std::string 的变量:

  • client_address : 连接的客户端的 IP 地址
  • client_info : 连接的客户端的名称
api:
# ...
on_client_connected:
- logger.log:
format: "客户端 %s 通过 IP %s 连接到 API"
args: ["client_info.c_str()", "client_address.c_str()"]

每当客户端从 API 断开时,此触发器就会激活。从该触发器内调用的动作可以使用两个类型为 std::string 的变量:

  • client_address : 断开的客户端的 IP 地址
  • client_info : 断开的客户端的名称
api:
# ...
on_client_disconnected:
- logger.log: "API 客户端已断开!"

条件 检查是否至少有一个客户端连接到 ESPHome 原生 API。

  • state_subscription_only (Optional, boolean): 如果启用,只计算已订阅实体状态更新的客户端。这会过滤掉仅用于日志记录的连接(如 esphome logs 命令),这在等待 Home Assistant 时可能导致误报。默认为 false

检查是否有任何客户端连接:

on_...:
if:
condition:
api.connected:
then:
- logger.log: 客户端已连接到 API!

等效的 lambda 表达式是 id(api_id).is_connected()

检查是否有订阅实体状态的客户端连接(通常是 Home Assistant):

on_boot:
- wait_until:
condition:
api.connected:
state_subscription_only: true
- logger.log: Home Assistant 已连接!
- homeassistant.event:
event: esphome.device_booted

等效的 lambda 表达式是 id(api_id).is_connected(true)

使用场景:

  • 使用 state_subscription_only: false(默认)来检测任何 API 连接
  • 使用 state_subscription_only: true 当您需要确保 Home Assistant(或其他订阅状态的连接)在发送事件或调用服务之前已连接,从而防止仅用于日志记录的连接导致错误

也可以通过用户定义动作从 Home Assistant 获取数据到 ESPHome。 当您在 ESPHome YAML 文件中声明动作时,它们会自动显示在 Home Assistant 中,您可以直接调用它们。

NOTE

用户定义动作还可以使用 api.respond 动作将响应发送回调用客户端。 有关详细信息,请参阅 动作响应

# 示例配置项
api:
actions:
- action: start_laundry
then:
- switch.turn_on: relay
- delay: 3h
- switch.turn_off: relay

例如,使用上面的配置,上传后您会看到一个名为 esphome.livingroom_start_laundry(livingroom 是节点名称)的动作,您可以 然后调用它。

此外,您还可以使用此方法将数据从 Home Assistant 传输到 ESPHome:

# 示例配置项
api:
actions:
- action: start_effect
variables:
my_brightness: int
my_effect: string
then:
- light.turn_on:
id: my_light
brightness: !lambda 'return my_brightness;'
effect: !lambda 'return my_effect;'

使用 variables 键,您可以告诉 ESPHome 期望从 Home Assistant 获取哪些变量。 例如,上面的动作将使用如下方式执行:

# 示例 Home Assistant 动作
action: esphome.livingroom_start_effect
data_template:
my_brightness: "{{ states.brightness.state }}"
my_effect: "Rainbow"

然后,您在 variables 部分定义的每个变量都可以在用户定义动作触发的自动化中通过您在变量部分中给它的名称访问 (注意:这是一个局部变量,所以不要用 id(...) 包装它来访问它)。

目前有 4 种类型的变量:

  • bool: 布尔值(ON/OFF)。C++ 类型:bool
  • int: 整数。C++ 类型:int /int32_t
  • float: 浮点数。C++ 类型:float
  • string: 字符串。C++ 类型:std::string

每种类型都有数组形式:

  • bool[]: 布尔值数组。C++ 类型:std::vector<bool>
  • … - 其他类型相同。

用户定义动作可以将响应发送回调用客户端(如 Home Assistant)。这实现了双向通信,动作可以报告成功/错误状态或返回结构化 JSON 数据。

响应行为由 supports_response 选项控制,该选项可以显式设置或根据您的动作配置自动检测:

  • none(默认):不发送响应。动作是”即发即弃”的。
  • status: 报告成功/错误状态但不包含数据。当使用不带 data:api.respond 时自动检测。
  • optional: 当客户端请求时返回 JSON 数据。当使用带 data:api.respond 时自动检测。
  • only: 始终返回 JSON 数据。必须显式设置。用于查询类型的动作。
  • supports_response (Optional, string): 此动作的响应模式。可选值为 nonestatusoptionalonly。如果未指定,则根据动作中 api.respond 的使用情况自动检测模式。

supports_response 不是 none 时,动作中可以使用以下变量:

  • call_id (uint32_t): 此动作调用的唯一标识符。由 api.respond 内部使用。
  • return_response (bool): 仅在 optional 模式下可用。指示客户端是否请求了响应。您通常不需要检查这个 - api.respond 会自动处理。

此动作将响应发送回调用用户定义动作的客户端。它可以报告成功/错误状态并可选地包含 JSON 数据。

  • success (Optional, boolean, templatable): 动作是否成功。 默认为 true
  • error_message (Optional, string, templatable): 当 successfalse 时包含的错误消息。 默认为空字符串。
  • data (Optional, lambda): 使用响应数据填充 JSON 对象的 lambda。 lambda 接收一个类型为 JsonObjectroot 变量,您可以用键值对填充它。

报告成功或错误而不返回数据:

api:
actions:
- action: validate_input
variables:
value: int
then:
- if:
condition:
lambda: 'return value < 0;'
then:
- api.respond:
success: false
error_message: "值必须为正数"
else:
- api.respond:
success: true

将结构化 JSON 数据返回给调用者:

api:
actions:
- action: get_sensor_data
variables:
sensor_name: string
then:
- api.respond:
data: !lambda |-
root["sensor"] = sensor_name;
root["value"] = id(my_sensor).state;
root["unit"] = "°C";
root["timestamp"] = id(homeassistant_time).now().timestamp;

此动作将自动检测为 optional 模式,因为它使用了带 data:api.respond

对于始终返回数据的动作(如查询),显式设置 supports_response: only

api:
actions:
- action: get_device_info
supports_response: only
then:
- api.respond:
data: !lambda |-
root["hostname"] = App.get_name();
root["version"] = ESPHOME_VERSION;
root["uptime"] = millis() / 1000;

您可以创建复杂的嵌套 JSON 结构:

api:
actions:
- action: get_full_status
supports_response: only
then:
- api.respond:
data: !lambda |-
root["device"]["name"] = "living_room";
root["device"]["version"] = 1;
root["sensors"]["temperature"] = id(temp_sensor).state;
root["sensors"]["humidity"] = id(humidity_sensor).state;

支持响应的动作会显示在 Home Assistant 中,并指示其响应模式。您可以调用它们并接收响应数据:

# Home Assistant 自动化示例
action: esphome.device_get_sensor_data
data:
sensor_name: "living_room"
response_variable: sensor_response

响应将在 sensor_response 变量中可用,其结构为您在 data: lambda 中定义的结构。

ESPHome 原生 API 与使用 MQTT 与家庭自动化软件(目前仅 Home Assistant 和 ioBroker)通信相比有许多优势。但 MQTT 是一个很好的协议,永远不会被移除。原生 API 的特点(对比 MQTT):

  • 更高效: ESPHome 使用协议缓冲区以高度优化的格式编码所有消息 - 例如,二进制传感器状态消息大约是 MQTT 消息大小的 1/10。

  • 一键配置: ESPHome 在 Home Assistant 中只需点击一下即可设置 - 不再需要处理保留的 MQTT 发现消息等。

  • 减少单点故障: 在 ESPHome 原生 API 中,每个 ESP 都是其自己的服务器。 使用 MQTT 时,当代理关闭时,任何东西都无法再通信。

  • 稳定性: 由于 ESPHome 对协议的控制比 MQTT 更多, 推出稳定性改进非常容易。

  • 低延迟: 原生 API 针对极低延迟进行了优化,通常只有几毫秒,远低于眼睛能注意到的程度。