原生 API 组件
ESPHome 原生 API 用于通过高度优化的网络协议与客户端直接通信。目前,只有 ESPHome 工具、Home Assistant 和 ioBroker 使用此原生 API。
在 ESPHome 配置中添加一行 api: 后,您可以进入 Home Assistant 网页界面,并在”配置”面板中导航到”集成”界面。然后等待 ESPHome 设备出现在”已发现”部分下(最多可能需要 5 分钟),或者在集成概览中选择”ESPHome”手动添加设备,并在”主机”字段中输入 “<NODE_NAME>.local” 或设备的 IP 地址。
ESPHome 原生 API 基于使用 protocol buffers 的自定义 TCP 协议。您可以在此处找到协议数据结构定义:api.proto 实现此协议的 Python 库是 aioesphomeapi。
NOTE
Actions 以前被称为 Services。ESPHome 为与
Home Assistant
保持一致而更改了名称,但在可预见的将来仍会继续支持带有 services 和 homeassistant.service 的 YAML。
文档将只引用 Actions。
# Example configuration entryapi:# Example with more optionsapi: port: 6053 batch_delay: 50ms # Reduce latency for real-time applications listen_backlog: 2 # Allow 2 pending connections in queue max_connections: 6 # Allow up to 6 simultaneous connections max_send_queue: 10 # Maximum queued messages per connection before disconnect encryption: key: "YOUR_ENCRYPTION_KEY_HERE" reboot_timeout: 30min-
port (可选, int):运行 API 服务器的端口。默认为
6053。 -
listen_backlog (可选, int):监听队列中允许的最大挂起连接数。必须在 1 到 10 之间。 ESP8266/RP2040 默认为
1,ESP32 和其他平台默认为4。值越小占用的内存越少,但在突发情况下可能拒绝连接。 -
max_connections (可选, int):允许的最大同时 API 连接数。必须在 1 到 20 之间。 默认值为:
- ESP8266/RP2040 为
4, - ESP32/BK72xx/RTL87xx/LN882x 为
5, - host 平台为
8。
NOTE
max_connections作为编译时常量固化在编译后的固件中——连接槽是静态分配的,因此每个槽无论是否被使用都会占用少量静态 RAM,更改该值必须重新刷写固件。 此外,每个活动的 API 连接在连接期间大约会消耗 500–1000 字节的 RAM。ESP8266 和 RP2040 设备的可用 RAM 有限(ESP8266 启动后通常约有 40KB 的空闲 RAM,但在配置了传感器和其他组件后可能会降至 20KB 以下;RP2040 使用 LWIP 原始套接字,限制类似),因此注意不要将该值设置得太高,否则可能导致内存不足崩溃。 默认值是在内存使用与允许多个同时连接之间取得平衡而设定的。 - ESP8266/RP2040 为
-
max_send_queue (可选, int):每个连接在断开之前可以排队等待发送的最大消息数。必须在 1 到 64 之间。 默认值为:
- ESP8266/RP2040 为
5, - ESP32/BK72xx/LN882x/nRF52/RTL87xx 为
8, - host 平台为
16。
这可以防止在客户端速度慢或网络停滞时耗尽内存。 每条排队的消息大约使用 8-12 字节的开销加上消息本身的大小。
NOTE
当某个连接的发送队列已满时,设备会记录错误并断开该客户端,以防止内存不足崩溃。 客户端速度慢、Wi-Fi 连接不佳导致的重试或网络拥塞都可能触发此情况。如果有正常客户端被断开,请增大此值,但要注意嵌入式设备的内存限制。
- ESP8266/RP2040 为
-
encryption (可选):如果存在此配置,将为 API 启用加密。使用加密有助于保护运行 ESPHome 的设备与已连接的客户端之间的通信。
-
key (可选, string):用作加密密钥的 32 字节 base64 编码字符串。如果未提供, 密钥可以在运行时设置,但在设置之前不会使用加密。
如果您需要密钥,可以使用下面的密钥;它会在每次页面加载时由您的浏览器随机生成:
-
NOTE
支持在运行中配置加密密钥将在 Home Assistant 的未来版本中实现。
TIP
有关包括 API 加密最佳实践在内的全面安全指南,请参阅安全最佳实践指南。
- actions (可选, list):用户定义的操作列表。请参阅用户定义操作。
- batch_delay (可选, 时间):将多个状态更新消息批量发送以降低网络开销的延迟时间。较低的值能使更新更快发送,但会使用更多网络数据包,而较高的值批量发送效率更高,但会增加延迟。必须在
0ms和65535ms(65.535 秒)之间。默认为100ms。
NOTE
设置 batch_delay: 0ms 可启用状态更新的立即发送模式。这对于需要实时响应的应用程序很有用,例如必须保留快速 ON→OFF 转换的红外遥控二进制传感器。但是,这会增加网络流量,并且可能在使用许多快速变化的传感器时影响 Wi-Fi 性能。仅在必要时使用此设置。
-
custom_services (可选, boolean):为使用 C++
CustomAPIDevice类的外部组件启用自定义 API 服务的编译。仅当外部组件通过原生 API 注册自己的服务时才需要。默认为false。 -
homeassistant_services (可选, boolean):为使用 C++
CustomAPIDevice::call_homeassistant_service()或CustomAPIDevice::fire_homeassistant_event()方法的外部组件启用编译 Home Assistant 服务调用支持。当使用homeassistant.service或homeassistant.event操作,或为 number 或 switch 组件使用homeassistant平台时,会自动启用。仅当外部组件在不使用内置操作的情况下调用 Home Assistant 服务时才需要手动设置。默认为false。 -
homeassistant_states (可选, boolean):为使用 C++
CustomAPIDevice::subscribe_homeassistant_state()方法的外部组件启用编译 Home Assistant 状态订阅支持。当使用任何homeassistant平台组件(sensor、binary_sensor、text_sensor、switch 或 number)时会自动启用。仅当外部组件在不使用内置组件的情况下订阅 Home Assistant 状态时才需要手动设置。默认为false。 -
reboot_timeout (可选, 时间):当没有客户端连接到 API 时,在重启之前等待的时间。这是必要的,因为有时底层 ESP 功能会报告 ESP 已连接到网络,而实际上并没有 - 只有完全重启才能解决。可以通过将其设置为
0s来禁用。默认为15min。 -
id (可选, ID):手动指定用于代码生成的 ID。
-
on_client_connected (可选, Action):当客户端连接到 API 时执行的自动化。请参阅
on_client_connected触发器。 -
on_client_disconnected (可选, Action):当客户端断开与 API 的连接时执行的自动化。请参阅
on_client_disconnected触发器。
Actions
Section titled “Actions”在使用下面的任何操作之前,您需要告诉 Home Assistant 允许您的设备执行操作。
NOTE
从 ESPHome 2025.10.0 开始,您可以使用 capture_response、on_success 和 on_error 配置操作来接收和处理来自 Home Assistant 的响应。有关详细信息,请参阅操作响应处理。
在您的 Home Assistant 实例上打开 ESPHome 集成页面:
然后:
-
在设备列表中找到您的设备
-
单击其旁边的”配置”按钮
-
选中”允许设备执行 Home Assistant 操作”复选框
-
然后点击”提交”
homeassistant.event Action
Section titled “homeassistant.event Action”NOTE
务必按照上面的说明告诉 Home Assistant 允许 您的设备执行操作。
将原生 API 与 Home Assistant 一起使用时,您可以直接从 ESPHome 自动化在 Home Assistant 事件总线中创建事件。
# In some triggeron_...: # Simple - homeassistant.event: event: esphome.button_pressed data: message: Button was pressed-
event (必填, string):要创建的事件 - 必须以
esphome.开头 -
data (可选, mapping):可选的要随事件传递的静态数据。
-
data_template (可选, mapping):可选的要随事件传递的模板数据。 这会使用 Home Assistant 的模板引擎在 Home Assistant 端求值。
-
variables (可选, mapping):可在
data_template中使用的可选变量。 值类型为 lambdas,将在发送请求前求值。
homeassistant.action Action
Section titled “homeassistant.action Action”NOTE
务必按照上面的说明告诉 Home Assistant 允许 您的设备执行操作。
将原生 API 与 Home Assistant 一起使用时,您可以直接从 ESPHome 自动化执行 Home Assistant 操作。
# In some triggeron_...: # Simple - homeassistant.action: action: notify.html5 data: message: Button was pressed # With templates and variables - homeassistant.action: action: notify.html5 data: title: New Humidity data_template: message: The humidity is {{ my_variable }}%. variables: my_variable: |- return id(my_sensor).state;-
action (必填, string, templatable):要执行的 Home Assistant Action。
-
data (可选, mapping):可选的要执行操作所用的静态数据。
-
data_template (可选, mapping):可选的要执行操作所用的模板数据。 这会使用 Home Assistant 的模板引擎在 Home Assistant 端求值。
-
variables (可选, mapping):可在
data_template中使用的可选变量。 值类型为 lambdas,将在发送请求前求值。 -
capture_response (可选, boolean):启用捕获 Home Assistant 操作调用的响应。 启用后,必须配置
on_success。默认为false。 -
response_template (可选, string, templatable):用于处理操作响应数据的可选 Jinja 模板。该模板会使用 Home Assistant 的模板引擎在 Home Assistant 端求值。 需要
capture_response: true。 -
on_success (可选, 自动化):当 Home Assistant 操作调用成功时执行的可选自动化。当
capture_response: true时,响应数据作为一个类型为JsonObjectConst的response变量可用。 请参阅操作响应处理。 -
on_error (可选, 自动化):当 Home Assistant 操作调用失败时执行的可选自动化。请参阅操作响应处理。
NOTE
Home Assistant 在 API 连接建立后稍晚才开始监听设备操作,因此在连接时立即触发的操作(例如来自 on_client_connected 或 on_time_sync)可能会在 Home Assistant 就绪之前触发。此类操作不会被传递,ESPHome 会记录警告(2026.8.0 之前的版本会静默丢弃)。homeassistant.event 也是如此。如果您需要在连接建立后立即执行操作,请在其之前添加一个短的 delay,以便 Home Assistant 有时间开始监听。
数据结构是不可能的,但您可以在 Home Assistant 中创建一个脚本并以纯格式调用所有参数。
# Home Assistant Configurationscript: ... set_light_rgb: alias: 'ESPHome RGB light set' sequence: - action: light.turn_on data_template: entity_id: '{{ light_name }}' rgb_color: - '{{ red }}' - '{{ green }}' - '{{ blue }}'然后,在 ESPHome 中:
# In some triggeron_...: - homeassistant.action: action: script.set_light_rgb data: light_name: 'my_light' red: '255' green: '199' blue: '71'操作响应处理
Section titled “操作响应处理”NOTE
操作响应处理在 ESPHome 2025.10.0 及更高版本中可用。
您可以配置操作来接收和处理来自 Home Assistant 的响应。这实现了双向通信,ESPHome 不仅可以调用 Home Assistant 操作,还可以处理它们的响应。
基本的成功/错误处理
Section titled “基本的成功/错误处理”使用 on_success 和 on_error 来响应操作完成:
on_...: - homeassistant.action: action: light.toggle data: entity_id: light.demo_light on_success: - logger.log: "Toggled demo light" on_error: - logger.log: "Failed to toggle demo light"捕获响应数据
Section titled “捕获响应数据”要捕获并处理来自操作的响应数据,请设置 capture_response: true。启用后,必须配置 on_success,并且响应数据作为一个名为 response 的 JsonObjectConst 变量可用。
# Example: Get weather forecast and parse JSON responseon_...: - 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", "Temperature next hour: %.1f", next_temperature);使用响应模板
Section titled “使用响应模板”使用 response_template 通过 Home Assistant 的 Jinja 模板引擎从复杂响应中提取和格式化数据。这需要 capture_response: true。
# Example: Extract temperature using a templateon_...: - 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", "Temperature next hour: %.1f", temperature);使用 response_template 时,处理后的结果可以在 response["response"] 中获取。
homeassistant.tag_scanned Action
Section titled “homeassistant.tag_scanned Action”NOTE
务必按照上面的说明告诉 Home Assistant 允许 您的设备进行操作调用。
将原生 API 与 Home Assistant 一起使用时,您可以直接从 ESPHome 自动化将 tag_scanned 推送到 Home Assistant。
# In some triggeron_...: # Simple - homeassistant.tag_scanned: some-tag- tag (必填, string, templatable):已扫描标签的 ID
on_client_connected 触发器
Section titled “on_client_connected 触发器”每当客户端连接到 API 时,都会激活此触发器。此触发器内部调用的操作可以使用两个 std::string 类型的变量:
client_address:已连接客户端的 IP 地址client_info:已连接客户端的名称
api: # ... on_client_connected: - logger.log: format: "Client %s connected to API with IP %s" args: ["client_info.c_str()", "client_address.c_str()"]on_client_disconnected 触发器
Section titled “on_client_disconnected 触发器”每当 API 与 API 断开连接时,都会激活此触发器。此触发器内部调用的操作可以使用两个 std::string 类型的变量:
client_address:已断开连接客户端的 IP 地址client_info:已断开连接客户端的名称
api: # ... on_client_disconnected: - logger.log: "API client disconnected!"Conditions
Section titled “Conditions”api.connected 条件
Section titled “api.connected 条件”此 Condition 检查是否至少有一个客户端连接到 ESPHome 原生 API。
- state_subscription_only (可选, boolean, templatable):启用后,只计算已订阅实体状态更新的客户端。这可过滤掉仅日志连接(例如
esphome logs命令),这些连接在等待 Home Assistant 时可能导致误报。默认为false。
检查是否有任何客户端已连接:
on_...: if: condition: api.connected: then: - logger.log: Client is connected to API!等效的 lambda 是 id(api_id).is_connected()。
检查是否有订阅实体状态的客户端已连接(通常是 Home Assistant):
on_boot: - wait_until: condition: api.connected: state_subscription_only: true - logger.log: Home Assistant is connected! - homeassistant.event: event: esphome.device_booted等效的 lambda 是 id(api_id).is_connected(true)。
使用场景:
- 使用
state_subscription_only: false(默认值)检测任何 API 连接 - 当您需要确保 Home Assistant(或其他订阅状态的连接)在发送事件或调用服务之前已连接时,使用
state_subscription_only: true,以防止仅日志连接导致的错误
用户定义操作
Section titled “用户定义操作”还可以通过用户定义操作将数据从 Home Assistant 获取到 ESPHome。当您在 ESPHome YAML 文件中声明操作时,它们会自动出现在 Home Assistant 中,您可以直接调用它们。
NOTE
用户定义操作还可以使用 api.respond 操作将响应发送回调用客户端。
有关详细信息,请参阅操作响应。
# Example configuration entryapi: actions: - action: start_laundry then: - switch.turn_on: relay - delay: 3h - switch.turn_off: relay例如,使用上面的配置,上传后您会看到一个名为 esphome.livingroom_start_laundry 的操作(livingroom 是节点名称),您可以随后调用它。
此外,您还可以使用此方法将数据从 Home Assistant 传输到 ESPHome:
# Example configuration entryapi: 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 收到哪些变量。例如,上面的操作会以类似于下面这样的方式执行:
# Example Home Assistant Actionaction: esphome.livingroom_start_effectdata_template: my_brightness: "{{ states.brightness.state }}" my_effect: "Rainbow"然后,您在 variables 部分中定义的每个变量都可以在由用户定义操作触发的自动化中通过您在 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:报告成功/错误状态而不带数据。当
api.respond不配合data:使用时自动检测。 - optional:当客户端请求时返回 JSON 数据。当
api.respond配合data:使用时自动检测。 - only:始终返回 JSON 数据。必须显式设置。适用于查询类型的操作。
- supports_response (可选, string):此操作的响应模式。为
none、status、optional或only之一。如果未指定,则根据操作中api.respond的使用情况自动检测模式。
当 supports_response 不是 none 时,以下变量在操作中可用:
- call_id (
uint32_t):此操作调用的唯一标识符。由api.respond在内部使用。 - return_response (
bool):仅在optional模式下可用。指示客户端是否请求了响应。您通常不需要检查它 -api.respond会自动处理。
api.respond Action
Section titled “api.respond Action”此操作将响应发送回调用用户定义操作的客户端。它可以报告成功/错误状态,并可选择包含 JSON 数据。
- success (可选, boolean, templatable):操作是否成功。
默认为
true。 - error_message (可选, string, templatable):当
success为false时要包含的错误消息。默认为空字符串。 - data (可选, lambda):用于填充包含响应数据的 JSON 对象的 lambda。该 lambda 接收一个类型为
JsonObject的root变量,您可以在其中填充键值对。
状态响应示例
Section titled “状态响应示例”在不返回数据的情况下报告成功或错误:
api: actions: - action: validate_input variables: value: int then: - if: condition: lambda: 'return value < 0;' then: - api.respond: success: false error_message: "Value must be positive" else: - api.respond: success: true数据响应示例
Section titled “数据响应示例”向调用方返回结构化 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。
查询操作示例
Section titled “查询操作示例”对于始终返回数据的操作(如查询),请显式设置 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 数据
Section titled “嵌套 JSON 数据”您可以创建复杂的嵌套 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 调用
Section titled “从 Home Assistant 调用”支持响应的操作在 Home Assistant 中会显示其响应模式。您可以调用它们并接收响应数据:
# Home Assistant automation exampleaction: esphome.device_get_sensor_datadata: sensor_name: "living_room"response_variable: sensor_response响应将在 sensor_response 变量中可用,其结构为您在 data: lambda 中定义的结构。
相对 MQTT 的优势
Section titled “相对 MQTT 的优势”ESPHome 原生 API 与使用 MQTT 和家庭自动化软件(目前只有 Home Assistant 和 ioBroker)通信相比有许多优势。但 MQTT 是一个很好的协议,永远不会被移除。原生 API 的功能(相对于 MQTT):
-
效率高得多: ESPHome 使用高度优化的格式配合 protocol buffers 对所有消息进行编码 - 例如,二进制传感器状态消息的大小约为 MQTT 的 1/10。
-
一键配置: ESPHome 只需一次点击即可在 Home Assistant 中完成设置 - 无需再处理保留的 MQTT 发现消息等类似内容。
-
少一个单点故障: 在 ESPHome 原生 API 中,每个 ESP 都是自己的服务器。使用 MQTT 时,当 broker 关闭后,就无法再进行任何通信。
-
稳定性: 由于 ESPHome 对协议的控制远强于对 MQTT 的,因此对我们来说推出稳定性改进非常容易。
-
低延迟: 原生 API 针对极低延迟进行了优化,通常只有几毫秒,远低于肉眼可察觉的程度。