Compare commits

...

12 Commits

Author SHA1 Message Date
Jesse Hills
27d7d10d94
Use reference 2022-03-10 10:46:38 +13:00
Jesse Hills
ba96647fba
Fix 2022-03-10 09:20:57 +13:00
Jesse Hills
7c7b508620
Remove unique_ptr wrapper 2022-03-10 09:19:28 +13:00
Daniel Cousens
1c44538fc9
Tidy up casting, explicit HttpResponse lifetime (#3265)
Co-authored-by: Daniel Cousens <dcousens@users.noreply.github.com>
2022-03-10 09:12:56 +13:00
Jesse Hills
6639121a5b
Fix 2022-03-09 09:38:34 +13:00
Jesse Hills
b3d4b1e2ee
Use unique_ptr 2022-03-08 14:03:26 +13:00
Jesse Hills
bcf98471cf
Merge branch 'dev' into jesserockz-2022-103 2022-03-03 10:12:52 +13:00
Jesse Hills
0be672179d
Set else to fail with error message 2022-03-01 12:38:18 +13:00
Jesse Hills
8491ec9a84
clang 2022-03-01 11:28:36 +13:00
Jesse Hills
a3119e8d83
Lint 2022-03-01 11:26:32 +13:00
Jesse Hills
f36d0c9b33
Fix ifdefs 2022-03-01 11:23:40 +13:00
Jesse Hills
aba8d63fe3
Implement http_request component for esp-idf 2022-02-28 16:55:57 +13:00
7 changed files with 411 additions and 165 deletions

View File

@ -12,17 +12,24 @@ from esphome.const import (
CONF_ESP8266_DISABLE_SSL_SUPPORT,
)
from esphome.core import Lambda, CORE
from esphome.components import esp32
DEPENDENCIES = ["network"]
AUTO_LOAD = ["json"]
http_request_ns = cg.esphome_ns.namespace("http_request")
HttpRequestComponent = http_request_ns.class_("HttpRequestComponent", cg.Component)
HttpRequestArduino = http_request_ns.class_("HttpRequestArduino", HttpRequestComponent)
HttpRequestIDF = http_request_ns.class_("HttpRequestIDF", HttpRequestComponent)
HttpResponse = http_request_ns.class_("HttpResponse")
HttpRequestSendAction = http_request_ns.class_(
"HttpRequestSendAction", automation.Action
)
HttpRequestResponseTrigger = http_request_ns.class_(
"HttpRequestResponseTrigger", automation.Trigger
"HttpRequestResponseTrigger",
automation.Trigger.template(int, HttpResponse.operator("ref")),
)
CONF_HEADERS = "headers"
@ -33,6 +40,7 @@ CONF_VERIFY_SSL = "verify_ssl"
CONF_ON_RESPONSE = "on_response"
CONF_FOLLOW_REDIRECTS = "follow_redirects"
CONF_REDIRECT_LIMIT = "redirect_limit"
CONF_CAPTURE_RESPONSE = "capture_response"
def validate_url(value):
@ -68,10 +76,18 @@ def validate_secure_url(config):
return config
def _declare_request_class(value):
if CORE.using_esp_idf:
return cv.declare_id(HttpRequestIDF)(value)
if CORE.is_esp8266 or CORE.is_esp32:
return cv.declare_id(HttpRequestArduino)(value)
return NotImplementedError
CONFIG_SCHEMA = cv.All(
cv.Schema(
{
cv.GenerateID(): cv.declare_id(HttpRequestComponent),
cv.GenerateID(): _declare_request_class,
cv.Optional(CONF_USERAGENT, "ESPHome"): cv.string,
cv.Optional(CONF_FOLLOW_REDIRECTS, True): cv.boolean,
cv.Optional(CONF_REDIRECT_LIMIT, 3): cv.int_,
@ -86,6 +102,7 @@ CONFIG_SCHEMA = cv.All(
cv.require_framework_version(
esp8266_arduino=cv.Version(2, 5, 1),
esp32_arduino=cv.Version(0, 0, 0),
esp_idf=cv.Version(0, 0, 0),
),
)
@ -101,8 +118,14 @@ async def to_code(config):
cg.add_define("USE_HTTP_REQUEST_ESP8266_HTTPS")
if CORE.is_esp32:
cg.add_library("WiFiClientSecure", None)
cg.add_library("HTTPClient", None)
if CORE.using_esp_idf:
esp32.add_idf_sdkconfig_option("CONFIG_ESP_TLS_INSECURE", True)
esp32.add_idf_sdkconfig_option(
"CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", True
)
else:
cg.add_library("WiFiClientSecure", None)
cg.add_library("HTTPClient", None)
if CORE.is_esp8266:
cg.add_library("ESP8266HTTPClient", None)
@ -117,6 +140,7 @@ HTTP_REQUEST_ACTION_SCHEMA = cv.Schema(
cv.Schema({cv.string: cv.templatable(cv.string)})
),
cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean,
cv.Optional(CONF_CAPTURE_RESPONSE, default=False): cv.boolean,
cv.Optional(CONF_ON_RESPONSE): automation.validate_automation(
{cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(HttpRequestResponseTrigger)}
),
@ -173,6 +197,7 @@ async def http_request_action_to_code(config, action_id, template_arg, args):
template_ = await cg.templatable(config[CONF_URL], args, cg.std_string)
cg.add(var.set_url(template_))
cg.add(var.set_method(config[CONF_METHOD]))
cg.add(var.set_capture_response(config[CONF_CAPTURE_RESPONSE]))
if CONF_BODY in config:
template_ = await cg.templatable(config[CONF_BODY], args, cg.std_string)
cg.add(var.set_body(template_))
@ -195,6 +220,13 @@ async def http_request_action_to_code(config, action_id, template_arg, args):
for conf in config.get(CONF_ON_RESPONSE, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID])
cg.add(var.register_response_trigger(trigger))
await automation.build_automation(trigger, [(int, "status_code")], conf)
await automation.build_automation(
trigger,
[
(int, "status_code"),
(HttpResponse.operator("ref"), "response"),
],
conf,
)
return var

View File

@ -1,15 +1,14 @@
#ifdef USE_ARDUINO
#include "http_request.h"
#include "esphome/core/defines.h"
#include "esphome/core/log.h"
#include "esphome/components/network/util.h"
namespace esphome {
namespace http_request {
static const char *const TAG = "http_request";
HttpRequestComponent::HttpRequestComponent() { global_http_request = this; }
void HttpRequestComponent::dump_config() {
ESP_LOGCONFIG(TAG, "HTTP Request:");
ESP_LOGCONFIG(TAG, " Timeout: %ums", this->timeout_);
@ -18,122 +17,7 @@ void HttpRequestComponent::dump_config() {
ESP_LOGCONFIG(TAG, " Redirect limit: %d", this->redirect_limit_);
}
void HttpRequestComponent::set_url(std::string url) {
this->url_ = std::move(url);
this->secure_ = this->url_.compare(0, 6, "https:") == 0;
if (!this->last_url_.empty() && this->url_ != this->last_url_) {
// Close connection if url has been changed
this->client_.setReuse(false);
this->client_.end();
}
this->client_.setReuse(true);
}
void HttpRequestComponent::send(const std::vector<HttpRequestResponseTrigger *> &response_triggers) {
if (!network::is_connected()) {
this->client_.end();
this->status_set_warning();
ESP_LOGW(TAG, "HTTP Request failed; Not connected to network");
return;
}
bool begin_status = false;
const String url = this->url_.c_str();
#if defined(USE_ESP32) || (defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0))
#if defined(USE_ESP32) || USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0)
if (this->follow_redirects_) {
this->client_.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
} else {
this->client_.setFollowRedirects(HTTPC_DISABLE_FOLLOW_REDIRECTS);
}
#else
this->client_.setFollowRedirects(this->follow_redirects_);
#endif
this->client_.setRedirectLimit(this->redirect_limit_);
#endif
#if defined(USE_ESP32)
begin_status = this->client_.begin(url);
#elif defined(USE_ESP8266)
begin_status = this->client_.begin(*this->get_wifi_client_(), url);
#endif
if (!begin_status) {
this->client_.end();
this->status_set_warning();
ESP_LOGW(TAG, "HTTP Request failed at the begin phase. Please check the configuration");
return;
}
this->client_.setTimeout(this->timeout_);
if (this->useragent_ != nullptr) {
this->client_.setUserAgent(this->useragent_);
}
for (const auto &header : this->headers_) {
this->client_.addHeader(header.name, header.value, false, true);
}
int http_code = this->client_.sendRequest(this->method_, this->body_.c_str());
for (auto *trigger : response_triggers)
trigger->process(http_code);
if (http_code < 0) {
ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s", this->url_.c_str(),
HTTPClient::errorToString(http_code).c_str());
this->status_set_warning();
return;
}
if (http_code < 200 || http_code >= 300) {
ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Code: %d", this->url_.c_str(), http_code);
this->status_set_warning();
return;
}
this->status_clear_warning();
ESP_LOGD(TAG, "HTTP Request completed; URL: %s; Code: %d", this->url_.c_str(), http_code);
}
#ifdef USE_ESP8266
std::shared_ptr<WiFiClient> HttpRequestComponent::get_wifi_client_() {
#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS
if (this->secure_) {
if (this->wifi_client_secure_ == nullptr) {
this->wifi_client_secure_ = std::make_shared<BearSSL::WiFiClientSecure>();
this->wifi_client_secure_->setInsecure();
this->wifi_client_secure_->setBufferSizes(512, 512);
}
return this->wifi_client_secure_;
}
#endif
if (this->wifi_client_ == nullptr) {
this->wifi_client_ = std::make_shared<WiFiClient>();
}
return this->wifi_client_;
}
#endif
void HttpRequestComponent::close() {
this->last_url_ = this->url_;
this->client_.end();
}
const char *HttpRequestComponent::get_string() {
#if defined(ESP32)
// The static variable is here because HTTPClient::getString() returns a String on ESP32,
// and we need something to keep a buffer alive.
static String str;
#else
// However on ESP8266, HTTPClient::getString() returns a String& to a member variable.
// Leaving this the default so that any new platform either doesn't copy, or encounters a compilation error.
auto &
#endif
str = this->client_.getString();
return str.c_str();
}
HttpRequestComponent *global_http_request; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
} // namespace http_request
} // namespace esphome
#endif // USE_ARDUINO

View File

@ -1,25 +1,14 @@
#pragma once
#ifdef USE_ARDUINO
#include <list>
#include <map>
#include <memory>
#include <utility>
#include "esphome/components/json/json_util.h"
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#include <list>
#include <map>
#include <utility>
#include <memory>
#ifdef USE_ESP32
#include <HTTPClient.h>
#endif
#ifdef USE_ESP8266
#include <ESP8266HTTPClient.h>
#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS
#include <WiFiClientSecure.h>
#endif
#endif
#include "esphome/core/helpers.h"
namespace esphome {
namespace http_request {
@ -29,44 +18,48 @@ struct Header {
const char *value;
};
class HttpRequestResponseTrigger;
struct HttpResponse {
int status_code;
int content_length;
std::vector<char> data;
};
class HttpRequestResponseTrigger : public Trigger<int, HttpResponse &> {
public:
void process(HttpResponse &response) { this->trigger(response.status_code, response); }
};
class HttpRequestComponent : public Component {
public:
HttpRequestComponent();
void dump_config() override;
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
void set_url(std::string url);
void set_method(const char *method) { this->method_ = method; }
void set_method(std::string method) { this->method_ = std::move(method); }
void set_useragent(const char *useragent) { this->useragent_ = useragent; }
void set_timeout(uint16_t timeout) { this->timeout_ = timeout; }
void set_follow_redirects(bool follow_redirects) { this->follow_redirects_ = follow_redirects; }
void set_redirect_limit(uint16_t limit) { this->redirect_limit_ = limit; }
void set_body(const std::string &body) { this->body_ = body; }
void set_headers(std::list<Header> headers) { this->headers_ = std::move(headers); }
void send(const std::vector<HttpRequestResponseTrigger *> &response_triggers);
void close();
const char *get_string();
void set_capture_response(bool capture_response) { this->capture_response_ = capture_response; }
bool get_capture_response() { return this->capture_response_; }
virtual void set_url(std::string url) = 0;
virtual HttpResponse send() = 0;
protected:
HTTPClient client_{};
std::string url_;
std::string last_url_;
const char *method_;
std::string method_;
const char *useragent_{nullptr};
bool secure_;
bool follow_redirects_;
bool capture_response_;
uint16_t redirect_limit_;
uint16_t timeout_{5000};
std::string body_;
std::list<Header> headers_;
#ifdef USE_ESP8266
std::shared_ptr<WiFiClient> wifi_client_;
#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS
std::shared_ptr<BearSSL::WiFiClientSecure> wifi_client_secure_;
#endif
std::shared_ptr<WiFiClient> get_wifi_client_();
#endif
};
template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
@ -77,6 +70,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
TEMPLATABLE_VALUE(std::string, body)
TEMPLATABLE_VALUE(const char *, useragent)
TEMPLATABLE_VALUE(uint16_t, timeout)
TEMPLATABLE_VALUE(bool, capture_response)
void add_header(const char *key, TemplatableValue<const char *, Ts...> value) { this->headers_.insert({key, value}); }
@ -89,6 +83,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
void play(Ts... x) override {
this->parent_->set_url(this->url_.value(x...));
this->parent_->set_method(this->method_.value(x...));
this->parent_->set_capture_response(this->capture_response_.value(x...));
if (this->body_.has_value()) {
this->parent_->set_body(this->body_.value(x...));
}
@ -117,8 +112,10 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
}
this->parent_->set_headers(headers);
}
this->parent_->send(this->response_triggers_);
this->parent_->close();
HttpResponse response = this->parent_->send();
for (auto *trigger : this->response_triggers_)
trigger->process(response);
}
protected:
@ -136,12 +133,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
std::vector<HttpRequestResponseTrigger *> response_triggers_;
};
class HttpRequestResponseTrigger : public Trigger<int> {
public:
void process(int status_code) { this->trigger(status_code); }
};
extern HttpRequestComponent *global_http_request; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
} // namespace http_request
} // namespace esphome
#endif // USE_ARDUINO

