跳转到内容

HTTP 请求

http_request 组件允许您发起 HTTP/HTTPS 请求。为此,您需要将其添加到设备的配置中:

# 示例配置条目
http_request:
  • id (可选, ID): 手动指定用于代码生成的 ID。

  • follow_redirects (可选, boolean): 启用跟随 HTTP 重定向。默认为 true

  • redirect_limit (可选, integer): 启用时跟随的最大重定向次数。默认为 3

  • timeout (可选, 时间): 请求超时时间。默认为 4.5s

  • useragent (可选, string): 请求的 User-Agent 头。默认为 ESPHome/<version> (https://esphome.io),其中 <version> 是设备运行的 ESPHome 版本。 例如:ESPHome/2024.6.0 (https://esphome.io)

  • verify_ssl (可选, boolean): 设置为 true(默认)时,SSL/TLS 证书将在连接时进行验证; 如果无效,连接将被中止。为此,ESP-IDF 的默认 ESP x509 证书包将包含在构建中。此证书包包含 Mozilla NSS 根证书存储中的完整根证书列表。仅 ESP32 支持;在其他平台上必须显式设置为 false。

  • watchdog_timeout (可选, 时间): 更改连接/数据传输期间的看门狗超时时间。 在慢速连接或高延迟连接上可能有用。除非您遇到因看门狗超时导致的设备重启,否则不要更改此值; 这样做可能会阻止设备因合法问题而重启。仅在 ESP32 和 RP2040 上可用

对于 ESP32:

  • buffer_size_rx (可选, integer): 更改 HTTP 接收缓冲区大小。默认为 512
  • buffer_size_tx (可选, integer): 更改 HTTP 发送缓冲区大小。默认为 512
  • ca_certificate_path (可选, file path): PEM 编码的 CA 证书文件路径。使用此选项在保持 verify_ssl 启用的同时验证使用自签名或自定义 CA 证书的服务器连接。 证书在编译时嵌入固件中。指定时,不包含默认证书包,从而减小固件大小。

对于 ESP8266:

  • esp8266_disable_ssl_support (可选, boolean): 确定是否在固件二进制文件中包含 HTTPS/SSL 支持。 从构建中排除 SSL 库将导致较小的二进制文件,这对于内存受限的设备(512 kB 或 1 MB)可能是必要的。 如果您在设备日志中看到 Error: ESP does not have enough space to store OTA file,您可能需要启用此选项。 默认为 false。将此选项设置为 true 后:

    • HTTPS 连接将无法进行
    • 隐含 verify_ssl: false

WARNING

verify_ssl 设置为 false 在使用 HTTPS 连接时会降低安全性

没有根证书包,远程 HTTPS 服务器使用的证书无法验证,使 HTTPS 连接容易受到中间人攻击。

为了最大限度地提高安全性,*除非满足以下条件,*否则不要将 verify_ssl 设置为 false

  • 在非 ESP32 设备上使用 Arduino 框架,或
  • 设备没有足够的内存来存储证书包

如果您需要在 ESP32 上连接使用自签名或自定义 CA 证书的服务器,请使用 ca_certificate_path 选项而不是禁用 verify_ssl

我们强烈建议使用正确支持 TLS/SSL 的硬件。

对于主机平台:

  • ca_certificate_path (可选, file path): CA 证书包的路径。在 MacOS 上不需要(使用内置 CA 包并默认启用 SSL)。 在 Linux 上,这是启用 SSL 所必需的。

NOTE

要在 Linux 上使用 SSL,您必须安装 libssl-dev 包(例如 sudo apt install libssl-dev)。 在 Linux 上,ca_certificate_path 的典型值是 /etc/ssl/certs/ca-certificates.crt

http_request 组件支持许多可用于发送请求的动作

动作发送 GET 请求。

on_...:
- http_request.get:
url: https://esphome.io
request_headers:
Content-Type: application/json
on_response:
then:
- logger.log:
format: '响应状态: %d, 持续时间: %u ms'
args:
- response->status_code
- response->duration_ms
# 简写形式
- http_request.get: https://esphome.io
  • url (必需, string, 可模板化): 发送请求的 URL。

  • request_headers (可选, mapping): HTTP 头映射。值为可模板化

  • collect_headers (可选, list of strings): 要从响应中收集的 HTTP 头名称列表。

  • capture_response (可选, boolean): 设置为 true 时,响应数据将被捕获并放入 body 变量中作为 std::string,用于 lambda。默认为 false

  • max_response_buffer_size (可选, integer): 用于存储响应的最大缓冲区大小。 默认为 1 kB

  • on_response (可选, 自动化): 收到请求后执行的自动化。

  • on_error (可选, 自动化): 请求无法完成时执行的自动化。

动作发送 POST 请求。

on_...:
- http_request.post:
url: https://esphome.io
request_headers:
Content-Type: application/json
json:
key: value
# 简写形式
- http_request.post: https://esphome.io

动作发送请求。

on_...:
- http_request.send:
method: PUT
url: https://esphome.io
request_headers:
Content-Type: application/json
body: "Some data"

当 HTTP 请求完成时将触发此自动化。 以下变量可在 lambda 中使用:

  • response 作为指向 HttpContainer 对象的指针,其中包含 content_lengthstatus_codeduration_ms
  • std::string get_response_header(const std::string &header_name) 用于读取响应头(只有名称在 collect_headers 中指定的头可用)。
  • body 作为 std::string,当设置 capture_response (请参阅 http_request.get 动作)为 true 时包含响应体。

NOTE

在使用 body 变量之前应该检查 status_code。成功的响应通常会有 状态码 200。服务器错误如”未找到”(404)或”内部服务器错误”(500)会有适当的状态码,并且可能在 body 变量中包含错误消息。

on_...
then:
- http_request.get:
url: https://esphome.io
collect_headers:
- Content-Type
on_response:
then:
- logger.log:
format: "响应状态: %d, 持续时间: %u ms, Content-Type: %s"
args:
- response->status_code
- response->duration_ms
- response->get_response_header("Content-Type").c_str()
- lambda: |-
ESP_LOGD(TAG, "响应状态: %d, 持续时间: %u ms, Content-Type: %s", response->status_code, response->duration_ms, response->get_response_header("Content-Type").c_str());
on_error:
then:
- logger.log: "请求失败!"

当 HTTP 请求无法完成时将触发此自动化。例如网络不可用或服务器不可达。 如果请求完成,即使响应码不是 200,也不会触发此触发器。没有关于错误类型的信息,也没有变量可在 lambda 中使用。请参阅上面的示例用法。

on_...:
- http_request.post:
url: !lambda |-
return ((std::string) "https://esphome.io?state=" + id(my_sensor).state).c_str();
request_headers:
X-Custom-Header: !lambda |-
return ((std::string) "Value-" + id(my_sensor).state).c_str();
body: !lambda |-
return id(my_sensor).state;

注意: 映射的所有值必须是字符串。使用此语法无法发送 JSON booleannumbers

on_...:
- http_request.post:
url: https://esphome.io
json:
key: !lambda |-
return id(my_sensor).state;
greeting: "Hello World"
# 将发送:
# {"key": "42.0", "greeting": "Hello World"}

注意: 使用此语法发送 JSON 中的 booleannumbers

JSON 消息将使用 ArduinoJson 库构建。 在 json 选项中,您可以访问一个 root 对象,它代表 JSON 消息的基对象。您 可以使用 root["KEY_NAME"] = VALUE; 语法为键分配值,如下所示。

on_...:
- http_request.post:
url: https://esphome.io
json: |-
root["key"] = id(my_sensor).state;
root["greeting"] = "Hello World";
# 将发送:
# {"key": 42.0, "greeting": "Hello World"}

如果您想检索 vol 键的值并将其分配给 id 设置为 player_volume 的模板传感器或数字组件,您可以这样做,但请注意,检查键的存在可以防止难以阅读的错误消息:

此示例假设服务器返回类似以下的 JSON 对象响应: {"status":"play","vol":"42","mute":"0"}

如果您想检索 vol 键的值并将其分配给 id 设置为 player_volume 的模板 sensornumber 组件:

on_...:
- http_request.get:
url: https://esphome.io
capture_response: true
on_response:
then:
- if:
condition:
lambda: return response->status_code == 200;
then:
- lambda: |-
json::parse_json(body, [](JsonObject root) -> bool {
if (root["vol"]) {
id(player_volume).publish_state(root["vol"]);
return true;
}
else {
ESP_LOGI(TAG,"此 json 中没有 'vol' 键!");
return false;
}
});
else:
- logger.log:
format: "错误: 响应状态: %d, 消息 %s"
args: [ 'response->status_code', 'body.c_str()' ]