View File

@ -0,0 +1,129 @@
#include "http_request_arduino.h"
#ifdef USE_ARDUINO
#include "esphome/components/network/util.h"
#include "esphome/core/defines.h"
#include "esphome/core/log.h"
namespace esphome {
namespace http_request {
static const char *const TAG = "http_request.arduino";
void HttpRequestArduino::set_url(std::string url) {
this->url_ = std::move(url);
this->secure_ = this->url_.compare(0, 6, "https:") == 0;
if (!this->last_url_.empty() && this->url_ != this->last_url_) {
// Close connection if url has been changed
this->client_.setReuse(false);
this->client_.end();
}
this->client_.setReuse(true);
}
HttpResponse HttpRequestArduino::send() {
if (!network::is_connected()) {
this->client_.end();
this->status_set_warning();
ESP_LOGW(TAG, "HTTP Request failed; Not connected to network");
return {-1, 0, {}};
}
bool begin_status = false;
const String url = this->url_.c_str();
#if defined(USE_ESP32) || (defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0))
#if defined(USE_ESP32) || USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0)
if (this->follow_redirects_) {
this->client_.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
} else {
this->client_.setFollowRedirects(HTTPC_DISABLE_FOLLOW_REDIRECTS);
}
#else
this->client_.setFollowRedirects(this->follow_redirects_);
#endif
this->client_.setRedirectLimit(this->redirect_limit_);
#endif
#if defined(USE_ESP32)
begin_status = this->client_.begin(url);
#elif defined(USE_ESP8266)
begin_status = this->client_.begin(*this->get_wifi_client_(), url);
#endif
if (!begin_status) {
this->client_.end();
this->status_set_warning();
ESP_LOGW(TAG, "HTTP Request failed at the begin phase. Please check the configuration");
return {-1, 0, {}};
}
this->client_.setTimeout(this->timeout_);
if (this->useragent_ != nullptr) {
this->client_.setUserAgent(this->useragent_);
}
for (const auto &header : this->headers_) {
this->client_.addHeader(header.name, header.value, false, true);
}
int http_code = this->client_.sendRequest(this->method_.c_str(), this->body_.c_str());
HttpResponse response = {};
response.status_code = http_code;
response.content_length = this->client_.getSize();
if (http_code < 0) {
ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s", this->url_.c_str(),
HTTPClient::errorToString(http_code).c_str());
this->status_set_warning();
return {http_code, 0, {}};
}
if (this->capture_response_) {
#ifdef USE_ESP32
String str;
#else
auto &
#endif
str = this->client_.getString();
response.data = std::vector<char>(str.c_str(), str.c_str() + str.length());
}
if (http_code < 200 || http_code >= 300) {
ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Code: %d", this->url_.c_str(), http_code);
this->status_set_warning();
return response;
}
this->status_clear_warning();
ESP_LOGD(TAG, "HTTP Request completed; URL: %s; Code: %d", this->url_.c_str(), http_code);
this->last_url_ = this->url_;
this->client_.end();
return response;
}
#ifdef USE_ESP8266
std::shared_ptr<WiFiClient> HttpRequestArduino::get_wifi_client_() {
#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS
if (this->secure_) {
if (this->wifi_client_secure_ == nullptr) {
this->wifi_client_secure_ = std::make_shared<BearSSL::WiFiClientSecure>();
this->wifi_client_secure_->setInsecure();
this->wifi_client_secure_->setBufferSizes(512, 512);
}
return this->wifi_client_secure_;
}
#endif
if (this->wifi_client_ == nullptr) {
this->wifi_client_ = std::make_shared<WiFiClient>();
}
return this->wifi_client_;
}
#endif
} // namespace http_request
} // namespace esphome
#endif // USE_ARDUINO

View File

@ -0,0 +1,40 @@
#pragma once
#include "http_request.h"
#ifdef USE_ARDUINO
#ifdef USE_ESP32
#include <HTTPClient.h>
#endif
#ifdef USE_ESP8266
#include <ESP8266HTTPClient.h>
#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS
#include <WiFiClientSecure.h>
#endif
#endif
namespace esphome {
namespace http_request {
class HttpRequestArduino : public HttpRequestComponent {
public:
void set_url(std::string url) override;
HttpResponse send() override;
protected:
std::string last_url_;
HTTPClient client_{};
#ifdef USE_ESP8266
std::shared_ptr<WiFiClient> wifi_client_;
#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS
std::shared_ptr<BearSSL::WiFiClientSecure> wifi_client_secure_;
#endif
std::shared_ptr<WiFiClient> get_wifi_client_();
#endif
};
} // namespace http_request
} // namespace esphome
#endif // USE_ARDUINO

View File

@ -0,0 +1,138 @@
#include "http_request_idf.h"
#ifdef USE_ESP_IDF
#include "esphome/components/network/util.h"
#include "esphome/core/application.h"
#include "esphome/core/defines.h"
#include "esphome/core/log.h"
namespace esphome {
namespace http_request {
static const char *const TAG = "http_request.idf";
esp_err_t http_event_handler(esp_http_client_event_t *evt) {
App.feed_wdt();
switch (evt->event_id) {
case HTTP_EVENT_ERROR:
ESP_LOGE(TAG, "HTTP_EVENT_ERROR");
break;
case HTTP_EVENT_ON_CONNECTED:
ESP_LOGV(TAG, "HTTP_EVENT_ON_CONNECTED");
break;
case HTTP_EVENT_HEADER_SENT:
ESP_LOGV(TAG, "HTTP_EVENT_HEADER_SENT");
break;
case HTTP_EVENT_ON_HEADER:
ESP_LOGV(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
break;
case HTTP_EVENT_ON_DATA:
ESP_LOGV(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
/*
* Check for chunked encoding is added as the URL for chunked encoding used in this example returns binary data.
* However, event handler can also be used in case chunked encoding is used.
*/
if (!esp_http_client_is_chunked_response(evt->client)) {
if (global_http_request->get_capture_response()) {
auto &response = *reinterpret_cast<HttpResponse *>(evt->user_data);
auto *const data_begin = reinterpret_cast<char *>(evt->data);
auto *const data_end = data_begin + evt->data_len;
response.data.insert(response.data.end(), data_begin, data_end);
}
}
break;
case HTTP_EVENT_ON_FINISH:
ESP_LOGV(TAG, "HTTP_EVENT_ON_FINISH");
break;
case HTTP_EVENT_DISCONNECTED:
ESP_LOGV(TAG, "HTTP_EVENT_DISCONNECTED");
break;
}
return ESP_OK;
}
void HttpRequestIDF::set_url(std::string url) { this->url_ = std::move(url); }
HttpResponse HttpRequestIDF::send() {
if (!network::is_connected()) {
this->status_set_warning();
ESP_LOGE(TAG, "HTTP Request failed; Not connected to network");
return {};
}
esp_http_client_method_t method;
if (this->method_ == "GET") {
method = HTTP_METHOD_GET;
} else if (this->method_ == "POST") {
method = HTTP_METHOD_POST;
} else if (this->method_ == "PUT") {
method = HTTP_METHOD_PUT;
} else if (this->method_ == "DELETE") {
method = HTTP_METHOD_DELETE;
} else if (this->method_ == "PATCH") {
method = HTTP_METHOD_PATCH;
} else {
this->status_set_warning();
ESP_LOGE(TAG, "HTTP Request failed; Unsupported method");
return {};
}
HttpResponse response = {}; // used as user_data, by http_event_handler, in esp_http_client_perform
esp_http_client_config_t config = {};
config.url = this->url_.c_str();
config.method = method;
config.timeout_ms = this->timeout_;
config.disable_auto_redirect = !this->follow_redirects_;
config.max_redirection_count = this->redirect_limit_;
config.user_data = reinterpret_cast<void *>(&response);
config.event_handler = &http_event_handler;
if (this->useragent_ != nullptr) {
config.user_agent = this->useragent_;
}
esp_http_client_handle_t client = esp_http_client_init(&config);
for (const auto &header : this->headers_) {
esp_http_client_set_header(client, header.name, header.value);
}
if (!this->body_.empty()) {
esp_http_client_set_post_field(client, this->body_.c_str(), this->body_.length());
}
esp_err_t err = esp_http_client_perform(client);
if (err != ESP_OK) {
this->status_set_warning();
ESP_LOGE(TAG, "HTTP Request failed: %s", esp_err_to_name(err));
esp_http_client_cleanup(client);
return {};
}
const auto status_code = esp_http_client_get_status_code(client);
response.status_code = status_code;
response.content_length = esp_http_client_get_content_length(client);
if (status_code < 200 || status_code >= 300) {
ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", this->url_.c_str(), status_code);
this->status_set_warning();
return response;
}
this->status_clear_warning();
ESP_LOGD(TAG, "HTTP Request completed; URL: %s; Code: %d", this->url_.c_str(), status_code);
esp_http_client_cleanup(client);
return response;
}
} // namespace http_request
} // namespace esphome
#endif // USE_ESP_IDF

View File

@ -0,0 +1,31 @@
#pragma once
#include "http_request.h"
#ifdef USE_ESP_IDF
#include "esp_event.h"
#include "esp_http_client.h"
#include "esp_netif.h"
#include "esp_tls.h"
namespace esphome {
namespace http_request {
static const size_t RESPONSE_BUFFER_SIZE = 2048;
class HttpRequestIDF : public HttpRequestComponent {
public:
void set_url(std::string url) override;
HttpResponse send() override;
protected:
char last_response_buffer_[RESPONSE_BUFFER_SIZE];
int last_status_code_ = 0;
int last_content_length_ = 0;
};
} // namespace http_request
} // namespace esphome
#endif // USE_ESP_IDF