From 353b001917ae3f135e6fd55c62818f23564660e8 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 23 Oct 2023 00:52:19 +0200 Subject: [PATCH 01/97] ota_http component --- esphome/components/ota_http/README.md | 38 +++++ esphome/components/ota_http/__init__.py | 140 ++++++++++++++++++ esphome/components/ota_http/ota_http.cpp | 129 ++++++++++++++++ esphome/components/ota_http/ota_http.h | 72 +++++++++ .../components/ota_http/ota_http_arduino.cpp | 125 ++++++++++++++++ .../components/ota_http/ota_http_arduino.h | 43 ++++++ esphome/components/ota_http/ota_http_idf.cpp | 89 +++++++++++ esphome/components/ota_http/ota_http_idf.h | 25 ++++ 8 files changed, 661 insertions(+) create mode 100644 esphome/components/ota_http/README.md create mode 100644 esphome/components/ota_http/__init__.py create mode 100644 esphome/components/ota_http/ota_http.cpp create mode 100644 esphome/components/ota_http/ota_http.h create mode 100644 esphome/components/ota_http/ota_http_arduino.cpp create mode 100644 esphome/components/ota_http/ota_http_arduino.h create mode 100644 esphome/components/ota_http/ota_http_idf.cpp create mode 100644 esphome/components/ota_http/ota_http_idf.h diff --git a/esphome/components/ota_http/README.md b/esphome/components/ota_http/README.md new file mode 100644 index 0000000000..14d77543d8 --- /dev/null +++ b/esphome/components/ota_http/README.md @@ -0,0 +1,38 @@ +### ota_http + +ota in client (http) mode: This allow to do a remote ota when the device is far away, behind a firewall, and only reachable with mqtt. (For ex in an other house). + + + +```yaml +external_components: + - source: github://oarcher/piotech/ + + +ota_http: + + +button: + - platform: template + name: "Firmware update" + on_press: + then: + - ota_http.flash: + url: http://example.com/firmware.bin + - logger.log: "This message should be not displayed(reboot)" +``` + +The file `firmware.bin` can be found at `.esphome/build/xxxx/.pioenvs/xxx/firmware.bin` if esphome CLI is used, or downloaded as `Legacy format` from the esphome HA addon. Do not use `firmware-factory.bin` or `Modern format`. + +You should got in the logs: +``` +[18:48:30][D][button:010]: 'Firmware update' Pressed. +[18:48:30][D][ota_http:079]: Trying to connect to http://rasp:8080/firmware.bin +[18:48:30][D][ota_http:042]: Using ArduinoESP32OTABackend +[18:48:30][D][ota_http:209]: Progress: 0.1% +... +[18:48:39][D][ota_http:209]: Progress: 100.0% +[18:48:39][D][ota_http:218]: Done in 100 secs +[18:48:39][D][ota_http:223]: md5sum recieved: 38e2cad1c79fb38583361a41b9d16d27 (size 1378112) +[18:48:39][I][ota_http:242]: OTA update finished! Rebooting... +``` diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py new file mode 100644 index 0000000000..f2ce0344ee --- /dev/null +++ b/esphome/components/ota_http/__init__.py @@ -0,0 +1,140 @@ +import urllib.parse as urlparse + +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import automation +from esphome.const import ( + CONF_ID, + CONF_TIMEOUT, + CONF_URL, + CONF_METHOD, + CONF_ESP8266_DISABLE_SSL_SUPPORT, +) +from esphome.components import esp32 +from esphome.core import Lambda, CORE + +DEPENDENCIES = ["network"] +AUTO_LOAD = ["md5"] + +ota_http_ns = cg.esphome_ns.namespace("ota_http") +OtaHttpComponent = ota_http_ns.class_("OtaHttpComponent", cg.Component) +OtaHttpArduino = ota_http_ns.class_("OtaHttpArduino", OtaHttpComponent) +OtaHttpIDF = ota_http_ns.class_("OtaHttpIDF", OtaHttpComponent) + +OtaHttpFlashAction = ota_http_ns.class_("OtaHttpFlashAction", automation.Action) + +CONF_VERIFY_SSL = "verify_ssl" + + +def validate_url(value): + value = cv.string(value) + try: + parsed = list(urlparse.urlparse(value)) + except Exception as err: + raise cv.Invalid("Invalid URL") from err + + if not parsed[0] or not parsed[1]: + raise cv.Invalid("URL must have a URL scheme and host") + + if parsed[0] not in ["http", "https"]: + raise cv.Invalid("Scheme must be http or https") + + if not parsed[2]: + parsed[2] = "/" + + return urlparse.urlunparse(parsed) + + +def validate_secure_url(config): + url_ = config[CONF_URL] + if ( + config.get(CONF_VERIFY_SSL) + and not isinstance(url_, Lambda) + and url_.lower().startswith("https:") + ): + raise cv.Invalid( + "Currently ESPHome doesn't support SSL verification. " + "Set 'verify_ssl: false' to make insecure HTTPS requests." + ) + return config + + +def _declare_request_class(value): + if CORE.using_esp_idf: + return cv.declare_id(OtaHttpIDF)(value) + + if CORE.is_esp8266 or CORE.is_esp32: + return cv.declare_id(OtaHttpArduino)(value) + return NotImplementedError + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + + cv.GenerateID(): _declare_request_class, + cv.Optional( + CONF_TIMEOUT, default="5min" + ): cv.positive_time_period_milliseconds, + cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( + cv.only_on_esp8266, cv.boolean + ), + } + ).extend(cv.COMPONENT_SCHEMA), + 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), + ), +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + cg.add(var.set_timeout(config[CONF_TIMEOUT])) + + if CORE.is_esp8266 and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT]: + cg.add_define("USE_HTTP_REQUEST_ESP8266_HTTPS") + + if CORE.is_esp32: + 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) + + await cg.register_component(var, config) + + +OTA_HTTP_ACTION_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(OtaHttpComponent), + cv.Required(CONF_URL): cv.templatable(validate_url), + cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, + } +).add_extra(validate_secure_url) +OTA_HTTP_FLASH_ACTION_SCHEMA = automation.maybe_conf( + CONF_URL, + OTA_HTTP_ACTION_SCHEMA.extend( + { + cv.Optional(CONF_METHOD, default="flash"): cv.string, + } + ), +) + + +@automation.register_action( + "ota_http.flash", OtaHttpFlashAction, OTA_HTTP_FLASH_ACTION_SCHEMA +) +async def ota_http_action_to_code(config, action_id, template_arg, args): + paren = await cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg, paren) + + template_ = await cg.templatable(config[CONF_URL], args, cg.std_string) + cg.add(var.set_url(template_)) + return var diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp new file mode 100644 index 0000000000..9dce1ea7c3 --- /dev/null +++ b/esphome/components/ota_http/ota_http.cpp @@ -0,0 +1,129 @@ +#include "esphome/core/defines.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" +#include "esphome/components/md5/md5.h" +#include "esphome/components/ota/ota_backend_arduino_esp32.h" +#include "esphome/components/ota/ota_backend_arduino_esp8266.h" +#include "esphome/components/ota/ota_backend_arduino_rp2040.h" +#include "esphome/components/ota/ota_backend_esp_idf.h" +#include "esphome/components/ota/ota_backend.h" +#include "ota_http.h" + +namespace esphome { +namespace ota_http { + +std::unique_ptr make_ota_backend() { +#ifdef USE_ESP8266 + ESP_LOGD(TAG, "Using ArduinoESP8266OTABackend"); + return make_unique(); +#endif // USE_ESP8266 + +#ifdef USE_ARDUINO +#ifdef USE_ESP32 + ESP_LOGD(TAG, "Using ArduinoESP32OTABackend"); + return make_unique(); +#endif // USE_ESP32 +#endif // USE_ARDUINO + +#ifdef USE_ESP_IDF + ESP_LOGD(TAG, "Using IDFOTABackend"); + return make_unique(); +#endif // USE_ESP_IDF +#ifdef USE_RP2040 + ESP_LOGD(TAG, "Using ArduinoRP2040OTABackend"); + return make_unique(); +#endif // USE_RP2040 + ESP_LOGE(TAG, "No OTA backend!"); +} + +std::unique_ptr OtaHttpComponent::backend_ = make_ota_backend(); + +void OtaHttpComponent::flash() { + unsigned long update_start_time = millis(); + const size_t chunk_size = 1024; // must be =< HTTP_TCP_BUFFER_SIZE; + uint8_t buf[chunk_size + 1]; + int error_code = 0; + unsigned long last_progress = 0; + esphome::md5::MD5Digest md5_receive; + char *md5_receive_str = new char[33]; + + if (!this->http_init()) { + return; + } + + // we will compute md5 on the fly + // TODO: better security if fetched from the http server + md5_receive.init(); + ESP_LOGV(TAG, "md5sum from received data initialized."); + + error_code = this->backend_->begin(this->body_length); + if (error_code != 0) { + ESP_LOGW(TAG, "this->backend_->begin error: %d", error_code); + this->cleanup(); + return; + } + ESP_LOGV(TAG, "OTA backend begin"); + + while (this->bytes_read != this->body_length) { + // read a maximum of chunk_size bytes into buf. (real read size returned) + size_t bufsize = this->http_read(buf, chunk_size); + + // add read bytes to md5 + md5_receive.add(buf, bufsize); + + // write bytes to OTA backend + this->update_started_ = true; + error_code = this->backend_->write(buf, bufsize); + if (error_code != 0) { + // error code explaination available at + // https://github.com/esphome/esphome/blob/dev/esphome/components/ota/ota_component.h + ESP_LOGE(TAG, "Error code (%d) writing binary data to flash at offset %d and size %d", error_code, + this->bytes_read - bufsize, this->body_length); + this->cleanup(); + return; + } + + unsigned long now = millis(); + if ((now - last_progress > 1000) or (this->bytes_read == this->body_length)) { + last_progress = now; + ESP_LOGI(TAG, "Progress: %0.1f%%", this->bytes_read * 100. / this->body_length); + // feed watchdog and give other tasks a chance to run + esphome::App.feed_wdt(); + yield(); + } + } // while + + ESP_LOGI(TAG, "Done in %.0f secs", float(millis() - update_start_time) / 1000); + + // send md5 to backend (backend will check that the flashed one has the same) + md5_receive.calculate(); + md5_receive.get_hex(md5_receive_str); + ESP_LOGD(TAG, "md5sum recieved: %s (size %d)", md5_receive_str, bytes_read); + this->backend_->set_update_md5(md5_receive_str); + + this->http_end(); + + delete[] md5_receive_str; + + // feed watchdog and give other tasks a chance to run + esphome::App.feed_wdt(); + yield(); + delay(100); + + error_code = this->backend_->end(); + if (error_code != 0) { + ESP_LOGE(TAG, "Error ending OTA!, error_code: %d", error_code); + this->cleanup(); + return; + } + + delay(10); + ESP_LOGI(TAG, "OTA update finished! Rebooting..."); + delay(100); // NOLINT + esphome::App.safe_reboot(); + // new firmware flashed! + return; +} + +} // namespace ota_http +} // namespace esphome diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h new file mode 100644 index 0000000000..eb332e3221 --- /dev/null +++ b/esphome/components/ota_http/ota_http.h @@ -0,0 +1,72 @@ +#pragma once + +#include "esphome/core/log.h" +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/components/ota/ota_backend.h" + +#include +#include +#include + +namespace esphome { +namespace ota_http { + +static const char *const TAG = "ota_http"; + +class OtaHttpComponent : public Component { + public: + void dump_config() override { + ESP_LOGCONFIG(TAG, "OTA_http:"); + ESP_LOGCONFIG(TAG, " Timeout: %llums", (uint64_t) this->timeout_); + }; + float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } + void set_url(std::string url) { + this->url_ = std::move(url); + this->secure_ = this->url_.rfind("https:", 0) == 0; + } + void set_timeout(uint64_t timeout) { this->timeout_ = timeout; } + void flash(); + virtual int http_init() { return -1; }; + virtual size_t http_read(uint8_t *buf, size_t len) { return 0; }; + virtual void http_end(){}; + + protected: + std::string url_; + bool secure_; + size_t body_length = 0; + size_t bytes_read = 0; + uint64_t timeout_{1000 * 60 * 10}; // must match CONF_TIMEOUT in __init__.py + bool update_started_ = false; + static std::unique_ptr backend_; + void cleanup() { + if (this->update_started_) { + ESP_LOGE(TAG, "Abort OTA backend"); + this->backend_->abort(); + } + ESP_LOGE(TAG, "Abort http con"); + this->http_end(); + }; +}; + +template class OtaHttpFlashAction : public Action { + public: + OtaHttpFlashAction(OtaHttpComponent *parent) : parent_(parent) {} + TEMPLATABLE_VALUE(std::string, url) + TEMPLATABLE_VALUE(uint16_t, timeout) + + void play(Ts... x) override { + this->parent_->set_url(this->url_.value(x...)); + if (this->timeout_.has_value()) { + this->parent_->set_timeout(this->timeout_.value(x...)); + } + this->parent_->flash(); + } + + protected: + OtaHttpComponent *parent_; +}; + +} // namespace ota_http +} // namespace esphome diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp new file mode 100644 index 0000000000..9c915e52ec --- /dev/null +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -0,0 +1,125 @@ +// firmware update from http (ie when OTA port is behind a firewall) +// code adapted from +// esphome/components/ota/ota_backend.cpp +// and +// esphome/components/http_request + +#include "ota_http.h" + +#ifdef USE_ARDUINO +#include "ota_http_arduino.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" +#include "esphome/components/network/util.h" +#include "esphome/components/md5/md5.h" + +namespace esphome { +namespace ota_http { + +struct Header { + const char *name; + const char *value; +}; + +int OtaHttpArduino::http_init() { + int http_code; + unsigned long start_time; + unsigned long duration; + + const char *headerKeys[] = {"Content-Length", "Content-Type"}; + const size_t headerCount = sizeof(headerKeys) / sizeof(headerKeys[0]); + +#ifdef USE_ESP8266 +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS + if (this->secure_) { + ESP_LOGE(TAG, "https connection not handled!"); + } +#endif // USE_HTTP_REQUEST_ESP8266_HTTPS +#endif // USE_ESP8266 + + ESP_LOGD(TAG, "Trying to connect to %s", this->url_.c_str()); + + bool status = false; +#ifdef USE_ESP32 + status = this->client_.begin(this->url_.c_str()); +#endif +#ifdef USE_ESP8266 + status = client_.begin(*this->streamPtr, this->url_.c_str()); +#endif + + if (!status) { + ESP_LOGE(TAG, "Unable to make http connection"); + this->client_.end(); + return -1; + } else { + ESP_LOGV(TAG, "http begin successfull."); + } + + this->client_.setReuse(true); + ESP_LOGVV(TAG, "http client setReuse."); + + // returned needed headers must be collected before the requests + this->client_.collectHeaders(headerKeys, headerCount); + ESP_LOGV(TAG, "http headers collected."); + + // http GET + start_time = millis(); + http_code = this->client_.GET(); + duration = millis() - start_time; + ESP_LOGV(TAG, "http GET finished."); + + if (http_code >= 310) { + ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s (%d); Duration: %lu ms", url_.c_str(), + HTTPClient::errorToString(http_code).c_str(), http_code, duration); + return -1; + } + + if (this->client_.getSize() < 0) { + ESP_LOGE(TAG, "Incorrect file size (%d) reported by http server (http status: %d). Aborting", + this->client_.getSize(), http_code); + return -1; + } + + this->body_length = (size_t) this->client_.getSize(); + ESP_LOGD(TAG, "firmware is %d bytes length.", this->body_length); + +#ifdef USE_ESP32 + this->streamPtr = this->client_.getStreamPtr(); +#endif + + return 1; +} + +size_t OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { + // wait for the stream to be populated + while (this->streamPtr->available() == 0) { + // give other tasks a chance to run while waiting for some data: + // ESP_LOGVV(TAG, "not enougth data available: %zu (total read: %zu)", streamPtr->available(), bytes_read); + yield(); + delay(1); + } + // size_t bufsize = std::min(max_len, this->body_length - this->bytes_read); + int available_data = this->streamPtr->available(); + if (available_data < 0) { + ESP_LOGE(TAG, "ERROR: stream closed"); + this->cleanup(); + return -1; + } + size_t bufsize = std::min(max_len, (size_t) available_data); + + // ESP_LOGVV(TAG, "data available: %zu", available_data); + + this->streamPtr->readBytes(buf, bufsize); + this->bytes_read += bufsize; + buf[bufsize] = '\0'; // not fed to ota + + return bufsize; +} + +void OtaHttpArduino::http_end() { this->client_.end(); } + +} // namespace ota_http +} // namespace esphome + +#endif // USE_ARDUINO diff --git a/esphome/components/ota_http/ota_http_arduino.h b/esphome/components/ota_http/ota_http_arduino.h new file mode 100644 index 0000000000..ed537e10ed --- /dev/null +++ b/esphome/components/ota_http/ota_http_arduino.h @@ -0,0 +1,43 @@ +#pragma once + +#include "ota_http.h" + +#ifdef USE_ARDUINO + +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/defines.h" + +#include +#include +#include + +#ifdef USE_ESP32 +#include +#endif +#ifdef USE_ESP8266 +#include +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS +#include +#endif +#endif + +namespace esphome { +namespace ota_http { + +class OtaHttpArduino : public OtaHttpComponent { + public: + int http_init() override; + size_t http_read(uint8_t *buf, size_t len) override; + void http_end() override; + + protected: + HTTPClient client_{}; + WiFiClient stream; // needed for 8266 + WiFiClient *streamPtr = &stream; +}; + +} // namespace ota_http +} // namespace esphome + +#endif // USE_ARDUINO diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp new file mode 100644 index 0000000000..c57050381a --- /dev/null +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -0,0 +1,89 @@ + + +#ifdef USE_ESP_IDF + +#include "ota_http_idf.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" +#include "esphome/components/network/util.h" +#include "esphome/components/md5/md5.h" + +#include +#include +#include +#include +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_event.h" +#include "esp_netif.h" +#include "esp_tls.h" +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE +#include "esp_crt_bundle.h" +#endif + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" + +#include "esp_http_client.h" + +#define MAX_HTTP_RECV_BUFFER 512 +#define MAX_HTTP_OUTPUT_BUFFER 2048 +static const char *TAG = "HTTP_CLIENT"; + +namespace esphome { +namespace ota_http { + +int OtaHttpIDF::http_init() { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" + esp_http_client_config_t config = {0}; + config.url = this->url_.c_str(); + config.method = HTTP_METHOD_GET; + config.timeout_ms = (int) this->timeout_; + config.buffer_size = MAX_HTTP_RECV_BUFFER; +#pragma GCC diagnostic pop + + this->client_ = esp_http_client_init(&config); + esp_err_t err; + if ((err = esp_http_client_open(this->client_, 0)) != ESP_OK) { + ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); + return 0; + } + this->body_length = esp_http_client_fetch_headers(this->client_); + + ESP_LOGD(TAG, "body_length: %d , esp_http_client_get_content_length: %d", this->body_length, + esp_http_client_get_content_length(this->client_)); + + if (this->body_length <= 0) { + ESP_LOGE(TAG, "Incorrect file size (%d) reported by http server (http status: %d). Aborting", this->body_length, + err); + return -1; + } + return 1; +} + +size_t OtaHttpIDF::http_read(uint8_t *buf, const size_t max_len) { + size_t bufsize = std::min(max_len, this->body_length - this->bytes_read); + int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); + if (read_len <= 0) { + ESP_LOGE(TAG, "Error read data"); + } else { + this->bytes_read += bufsize; + buf[bufsize] = '\0'; // not fed to ota + } + // ESP_LOGVV(TAG, "Read %d bytes, %d remainings", read_len, this->body_length - this->bytes_read); + + return (size_t) read_len; // FIXME size_t dosen't allow < 0 +} + +void OtaHttpIDF::http_end() { + esp_http_client_close(this->client_); + esp_http_client_cleanup(this->client_); +} + +} // namespace ota_http +} // namespace esphome + +#endif // USE_ESP_IDF diff --git a/esphome/components/ota_http/ota_http_idf.h b/esphome/components/ota_http/ota_http_idf.h new file mode 100644 index 0000000000..bcae2fbf08 --- /dev/null +++ b/esphome/components/ota_http/ota_http_idf.h @@ -0,0 +1,25 @@ +#pragma once + +#include "ota_http.h" + +#ifdef USE_ESP_IDF + +#include "esp_http_client.h" + +namespace esphome { +namespace ota_http { + +class OtaHttpIDF : public OtaHttpComponent { + public: + int http_init() override; + size_t http_read(uint8_t *buf, size_t len) override; + void http_end() override; + + protected: + esp_http_client_handle_t client_{}; +}; + +} // namespace ota_http +} // namespace esphome + +#endif // USE_ESP_IDF From 5d8349c26c8c1adbdcc2e3d7e58ff14c975d7b5f Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 23 Oct 2023 01:36:29 +0200 Subject: [PATCH 02/97] updated CODEOWNERS --- CODEOWNERS | 1 + esphome/components/ota_http/__init__.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CODEOWNERS b/CODEOWNERS index 4c24096faa..af9aa4c0ec 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -246,6 +246,7 @@ esphome/components/nfc/* @jesserockz @kbx81 esphome/components/noblex/* @AGalfra esphome/components/number/* @esphome/core esphome/components/ota/* @esphome/core +esphome/components/ota_http/* @oarcher esphome/components/output/* @esphome/core esphome/components/pca6416a/* @Mat931 esphome/components/pca9554/* @clydebarrow @hwstar diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index f2ce0344ee..4f099c0bad 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -13,6 +13,8 @@ from esphome.const import ( from esphome.components import esp32 from esphome.core import Lambda, CORE +CODEOWNERS = ["@oarcher"] + DEPENDENCIES = ["network"] AUTO_LOAD = ["md5"] From 75eae0363a7a963642fdf83bc5ee2d072e965ef3 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 23 Oct 2023 01:42:59 +0200 Subject: [PATCH 03/97] black --- esphome/components/ota_http/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 4f099c0bad..28384b6c5e 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -73,7 +73,6 @@ def _declare_request_class(value): CONFIG_SCHEMA = cv.All( cv.Schema( { - cv.GenerateID(): _declare_request_class, cv.Optional( CONF_TIMEOUT, default="5min" From 0d3fc410e2bfb9956cdfa365fcd7f7eb672d4138 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 23 Oct 2023 14:12:33 +0200 Subject: [PATCH 04/97] ci-custom fixes --- esphome/components/ota_http/ota_http.cpp | 18 ++++++++++++++++-- esphome/components/ota_http/ota_http.h | 15 ++------------- esphome/components/ota_http/ota_http_idf.cpp | 3 +-- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 9dce1ea7c3..dbba90793b 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -38,6 +38,11 @@ std::unique_ptr make_ota_backend() { std::unique_ptr OtaHttpComponent::backend_ = make_ota_backend(); +void OtaHttpComponent::dump_config() { + ESP_LOGCONFIG(TAG, "OTA_http:"); + ESP_LOGCONFIG(TAG, " Timeout: %llums", (uint64_t) this->timeout_); +}; + void OtaHttpComponent::flash() { unsigned long update_start_time = millis(); const size_t chunk_size = 1024; // must be =< HTTP_TCP_BUFFER_SIZE; @@ -108,7 +113,7 @@ void OtaHttpComponent::flash() { // feed watchdog and give other tasks a chance to run esphome::App.feed_wdt(); yield(); - delay(100); + delay(100); // NOLINT error_code = this->backend_->end(); if (error_code != 0) { @@ -119,11 +124,20 @@ void OtaHttpComponent::flash() { delay(10); ESP_LOGI(TAG, "OTA update finished! Rebooting..."); - delay(100); // NOLINT + delay(10); esphome::App.safe_reboot(); // new firmware flashed! return; } +void OtaHttpComponent::cleanup() { + if (this->update_started_) { + ESP_LOGE(TAG, "Abort OTA backend"); + this->backend_->abort(); + } + ESP_LOGE(TAG, "Abort http con"); + this->http_end(); +}; + } // namespace ota_http } // namespace esphome diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index eb332e3221..cb84ee51f5 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -1,6 +1,5 @@ #pragma once -#include "esphome/core/log.h" #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/defines.h" @@ -17,10 +16,7 @@ static const char *const TAG = "ota_http"; class OtaHttpComponent : public Component { public: - void dump_config() override { - ESP_LOGCONFIG(TAG, "OTA_http:"); - ESP_LOGCONFIG(TAG, " Timeout: %llums", (uint64_t) this->timeout_); - }; + void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } void set_url(std::string url) { this->url_ = std::move(url); @@ -40,14 +36,7 @@ class OtaHttpComponent : public Component { uint64_t timeout_{1000 * 60 * 10}; // must match CONF_TIMEOUT in __init__.py bool update_started_ = false; static std::unique_ptr backend_; - void cleanup() { - if (this->update_started_) { - ESP_LOGE(TAG, "Abort OTA backend"); - this->backend_->abort(); - } - ESP_LOGE(TAG, "Abort http con"); - this->http_end(); - }; + void cleanup(); }; template class OtaHttpFlashAction : public Action { diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index c57050381a..bbacfd7453 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -28,8 +28,7 @@ #include "esp_http_client.h" -#define MAX_HTTP_RECV_BUFFER 512 -#define MAX_HTTP_OUTPUT_BUFFER 2048 +static const uint16_t MAX_HTTP_RECV_BUFFER = 1024; static const char *TAG = "HTTP_CLIENT"; namespace esphome { From 1350bd803a48ada77dba8c565fa75378884a5724 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 23 Oct 2023 14:17:30 +0200 Subject: [PATCH 05/97] lint: Trailing whitespace --- esphome/components/ota_http/ota_http.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index dbba90793b..d4db64bb03 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -124,7 +124,7 @@ void OtaHttpComponent::flash() { delay(10); ESP_LOGI(TAG, "OTA update finished! Rebooting..."); - delay(10); + delay(10); esphome::App.safe_reboot(); // new firmware flashed! return; From 97949bf58b053e6450b87d45ebd7dff861226263 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 23 Oct 2023 14:48:44 +0200 Subject: [PATCH 06/97] clang-tidy --- esphome/components/ota_http/ota_http.cpp | 32 +++++++++---------- esphome/components/ota_http/ota_http.h | 8 ++--- .../components/ota_http/ota_http_arduino.cpp | 24 +++++++------- .../components/ota_http/ota_http_arduino.h | 4 +-- esphome/components/ota_http/ota_http_idf.cpp | 14 ++++---- 5 files changed, 40 insertions(+), 42 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index d4db64bb03..62e5ba3d56 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -36,7 +36,7 @@ std::unique_ptr make_ota_backend() { ESP_LOGE(TAG, "No OTA backend!"); } -std::unique_ptr OtaHttpComponent::backend_ = make_ota_backend(); +std::unique_ptr OtaHttpComponent::backend = make_ota_backend(); void OtaHttpComponent::dump_config() { ESP_LOGCONFIG(TAG, "OTA_http:"); @@ -61,15 +61,15 @@ void OtaHttpComponent::flash() { md5_receive.init(); ESP_LOGV(TAG, "md5sum from received data initialized."); - error_code = this->backend_->begin(this->body_length); + error_code = esphome::ota_http::OtaHttpComponent::backend->begin(this->body_length_); if (error_code != 0) { ESP_LOGW(TAG, "this->backend_->begin error: %d", error_code); - this->cleanup(); + this->cleanup_(); return; } ESP_LOGV(TAG, "OTA backend begin"); - while (this->bytes_read != this->body_length) { + while (this->bytes_read_ != this->body_length_) { // read a maximum of chunk_size bytes into buf. (real read size returned) size_t bufsize = this->http_read(buf, chunk_size); @@ -78,20 +78,20 @@ void OtaHttpComponent::flash() { // write bytes to OTA backend this->update_started_ = true; - error_code = this->backend_->write(buf, bufsize); + error_code = esphome::ota_http::OtaHttpComponent::backend->write(buf, bufsize); if (error_code != 0) { // error code explaination available at // https://github.com/esphome/esphome/blob/dev/esphome/components/ota/ota_component.h ESP_LOGE(TAG, "Error code (%d) writing binary data to flash at offset %d and size %d", error_code, - this->bytes_read - bufsize, this->body_length); - this->cleanup(); + this->bytes_read_ - bufsize, this->body_length_); + this->cleanup_(); return; } unsigned long now = millis(); - if ((now - last_progress > 1000) or (this->bytes_read == this->body_length)) { + if ((now - last_progress > 1000) or (this->bytes_read_ == this->body_length_)) { last_progress = now; - ESP_LOGI(TAG, "Progress: %0.1f%%", this->bytes_read * 100. / this->body_length); + ESP_LOGI(TAG, "Progress: %0.1f%%", this->bytes_read_ * 100. / this->body_length_); // feed watchdog and give other tasks a chance to run esphome::App.feed_wdt(); yield(); @@ -103,8 +103,8 @@ void OtaHttpComponent::flash() { // send md5 to backend (backend will check that the flashed one has the same) md5_receive.calculate(); md5_receive.get_hex(md5_receive_str); - ESP_LOGD(TAG, "md5sum recieved: %s (size %d)", md5_receive_str, bytes_read); - this->backend_->set_update_md5(md5_receive_str); + ESP_LOGD(TAG, "md5sum recieved: %s (size %d)", md5_receive_str, bytes_read_); + esphome::ota_http::OtaHttpComponent::backend->set_update_md5(md5_receive_str); this->http_end(); @@ -115,10 +115,10 @@ void OtaHttpComponent::flash() { yield(); delay(100); // NOLINT - error_code = this->backend_->end(); + error_code = esphome::ota_http::OtaHttpComponent::backend->end(); if (error_code != 0) { ESP_LOGE(TAG, "Error ending OTA!, error_code: %d", error_code); - this->cleanup(); + this->cleanup_(); return; } @@ -126,14 +126,12 @@ void OtaHttpComponent::flash() { ESP_LOGI(TAG, "OTA update finished! Rebooting..."); delay(10); esphome::App.safe_reboot(); - // new firmware flashed! - return; } -void OtaHttpComponent::cleanup() { +void OtaHttpComponent::cleanup_() { if (this->update_started_) { ESP_LOGE(TAG, "Abort OTA backend"); - this->backend_->abort(); + esphome::ota_http::OtaHttpComponent::backend->abort(); } ESP_LOGE(TAG, "Abort http con"); this->http_end(); diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index cb84ee51f5..3a65074e98 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -31,12 +31,12 @@ class OtaHttpComponent : public Component { protected: std::string url_; bool secure_; - size_t body_length = 0; - size_t bytes_read = 0; + size_t body_length_ = 0; + size_t bytes_read_ = 0; uint64_t timeout_{1000 * 60 * 10}; // must match CONF_TIMEOUT in __init__.py bool update_started_ = false; - static std::unique_ptr backend_; - void cleanup(); + static std::unique_ptr backend; + void cleanup_(); }; template class OtaHttpFlashAction : public Action { diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 9c915e52ec..8f3cbe3d44 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -27,8 +27,8 @@ int OtaHttpArduino::http_init() { unsigned long start_time; unsigned long duration; - const char *headerKeys[] = {"Content-Length", "Content-Type"}; - const size_t headerCount = sizeof(headerKeys) / sizeof(headerKeys[0]); + const char *header_keys[] = {"Content-Length", "Content-Type"}; + const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); #ifdef USE_ESP8266 #ifdef USE_HTTP_REQUEST_ESP8266_HTTPS @@ -45,7 +45,7 @@ int OtaHttpArduino::http_init() { status = this->client_.begin(this->url_.c_str()); #endif #ifdef USE_ESP8266 - status = client_.begin(*this->streamPtr, this->url_.c_str()); + status = client_.begin(*this->stream_ptr_, this->url_.c_str()); #endif if (!status) { @@ -60,7 +60,7 @@ int OtaHttpArduino::http_init() { ESP_LOGVV(TAG, "http client setReuse."); // returned needed headers must be collected before the requests - this->client_.collectHeaders(headerKeys, headerCount); + this->client_.collectHeaders(header_keys, header_count); ESP_LOGV(TAG, "http headers collected."); // http GET @@ -81,11 +81,11 @@ int OtaHttpArduino::http_init() { return -1; } - this->body_length = (size_t) this->client_.getSize(); - ESP_LOGD(TAG, "firmware is %d bytes length.", this->body_length); + this->body_length_ = (size_t) this->client_.getSize(); + ESP_LOGD(TAG, "firmware is %d bytes length.", this->body_length_); #ifdef USE_ESP32 - this->streamPtr = this->client_.getStreamPtr(); + this->stream_ptr_ = this->client_.getStreamPtr(); #endif return 1; @@ -93,25 +93,25 @@ int OtaHttpArduino::http_init() { size_t OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { // wait for the stream to be populated - while (this->streamPtr->available() == 0) { + while (this->stream_ptr_->available() == 0) { // give other tasks a chance to run while waiting for some data: // ESP_LOGVV(TAG, "not enougth data available: %zu (total read: %zu)", streamPtr->available(), bytes_read); yield(); delay(1); } // size_t bufsize = std::min(max_len, this->body_length - this->bytes_read); - int available_data = this->streamPtr->available(); + int available_data = this->stream_ptr_->available(); if (available_data < 0) { ESP_LOGE(TAG, "ERROR: stream closed"); - this->cleanup(); + this->cleanup_(); return -1; } size_t bufsize = std::min(max_len, (size_t) available_data); // ESP_LOGVV(TAG, "data available: %zu", available_data); - this->streamPtr->readBytes(buf, bufsize); - this->bytes_read += bufsize; + this->stream_ptr_->readBytes(buf, bufsize); + this->bytes_read_ += bufsize; buf[bufsize] = '\0'; // not fed to ota return bufsize; diff --git a/esphome/components/ota_http/ota_http_arduino.h b/esphome/components/ota_http/ota_http_arduino.h index ed537e10ed..3a43f485d4 100644 --- a/esphome/components/ota_http/ota_http_arduino.h +++ b/esphome/components/ota_http/ota_http_arduino.h @@ -33,8 +33,8 @@ class OtaHttpArduino : public OtaHttpComponent { protected: HTTPClient client_{}; - WiFiClient stream; // needed for 8266 - WiFiClient *streamPtr = &stream; + WiFiClient stream_; // needed for 8266 + WiFiClient *stream_ptr_ = &stream_; }; } // namespace ota_http diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index bbacfd7453..72b47d934f 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -50,13 +50,13 @@ int OtaHttpIDF::http_init() { ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); return 0; } - this->body_length = esp_http_client_fetch_headers(this->client_); + this->body_length_ = esp_http_client_fetch_headers(this->client_); - ESP_LOGD(TAG, "body_length: %d , esp_http_client_get_content_length: %d", this->body_length, + ESP_LOGD(TAG, "body_length: %d , esp_http_client_get_content_length: %d", this->body_length_, esp_http_client_get_content_length(this->client_)); - if (this->body_length <= 0) { - ESP_LOGE(TAG, "Incorrect file size (%d) reported by http server (http status: %d). Aborting", this->body_length, + if (this->body_length_ <= 0) { + ESP_LOGE(TAG, "Incorrect file size (%d) reported by http server (http status: %d). Aborting", this->body_length_, err); return -1; } @@ -64,15 +64,15 @@ int OtaHttpIDF::http_init() { } size_t OtaHttpIDF::http_read(uint8_t *buf, const size_t max_len) { - size_t bufsize = std::min(max_len, this->body_length - this->bytes_read); + size_t bufsize = std::min(max_len, this->body_length_ - this->bytes_read_); int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); if (read_len <= 0) { ESP_LOGE(TAG, "Error read data"); } else { - this->bytes_read += bufsize; + this->bytes_read_ += bufsize; buf[bufsize] = '\0'; // not fed to ota } - // ESP_LOGVV(TAG, "Read %d bytes, %d remainings", read_len, this->body_length - this->bytes_read); + // ESP_LOGVV(TAG, "Read %d bytes, %d remainings", read_len, this->body_length_ - this->bytes_read); return (size_t) read_len; // FIXME size_t dosen't allow < 0 } From 6f42eb662daa8377fc4eefd13c719d74b503f45d Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 23 Oct 2023 15:54:36 +0200 Subject: [PATCH 07/97] clang-tidy --- esphome/components/ota_http/ota_http.cpp | 18 ++++++++---------- esphome/components/ota_http/ota_http.h | 2 +- .../components/ota_http/ota_http_arduino.cpp | 4 ++-- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 62e5ba3d56..a55b8d3ff4 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -36,7 +36,7 @@ std::unique_ptr make_ota_backend() { ESP_LOGE(TAG, "No OTA backend!"); } -std::unique_ptr OtaHttpComponent::backend = make_ota_backend(); +const std::unique_ptr OtaHttpComponent::backend = make_ota_backend(); void OtaHttpComponent::dump_config() { ESP_LOGCONFIG(TAG, "OTA_http:"); @@ -44,13 +44,13 @@ void OtaHttpComponent::dump_config() { }; void OtaHttpComponent::flash() { - unsigned long update_start_time = millis(); + uint32_t update_start_time = millis(); const size_t chunk_size = 1024; // must be =< HTTP_TCP_BUFFER_SIZE; uint8_t buf[chunk_size + 1]; int error_code = 0; - unsigned long last_progress = 0; + uint32_t last_progress = 0; esphome::md5::MD5Digest md5_receive; - char *md5_receive_str = new char[33]; + std::unique_ptr md5_receive_str(new char[33]); if (!this->http_init()) { return; @@ -88,7 +88,7 @@ void OtaHttpComponent::flash() { return; } - unsigned long now = millis(); + uint32_t now = millis(); if ((now - last_progress > 1000) or (this->bytes_read_ == this->body_length_)) { last_progress = now; ESP_LOGI(TAG, "Progress: %0.1f%%", this->bytes_read_ * 100. / this->body_length_); @@ -102,14 +102,12 @@ void OtaHttpComponent::flash() { // send md5 to backend (backend will check that the flashed one has the same) md5_receive.calculate(); - md5_receive.get_hex(md5_receive_str); - ESP_LOGD(TAG, "md5sum recieved: %s (size %d)", md5_receive_str, bytes_read_); - esphome::ota_http::OtaHttpComponent::backend->set_update_md5(md5_receive_str); + md5_receive.get_hex(md5_receive_str.get()); + ESP_LOGD(TAG, "md5sum recieved: %s (size %d)", md5_receive_str.get(), bytes_read_); + esphome::ota_http::OtaHttpComponent::backend->set_update_md5(md5_receive_str.get()); this->http_end(); - delete[] md5_receive_str; - // feed watchdog and give other tasks a chance to run esphome::App.feed_wdt(); yield(); diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 3a65074e98..bb592089bd 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -35,7 +35,7 @@ class OtaHttpComponent : public Component { size_t bytes_read_ = 0; uint64_t timeout_{1000 * 60 * 10}; // must match CONF_TIMEOUT in __init__.py bool update_started_ = false; - static std::unique_ptr backend; + static const std::unique_ptr backend; void cleanup_(); }; diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 8f3cbe3d44..015ed7441c 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -24,8 +24,8 @@ struct Header { int OtaHttpArduino::http_init() { int http_code; - unsigned long start_time; - unsigned long duration; + uint32_t start_time; + uint32_t long duration; const char *header_keys[] = {"Content-Length", "Content-Type"}; const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); From 7a0f74780d18caa923442a8467a07a84d82e4b3a Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 23 Oct 2023 16:16:38 +0200 Subject: [PATCH 08/97] clang-tidy --- esphome/components/ota_http/ota_http.cpp | 14 +++++++------- esphome/components/ota_http/ota_http.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index a55b8d3ff4..2e0a8ac6be 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -36,7 +36,7 @@ std::unique_ptr make_ota_backend() { ESP_LOGE(TAG, "No OTA backend!"); } -const std::unique_ptr OtaHttpComponent::backend = make_ota_backend(); +const std::unique_ptr OtaHttpComponent::BACKEND = make_ota_backend(); void OtaHttpComponent::dump_config() { ESP_LOGCONFIG(TAG, "OTA_http:"); @@ -61,9 +61,9 @@ void OtaHttpComponent::flash() { md5_receive.init(); ESP_LOGV(TAG, "md5sum from received data initialized."); - error_code = esphome::ota_http::OtaHttpComponent::backend->begin(this->body_length_); + error_code = esphome::ota_http::OtaHttpComponent::BACKEND->begin(this->body_length_); if (error_code != 0) { - ESP_LOGW(TAG, "this->backend_->begin error: %d", error_code); + ESP_LOGW(TAG, "BACKEND->begin error: %d", error_code); this->cleanup_(); return; } @@ -78,7 +78,7 @@ void OtaHttpComponent::flash() { // write bytes to OTA backend this->update_started_ = true; - error_code = esphome::ota_http::OtaHttpComponent::backend->write(buf, bufsize); + error_code = esphome::ota_http::OtaHttpComponent::BACKEND->write(buf, bufsize); if (error_code != 0) { // error code explaination available at // https://github.com/esphome/esphome/blob/dev/esphome/components/ota/ota_component.h @@ -104,7 +104,7 @@ void OtaHttpComponent::flash() { md5_receive.calculate(); md5_receive.get_hex(md5_receive_str.get()); ESP_LOGD(TAG, "md5sum recieved: %s (size %d)", md5_receive_str.get(), bytes_read_); - esphome::ota_http::OtaHttpComponent::backend->set_update_md5(md5_receive_str.get()); + esphome::ota_http::OtaHttpComponent::BACKEND->set_update_md5(md5_receive_str.get()); this->http_end(); @@ -113,7 +113,7 @@ void OtaHttpComponent::flash() { yield(); delay(100); // NOLINT - error_code = esphome::ota_http::OtaHttpComponent::backend->end(); + error_code = esphome::ota_http::OtaHttpComponent::BACKEND->end(); if (error_code != 0) { ESP_LOGE(TAG, "Error ending OTA!, error_code: %d", error_code); this->cleanup_(); @@ -129,7 +129,7 @@ void OtaHttpComponent::flash() { void OtaHttpComponent::cleanup_() { if (this->update_started_) { ESP_LOGE(TAG, "Abort OTA backend"); - esphome::ota_http::OtaHttpComponent::backend->abort(); + esphome::ota_http::OtaHttpComponent::BACKEND->abort(); } ESP_LOGE(TAG, "Abort http con"); this->http_end(); diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index bb592089bd..3aaf124080 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -35,7 +35,7 @@ class OtaHttpComponent : public Component { size_t bytes_read_ = 0; uint64_t timeout_{1000 * 60 * 10}; // must match CONF_TIMEOUT in __init__.py bool update_started_ = false; - static const std::unique_ptr backend; + static const std::unique_ptr BACKEND; void cleanup_(); }; From d3508a379d6708b26225d54e04dca62bbff23014 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 23 Oct 2023 16:26:29 +0200 Subject: [PATCH 09/97] bad type --- esphome/components/ota_http/ota_http_arduino.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 015ed7441c..fca835ec05 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -25,7 +25,7 @@ struct Header { int OtaHttpArduino::http_init() { int http_code; uint32_t start_time; - uint32_t long duration; + uint32_t duration; const char *header_keys[] = {"Content-Length", "Content-Type"}; const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); From da895fc3b39adc58096e676d8d63a1201598c8be Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 23 Oct 2023 19:25:48 +0200 Subject: [PATCH 10/97] clang-tidy --- esphome/components/ota_http/ota_http_arduino.cpp | 2 +- esphome/components/ota_http/ota_http_idf.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index fca835ec05..5483b2b2c4 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -70,7 +70,7 @@ int OtaHttpArduino::http_init() { ESP_LOGV(TAG, "http GET finished."); if (http_code >= 310) { - ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s (%d); Duration: %lu ms", url_.c_str(), + ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s (%d); Duration: %u ms", url_.c_str(), HTTPClient::errorToString(http_code).c_str(), http_code, duration); return -1; } diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 72b47d934f..bb331b851f 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -9,15 +9,15 @@ #include "esphome/components/network/util.h" #include "esphome/components/md5/md5.h" -#include -#include -#include -#include -#include "esp_log.h" -#include "nvs_flash.h" #include "esp_event.h" +#include "esp_log.h" #include "esp_netif.h" #include "esp_tls.h" +#include "nvs_flash.h" +#include +#include +#include +#include #if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE #include "esp_crt_bundle.h" #endif @@ -37,7 +37,7 @@ namespace ota_http { int OtaHttpIDF::http_init() { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" - esp_http_client_config_t config = {0}; + esp_http_client_config_t config = {nullptr}; config.url = this->url_.c_str(); config.method = HTTP_METHOD_GET; config.timeout_ms = (int) this->timeout_; From dadf2d02ecab319d6ab88040b1ee933302b21782 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 23 Oct 2023 20:01:53 +0200 Subject: [PATCH 11/97] removed log tag for idf --- esphome/components/ota_http/ota_http_idf.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index bb331b851f..0b49911bd2 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -29,7 +29,6 @@ #include "esp_http_client.h" static const uint16_t MAX_HTTP_RECV_BUFFER = 1024; -static const char *TAG = "HTTP_CLIENT"; namespace esphome { namespace ota_http { From c3207f63e217e7f2a9e84fdd338d6006bc7d65e6 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 23 Oct 2023 20:09:40 +0000 Subject: [PATCH 12/97] added tests --- tests/test1.yaml | 2 ++ tests/test3.yaml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/test1.yaml b/tests/test1.yaml index c8ae9691c2..37f106da78 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -289,6 +289,8 @@ ota: lambda: >- ESP_LOGD("ota", "Got error code %d", x); +ota_http: + logger: baud_rate: 0 level: VERBOSE diff --git a/tests/test3.yaml b/tests/test3.yaml index 61d814385b..bf819d60f0 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -332,6 +332,8 @@ ota: port: 3286 reboot_timeout: 15min +ota_http: + logger: hardware_uart: UART1 level: DEBUG From b753f6d06ef50b4d468b40c2844536887b204290 Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 27 Oct 2023 02:11:28 +0000 Subject: [PATCH 13/97] allow https for 8266 --- esphome/components/ota_http/ota_http.cpp | 5 ++--- esphome/components/ota_http/ota_http.h | 2 ++ esphome/components/ota_http/ota_http_arduino.cpp | 11 ++++++++--- esphome/components/ota_http/ota_http_arduino.h | 5 +++-- esphome/components/ota_http/ota_http_idf.cpp | 4 +--- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 2e0a8ac6be..9c33178a2a 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -45,8 +45,7 @@ void OtaHttpComponent::dump_config() { void OtaHttpComponent::flash() { uint32_t update_start_time = millis(); - const size_t chunk_size = 1024; // must be =< HTTP_TCP_BUFFER_SIZE; - uint8_t buf[chunk_size + 1]; + uint8_t buf[this->HTTP_RECV_BUFFER_ + 1]; int error_code = 0; uint32_t last_progress = 0; esphome::md5::MD5Digest md5_receive; @@ -71,7 +70,7 @@ void OtaHttpComponent::flash() { while (this->bytes_read_ != this->body_length_) { // read a maximum of chunk_size bytes into buf. (real read size returned) - size_t bufsize = this->http_read(buf, chunk_size); + size_t bufsize = this->http_read(buf, this->HTTP_RECV_BUFFER_); // add read bytes to md5 md5_receive.add(buf, bufsize); diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 3aaf124080..a88fd6f13b 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -34,6 +34,8 @@ class OtaHttpComponent : public Component { size_t body_length_ = 0; size_t bytes_read_ = 0; uint64_t timeout_{1000 * 60 * 10}; // must match CONF_TIMEOUT in __init__.py + const uint16_t HTTP_RECV_BUFFER_ = 1000; // the firwmware GET chunk size + const uint16_t MAX_HTTP_RECV_BUFFER_ = 1024; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS overhead) and must be a power of two from 512 to 4096 bool update_started_ = false; static const std::unique_ptr BACKEND; void cleanup_(); diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 5483b2b2c4..3c76defda4 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -33,7 +33,12 @@ int OtaHttpArduino::http_init() { #ifdef USE_ESP8266 #ifdef USE_HTTP_REQUEST_ESP8266_HTTPS if (this->secure_) { - ESP_LOGE(TAG, "https connection not handled!"); + this->stream_ptr_ = std::make_unique(); + WiFiClientSecure *secureClient = static_cast(this->stream_ptr_.get()); + secureClient->setBufferSizes(this->MAX_HTTP_RECV_BUFFER_, 512); + secureClient->setInsecure(); + } else { + this->stream_ptr_ = std::make_unique(); } #endif // USE_HTTP_REQUEST_ESP8266_HTTPS #endif // USE_ESP8266 @@ -45,7 +50,7 @@ int OtaHttpArduino::http_init() { status = this->client_.begin(this->url_.c_str()); #endif #ifdef USE_ESP8266 - status = client_.begin(*this->stream_ptr_, this->url_.c_str()); + status = this->client_.begin(*this->stream_ptr_.get(), this->url_.c_str()); #endif if (!status) { @@ -85,7 +90,7 @@ int OtaHttpArduino::http_init() { ESP_LOGD(TAG, "firmware is %d bytes length.", this->body_length_); #ifdef USE_ESP32 - this->stream_ptr_ = this->client_.getStreamPtr(); + this->stream_ptr_ = std::unique_ptr(this->client_.getStreamPtr()); #endif return 1; diff --git a/esphome/components/ota_http/ota_http_arduino.h b/esphome/components/ota_http/ota_http_arduino.h index 3a43f485d4..e159d250c8 100644 --- a/esphome/components/ota_http/ota_http_arduino.h +++ b/esphome/components/ota_http/ota_http_arduino.h @@ -33,8 +33,9 @@ class OtaHttpArduino : public OtaHttpComponent { protected: HTTPClient client_{}; - WiFiClient stream_; // needed for 8266 - WiFiClient *stream_ptr_ = &stream_; + // WiFiClient stream_; // needed for 8266 + // WiFiClient *stream_ptr_ = nullptr; // &stream_; + std::unique_ptr stream_ptr_; }; } // namespace ota_http diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 0b49911bd2..0e965d3052 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -28,8 +28,6 @@ #include "esp_http_client.h" -static const uint16_t MAX_HTTP_RECV_BUFFER = 1024; - namespace esphome { namespace ota_http { @@ -40,7 +38,7 @@ int OtaHttpIDF::http_init() { config.url = this->url_.c_str(); config.method = HTTP_METHOD_GET; config.timeout_ms = (int) this->timeout_; - config.buffer_size = MAX_HTTP_RECV_BUFFER; + config.buffer_size = this->MAX_HTTP_RECV_BUFFER_; #pragma GCC diagnostic pop this->client_ = esp_http_client_init(&config); From 90717cd6526b883e4ed6d6d86c6118bf50cc1593 Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 27 Oct 2023 02:16:13 +0000 Subject: [PATCH 14/97] clang --- esphome/components/ota_http/ota_http.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index a88fd6f13b..96c25de9ba 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -33,9 +33,10 @@ class OtaHttpComponent : public Component { bool secure_; size_t body_length_ = 0; size_t bytes_read_ = 0; - uint64_t timeout_{1000 * 60 * 10}; // must match CONF_TIMEOUT in __init__.py - const uint16_t HTTP_RECV_BUFFER_ = 1000; // the firwmware GET chunk size - const uint16_t MAX_HTTP_RECV_BUFFER_ = 1024; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS overhead) and must be a power of two from 512 to 4096 + uint64_t timeout_{1000 * 60 * 10}; // must match CONF_TIMEOUT in __init__.py + const uint16_t HTTP_RECV_BUFFER_ = 1000; // the firwmware GET chunk size + const uint16_t MAX_HTTP_RECV_BUFFER_ = 1024; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS + // overhead) and must be a power of two from 512 to 4096 bool update_started_ = false; static const std::unique_ptr BACKEND; void cleanup_(); From 7026376a336b98801fd3a7cbbb15ee5c45157d8e Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 27 Oct 2023 02:29:04 +0000 Subject: [PATCH 15/97] clang --- esphome/components/ota_http/ota_http.cpp | 4 ++-- esphome/components/ota_http/ota_http.h | 4 ++-- esphome/components/ota_http/ota_http_arduino.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 9c33178a2a..e2e6bb7271 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -45,7 +45,7 @@ void OtaHttpComponent::dump_config() { void OtaHttpComponent::flash() { uint32_t update_start_time = millis(); - uint8_t buf[this->HTTP_RECV_BUFFER_ + 1]; + uint8_t buf[this->http_recv_buffer_ + 1]; int error_code = 0; uint32_t last_progress = 0; esphome::md5::MD5Digest md5_receive; @@ -70,7 +70,7 @@ void OtaHttpComponent::flash() { while (this->bytes_read_ != this->body_length_) { // read a maximum of chunk_size bytes into buf. (real read size returned) - size_t bufsize = this->http_read(buf, this->HTTP_RECV_BUFFER_); + size_t bufsize = this->http_read(buf, this->http_recv_buffer_); // add read bytes to md5 md5_receive.add(buf, bufsize); diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 96c25de9ba..e73bb94896 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -34,8 +34,8 @@ class OtaHttpComponent : public Component { size_t body_length_ = 0; size_t bytes_read_ = 0; uint64_t timeout_{1000 * 60 * 10}; // must match CONF_TIMEOUT in __init__.py - const uint16_t HTTP_RECV_BUFFER_ = 1000; // the firwmware GET chunk size - const uint16_t MAX_HTTP_RECV_BUFFER_ = 1024; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS + const uint16_t http_recv_buffer_ = 1000; // the firwmware GET chunk size + const uint16_t max_http_recv_buffer_ = 1024; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS // overhead) and must be a power of two from 512 to 4096 bool update_started_ = false; static const std::unique_ptr BACKEND; diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 3c76defda4..dd39249c40 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -34,9 +34,9 @@ int OtaHttpArduino::http_init() { #ifdef USE_HTTP_REQUEST_ESP8266_HTTPS if (this->secure_) { this->stream_ptr_ = std::make_unique(); - WiFiClientSecure *secureClient = static_cast(this->stream_ptr_.get()); - secureClient->setBufferSizes(this->MAX_HTTP_RECV_BUFFER_, 512); - secureClient->setInsecure(); + WiFiClientSecure *secure_client = static_cast(this->stream_ptr_.get()); + secure_client->setBufferSizes(this->max_http_recv_buffer_, 512); + secure_client->setInsecure(); } else { this->stream_ptr_ = std::make_unique(); } @@ -50,7 +50,7 @@ int OtaHttpArduino::http_init() { status = this->client_.begin(this->url_.c_str()); #endif #ifdef USE_ESP8266 - status = this->client_.begin(*this->stream_ptr_.get(), this->url_.c_str()); + status = this->client_.begin(*this->stream_ptr_, this->url_.c_str()); #endif if (!status) { From 6750f20f52e705f0bee109597c2e611b347587b1 Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 27 Oct 2023 02:32:44 +0000 Subject: [PATCH 16/97] fix max_http_recv_buffer_ --- esphome/components/ota_http/ota_http_idf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 0e965d3052..d1106bd69c 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -38,7 +38,7 @@ int OtaHttpIDF::http_init() { config.url = this->url_.c_str(); config.method = HTTP_METHOD_GET; config.timeout_ms = (int) this->timeout_; - config.buffer_size = this->MAX_HTTP_RECV_BUFFER_; + config.buffer_size = this->max_http_recv_buffer_; #pragma GCC diagnostic pop this->client_ = esp_http_client_init(&config); From dc745b74039cd480f722da2287d9a18122e59368 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sun, 12 Nov 2023 01:29:52 +0000 Subject: [PATCH 17/97] allow esp-idf basic auth --- esphome/components/ota_http/ota_http_idf.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index d1106bd69c..b96765f834 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -39,6 +39,8 @@ int OtaHttpIDF::http_init() { config.method = HTTP_METHOD_GET; config.timeout_ms = (int) this->timeout_; config.buffer_size = this->max_http_recv_buffer_; + config.auth_type = HTTP_AUTH_TYPE_BASIC; + config.max_authorization_retries = -1; #pragma GCC diagnostic pop this->client_ = esp_http_client_init(&config); From 77b43a60f7f49c9ed6519d0b9011c6a9b3cdf624 Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 16 Nov 2023 21:56:18 +0000 Subject: [PATCH 18/97] wip rp2040 --- esphome/components/ota_http/__init__.py | 6 +++++- esphome/components/ota_http/ota_http_arduino.cpp | 2 +- esphome/components/ota_http/ota_http_arduino.h | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 28384b6c5e..802c07b279 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -65,7 +65,7 @@ def _declare_request_class(value): if CORE.using_esp_idf: return cv.declare_id(OtaHttpIDF)(value) - if CORE.is_esp8266 or CORE.is_esp32: + if CORE.is_esp8266 or CORE.is_esp32 or CORE.is_rp2040: return cv.declare_id(OtaHttpArduino)(value) return NotImplementedError @@ -86,6 +86,7 @@ CONFIG_SCHEMA = cv.All( esp8266_arduino=cv.Version(2, 5, 1), esp32_arduino=cv.Version(0, 0, 0), esp_idf=cv.Version(0, 0, 0), + rp2040_arduino=cv.Version(0, 0, 0) ), ) @@ -108,6 +109,9 @@ async def to_code(config): cg.add_library("HTTPClient", None) if CORE.is_esp8266: cg.add_library("ESP8266HTTPClient", None) + if CORE.is_rp2040 and CORE.using_arduino: + cg.add_library("HTTPClient", None) + await cg.register_component(var, config) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index dd39249c40..18935dd8cc 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -46,7 +46,7 @@ int OtaHttpArduino::http_init() { ESP_LOGD(TAG, "Trying to connect to %s", this->url_.c_str()); bool status = false; -#ifdef USE_ESP32 +#if defined(USE_ESP32) || defined(USE_RP2040) status = this->client_.begin(this->url_.c_str()); #endif #ifdef USE_ESP8266 diff --git a/esphome/components/ota_http/ota_http_arduino.h b/esphome/components/ota_http/ota_http_arduino.h index e159d250c8..605e1cafb5 100644 --- a/esphome/components/ota_http/ota_http_arduino.h +++ b/esphome/components/ota_http/ota_http_arduino.h @@ -12,7 +12,7 @@ #include #include -#ifdef USE_ESP32 +#if defined(USE_ESP32) || defined(USE_RP2040) #include #endif #ifdef USE_ESP8266 From 38312f6fed560b1dcdbbf080807b3e79210501e2 Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 16 Nov 2023 22:16:00 +0000 Subject: [PATCH 19/97] fix esp8266_disable_ssl_support --- esphome/components/ota_http/README.md | 4 +++- esphome/components/ota_http/ota_http_arduino.cpp | 2 ++ esphome/components/ota_http/ota_http_arduino.h | 2 -- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/esphome/components/ota_http/README.md b/esphome/components/ota_http/README.md index 14d77543d8..1303fd5ad8 100644 --- a/esphome/components/ota_http/README.md +++ b/esphome/components/ota_http/README.md @@ -10,6 +10,7 @@ external_components: ota_http: + esp8266_disable_ssl_support: no # will reduce the firwmare size if set to `yes` button: @@ -19,6 +20,7 @@ button: then: - ota_http.flash: url: http://example.com/firmware.bin + disable_ssl: no # must be explicitely set to `yes` if https is used. - logger.log: "This message should be not displayed(reboot)" ``` @@ -27,7 +29,7 @@ The file `firmware.bin` can be found at `.esphome/build/xxxx/.pioenvs/xxx/firmwa You should got in the logs: ``` [18:48:30][D][button:010]: 'Firmware update' Pressed. -[18:48:30][D][ota_http:079]: Trying to connect to http://rasp:8080/firmware.bin +[18:48:30][D][ota_http:079]: Trying to connect to http://example.com/firmware.bin [18:48:30][D][ota_http:042]: Using ArduinoESP32OTABackend [18:48:30][D][ota_http:209]: Progress: 0.1% ... diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 18935dd8cc..7258a3f479 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -40,6 +40,8 @@ int OtaHttpArduino::http_init() { } else { this->stream_ptr_ = std::make_unique(); } +#else + this->stream_ptr_ = std::make_unique(); #endif // USE_HTTP_REQUEST_ESP8266_HTTPS #endif // USE_ESP8266 diff --git a/esphome/components/ota_http/ota_http_arduino.h b/esphome/components/ota_http/ota_http_arduino.h index 605e1cafb5..0edd7d4411 100644 --- a/esphome/components/ota_http/ota_http_arduino.h +++ b/esphome/components/ota_http/ota_http_arduino.h @@ -33,8 +33,6 @@ class OtaHttpArduino : public OtaHttpComponent { protected: HTTPClient client_{}; - // WiFiClient stream_; // needed for 8266 - // WiFiClient *stream_ptr_ = nullptr; // &stream_; std::unique_ptr stream_ptr_; }; From 7bc63faa1ae23feba0fac6d02e98d4909f86c53a Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 17 Nov 2023 19:26:40 +0000 Subject: [PATCH 20/97] safe mode --- esphome/components/ota_http/__init__.py | 15 +++++++--- esphome/components/ota_http/ota_http.cpp | 35 ++++++++++++++++++++++++ esphome/components/ota_http/ota_http.h | 10 +++++++ 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 802c07b279..23ad75814e 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -1,5 +1,5 @@ import urllib.parse as urlparse - +from esphome.cpp_generator import RawExpression import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation @@ -9,9 +9,10 @@ from esphome.const import ( CONF_URL, CONF_METHOD, CONF_ESP8266_DISABLE_SSL_SUPPORT, + CONF_SAFE_MODE, ) from esphome.components import esp32 -from esphome.core import Lambda, CORE +from esphome.core import Lambda, CORE, coroutine_with_priority CODEOWNERS = ["@oarcher"] @@ -80,17 +81,19 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( cv.only_on_esp8266, cv.boolean ), + cv.Optional(CONF_SAFE_MODE, default=False): cv.boolean, } ).extend(cv.COMPONENT_SCHEMA), 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), - rp2040_arduino=cv.Version(0, 0, 0) + rp2040_arduino=cv.Version(0, 0, 0), ), ) +@coroutine_with_priority(50.0) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_timeout(config[CONF_TIMEOUT])) @@ -112,9 +115,13 @@ async def to_code(config): if CORE.is_rp2040 and CORE.using_arduino: cg.add_library("HTTPClient", None) - await cg.register_component(var, config) + if config[CONF_SAFE_MODE]: + check_upgrade = var.check_upgrade() + # cg.add(RawExpression(f"{check_upgrade}")) + cg.add(var.check_upgrade()) + OTA_HTTP_ACTION_SCHEMA = cv.Schema( { diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index e2e6bb7271..dd87dca344 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -44,6 +44,18 @@ void OtaHttpComponent::dump_config() { }; void OtaHttpComponent::flash() { + if(pref_ota_http_state_.load(&ota_http_state_)){ + ESP_LOGV(TAG, "restored pref ota_http_state: %d", ota_http_state_); + } + + if (ota_http_state_ != OTA_HTTP_STATE_SAFE_MODE){ + ESP_LOGV(TAG, "setting mode to progress"); + ota_http_state_ = OTA_HTTP_STATE_PROGRESS; + pref_ota_http_state_.save(&ota_http_state_); + } + + global_preferences->sync(); + uint32_t update_start_time = millis(); uint8_t buf[this->http_recv_buffer_ + 1]; int error_code = 0; @@ -119,6 +131,8 @@ void OtaHttpComponent::flash() { return; } + ota_http_state_ = OTA_HTTP_STATE_OK; + pref_ota_http_state_.save(&ota_http_state_); delay(10); ESP_LOGI(TAG, "OTA update finished! Rebooting..."); delay(10); @@ -132,7 +146,28 @@ void OtaHttpComponent::cleanup_() { } ESP_LOGE(TAG, "Abort http con"); this->http_end(); + ESP_LOGE(TAG, "previous safe mode didn't succed. ota_http skipped"); + ota_http_state_ = OTA_HTTP_STATE_ABORT; + pref_ota_http_state_.save(&ota_http_state_); }; +void OtaHttpComponent::check_upgrade() { + if(pref_ota_http_state_.load(&ota_http_state_)){ + if(ota_http_state_ == OTA_HTTP_STATE_PROGRESS){ + // progress at boot time means that there was a problem + ESP_LOGV(TAG, "previous ota_http doesn't succed. Retrying"); + ota_http_state_ = OTA_HTTP_STATE_SAFE_MODE; + pref_ota_http_state_.save(&ota_http_state_); + this->flash(); + return; + } + if(ota_http_state_ == OTA_HTTP_STATE_SAFE_MODE){ + ESP_LOGE(TAG, "previous safe mode didn't succeed. ota_http skipped"); + ota_http_state_ = OTA_HTTP_STATE_ABORT; + pref_ota_http_state_.save(&ota_http_state_); + } + } +} + } // namespace ota_http } // namespace esphome diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index e73bb94896..6fb094d598 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -12,6 +12,13 @@ namespace esphome { namespace ota_http { +#define OTA_HTTP_STATE_OK 10 +#define OTA_HTTP_STATE_PROGRESS 20 +#define OTA_HTTP_STATE_SAFE_MODE 30 +#define OTA_HTTP_STATE_ABORT 40 + +#define OTA_HTTP_PREF_SAFE_MODE_HASH 99380597UL + static const char *const TAG = "ota_http"; class OtaHttpComponent : public Component { @@ -24,6 +31,7 @@ class OtaHttpComponent : public Component { } void set_timeout(uint64_t timeout) { this->timeout_ = timeout; } void flash(); + void check_upgrade(); virtual int http_init() { return -1; }; virtual size_t http_read(uint8_t *buf, size_t len) { return 0; }; virtual void http_end(){}; @@ -40,6 +48,8 @@ class OtaHttpComponent : public Component { bool update_started_ = false; static const std::unique_ptr BACKEND; void cleanup_(); + ESPPreferenceObject pref_ota_http_state_ = global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); + int ota_http_state_ = OTA_HTTP_STATE_OK; }; template class OtaHttpFlashAction : public Action { From c8cdd565bd0dd3ca7af38811c1ef6c32e0466fc3 Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 17 Nov 2023 19:35:31 +0000 Subject: [PATCH 21/97] lint --- esphome/components/ota_http/__init__.py | 3 --- esphome/components/ota_http/ota_http.h | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 23ad75814e..9c8b8a5b09 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -1,5 +1,4 @@ import urllib.parse as urlparse -from esphome.cpp_generator import RawExpression import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation @@ -118,8 +117,6 @@ async def to_code(config): await cg.register_component(var, config) if config[CONF_SAFE_MODE]: - check_upgrade = var.check_upgrade() - # cg.add(RawExpression(f"{check_upgrade}")) cg.add(var.check_upgrade()) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 6fb094d598..2aecc789cc 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -48,7 +48,8 @@ class OtaHttpComponent : public Component { bool update_started_ = false; static const std::unique_ptr BACKEND; void cleanup_(); - ESPPreferenceObject pref_ota_http_state_ = global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); + ESPPreferenceObject pref_ota_http_state_ = + global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); int ota_http_state_ = OTA_HTTP_STATE_OK; }; From d66bd012c9e02a594f63d22dde2944609a708bc4 Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 17 Nov 2023 19:44:18 +0000 Subject: [PATCH 22/97] lint --- esphome/components/ota_http/ota_http.cpp | 12 ++++++------ esphome/components/ota_http/ota_http.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index dd87dca344..d400cb2031 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -44,11 +44,11 @@ void OtaHttpComponent::dump_config() { }; void OtaHttpComponent::flash() { - if(pref_ota_http_state_.load(&ota_http_state_)){ - ESP_LOGV(TAG, "restored pref ota_http_state: %d", ota_http_state_); + if (pref_ota_http_state_.load(&ota_http_state_)) { + ESP_LOGV(TAG, "restored pref ota_http_state: %d", ota_http_state_); } - if (ota_http_state_ != OTA_HTTP_STATE_SAFE_MODE){ + if (ota_http_state_ != OTA_HTTP_STATE_SAFE_MODE) { ESP_LOGV(TAG, "setting mode to progress"); ota_http_state_ = OTA_HTTP_STATE_PROGRESS; pref_ota_http_state_.save(&ota_http_state_); @@ -152,8 +152,8 @@ void OtaHttpComponent::cleanup_() { }; void OtaHttpComponent::check_upgrade() { - if(pref_ota_http_state_.load(&ota_http_state_)){ - if(ota_http_state_ == OTA_HTTP_STATE_PROGRESS){ + if (pref_ota_http_state_.load(&ota_http_state_)) { + if (ota_http_state_ == OTA_HTTP_STATE_PROGRESS) { // progress at boot time means that there was a problem ESP_LOGV(TAG, "previous ota_http doesn't succed. Retrying"); ota_http_state_ = OTA_HTTP_STATE_SAFE_MODE; @@ -161,7 +161,7 @@ void OtaHttpComponent::check_upgrade() { this->flash(); return; } - if(ota_http_state_ == OTA_HTTP_STATE_SAFE_MODE){ + if (ota_http_state_ == OTA_HTTP_STATE_SAFE_MODE) { ESP_LOGE(TAG, "previous safe mode didn't succeed. ota_http skipped"); ota_http_state_ = OTA_HTTP_STATE_ABORT; pref_ota_http_state_.save(&ota_http_state_); diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 2aecc789cc..42cf3f95c1 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -49,7 +49,7 @@ class OtaHttpComponent : public Component { static const std::unique_ptr BACKEND; void cleanup_(); ESPPreferenceObject pref_ota_http_state_ = - global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); + global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); int ota_http_state_ = OTA_HTTP_STATE_OK; }; From 3ed41d37429b45200943a974aeecf8b56a118311 Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 17 Nov 2023 20:03:34 +0000 Subject: [PATCH 23/97] lint --- esphome/components/ota_http/ota_http.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 42cf3f95c1..883dbfa048 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -12,10 +12,10 @@ namespace esphome { namespace ota_http { -#define OTA_HTTP_STATE_OK 10 -#define OTA_HTTP_STATE_PROGRESS 20 -#define OTA_HTTP_STATE_SAFE_MODE 30 -#define OTA_HTTP_STATE_ABORT 40 +static const uint8_t OTA_HTTP_STATE_OK = 10; +static const uint8_t OTA_HTTP_STATE_PROGRESS = 20; +static const uint8_t OTA_HTTP_STATE_SAFE_MODE = 30; +static const uint8_t OTA_HTTP_STATE_ABORT = 40; #define OTA_HTTP_PREF_SAFE_MODE_HASH 99380597UL From 6bc6ad5fc918595793027418c775cc84af016e71 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sat, 18 Nov 2023 23:00:29 +0000 Subject: [PATCH 24/97] allow templates in safe mode --- esphome/components/ota_http/README.md | 2 +- esphome/components/ota_http/ota_http.cpp | 40 +++++++++++-------- esphome/components/ota_http/ota_http.h | 28 +++++++++---- .../components/ota_http/ota_http_arduino.cpp | 16 +++++--- esphome/components/ota_http/ota_http_idf.cpp | 2 +- 5 files changed, 56 insertions(+), 32 deletions(-) diff --git a/esphome/components/ota_http/README.md b/esphome/components/ota_http/README.md index 1303fd5ad8..0f03ecfb7b 100644 --- a/esphome/components/ota_http/README.md +++ b/esphome/components/ota_http/README.md @@ -20,7 +20,7 @@ button: then: - ota_http.flash: url: http://example.com/firmware.bin - disable_ssl: no # must be explicitely set to `yes` if https is used. + disable_ssl: no # must be explicitly set to `yes` if https is used. - logger.log: "This message should be not displayed(reboot)" ``` diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index d400cb2031..d44f0934b2 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -44,14 +44,14 @@ void OtaHttpComponent::dump_config() { }; void OtaHttpComponent::flash() { - if (pref_ota_http_state_.load(&ota_http_state_)) { - ESP_LOGV(TAG, "restored pref ota_http_state: %d", ota_http_state_); + if (pref_obj_.load(&pref_)) { + ESP_LOGV(TAG, "restored pref ota_http_state: %d", pref_.ota_http_state); } - if (ota_http_state_ != OTA_HTTP_STATE_SAFE_MODE) { + if (pref_.ota_http_state != OTA_HTTP_STATE_SAFE_MODE) { ESP_LOGV(TAG, "setting mode to progress"); - ota_http_state_ = OTA_HTTP_STATE_PROGRESS; - pref_ota_http_state_.save(&ota_http_state_); + pref_.ota_http_state = OTA_HTTP_STATE_PROGRESS; + pref_obj_.save(&pref_); } global_preferences->sync(); @@ -131,8 +131,8 @@ void OtaHttpComponent::flash() { return; } - ota_http_state_ = OTA_HTTP_STATE_OK; - pref_ota_http_state_.save(&ota_http_state_); + pref_.ota_http_state = OTA_HTTP_STATE_OK; + pref_obj_.save(&pref_); delay(10); ESP_LOGI(TAG, "OTA update finished! Rebooting..."); delay(10); @@ -147,24 +147,30 @@ void OtaHttpComponent::cleanup_() { ESP_LOGE(TAG, "Abort http con"); this->http_end(); ESP_LOGE(TAG, "previous safe mode didn't succed. ota_http skipped"); - ota_http_state_ = OTA_HTTP_STATE_ABORT; - pref_ota_http_state_.save(&ota_http_state_); + pref_.ota_http_state = OTA_HTTP_STATE_ABORT; + pref_obj_.save(&pref_); }; void OtaHttpComponent::check_upgrade() { - if (pref_ota_http_state_.load(&ota_http_state_)) { - if (ota_http_state_ == OTA_HTTP_STATE_PROGRESS) { + if (pref_obj_.load(&pref_)) { + if (pref_.ota_http_state == OTA_HTTP_STATE_PROGRESS) { // progress at boot time means that there was a problem - ESP_LOGV(TAG, "previous ota_http doesn't succed. Retrying"); - ota_http_state_ = OTA_HTTP_STATE_SAFE_MODE; - pref_ota_http_state_.save(&ota_http_state_); + + // Delay here to allow power to stabilise before Wi-Fi/Ethernet is initialised. + delay(300); // NOLINT + App.setup(); + + ESP_LOGI(TAG, "previous ota_http doesn't succed. Retrying"); + pref_.ota_http_state = OTA_HTTP_STATE_SAFE_MODE; + pref_obj_.save(&pref_); this->flash(); return; } - if (ota_http_state_ == OTA_HTTP_STATE_SAFE_MODE) { + if (pref_.ota_http_state == OTA_HTTP_STATE_SAFE_MODE) { ESP_LOGE(TAG, "previous safe mode didn't succeed. ota_http skipped"); - ota_http_state_ = OTA_HTTP_STATE_ABORT; - pref_ota_http_state_.save(&ota_http_state_); + pref_.ota_http_state = OTA_HTTP_STATE_ABORT; + pref_obj_.save(&pref_); + global_preferences->sync(); } } } diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 883dbfa048..0391cf8d43 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -17,17 +17,29 @@ static const uint8_t OTA_HTTP_STATE_PROGRESS = 20; static const uint8_t OTA_HTTP_STATE_SAFE_MODE = 30; static const uint8_t OTA_HTTP_STATE_ABORT = 40; -#define OTA_HTTP_PREF_SAFE_MODE_HASH 99380597UL +#define OTA_HTTP_PREF_SAFE_MODE_HASH 99380598UL static const char *const TAG = "ota_http"; +struct otaHttpGlobalPrefType { + int ota_http_state; + char url[128]; + bool verify_ssl; +} PACKED; + class OtaHttpComponent : public Component { public: void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } void set_url(std::string url) { - this->url_ = std::move(url); - this->secure_ = this->url_.rfind("https:", 0) == 0; + // this->url_ = std::move(url); + // TODO check size + size_t length = std::min(url.length(), sizeof(pref_.url) - 1); + strncpy(pref_.url, url.c_str(), length); + pref_.url[length] = '\0'; + // this->secure_ = url.rfind("https:", 0) == 0; + // this->secure_ = strncmp(pref_.url, "https:", 6) == 0; + pref_obj_.save(&pref_); } void set_timeout(uint64_t timeout) { this->timeout_ = timeout; } void flash(); @@ -37,8 +49,8 @@ class OtaHttpComponent : public Component { virtual void http_end(){}; protected: - std::string url_; - bool secure_; + // std::string url_; + bool secure_() { return strncmp(pref_.url, "https:", 6) == 0; }; size_t body_length_ = 0; size_t bytes_read_ = 0; uint64_t timeout_{1000 * 60 * 10}; // must match CONF_TIMEOUT in __init__.py @@ -48,9 +60,9 @@ class OtaHttpComponent : public Component { bool update_started_ = false; static const std::unique_ptr BACKEND; void cleanup_(); - ESPPreferenceObject pref_ota_http_state_ = - global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); - int ota_http_state_ = OTA_HTTP_STATE_OK; + otaHttpGlobalPrefType pref_ = {OTA_HTTP_STATE_OK, "", true}; + ESPPreferenceObject pref_obj_ = + global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); }; template class OtaHttpFlashAction : public Action { diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 7258a3f479..fcea0b7e2f 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -32,7 +32,8 @@ int OtaHttpArduino::http_init() { #ifdef USE_ESP8266 #ifdef USE_HTTP_REQUEST_ESP8266_HTTPS - if (this->secure_) { + if (this->secure_()) { + ESP_LOGD(TAG, "esp8266 https connection with WiFiClientSecure"); this->stream_ptr_ = std::make_unique(); WiFiClientSecure *secure_client = static_cast(this->stream_ptr_.get()); secure_client->setBufferSizes(this->max_http_recv_buffer_, 512); @@ -41,18 +42,23 @@ int OtaHttpArduino::http_init() { this->stream_ptr_ = std::make_unique(); } #else + ESP_LOGD(TAG, "esp8266 http connection with WiFiClient"); + if (this->secure_()) { + ESP_LOGE(TAG, "Can't use https connection with esp8266_disable_ssl_support"); + return -1; + } this->stream_ptr_ = std::make_unique(); #endif // USE_HTTP_REQUEST_ESP8266_HTTPS #endif // USE_ESP8266 - ESP_LOGD(TAG, "Trying to connect to %s", this->url_.c_str()); + ESP_LOGD(TAG, "Trying to connect to %s", pref_.url); bool status = false; #if defined(USE_ESP32) || defined(USE_RP2040) - status = this->client_.begin(this->url_.c_str()); + status = this->client_.begin(pref_.url); #endif #ifdef USE_ESP8266 - status = this->client_.begin(*this->stream_ptr_, this->url_.c_str()); + status = this->client_.begin(*this->stream_ptr_, pref_.url); #endif if (!status) { @@ -77,7 +83,7 @@ int OtaHttpArduino::http_init() { ESP_LOGV(TAG, "http GET finished."); if (http_code >= 310) { - ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s (%d); Duration: %u ms", url_.c_str(), + ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s (%d); Duration: %u ms", pref_.url, HTTPClient::errorToString(http_code).c_str(), http_code, duration); return -1; } diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index b96765f834..a3ac5b28cf 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -35,7 +35,7 @@ int OtaHttpIDF::http_init() { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" esp_http_client_config_t config = {nullptr}; - config.url = this->url_.c_str(); + config.url = pref_.url; config.method = HTTP_METHOD_GET; config.timeout_ms = (int) this->timeout_; config.buffer_size = this->max_http_recv_buffer_; From 85911ba30cae14ce9dc6be7fca36be124e7153a2 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sat, 18 Nov 2023 23:23:05 +0000 Subject: [PATCH 25/97] lint --- esphome/components/ota_http/ota_http.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 0391cf8d43..ab015cb7e6 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -21,7 +21,7 @@ static const uint8_t OTA_HTTP_STATE_ABORT = 40; static const char *const TAG = "ota_http"; -struct otaHttpGlobalPrefType { +struct OtaHttpGlobalPrefType { int ota_http_state; char url[128]; bool verify_ssl; @@ -31,10 +31,10 @@ class OtaHttpComponent : public Component { public: void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } - void set_url(std::string url) { + void set_url(const std::string& url) { // this->url_ = std::move(url); // TODO check size - size_t length = std::min(url.length(), sizeof(pref_.url) - 1); + size_t length = std::min(url.length(), static_cast(sizeof(pref_.url) - 1)); strncpy(pref_.url, url.c_str(), length); pref_.url[length] = '\0'; // this->secure_ = url.rfind("https:", 0) == 0; @@ -60,9 +60,9 @@ class OtaHttpComponent : public Component { bool update_started_ = false; static const std::unique_ptr BACKEND; void cleanup_(); - otaHttpGlobalPrefType pref_ = {OTA_HTTP_STATE_OK, "", true}; + OtaHttpGlobalPrefType pref_ = {OTA_HTTP_STATE_OK, "", true}; ESPPreferenceObject pref_obj_ = - global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); + global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); }; template class OtaHttpFlashAction : public Action { From c2504309814d38888007401df9e801c4e90e4fb7 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sat, 18 Nov 2023 23:40:07 +0000 Subject: [PATCH 26/97] lint --- esphome/components/ota_http/ota_http.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index ab015cb7e6..cd69eddf8a 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -31,7 +31,7 @@ class OtaHttpComponent : public Component { public: void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } - void set_url(const std::string& url) { + void set_url(const std::string &url) { // this->url_ = std::move(url); // TODO check size size_t length = std::min(url.length(), static_cast(sizeof(pref_.url) - 1)); From 71073f6252fefd49ec9e6f1e380a9bc89bfb3c53 Mon Sep 17 00:00:00 2001 From: oarcher Date: Tue, 21 Nov 2023 20:57:04 +0000 Subject: [PATCH 27/97] add http (not https) support for rp2040 --- esphome/components/ota_http/ota_http_arduino.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index fcea0b7e2f..9da80847f1 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -97,7 +97,7 @@ int OtaHttpArduino::http_init() { this->body_length_ = (size_t) this->client_.getSize(); ESP_LOGD(TAG, "firmware is %d bytes length.", this->body_length_); -#ifdef USE_ESP32 +#if defined(USE_ESP32) || defined(USE_RP2040) this->stream_ptr_ = std::unique_ptr(this->client_.getStreamPtr()); #endif From d874130884e98870fcc4ebce6e92a6b31351f584 Mon Sep 17 00:00:00 2001 From: oarcher Date: Tue, 21 Nov 2023 21:20:05 +0000 Subject: [PATCH 28/97] https support for rp2040 --- esphome/components/ota_http/ota_http_arduino.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 9da80847f1..e37dd9f452 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -54,6 +54,9 @@ int OtaHttpArduino::http_init() { ESP_LOGD(TAG, "Trying to connect to %s", pref_.url); bool status = false; +#ifdef USE_RP2040 + this->client_.setInsecure(); +#endif #if defined(USE_ESP32) || defined(USE_RP2040) status = this->client_.begin(pref_.url); #endif From 2929f9db7d4f7185cdfb0a2f481052c70593c065 Mon Sep 17 00:00:00 2001 From: oarcher Date: Tue, 21 Nov 2023 23:42:54 +0000 Subject: [PATCH 29/97] add "fallback" option to safe_mode --- esphome/components/ota_http/__init__.py | 4 +++- esphome/components/ota_http/ota_http.cpp | 23 +++++++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 9c8b8a5b09..08d8e9b118 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -80,7 +80,7 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( cv.only_on_esp8266, cv.boolean ), - cv.Optional(CONF_SAFE_MODE, default=False): cv.boolean, + cv.Optional(CONF_SAFE_MODE, default="fallback"): cv.Any(cv.boolean, "fallback"), # cv.enum(SAFE_MODE_STATES, upper=True), } ).extend(cv.COMPONENT_SCHEMA), cv.require_framework_version( @@ -117,6 +117,8 @@ async def to_code(config): await cg.register_component(var, config) if config[CONF_SAFE_MODE]: + if config[CONF_SAFE_MODE] is True: + cg.add_define("OTA_HTTP_ONLY_AT_BOOT") cg.add(var.check_upgrade()) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index d44f0934b2..e676797e41 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -56,15 +56,22 @@ void OtaHttpComponent::flash() { global_preferences->sync(); - uint32_t update_start_time = millis(); - uint8_t buf[this->http_recv_buffer_ + 1]; - int error_code = 0; - uint32_t last_progress = 0; - esphome::md5::MD5Digest md5_receive; - std::unique_ptr md5_receive_str(new char[33]); +#ifdef OTA_HTTP_ONLY_AT_BOOT + if (pref_.ota_http_state != OTA_HTTP_STATE_SAFE_MODE) { + ESP_LOGI(TAG, "Rebotting before flashing new firmware."); + App.safe_reboot(); + } +#endif - if (!this->http_init()) { - return; + uint32_t update_start_time = millis(); + uint8_t buf[this->http_recv_buffer_ + 1]; + int error_code = 0; + uint32_t last_progress = 0; + esphome::md5::MD5Digest md5_receive; + std::unique_ptr md5_receive_str(new char[33]); + + if (!this->http_init()) { + return; } // we will compute md5 on the fly From 1a2a4c66cef1d46601a905000cb38c56ef3ed434 Mon Sep 17 00:00:00 2001 From: oarcher Date: Wed, 22 Nov 2023 00:18:01 +0000 Subject: [PATCH 30/97] lint --- esphome/components/ota_http/__init__.py | 4 +++- esphome/components/ota_http/ota_http.cpp | 17 ++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 08d8e9b118..177b3782bd 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -80,7 +80,9 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( cv.only_on_esp8266, cv.boolean ), - cv.Optional(CONF_SAFE_MODE, default="fallback"): cv.Any(cv.boolean, "fallback"), # cv.enum(SAFE_MODE_STATES, upper=True), + cv.Optional(CONF_SAFE_MODE, default="fallback"): cv.Any( + cv.boolean, "fallback" + ), } ).extend(cv.COMPONENT_SCHEMA), cv.require_framework_version( diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index e676797e41..f4e3bf1058 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -63,15 +63,14 @@ void OtaHttpComponent::flash() { } #endif - uint32_t update_start_time = millis(); - uint8_t buf[this->http_recv_buffer_ + 1]; - int error_code = 0; - uint32_t last_progress = 0; - esphome::md5::MD5Digest md5_receive; - std::unique_ptr md5_receive_str(new char[33]); - - if (!this->http_init()) { - return; + uint32_t update_start_time = millis(); + uint8_t buf[this->http_recv_buffer_ + 1]; + int error_code = 0; + uint32_t last_progress = 0; + esphome::md5::MD5Digest md5_receive; + std::unique_ptr md5_receive_str(new char[33]); + if (!this->http_init()) { + return; } // we will compute md5 on the fly From a61a5776487706fd43fb976ec7c77538ec34e5ac Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 8 Dec 2023 18:02:51 +0000 Subject: [PATCH 31/97] typo + remove README --- esphome/components/ota_http/README.md | 40 ------------------------ esphome/components/ota_http/ota_http.cpp | 2 +- 2 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 esphome/components/ota_http/README.md diff --git a/esphome/components/ota_http/README.md b/esphome/components/ota_http/README.md deleted file mode 100644 index 0f03ecfb7b..0000000000 --- a/esphome/components/ota_http/README.md +++ /dev/null @@ -1,40 +0,0 @@ -### ota_http - -ota in client (http) mode: This allow to do a remote ota when the device is far away, behind a firewall, and only reachable with mqtt. (For ex in an other house). - - - -```yaml -external_components: - - source: github://oarcher/piotech/ - - -ota_http: - esp8266_disable_ssl_support: no # will reduce the firwmare size if set to `yes` - - -button: - - platform: template - name: "Firmware update" - on_press: - then: - - ota_http.flash: - url: http://example.com/firmware.bin - disable_ssl: no # must be explicitly set to `yes` if https is used. - - logger.log: "This message should be not displayed(reboot)" -``` - -The file `firmware.bin` can be found at `.esphome/build/xxxx/.pioenvs/xxx/firmware.bin` if esphome CLI is used, or downloaded as `Legacy format` from the esphome HA addon. Do not use `firmware-factory.bin` or `Modern format`. - -You should got in the logs: -``` -[18:48:30][D][button:010]: 'Firmware update' Pressed. -[18:48:30][D][ota_http:079]: Trying to connect to http://example.com/firmware.bin -[18:48:30][D][ota_http:042]: Using ArduinoESP32OTABackend -[18:48:30][D][ota_http:209]: Progress: 0.1% -... -[18:48:39][D][ota_http:209]: Progress: 100.0% -[18:48:39][D][ota_http:218]: Done in 100 secs -[18:48:39][D][ota_http:223]: md5sum recieved: 38e2cad1c79fb38583361a41b9d16d27 (size 1378112) -[18:48:39][I][ota_http:242]: OTA update finished! Rebooting... -``` diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index f4e3bf1058..0675781572 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -58,7 +58,7 @@ void OtaHttpComponent::flash() { #ifdef OTA_HTTP_ONLY_AT_BOOT if (pref_.ota_http_state != OTA_HTTP_STATE_SAFE_MODE) { - ESP_LOGI(TAG, "Rebotting before flashing new firmware."); + ESP_LOGI(TAG, "Rebooting before flashing new firmware."); App.safe_reboot(); } #endif From 3840f06c7319586a887c4037206f91f6f6681c16 Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 11 Jan 2024 20:16:46 +0000 Subject: [PATCH 32/97] increase url buf size --- esphome/components/ota_http/ota_http.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index cd69eddf8a..222600d6f1 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -23,7 +23,7 @@ static const char *const TAG = "ota_http"; struct OtaHttpGlobalPrefType { int ota_http_state; - char url[128]; + char url[256]; bool verify_ssl; } PACKED; From fbf91585ebe8faf8996f338f53d32ae03d989f8f Mon Sep 17 00:00:00 2001 From: oarcher Date: Sat, 27 Jan 2024 21:32:23 +0000 Subject: [PATCH 33/97] added "ota" in AUTO_LOAD --- esphome/components/ota_http/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 177b3782bd..af5f6237bb 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -16,7 +16,7 @@ from esphome.core import Lambda, CORE, coroutine_with_priority CODEOWNERS = ["@oarcher"] DEPENDENCIES = ["network"] -AUTO_LOAD = ["md5"] +AUTO_LOAD = ["md5", "ota"] ota_http_ns = cg.esphome_ns.namespace("ota_http") OtaHttpComponent = ota_http_ns.class_("OtaHttpComponent", cg.Component) From 5b3c72779cc0a766dda698be8913cb58845fb2dd Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Mon, 19 Feb 2024 22:48:45 +0100 Subject: [PATCH 34/97] Adds support to IDF v5 --- esphome/components/ota_http/ota_http_idf.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index a3ac5b28cf..9dee789323 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -14,6 +14,7 @@ #include "esp_netif.h" #include "esp_tls.h" #include "nvs_flash.h" +#include #include #include #include @@ -51,7 +52,7 @@ int OtaHttpIDF::http_init() { } this->body_length_ = esp_http_client_fetch_headers(this->client_); - ESP_LOGD(TAG, "body_length: %d , esp_http_client_get_content_length: %d", this->body_length_, + ESP_LOGD(TAG, "body_length: %d , esp_http_client_get_content_length: %" PRId64, this->body_length_, esp_http_client_get_content_length(this->client_)); if (this->body_length_ <= 0) { From 431e1e556a7efb761cc875eee2300763d9038a73 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sat, 2 Mar 2024 00:32:58 +0000 Subject: [PATCH 35/97] cinttypes fix for idf v5 --- esphome/components/ota_http/ota_http_idf.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 9dee789323..d23e69dab5 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -14,7 +14,7 @@ #include "esp_netif.h" #include "esp_tls.h" #include "nvs_flash.h" -#include +#include #include #include #include @@ -52,7 +52,7 @@ int OtaHttpIDF::http_init() { } this->body_length_ = esp_http_client_fetch_headers(this->client_); - ESP_LOGD(TAG, "body_length: %d , esp_http_client_get_content_length: %" PRId64, this->body_length_, + ESP_LOGD(TAG, "body_length: %d , esp_http_client_get_content_length: %" PRId32, this->body_length_, esp_http_client_get_content_length(this->client_)); if (this->body_length_ <= 0) { From 244e6f03adbebfa266c13b45ee53fe6869ffefba Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Tue, 5 Mar 2024 20:57:06 +0100 Subject: [PATCH 36/97] Log messages in ota_http_arduino.cpp Co-authored-by: Keith Burzinski --- esphome/components/ota_http/ota_http_arduino.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index e37dd9f452..d7533234d3 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -69,7 +69,7 @@ int OtaHttpArduino::http_init() { this->client_.end(); return -1; } else { - ESP_LOGV(TAG, "http begin successfull."); + ESP_LOGV(TAG, "http begin successful"); } this->client_.setReuse(true); From d9b0084dc979f23c24e02b2ff024876e4fb9eb3a Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Tue, 5 Mar 2024 20:57:27 +0100 Subject: [PATCH 37/97] Log messages in ota_http.cpp Co-authored-by: Keith Burzinski --- esphome/components/ota_http/ota_http.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 0675781572..b289b6254b 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -173,7 +173,7 @@ void OtaHttpComponent::check_upgrade() { return; } if (pref_.ota_http_state == OTA_HTTP_STATE_SAFE_MODE) { - ESP_LOGE(TAG, "previous safe mode didn't succeed. ota_http skipped"); + ESP_LOGE(TAG, "Previous safe mode unsuccessful; skipped ota_http"); pref_.ota_http_state = OTA_HTTP_STATE_ABORT; pref_obj_.save(&pref_); global_preferences->sync(); From 6090a69148da6ef7354a2cc1c98d5fba59a207c3 Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Tue, 5 Mar 2024 20:57:57 +0100 Subject: [PATCH 38/97] Log messages in ota_http.cpp Co-authored-by: Keith Burzinski --- esphome/components/ota_http/ota_http.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index b289b6254b..e7d3c86ca1 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -166,7 +166,7 @@ void OtaHttpComponent::check_upgrade() { delay(300); // NOLINT App.setup(); - ESP_LOGI(TAG, "previous ota_http doesn't succed. Retrying"); + ESP_LOGI(TAG, "Previous ota_http unsuccessful. Retrying"); pref_.ota_http_state = OTA_HTTP_STATE_SAFE_MODE; pref_obj_.save(&pref_); this->flash(); From 913bb1f4ec2b4ff44815c4dc96c108269aa1d6f8 Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Tue, 5 Mar 2024 20:58:22 +0100 Subject: [PATCH 39/97] Log messages in ota_http.cpp Co-authored-by: Keith Burzinski --- esphome/components/ota_http/ota_http.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index e7d3c86ca1..ecaff83f86 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -150,9 +150,9 @@ void OtaHttpComponent::cleanup_() { ESP_LOGE(TAG, "Abort OTA backend"); esphome::ota_http::OtaHttpComponent::BACKEND->abort(); } - ESP_LOGE(TAG, "Abort http con"); + ESP_LOGE(TAG, "Aborting http connection"); this->http_end(); - ESP_LOGE(TAG, "previous safe mode didn't succed. ota_http skipped"); + ESP_LOGE(TAG, "Previous safe mode unsuccessful; skipped ota_http"); pref_.ota_http_state = OTA_HTTP_STATE_ABORT; pref_obj_.save(&pref_); }; From 13feb401cca4ff3d9c6df7a45d9efada83fe7e75 Mon Sep 17 00:00:00 2001 From: oarcher Date: Tue, 5 Mar 2024 20:53:15 +0000 Subject: [PATCH 40/97] cast esp_http_client_get_content_length to int64_t for idf v4 and v5 --- esphome/components/ota_http/ota_http_idf.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index d23e69dab5..eca96340c5 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -52,8 +52,8 @@ int OtaHttpIDF::http_init() { } this->body_length_ = esp_http_client_fetch_headers(this->client_); - ESP_LOGD(TAG, "body_length: %d , esp_http_client_get_content_length: %" PRId32, this->body_length_, - esp_http_client_get_content_length(this->client_)); + ESP_LOGD(TAG, "body_length: %d , esp_http_client_get_content_length: %" PRId64, this->body_length_, + (int64_t) esp_http_client_get_content_length(this->client_)); if (this->body_length_ <= 0) { ESP_LOGE(TAG, "Incorrect file size (%d) reported by http server (http status: %d). Aborting", this->body_length_, From e09590184e1a54219319e2b9d803377b4450c337 Mon Sep 17 00:00:00 2001 From: oarcher Date: Wed, 6 Mar 2024 20:07:27 +0000 Subject: [PATCH 41/97] allow return -1 for http_read for better error handling --- esphome/components/ota_http/ota_http.cpp | 8 ++++++- esphome/components/ota_http/ota_http.h | 2 +- .../components/ota_http/ota_http_arduino.cpp | 21 +++++++------------ .../components/ota_http/ota_http_arduino.h | 2 +- esphome/components/ota_http/ota_http_idf.cpp | 10 ++++----- esphome/components/ota_http/ota_http_idf.h | 2 +- 6 files changed, 22 insertions(+), 23 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index ecaff83f86..5f29b3f40f 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -88,7 +88,13 @@ void OtaHttpComponent::flash() { while (this->bytes_read_ != this->body_length_) { // read a maximum of chunk_size bytes into buf. (real read size returned) - size_t bufsize = this->http_read(buf, this->http_recv_buffer_); + int bufsize = this->http_read(buf, this->http_recv_buffer_); + + if (bufsize < 0) { + ESP_LOGE(TAG, "ERROR: stream closed"); + this->cleanup_(); + return; + } // add read bytes to md5 md5_receive.add(buf, bufsize); diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 222600d6f1..d01579370c 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -45,7 +45,7 @@ class OtaHttpComponent : public Component { void flash(); void check_upgrade(); virtual int http_init() { return -1; }; - virtual size_t http_read(uint8_t *buf, size_t len) { return 0; }; + virtual int http_read(uint8_t *buf, size_t len) { return 0; }; virtual void http_end(){}; protected: diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index d7533234d3..985118156c 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -107,7 +107,7 @@ int OtaHttpArduino::http_init() { return 1; } -size_t OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { +int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { // wait for the stream to be populated while (this->stream_ptr_->available() == 0) { // give other tasks a chance to run while waiting for some data: @@ -115,20 +115,15 @@ size_t OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { yield(); delay(1); } - // size_t bufsize = std::min(max_len, this->body_length - this->bytes_read); int available_data = this->stream_ptr_->available(); - if (available_data < 0) { - ESP_LOGE(TAG, "ERROR: stream closed"); - this->cleanup_(); - return -1; + int bufsize = std::min((int)max_len, available_data); + if (bufsize > 0) { + // ESP_LOGVV(TAG, "data available: %zu", available_data); + + this->stream_ptr_->readBytes(buf, bufsize); + this->bytes_read_ += bufsize; + buf[bufsize] = '\0'; // not fed to ota } - size_t bufsize = std::min(max_len, (size_t) available_data); - - // ESP_LOGVV(TAG, "data available: %zu", available_data); - - this->stream_ptr_->readBytes(buf, bufsize); - this->bytes_read_ += bufsize; - buf[bufsize] = '\0'; // not fed to ota return bufsize; } diff --git a/esphome/components/ota_http/ota_http_arduino.h b/esphome/components/ota_http/ota_http_arduino.h index 0edd7d4411..16f0783050 100644 --- a/esphome/components/ota_http/ota_http_arduino.h +++ b/esphome/components/ota_http/ota_http_arduino.h @@ -28,7 +28,7 @@ namespace ota_http { class OtaHttpArduino : public OtaHttpComponent { public: int http_init() override; - size_t http_read(uint8_t *buf, size_t len) override; + int http_read(uint8_t *buf, size_t len) override; void http_end() override; protected: diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index eca96340c5..92a61a603d 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -63,18 +63,16 @@ int OtaHttpIDF::http_init() { return 1; } -size_t OtaHttpIDF::http_read(uint8_t *buf, const size_t max_len) { - size_t bufsize = std::min(max_len, this->body_length_ - this->bytes_read_); +int OtaHttpIDF::http_read(uint8_t *buf, const size_t max_len) { + int bufsize = std::min(max_len, this->body_length_ - this->bytes_read_); int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); - if (read_len <= 0) { - ESP_LOGE(TAG, "Error read data"); - } else { + if (read_len > 0) { this->bytes_read_ += bufsize; buf[bufsize] = '\0'; // not fed to ota } // ESP_LOGVV(TAG, "Read %d bytes, %d remainings", read_len, this->body_length_ - this->bytes_read); - return (size_t) read_len; // FIXME size_t dosen't allow < 0 + return read_len; } void OtaHttpIDF::http_end() { diff --git a/esphome/components/ota_http/ota_http_idf.h b/esphome/components/ota_http/ota_http_idf.h index bcae2fbf08..a52b859203 100644 --- a/esphome/components/ota_http/ota_http_idf.h +++ b/esphome/components/ota_http/ota_http_idf.h @@ -12,7 +12,7 @@ namespace ota_http { class OtaHttpIDF : public OtaHttpComponent { public: int http_init() override; - size_t http_read(uint8_t *buf, size_t len) override; + int http_read(uint8_t *buf, size_t len) override; void http_end() override; protected: From 6328474411bb80bc015a8f0712b07aea1e123f34 Mon Sep 17 00:00:00 2001 From: oarcher Date: Wed, 6 Mar 2024 20:52:11 +0000 Subject: [PATCH 42/97] clang format --- esphome/components/ota_http/ota_http_arduino.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 985118156c..f5281617e9 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -116,7 +116,7 @@ int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { delay(1); } int available_data = this->stream_ptr_->available(); - int bufsize = std::min((int)max_len, available_data); + int bufsize = std::min((int) max_len, available_data); if (bufsize > 0) { // ESP_LOGVV(TAG, "data available: %zu", available_data); From 001f14e6cae5e7af18aabc0fec0ef1307afad18e Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 7 Mar 2024 05:23:10 +0000 Subject: [PATCH 43/97] use this-> prefix when accessing member variables. --- esphome/components/ota_http/ota_http.cpp | 36 +++++++++---------- esphome/components/ota_http/ota_http.h | 15 +++----- .../components/ota_http/ota_http_arduino.cpp | 6 ++-- esphome/components/ota_http/ota_http_idf.cpp | 2 +- 4 files changed, 27 insertions(+), 32 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 5f29b3f40f..b7177e6082 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -44,20 +44,20 @@ void OtaHttpComponent::dump_config() { }; void OtaHttpComponent::flash() { - if (pref_obj_.load(&pref_)) { - ESP_LOGV(TAG, "restored pref ota_http_state: %d", pref_.ota_http_state); + if (this->pref_obj_.load(&this->pref_)) { + ESP_LOGV(TAG, "restored pref ota_http_state: %d", this->pref_.ota_http_state); } - if (pref_.ota_http_state != OTA_HTTP_STATE_SAFE_MODE) { + if (this->pref_.ota_http_state != OTA_HTTP_STATE_SAFE_MODE) { ESP_LOGV(TAG, "setting mode to progress"); - pref_.ota_http_state = OTA_HTTP_STATE_PROGRESS; - pref_obj_.save(&pref_); + this->pref_.ota_http_state = OTA_HTTP_STATE_PROGRESS; + this->pref_obj_.save(&this->pref_); } global_preferences->sync(); #ifdef OTA_HTTP_ONLY_AT_BOOT - if (pref_.ota_http_state != OTA_HTTP_STATE_SAFE_MODE) { + if (this->pref_.ota_http_state != OTA_HTTP_STATE_SAFE_MODE) { ESP_LOGI(TAG, "Rebooting before flashing new firmware."); App.safe_reboot(); } @@ -126,7 +126,7 @@ void OtaHttpComponent::flash() { // send md5 to backend (backend will check that the flashed one has the same) md5_receive.calculate(); md5_receive.get_hex(md5_receive_str.get()); - ESP_LOGD(TAG, "md5sum recieved: %s (size %d)", md5_receive_str.get(), bytes_read_); + ESP_LOGD(TAG, "md5sum recieved: %s (size %d)", md5_receive_str.get(), this->bytes_read_); esphome::ota_http::OtaHttpComponent::BACKEND->set_update_md5(md5_receive_str.get()); this->http_end(); @@ -143,8 +143,8 @@ void OtaHttpComponent::flash() { return; } - pref_.ota_http_state = OTA_HTTP_STATE_OK; - pref_obj_.save(&pref_); + this->pref_.ota_http_state = OTA_HTTP_STATE_OK; + this->pref_obj_.save(&this->pref_); delay(10); ESP_LOGI(TAG, "OTA update finished! Rebooting..."); delay(10); @@ -159,13 +159,13 @@ void OtaHttpComponent::cleanup_() { ESP_LOGE(TAG, "Aborting http connection"); this->http_end(); ESP_LOGE(TAG, "Previous safe mode unsuccessful; skipped ota_http"); - pref_.ota_http_state = OTA_HTTP_STATE_ABORT; - pref_obj_.save(&pref_); + this->pref_.ota_http_state = OTA_HTTP_STATE_ABORT; + this->pref_obj_.save(&this->pref_); }; void OtaHttpComponent::check_upgrade() { - if (pref_obj_.load(&pref_)) { - if (pref_.ota_http_state == OTA_HTTP_STATE_PROGRESS) { + if (this->pref_obj_.load(&this->pref_)) { + if (this->pref_.ota_http_state == OTA_HTTP_STATE_PROGRESS) { // progress at boot time means that there was a problem // Delay here to allow power to stabilise before Wi-Fi/Ethernet is initialised. @@ -173,15 +173,15 @@ void OtaHttpComponent::check_upgrade() { App.setup(); ESP_LOGI(TAG, "Previous ota_http unsuccessful. Retrying"); - pref_.ota_http_state = OTA_HTTP_STATE_SAFE_MODE; - pref_obj_.save(&pref_); + this->pref_.ota_http_state = OTA_HTTP_STATE_SAFE_MODE; + this->pref_obj_.save(&this->pref_); this->flash(); return; } - if (pref_.ota_http_state == OTA_HTTP_STATE_SAFE_MODE) { + if (this->pref_.ota_http_state == OTA_HTTP_STATE_SAFE_MODE) { ESP_LOGE(TAG, "Previous safe mode unsuccessful; skipped ota_http"); - pref_.ota_http_state = OTA_HTTP_STATE_ABORT; - pref_obj_.save(&pref_); + this->pref_.ota_http_state = OTA_HTTP_STATE_ABORT; + this->pref_obj_.save(&this->pref_); global_preferences->sync(); } } diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index d01579370c..a409bff7f2 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -32,14 +32,10 @@ class OtaHttpComponent : public Component { void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } void set_url(const std::string &url) { - // this->url_ = std::move(url); - // TODO check size - size_t length = std::min(url.length(), static_cast(sizeof(pref_.url) - 1)); - strncpy(pref_.url, url.c_str(), length); - pref_.url[length] = '\0'; - // this->secure_ = url.rfind("https:", 0) == 0; - // this->secure_ = strncmp(pref_.url, "https:", 6) == 0; - pref_obj_.save(&pref_); + size_t length = std::min(url.length(), static_cast(sizeof(this->pref_.url) - 1)); + strncpy(this->pref_.url, url.c_str(), length); + this->pref_.url[length] = '\0'; + this->pref_obj_.save(&this->pref_); } void set_timeout(uint64_t timeout) { this->timeout_ = timeout; } void flash(); @@ -49,8 +45,7 @@ class OtaHttpComponent : public Component { virtual void http_end(){}; protected: - // std::string url_; - bool secure_() { return strncmp(pref_.url, "https:", 6) == 0; }; + bool secure_() { return strncmp(this->pref_.url, "https:", 6) == 0; }; size_t body_length_ = 0; size_t bytes_read_ = 0; uint64_t timeout_{1000 * 60 * 10}; // must match CONF_TIMEOUT in __init__.py diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index f5281617e9..bc6c02ff70 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -51,17 +51,17 @@ int OtaHttpArduino::http_init() { #endif // USE_HTTP_REQUEST_ESP8266_HTTPS #endif // USE_ESP8266 - ESP_LOGD(TAG, "Trying to connect to %s", pref_.url); + ESP_LOGD(TAG, "Trying to connect to %s", this->pref_.url); bool status = false; #ifdef USE_RP2040 this->client_.setInsecure(); #endif #if defined(USE_ESP32) || defined(USE_RP2040) - status = this->client_.begin(pref_.url); + status = this->client_.begin(this->pref_.url); #endif #ifdef USE_ESP8266 - status = this->client_.begin(*this->stream_ptr_, pref_.url); + status = this->client_.begin(*this->stream_ptr_, this->pref_.url); #endif if (!status) { diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 92a61a603d..19e0744617 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -36,7 +36,7 @@ int OtaHttpIDF::http_init() { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" esp_http_client_config_t config = {nullptr}; - config.url = pref_.url; + config.url = this->pref_.url; config.method = HTTP_METHOD_GET; config.timeout_ms = (int) this->timeout_; config.buffer_size = this->max_http_recv_buffer_; From a404701ca2dc86d0a496e063d1895cf80406bfb8 Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 8 Mar 2024 21:31:32 +0000 Subject: [PATCH 44/97] OTA_HTTP_STATE_ as enum, and removed unneeded nvs load --- esphome/components/ota_http/ota_http.cpp | 7 ++----- esphome/components/ota_http/ota_http.h | 12 +++++++----- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index b7177e6082..939b1ba042 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -44,12 +44,8 @@ void OtaHttpComponent::dump_config() { }; void OtaHttpComponent::flash() { - if (this->pref_obj_.load(&this->pref_)) { - ESP_LOGV(TAG, "restored pref ota_http_state: %d", this->pref_.ota_http_state); - } - if (this->pref_.ota_http_state != OTA_HTTP_STATE_SAFE_MODE) { - ESP_LOGV(TAG, "setting mode to progress"); + ESP_LOGV(TAG, "Setting mode to progress"); this->pref_.ota_http_state = OTA_HTTP_STATE_PROGRESS; this->pref_obj_.save(&this->pref_); } @@ -164,6 +160,7 @@ void OtaHttpComponent::cleanup_() { }; void OtaHttpComponent::check_upgrade() { + // function called at boot time if CONF_SAFE_MODE is True or "fallback" if (this->pref_obj_.load(&this->pref_)) { if (this->pref_.ota_http_state == OTA_HTTP_STATE_PROGRESS) { // progress at boot time means that there was a problem diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index a409bff7f2..9c37d3d1de 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -12,17 +12,19 @@ namespace esphome { namespace ota_http { -static const uint8_t OTA_HTTP_STATE_OK = 10; -static const uint8_t OTA_HTTP_STATE_PROGRESS = 20; -static const uint8_t OTA_HTTP_STATE_SAFE_MODE = 30; -static const uint8_t OTA_HTTP_STATE_ABORT = 40; +enum OtaHttpState { + OTA_HTTP_STATE_OK, + OTA_HTTP_STATE_PROGRESS, + OTA_HTTP_STATE_SAFE_MODE, + OTA_HTTP_STATE_ABORT +}; #define OTA_HTTP_PREF_SAFE_MODE_HASH 99380598UL static const char *const TAG = "ota_http"; struct OtaHttpGlobalPrefType { - int ota_http_state; + OtaHttpState ota_http_state; char url[256]; bool verify_ssl; } PACKED; From ce4235f172f9535142e84bf256419217518d3e7f Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 8 Mar 2024 21:34:49 +0000 Subject: [PATCH 45/97] lint --- esphome/components/ota_http/ota_http.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 9c37d3d1de..0320262fa1 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -12,12 +12,7 @@ namespace esphome { namespace ota_http { -enum OtaHttpState { - OTA_HTTP_STATE_OK, - OTA_HTTP_STATE_PROGRESS, - OTA_HTTP_STATE_SAFE_MODE, - OTA_HTTP_STATE_ABORT -}; +enum OtaHttpState { OTA_HTTP_STATE_OK, OTA_HTTP_STATE_PROGRESS, OTA_HTTP_STATE_SAFE_MODE, OTA_HTTP_STATE_ABORT }; #define OTA_HTTP_PREF_SAFE_MODE_HASH 99380598UL From cbb3784a1350ba09883f591126bfe805ffc29f47 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sat, 9 Mar 2024 22:43:18 +0000 Subject: [PATCH 46/97] let timeout_ uninitialized , and set templatable type to uint64_t --- esphome/components/ota_http/ota_http.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 0320262fa1..83c35bde29 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -45,7 +45,7 @@ class OtaHttpComponent : public Component { bool secure_() { return strncmp(this->pref_.url, "https:", 6) == 0; }; size_t body_length_ = 0; size_t bytes_read_ = 0; - uint64_t timeout_{1000 * 60 * 10}; // must match CONF_TIMEOUT in __init__.py + uint64_t timeout_; const uint16_t http_recv_buffer_ = 1000; // the firwmware GET chunk size const uint16_t max_http_recv_buffer_ = 1024; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS // overhead) and must be a power of two from 512 to 4096 @@ -61,7 +61,7 @@ template class OtaHttpFlashAction : public Action { public: OtaHttpFlashAction(OtaHttpComponent *parent) : parent_(parent) {} TEMPLATABLE_VALUE(std::string, url) - TEMPLATABLE_VALUE(uint16_t, timeout) + TEMPLATABLE_VALUE(uint64_t, timeout) void play(Ts... x) override { this->parent_->set_url(this->url_.value(x...)); From f525c27e48cbbe6e005a57939702d62db9771d5c Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Sun, 10 Mar 2024 19:28:41 +0100 Subject: [PATCH 47/97] Trailing comma in enum Co-authored-by: Keith Burzinski --- esphome/components/ota_http/ota_http.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 83c35bde29..eedc755fc5 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -12,7 +12,12 @@ namespace esphome { namespace ota_http { -enum OtaHttpState { OTA_HTTP_STATE_OK, OTA_HTTP_STATE_PROGRESS, OTA_HTTP_STATE_SAFE_MODE, OTA_HTTP_STATE_ABORT }; +enum OtaHttpState { + OTA_HTTP_STATE_OK, + OTA_HTTP_STATE_PROGRESS, + OTA_HTTP_STATE_SAFE_MODE, + OTA_HTTP_STATE_ABORT, +}; #define OTA_HTTP_PREF_SAFE_MODE_HASH 99380598UL From e052150ecdd9bfc79cfc2cb2c4af720b27c1e140 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 11 Mar 2024 23:52:53 +0000 Subject: [PATCH 48/97] check 'restore_from_flash' is enabled on 8266 if safe_mode used --- esphome/components/ota_http/__init__.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index af5f6237bb..4ec8607678 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -1,6 +1,7 @@ import urllib.parse as urlparse import esphome.codegen as cg import esphome.config_validation as cv +import esphome.final_validate as fv from esphome import automation from esphome.const import ( CONF_ID, @@ -16,7 +17,7 @@ from esphome.core import Lambda, CORE, coroutine_with_priority CODEOWNERS = ["@oarcher"] DEPENDENCIES = ["network"] -AUTO_LOAD = ["md5", "ota"] +AUTO_LOAD = ["md5", "ota", "preferences"] ota_http_ns = cg.esphome_ns.namespace("ota_http") OtaHttpComponent = ota_http_ns.class_("OtaHttpComponent", cg.Component) @@ -60,6 +61,16 @@ def validate_secure_url(config): ) return config +def validate_safe_mode(config): + # using 'safe_mode' on 'esp8266' require 'restore_from_flash' + if CORE.is_esp8266 and config[CONF_SAFE_MODE]: + if not fv.full_config.get()["esp8266"]["restore_from_flash"]: + raise cv.Invalid( + "Using 'safe_mode' on 'esp8266' require 'restore_from_flash'." + "See https://esphome.io/components/esp8266#configuration-variables" + ) + return config + def _declare_request_class(value): if CORE.using_esp_idf: @@ -93,6 +104,10 @@ CONFIG_SCHEMA = cv.All( ), ) +FINAL_VALIDATE_SCHEMA = cv.All( + validate_safe_mode +) + @coroutine_with_priority(50.0) async def to_code(config): From d6d07e851e2f4db89f9e07bfa01507a9c197b17a Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 11 Mar 2024 23:55:35 +0000 Subject: [PATCH 49/97] removed 'preferences' from AUTO_LOAD --- esphome/components/ota_http/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 4ec8607678..c69498f01e 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -17,7 +17,7 @@ from esphome.core import Lambda, CORE, coroutine_with_priority CODEOWNERS = ["@oarcher"] DEPENDENCIES = ["network"] -AUTO_LOAD = ["md5", "ota", "preferences"] +AUTO_LOAD = ["md5", "ota"] ota_http_ns = cg.esphome_ns.namespace("ota_http") OtaHttpComponent = ota_http_ns.class_("OtaHttpComponent", cg.Component) From e5c4bf3cf1d947163ae1aeb3ca8593899b0b080a Mon Sep 17 00:00:00 2001 From: oarcher Date: Tue, 12 Mar 2024 00:06:46 +0000 Subject: [PATCH 50/97] disable 'safe_mode' for 8266 tests --- tests/test3.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test3.yaml b/tests/test3.yaml index bf819d60f0..8ef50b1009 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -333,6 +333,7 @@ ota: reboot_timeout: 15min ota_http: + safe_mode: false logger: hardware_uart: UART1 From 5393af1e828593132d49d9a9414c7485705b6a1a Mon Sep 17 00:00:00 2001 From: oarcher Date: Tue, 12 Mar 2024 00:08:28 +0000 Subject: [PATCH 51/97] lint --- esphome/components/ota_http/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index c69498f01e..8766a2cdc7 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -61,6 +61,7 @@ def validate_secure_url(config): ) return config + def validate_safe_mode(config): # using 'safe_mode' on 'esp8266' require 'restore_from_flash' if CORE.is_esp8266 and config[CONF_SAFE_MODE]: @@ -104,9 +105,7 @@ CONFIG_SCHEMA = cv.All( ), ) -FINAL_VALIDATE_SCHEMA = cv.All( - validate_safe_mode -) +FINAL_VALIDATE_SCHEMA = cv.All(validate_safe_mode) @coroutine_with_priority(50.0) From c48f3a68a8fa57688ff1833793a7dd13d38d4f1c Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sat, 16 Mar 2024 01:21:17 -0500 Subject: [PATCH 52/97] Cert validation for IDF --- esphome/components/ota_http/__init__.py | 47 +++++++++++--------- esphome/components/ota_http/ota_http_idf.cpp | 7 ++- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 8766a2cdc7..f1a0154c49 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -12,7 +12,7 @@ from esphome.const import ( CONF_SAFE_MODE, ) from esphome.components import esp32 -from esphome.core import Lambda, CORE, coroutine_with_priority +from esphome.core import CORE, coroutine_with_priority CODEOWNERS = ["@oarcher"] @@ -26,7 +26,17 @@ OtaHttpIDF = ota_http_ns.class_("OtaHttpIDF", OtaHttpComponent) OtaHttpFlashAction = ota_http_ns.class_("OtaHttpFlashAction", automation.Action) -CONF_VERIFY_SSL = "verify_ssl" +CONF_EXCLUDE_CERTIFICATE_BUNDLE = "exclude_certificate_bundle" + + +def validate_certificate_bundle(config): + if not config.get(CONF_EXCLUDE_CERTIFICATE_BUNDLE) and not CORE.using_esp_idf: + raise cv.Invalid( + "ESPHome supports certificate verification only via ESP-IDF. " + f"Set '{CONF_EXCLUDE_CERTIFICATE_BUNDLE}: true' to skip certificate validation." + ) + + return config def validate_url(value): @@ -48,20 +58,6 @@ def validate_url(value): return urlparse.urlunparse(parsed) -def validate_secure_url(config): - url_ = config[CONF_URL] - if ( - config.get(CONF_VERIFY_SSL) - and not isinstance(url_, Lambda) - and url_.lower().startswith("https:") - ): - raise cv.Invalid( - "Currently ESPHome doesn't support SSL verification. " - "Set 'verify_ssl: false' to make insecure HTTPS requests." - ) - return config - - def validate_safe_mode(config): # using 'safe_mode' on 'esp8266' require 'restore_from_flash' if CORE.is_esp8266 and config[CONF_SAFE_MODE]: @@ -92,6 +88,7 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( cv.only_on_esp8266, cv.boolean ), + cv.Optional(CONF_EXCLUDE_CERTIFICATE_BUNDLE, default=False): cv.boolean, cv.Optional(CONF_SAFE_MODE, default="fallback"): cv.Any( cv.boolean, "fallback" ), @@ -103,6 +100,7 @@ CONFIG_SCHEMA = cv.All( esp_idf=cv.Version(0, 0, 0), rp2040_arduino=cv.Version(0, 0, 0), ), + validate_certificate_bundle, ) FINAL_VALIDATE_SCHEMA = cv.All(validate_safe_mode) @@ -118,9 +116,17 @@ async def to_code(config): if CORE.is_esp32: 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 + "CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", + not config.get(CONF_EXCLUDE_CERTIFICATE_BUNDLE), + ) + esp32.add_idf_sdkconfig_option( + "CONFIG_ESP_TLS_INSECURE", + config.get(CONF_EXCLUDE_CERTIFICATE_BUNDLE), + ) + esp32.add_idf_sdkconfig_option( + "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", + config.get(CONF_EXCLUDE_CERTIFICATE_BUNDLE), ) else: cg.add_library("WiFiClientSecure", None) @@ -142,9 +148,10 @@ OTA_HTTP_ACTION_SCHEMA = cv.Schema( { cv.GenerateID(): cv.use_id(OtaHttpComponent), cv.Required(CONF_URL): cv.templatable(validate_url), - cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, } -).add_extra(validate_secure_url) +) + + OTA_HTTP_FLASH_ACTION_SCHEMA = automation.maybe_conf( CONF_URL, OTA_HTTP_ACTION_SCHEMA.extend( diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 19e0744617..eeace9f4e5 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -1,5 +1,3 @@ - - #ifdef USE_ESP_IDF #include "ota_http_idf.h" @@ -42,6 +40,11 @@ int OtaHttpIDF::http_init() { config.buffer_size = this->max_http_recv_buffer_; config.auth_type = HTTP_AUTH_TYPE_BASIC; config.max_authorization_retries = -1; +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + if (this->secure_()) { + config.crt_bundle_attach = esp_crt_bundle_attach; + } +#endif #pragma GCC diagnostic pop this->client_ = esp_http_client_init(&config); From 1cc6aa0a6852def0f30c3afe87681ff63623afcc Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 18 Mar 2024 01:54:24 -0500 Subject: [PATCH 53/97] Add MD5 validation Linting, update tests Fix test One more... Couple 8266 fixes --- esphome/components/ota_http/__init__.py | 4 + esphome/components/ota_http/ota_http.cpp | 72 +++++++++------ esphome/components/ota_http/ota_http.h | 21 +++-- .../components/ota_http/ota_http_arduino.cpp | 87 ++++++++++--------- .../components/ota_http/ota_http_arduino.h | 3 +- esphome/components/ota_http/ota_http_idf.cpp | 13 ++- esphome/components/ota_http/ota_http_idf.h | 2 +- .../ota_http/test.esp32-c3-idf.yaml | 6 ++ tests/components/ota_http/test.esp32-c3.yaml | 6 ++ tests/components/ota_http/test.esp32-idf.yaml | 5 ++ tests/components/ota_http/test.esp32.yaml | 6 ++ tests/components/ota_http/test.esp8266.yaml | 10 +++ tests/components/ota_http/test.rp2040.yaml | 6 ++ tests/test1.yaml | 2 - tests/test3.yaml | 3 - 15 files changed, 162 insertions(+), 84 deletions(-) create mode 100644 tests/components/ota_http/test.esp32-c3-idf.yaml create mode 100644 tests/components/ota_http/test.esp32-c3.yaml create mode 100644 tests/components/ota_http/test.esp32-idf.yaml create mode 100644 tests/components/ota_http/test.esp32.yaml create mode 100644 tests/components/ota_http/test.esp8266.yaml create mode 100644 tests/components/ota_http/test.rp2040.yaml diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index f1a0154c49..b15784cf33 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -27,6 +27,7 @@ OtaHttpIDF = ota_http_ns.class_("OtaHttpIDF", OtaHttpComponent) OtaHttpFlashAction = ota_http_ns.class_("OtaHttpFlashAction", automation.Action) CONF_EXCLUDE_CERTIFICATE_BUNDLE = "exclude_certificate_bundle" +CONF_MD5_URL = "md5_url" def validate_certificate_bundle(config): @@ -147,6 +148,7 @@ async def to_code(config): OTA_HTTP_ACTION_SCHEMA = cv.Schema( { cv.GenerateID(): cv.use_id(OtaHttpComponent), + cv.Required(CONF_MD5_URL): cv.templatable(validate_url), cv.Required(CONF_URL): cv.templatable(validate_url), } ) @@ -169,6 +171,8 @@ async def ota_http_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_arg, paren) + template_ = await cg.templatable(config[CONF_MD5_URL], args, cg.std_string) + cg.add(var.set_md5_url(template_)) template_ = await cg.templatable(config[CONF_URL], args, cg.std_string) cg.add(var.set_url(template_)) return var diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 939b1ba042..7fc13551f7 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -39,13 +39,13 @@ std::unique_ptr make_ota_backend() { const std::unique_ptr OtaHttpComponent::BACKEND = make_ota_backend(); void OtaHttpComponent::dump_config() { - ESP_LOGCONFIG(TAG, "OTA_http:"); + ESP_LOGCONFIG(TAG, "ota_http:"); ESP_LOGCONFIG(TAG, " Timeout: %llums", (uint64_t) this->timeout_); }; void OtaHttpComponent::flash() { if (this->pref_.ota_http_state != OTA_HTTP_STATE_SAFE_MODE) { - ESP_LOGV(TAG, "Setting mode to progress"); + ESP_LOGV(TAG, "Setting state to 'progress'"); this->pref_.ota_http_state = OTA_HTTP_STATE_PROGRESS; this->pref_obj_.save(&this->pref_); } @@ -54,7 +54,7 @@ void OtaHttpComponent::flash() { #ifdef OTA_HTTP_ONLY_AT_BOOT if (this->pref_.ota_http_state != OTA_HTTP_STATE_SAFE_MODE) { - ESP_LOGI(TAG, "Rebooting before flashing new firmware."); + ESP_LOGI(TAG, "Rebooting before flashing new firmware"); App.safe_reboot(); } #endif @@ -63,16 +63,16 @@ void OtaHttpComponent::flash() { uint8_t buf[this->http_recv_buffer_ + 1]; int error_code = 0; uint32_t last_progress = 0; - esphome::md5::MD5Digest md5_receive; + md5::MD5Digest md5_receive; std::unique_ptr md5_receive_str(new char[33]); - if (!this->http_init()) { + if (!this->http_get_md5() || !this->http_init(this->pref_.url)) { return; } - // we will compute md5 on the fly - // TODO: better security if fetched from the http server + ESP_LOGD(TAG, "MD5 expected: %s", this->md5_expected_); + // we will compute MD5 on the fly for verification -- Arduino OTA seems to ignore it md5_receive.init(); - ESP_LOGV(TAG, "md5sum from received data initialized."); + ESP_LOGV(TAG, "MD5Digest initialized"); error_code = esphome::ota_http::OtaHttpComponent::BACKEND->begin(this->body_length_); if (error_code != 0) { @@ -82,22 +82,23 @@ void OtaHttpComponent::flash() { } ESP_LOGV(TAG, "OTA backend begin"); + this->bytes_read_ = 0; while (this->bytes_read_ != this->body_length_) { // read a maximum of chunk_size bytes into buf. (real read size returned) int bufsize = this->http_read(buf, this->http_recv_buffer_); if (bufsize < 0) { - ESP_LOGE(TAG, "ERROR: stream closed"); + ESP_LOGE(TAG, "Stream closed"); this->cleanup_(); return; } - // add read bytes to md5 + // add read bytes to MD5 md5_receive.add(buf, bufsize); // write bytes to OTA backend this->update_started_ = true; - error_code = esphome::ota_http::OtaHttpComponent::BACKEND->write(buf, bufsize); + error_code = ota_http::OtaHttpComponent::BACKEND->write(buf, bufsize); if (error_code != 0) { // error code explaination available at // https://github.com/esphome/esphome/blob/dev/esphome/components/ota/ota_component.h @@ -112,29 +113,34 @@ void OtaHttpComponent::flash() { last_progress = now; ESP_LOGI(TAG, "Progress: %0.1f%%", this->bytes_read_ * 100. / this->body_length_); // feed watchdog and give other tasks a chance to run - esphome::App.feed_wdt(); + App.feed_wdt(); yield(); } } // while - ESP_LOGI(TAG, "Done in %.0f secs", float(millis() - update_start_time) / 1000); + ESP_LOGI(TAG, "Done in %.0f seconds", float(millis() - update_start_time) / 1000); - // send md5 to backend (backend will check that the flashed one has the same) + // verify MD5 is as expected and act accordingly md5_receive.calculate(); md5_receive.get_hex(md5_receive_str.get()); - ESP_LOGD(TAG, "md5sum recieved: %s (size %d)", md5_receive_str.get(), this->bytes_read_); - esphome::ota_http::OtaHttpComponent::BACKEND->set_update_md5(md5_receive_str.get()); + if (strncmp(md5_receive_str.get(), this->md5_expected_, MD5_SIZE) != 0) { + ESP_LOGE(TAG, "MD5 computed: %s - Aborting due to MD5 mismatch", md5_receive_str.get()); + this->cleanup_(); + return; + } else { + ota_http::OtaHttpComponent::BACKEND->set_update_md5(md5_receive_str.get()); + } this->http_end(); // feed watchdog and give other tasks a chance to run - esphome::App.feed_wdt(); + App.feed_wdt(); yield(); delay(100); // NOLINT - error_code = esphome::ota_http::OtaHttpComponent::BACKEND->end(); + error_code = ota_http::OtaHttpComponent::BACKEND->end(); if (error_code != 0) { - ESP_LOGE(TAG, "Error ending OTA!, error_code: %d", error_code); + ESP_LOGE(TAG, "Error ending OTA (%d)", error_code); this->cleanup_(); return; } @@ -142,20 +148,22 @@ void OtaHttpComponent::flash() { this->pref_.ota_http_state = OTA_HTTP_STATE_OK; this->pref_obj_.save(&this->pref_); delay(10); - ESP_LOGI(TAG, "OTA update finished! Rebooting..."); + ESP_LOGI(TAG, "OTA update completed"); delay(10); esphome::App.safe_reboot(); } void OtaHttpComponent::cleanup_() { if (this->update_started_) { - ESP_LOGE(TAG, "Abort OTA backend"); - esphome::ota_http::OtaHttpComponent::BACKEND->abort(); + ESP_LOGV(TAG, "Aborting OTA backend"); + ota_http::OtaHttpComponent::BACKEND->abort(); } - ESP_LOGE(TAG, "Aborting http connection"); + ESP_LOGV(TAG, "Aborting HTTP connection"); this->http_end(); - ESP_LOGE(TAG, "Previous safe mode unsuccessful; skipped ota_http"); - this->pref_.ota_http_state = OTA_HTTP_STATE_ABORT; + if (this->pref_.ota_http_state == OTA_HTTP_STATE_SAFE_MODE) { + ESP_LOGE(TAG, "Previous safe mode unsuccessful; skipped ota_http"); + this->pref_.ota_http_state = OTA_HTTP_STATE_ABORT; + } this->pref_obj_.save(&this->pref_); }; @@ -169,7 +177,7 @@ void OtaHttpComponent::check_upgrade() { delay(300); // NOLINT App.setup(); - ESP_LOGI(TAG, "Previous ota_http unsuccessful. Retrying"); + ESP_LOGI(TAG, "Previous ota_http unsuccessful. Retrying..."); this->pref_.ota_http_state = OTA_HTTP_STATE_SAFE_MODE; this->pref_obj_.save(&this->pref_); this->flash(); @@ -184,5 +192,17 @@ void OtaHttpComponent::check_upgrade() { } } +bool OtaHttpComponent::http_get_md5() { + if (this->http_init(this->pref_.md5_url) != MD5_SIZE) { + ESP_LOGE(TAG, "Incorrect file size (%d) for MD5 reported by HTTP server. Aborting", this->body_length_); + return false; + } + + auto read_len = this->http_read((uint8_t *) this->md5_expected_, MD5_SIZE); + this->http_end(); + + return read_len == MD5_SIZE; +} + } // namespace ota_http } // namespace esphome diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index eedc755fc5..b8d4f4109f 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -22,27 +22,35 @@ enum OtaHttpState { #define OTA_HTTP_PREF_SAFE_MODE_HASH 99380598UL static const char *const TAG = "ota_http"; +static const uint8_t MD5_SIZE = 32; struct OtaHttpGlobalPrefType { OtaHttpState ota_http_state; + char md5_url[256]; char url[256]; - bool verify_ssl; } PACKED; class OtaHttpComponent : public Component { public: void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } + void set_md5_url(const std::string &md5_url) { + size_t length = std::min(md5_url.length(), static_cast(sizeof(this->pref_.md5_url) - 1)); + strncpy(this->pref_.md5_url, md5_url.c_str(), length); + this->pref_.md5_url[length] = 0; // null terminator + this->pref_obj_.save(&this->pref_); + } void set_url(const std::string &url) { size_t length = std::min(url.length(), static_cast(sizeof(this->pref_.url) - 1)); strncpy(this->pref_.url, url.c_str(), length); - this->pref_.url[length] = '\0'; + this->pref_.url[length] = 0; // null terminator this->pref_obj_.save(&this->pref_); } void set_timeout(uint64_t timeout) { this->timeout_ = timeout; } void flash(); void check_upgrade(); - virtual int http_init() { return -1; }; + bool http_get_md5(); + virtual int http_init(char *url) { return -1; }; virtual int http_read(uint8_t *buf, size_t len) { return 0; }; virtual void http_end(){}; @@ -51,13 +59,14 @@ class OtaHttpComponent : public Component { size_t body_length_ = 0; size_t bytes_read_ = 0; uint64_t timeout_; - const uint16_t http_recv_buffer_ = 1000; // the firwmware GET chunk size + const uint16_t http_recv_buffer_ = 1000; // the firmware GET chunk size const uint16_t max_http_recv_buffer_ = 1024; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS // overhead) and must be a power of two from 512 to 4096 bool update_started_ = false; static const std::unique_ptr BACKEND; void cleanup_(); - OtaHttpGlobalPrefType pref_ = {OTA_HTTP_STATE_OK, "", true}; + char md5_expected_[MD5_SIZE]; + OtaHttpGlobalPrefType pref_ = {OTA_HTTP_STATE_OK, "", ""}; ESPPreferenceObject pref_obj_ = global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); }; @@ -65,10 +74,12 @@ class OtaHttpComponent : public Component { template class OtaHttpFlashAction : public Action { public: OtaHttpFlashAction(OtaHttpComponent *parent) : parent_(parent) {} + TEMPLATABLE_VALUE(std::string, md5_url) TEMPLATABLE_VALUE(std::string, url) TEMPLATABLE_VALUE(uint64_t, timeout) void play(Ts... x) override { + this->parent_->set_md5_url(this->md5_url_.value(x...)); this->parent_->set_url(this->url_.value(x...)); if (this->timeout_.has_value()) { this->parent_->set_timeout(this->timeout_.value(x...)); diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index bc6c02ff70..4329c582a2 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -1,9 +1,3 @@ -// firmware update from http (ie when OTA port is behind a firewall) -// code adapted from -// esphome/components/ota/ota_backend.cpp -// and -// esphome/components/http_request - #include "ota_http.h" #ifdef USE_ARDUINO @@ -22,7 +16,7 @@ struct Header { const char *value; }; -int OtaHttpArduino::http_init() { +int OtaHttpArduino::http_init(char *url) { int http_code; uint32_t start_time; uint32_t duration; @@ -31,80 +25,67 @@ int OtaHttpArduino::http_init() { const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); #ifdef USE_ESP8266 -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS - if (this->secure_()) { - ESP_LOGD(TAG, "esp8266 https connection with WiFiClientSecure"); - this->stream_ptr_ = std::make_unique(); - WiFiClientSecure *secure_client = static_cast(this->stream_ptr_.get()); - secure_client->setBufferSizes(this->max_http_recv_buffer_, 512); - secure_client->setInsecure(); - } else { - this->stream_ptr_ = std::make_unique(); + if (this->stream_ptr_ == nullptr && this->set_stream_ptr_()) { + ESP_LOGE(TAG, "Unable to set client"); } -#else - ESP_LOGD(TAG, "esp8266 http connection with WiFiClient"); - if (this->secure_()) { - ESP_LOGE(TAG, "Can't use https connection with esp8266_disable_ssl_support"); - return -1; - } - this->stream_ptr_ = std::make_unique(); -#endif // USE_HTTP_REQUEST_ESP8266_HTTPS #endif // USE_ESP8266 - ESP_LOGD(TAG, "Trying to connect to %s", this->pref_.url); + ESP_LOGD(TAG, "Trying to connect to %s", url); bool status = false; #ifdef USE_RP2040 this->client_.setInsecure(); #endif #if defined(USE_ESP32) || defined(USE_RP2040) - status = this->client_.begin(this->pref_.url); + status = this->client_.begin(url); #endif #ifdef USE_ESP8266 - status = this->client_.begin(*this->stream_ptr_, this->pref_.url); + status = this->client_.begin(*this->stream_ptr_, String(url)); #endif if (!status) { - ESP_LOGE(TAG, "Unable to make http connection"); + ESP_LOGE(TAG, "Unable to make HTTP connection"); this->client_.end(); return -1; } else { - ESP_LOGV(TAG, "http begin successful"); + ESP_LOGV(TAG, "HTTP begin successful"); } this->client_.setReuse(true); - ESP_LOGVV(TAG, "http client setReuse."); + ESP_LOGVV(TAG, "HTTP client setReuse"); // returned needed headers must be collected before the requests this->client_.collectHeaders(header_keys, header_count); - ESP_LOGV(TAG, "http headers collected."); + ESP_LOGV(TAG, "HTTP headers collected"); - // http GET + // HTTP GET start_time = millis(); http_code = this->client_.GET(); duration = millis() - start_time; - ESP_LOGV(TAG, "http GET finished."); + ESP_LOGV(TAG, "HTTP GET finished"); if (http_code >= 310) { - ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s (%d); Duration: %u ms", pref_.url, + ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s (%d); Duration: %u ms", url, HTTPClient::errorToString(http_code).c_str(), http_code, duration); return -1; } if (this->client_.getSize() < 0) { - ESP_LOGE(TAG, "Incorrect file size (%d) reported by http server (http status: %d). Aborting", - this->client_.getSize(), http_code); + ESP_LOGE(TAG, "Incorrect file size (%d) reported by HTTP server (status: %d). Aborting", this->client_.getSize(), + http_code); return -1; } this->body_length_ = (size_t) this->client_.getSize(); - ESP_LOGD(TAG, "firmware is %d bytes length.", this->body_length_); + ESP_LOGV(TAG, "body_length: %d", this->body_length_); #if defined(USE_ESP32) || defined(USE_RP2040) - this->stream_ptr_ = std::unique_ptr(this->client_.getStreamPtr()); + if (this->stream_ptr_ == nullptr) { + this->set_stream_ptr_(); + } #endif - return 1; + return this->body_length_; } int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { @@ -130,6 +111,34 @@ int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { void OtaHttpArduino::http_end() { this->client_.end(); } +int OtaHttpArduino::set_stream_ptr_() { +#ifdef USE_ESP8266 +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS + if (this->secure_()) { + ESP_LOGD(TAG, "ESP8266 HTTPS connection with WiFiClientSecure"); + this->stream_ptr_ = std::make_unique(); + WiFiClientSecure *secure_client = static_cast(this->stream_ptr_.get()); + secure_client->setBufferSizes(this->max_http_recv_buffer_, 512); + secure_client->setInsecure(); + } else { + this->stream_ptr_ = std::make_unique(); + } +#else + ESP_LOGD(TAG, "ESP8266 HTTP connection with WiFiClient"); + if (this->secure_()) { + ESP_LOGE(TAG, "Can't use HTTPS connection with esp8266_disable_ssl_support"); + return -1; + } + this->stream_ptr_ = std::make_unique(); +#endif // USE_HTTP_REQUEST_ESP8266_HTTPS +#endif // USE_ESP8266 + +#if defined(USE_ESP32) || defined(USE_RP2040) + this->stream_ptr_ = std::unique_ptr(this->client_.getStreamPtr()); +#endif + return 0; +} + } // namespace ota_http } // namespace esphome diff --git a/esphome/components/ota_http/ota_http_arduino.h b/esphome/components/ota_http/ota_http_arduino.h index 16f0783050..7885bef97e 100644 --- a/esphome/components/ota_http/ota_http_arduino.h +++ b/esphome/components/ota_http/ota_http_arduino.h @@ -27,11 +27,12 @@ namespace ota_http { class OtaHttpArduino : public OtaHttpComponent { public: - int http_init() override; + int http_init(char *url) override; int http_read(uint8_t *buf, size_t len) override; void http_end() override; protected: + int set_stream_ptr_(); HTTPClient client_{}; std::unique_ptr stream_ptr_; }; diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index eeace9f4e5..7b9d4e0967 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -30,11 +30,11 @@ namespace esphome { namespace ota_http { -int OtaHttpIDF::http_init() { +int OtaHttpIDF::http_init(char *url) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" esp_http_client_config_t config = {nullptr}; - config.url = this->pref_.url; + config.url = url; config.method = HTTP_METHOD_GET; config.timeout_ms = (int) this->timeout_; config.buffer_size = this->max_http_recv_buffer_; @@ -55,15 +55,14 @@ int OtaHttpIDF::http_init() { } this->body_length_ = esp_http_client_fetch_headers(this->client_); - ESP_LOGD(TAG, "body_length: %d , esp_http_client_get_content_length: %" PRId64, this->body_length_, + ESP_LOGV(TAG, "body_length: %d , esp_http_client_get_content_length: %" PRId64, this->body_length_, (int64_t) esp_http_client_get_content_length(this->client_)); if (this->body_length_ <= 0) { - ESP_LOGE(TAG, "Incorrect file size (%d) reported by http server (http status: %d). Aborting", this->body_length_, - err); + ESP_LOGE(TAG, "Incorrect file size (%d) reported by HTTP server (status: %d). Aborting", this->body_length_, err); return -1; } - return 1; + return this->body_length_; } int OtaHttpIDF::http_read(uint8_t *buf, const size_t max_len) { @@ -73,7 +72,7 @@ int OtaHttpIDF::http_read(uint8_t *buf, const size_t max_len) { this->bytes_read_ += bufsize; buf[bufsize] = '\0'; // not fed to ota } - // ESP_LOGVV(TAG, "Read %d bytes, %d remainings", read_len, this->body_length_ - this->bytes_read); + // ESP_LOGVV(TAG, "Read %d bytes, %d remaining", read_len, this->body_length_ - this->bytes_read); return read_len; } diff --git a/esphome/components/ota_http/ota_http_idf.h b/esphome/components/ota_http/ota_http_idf.h index a52b859203..5db1e4c0d1 100644 --- a/esphome/components/ota_http/ota_http_idf.h +++ b/esphome/components/ota_http/ota_http_idf.h @@ -11,7 +11,7 @@ namespace ota_http { class OtaHttpIDF : public OtaHttpComponent { public: - int http_init() override; + int http_init(char *url) override; int http_read(uint8_t *buf, size_t len) override; void http_end() override; diff --git a/tests/components/ota_http/test.esp32-c3-idf.yaml b/tests/components/ota_http/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..792ed87ad4 --- /dev/null +++ b/tests/components/ota_http/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +ota_http: + safe_mode: false diff --git a/tests/components/ota_http/test.esp32-c3.yaml b/tests/components/ota_http/test.esp32-c3.yaml new file mode 100644 index 0000000000..ad3e1b1c6c --- /dev/null +++ b/tests/components/ota_http/test.esp32-c3.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +ota_http: + exclude_certificate_bundle: true diff --git a/tests/components/ota_http/test.esp32-idf.yaml b/tests/components/ota_http/test.esp32-idf.yaml new file mode 100644 index 0000000000..0dfc346fe3 --- /dev/null +++ b/tests/components/ota_http/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +wifi: + ssid: MySSID + password: password1 + +ota_http: diff --git a/tests/components/ota_http/test.esp32.yaml b/tests/components/ota_http/test.esp32.yaml new file mode 100644 index 0000000000..ad3e1b1c6c --- /dev/null +++ b/tests/components/ota_http/test.esp32.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +ota_http: + exclude_certificate_bundle: true diff --git a/tests/components/ota_http/test.esp8266.yaml b/tests/components/ota_http/test.esp8266.yaml new file mode 100644 index 0000000000..c684e22e0d --- /dev/null +++ b/tests/components/ota_http/test.esp8266.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +esp8266: + restore_from_flash: true + +ota_http: + exclude_certificate_bundle: true + safe_mode: true diff --git a/tests/components/ota_http/test.rp2040.yaml b/tests/components/ota_http/test.rp2040.yaml new file mode 100644 index 0000000000..ad3e1b1c6c --- /dev/null +++ b/tests/components/ota_http/test.rp2040.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +ota_http: + exclude_certificate_bundle: true diff --git a/tests/test1.yaml b/tests/test1.yaml index 37f106da78..c8ae9691c2 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -289,8 +289,6 @@ ota: lambda: >- ESP_LOGD("ota", "Got error code %d", x); -ota_http: - logger: baud_rate: 0 level: VERBOSE diff --git a/tests/test3.yaml b/tests/test3.yaml index 8ef50b1009..61d814385b 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -332,9 +332,6 @@ ota: port: 3286 reboot_timeout: 15min -ota_http: - safe_mode: false - logger: hardware_uart: UART1 level: DEBUG From d192fb80c744f0baa56ccac4d27779a9f24e37d7 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 19 Mar 2024 21:32:25 -0500 Subject: [PATCH 54/97] Be less fussy about MD5 file size --- esphome/components/ota_http/ota_http.cpp | 5 +++-- esphome/components/ota_http/ota_http_arduino.cpp | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 7fc13551f7..f85aece18a 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -193,8 +193,9 @@ void OtaHttpComponent::check_upgrade() { } bool OtaHttpComponent::http_get_md5() { - if (this->http_init(this->pref_.md5_url) != MD5_SIZE) { - ESP_LOGE(TAG, "Incorrect file size (%d) for MD5 reported by HTTP server. Aborting", this->body_length_); + if (this->http_init(this->pref_.md5_url) < MD5_SIZE) { + ESP_LOGE(TAG, "MD5 file must be %u bytes; %u bytes reported by HTTP server. Aborting", MD5_SIZE, + this->body_length_); return false; } diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 4329c582a2..6360d0805b 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -30,7 +30,7 @@ int OtaHttpArduino::http_init(char *url) { } #endif // USE_ESP8266 - ESP_LOGD(TAG, "Trying to connect to %s", url); + ESP_LOGD(TAG, "Connecting to %s", url); bool status = false; #ifdef USE_RP2040 @@ -115,7 +115,7 @@ int OtaHttpArduino::set_stream_ptr_() { #ifdef USE_ESP8266 #ifdef USE_HTTP_REQUEST_ESP8266_HTTPS if (this->secure_()) { - ESP_LOGD(TAG, "ESP8266 HTTPS connection with WiFiClientSecure"); + ESP_LOGV(TAG, "ESP8266 HTTPS connection with WiFiClientSecure"); this->stream_ptr_ = std::make_unique(); WiFiClientSecure *secure_client = static_cast(this->stream_ptr_.get()); secure_client->setBufferSizes(this->max_http_recv_buffer_, 512); @@ -124,7 +124,7 @@ int OtaHttpArduino::set_stream_ptr_() { this->stream_ptr_ = std::make_unique(); } #else - ESP_LOGD(TAG, "ESP8266 HTTP connection with WiFiClient"); + ESP_LOGV(TAG, "ESP8266 HTTP connection with WiFiClient"); if (this->secure_()) { ESP_LOGE(TAG, "Can't use HTTPS connection with esp8266_disable_ssl_support"); return -1; From 300f096621f85ba579c2dc0f7682623740a97e0e Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 21 Mar 2024 23:16:14 +0000 Subject: [PATCH 55/97] skip CONF_EXCLUDE_CERTIFICATE_BUNDLE if CONF_ESP8266_DISABLE_SSL_SUPPORT --- esphome/components/ota_http/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index b15784cf33..22a28453b3 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -31,7 +31,7 @@ CONF_MD5_URL = "md5_url" def validate_certificate_bundle(config): - if not config.get(CONF_EXCLUDE_CERTIFICATE_BUNDLE) and not CORE.using_esp_idf: + if not (CORE.is_esp8266 and config.get(CONF_ESP8266_DISABLE_SSL_SUPPORT)) and (not config.get(CONF_EXCLUDE_CERTIFICATE_BUNDLE) and not CORE.using_esp_idf): raise cv.Invalid( "ESPHome supports certificate verification only via ESP-IDF. " f"Set '{CONF_EXCLUDE_CERTIFICATE_BUNDLE}: true' to skip certificate validation." From 7fac2c03e72a8472ef128dcc0eed22b1da929fa5 Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 21 Mar 2024 23:48:27 +0000 Subject: [PATCH 56/97] lint --- esphome/components/ota_http/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 22a28453b3..21b9176d25 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -31,7 +31,9 @@ CONF_MD5_URL = "md5_url" def validate_certificate_bundle(config): - if not (CORE.is_esp8266 and config.get(CONF_ESP8266_DISABLE_SSL_SUPPORT)) and (not config.get(CONF_EXCLUDE_CERTIFICATE_BUNDLE) and not CORE.using_esp_idf): + if not (CORE.is_esp8266 and config.get(CONF_ESP8266_DISABLE_SSL_SUPPORT)) and ( + not config.get(CONF_EXCLUDE_CERTIFICATE_BUNDLE) and not CORE.using_esp_idf + ): raise cv.Invalid( "ESPHome supports certificate verification only via ESP-IDF. " f"Set '{CONF_EXCLUDE_CERTIFICATE_BUNDLE}: true' to skip certificate validation." From 28dbcbe692341a9dc8b0658d33ecec5e1fe1325c Mon Sep 17 00:00:00 2001 From: oarcher Date: Sun, 24 Mar 2024 19:49:30 +0000 Subject: [PATCH 57/97] reduce http_recv_buffer_ from 1024 to 512 --- esphome/components/ota_http/ota_http.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index b8d4f4109f..c2663fdaa8 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -59,8 +59,8 @@ class OtaHttpComponent : public Component { size_t body_length_ = 0; size_t bytes_read_ = 0; uint64_t timeout_; - const uint16_t http_recv_buffer_ = 1000; // the firmware GET chunk size - const uint16_t max_http_recv_buffer_ = 1024; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS + const uint16_t http_recv_buffer_ = 500; // the firmware GET chunk size + const uint16_t max_http_recv_buffer_ = 512; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS // overhead) and must be a power of two from 512 to 4096 bool update_started_ = false; static const std::unique_ptr BACKEND; From c663f535e7f96f13821efd1b4d6fc3a0aa3af061 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sun, 24 Mar 2024 19:55:48 +0000 Subject: [PATCH 58/97] lint --- esphome/components/ota_http/ota_http.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index c2663fdaa8..46bcb91363 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -59,8 +59,8 @@ class OtaHttpComponent : public Component { size_t body_length_ = 0; size_t bytes_read_ = 0; uint64_t timeout_; - const uint16_t http_recv_buffer_ = 500; // the firmware GET chunk size - const uint16_t max_http_recv_buffer_ = 512; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS + const uint16_t http_recv_buffer_ = 500; // the firmware GET chunk size + const uint16_t max_http_recv_buffer_ = 512; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS // overhead) and must be a power of two from 512 to 4096 bool update_started_ = false; static const std::unique_ptr BACKEND; From f15a92b6bf72cd1dd27d77ed2637a6aaf619e649 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sun, 24 Mar 2024 20:00:51 +0000 Subject: [PATCH 59/97] lint --- esphome/components/ota_http/ota_http.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 46bcb91363..815906e6e6 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -59,9 +59,9 @@ class OtaHttpComponent : public Component { size_t body_length_ = 0; size_t bytes_read_ = 0; uint64_t timeout_; - const uint16_t http_recv_buffer_ = 500; // the firmware GET chunk size - const uint16_t max_http_recv_buffer_ = 512; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS - // overhead) and must be a power of two from 512 to 4096 + const uint16_t http_recv_buffer_ = 500; // the firmware GET chunk size + const uint16_t max_http_recv_buffer_ = 512; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS + // overhead) and must be a power of two from 512 to 4096 bool update_started_ = false; static const std::unique_ptr BACKEND; void cleanup_(); From 6bfd23a5a78bd7de722ba36cd026bb5e520bcf60 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sun, 24 Mar 2024 20:05:43 +0000 Subject: [PATCH 60/97] lint --- esphome/components/ota_http/ota_http.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 815906e6e6..11edf6b6eb 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -61,7 +61,7 @@ class OtaHttpComponent : public Component { uint64_t timeout_; const uint16_t http_recv_buffer_ = 500; // the firmware GET chunk size const uint16_t max_http_recv_buffer_ = 512; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS - // overhead) and must be a power of two from 512 to 4096 + // overhead) and must be a power of two from 512 to 4096 bool update_started_ = false; static const std::unique_ptr BACKEND; void cleanup_(); From 8c65721141a57211f94e08423848474e223842a2 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 25 Mar 2024 18:16:30 +0000 Subject: [PATCH 61/97] increase wdt for idf --- esphome/components/ota_http/ota_http_idf.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 7b9d4e0967..d3ba87c203 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -12,6 +12,7 @@ #include "esp_netif.h" #include "esp_tls.h" #include "nvs_flash.h" +#include "esp_task_wdt.h" #include #include #include @@ -31,6 +32,8 @@ namespace esphome { namespace ota_http { int OtaHttpIDF::http_init(char *url) { + esp_task_wdt_init(20, true); + App.feed_wdt(); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" esp_http_client_config_t config = {nullptr}; From a6e58daf91a32027e8b82bac97f213144ad43a1a Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 25 Mar 2024 21:32:02 +0000 Subject: [PATCH 62/97] increase wdt for idf>=5, rp2040 and 8266 --- esphome/components/ota_http/ota_http.h | 5 +++-- .../components/ota_http/ota_http_arduino.cpp | 22 +++++++++++++++++++ esphome/components/ota_http/ota_http_idf.cpp | 12 +++++++++- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 11edf6b6eb..977b0bcd84 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -23,11 +23,12 @@ enum OtaHttpState { static const char *const TAG = "ota_http"; static const uint8_t MD5_SIZE = 32; +static const uint32_t WDT_TIMEOUT_S = 20; struct OtaHttpGlobalPrefType { OtaHttpState ota_http_state; - char md5_url[256]; - char url[256]; + char md5_url[512]; + char url[512]; } PACKED; class OtaHttpComponent : public Component { diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 6360d0805b..fa8fb4bedf 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -7,6 +7,10 @@ #include "esphome/core/application.h" #include "esphome/components/network/util.h" #include "esphome/components/md5/md5.h" +#ifdef USE_ESP32 +#include "esp_task_wdt.h" +#include "esp_idf_version.h" +#endif namespace esphome { namespace ota_http { @@ -25,17 +29,35 @@ int OtaHttpArduino::http_init(char *url) { const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); #ifdef USE_ESP8266 + ESP.wdtEnable(WDT_TIMEOUT_S * 1000); if (this->stream_ptr_ == nullptr && this->set_stream_ptr_()) { ESP_LOGE(TAG, "Unable to set client"); } #endif // USE_ESP8266 +#ifdef USE_ESP32 +#if ESP_IDF_VERSION_MAJOR >= 5 + esp_task_wdt_config_t wdt_config = { + .timeout_ms = WDT_TIMEOUT_S * 1000, + .idle_core_mask = 0x03, + .trigger_panic = true, + }; + esp_task_wdt_reconfigure(&wdt_config); +#else + esp_task_wdt_init(WDT_TIMEOUT_S, true); +#endif // ESP_IDF_VERSION_MAJOR +#endif // USE_ESP32 + ESP_LOGD(TAG, "Connecting to %s", url); bool status = false; #ifdef USE_RP2040 + watchdog_enable(WDT_TIMEOUT_S * 1000, true); this->client_.setInsecure(); #endif + + App.feed_wdt(); + #if defined(USE_ESP32) || defined(USE_RP2040) status = this->client_.begin(url); #endif diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index d3ba87c203..9ff67647bd 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -13,6 +13,7 @@ #include "esp_tls.h" #include "nvs_flash.h" #include "esp_task_wdt.h" +#include "esp_idf_version.h" #include #include #include @@ -32,7 +33,16 @@ namespace esphome { namespace ota_http { int OtaHttpIDF::http_init(char *url) { - esp_task_wdt_init(20, true); +#if ESP_IDF_VERSION_MAJOR >= 5 + esp_task_wdt_config_t wdt_config = { + .timeout_ms = WDT_TIMEOUT_S * 1000, + .idle_core_mask = 0x03, + .trigger_panic = true, + }; + esp_task_wdt_reconfigure(&wdt_config); +#else + esp_task_wdt_init(WDT_TIMEOUT_S, true); +#endif App.feed_wdt(); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" From 8ddd5e393ab1d7bb804eb9c83de2d9cdf81b5601 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 25 Mar 2024 21:43:53 +0000 Subject: [PATCH 63/97] lint --- esphome/components/ota_http/ota_http_arduino.cpp | 4 ++-- esphome/components/ota_http/ota_http_idf.cpp | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index fa8fb4bedf..c0def77617 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -45,8 +45,8 @@ int OtaHttpArduino::http_init(char *url) { esp_task_wdt_reconfigure(&wdt_config); #else esp_task_wdt_init(WDT_TIMEOUT_S, true); -#endif // ESP_IDF_VERSION_MAJOR -#endif // USE_ESP32 +#endif // ESP_IDF_VERSION_MAJOR +#endif // USE_ESP32 ESP_LOGD(TAG, "Connecting to %s", url); diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 9ff67647bd..07e7637ac6 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -34,14 +34,14 @@ namespace ota_http { int OtaHttpIDF::http_init(char *url) { #if ESP_IDF_VERSION_MAJOR >= 5 - esp_task_wdt_config_t wdt_config = { - .timeout_ms = WDT_TIMEOUT_S * 1000, - .idle_core_mask = 0x03, - .trigger_panic = true, - }; - esp_task_wdt_reconfigure(&wdt_config); + esp_task_wdt_config_t wdt_config = { + .timeout_ms = WDT_TIMEOUT_S * 1000, + .idle_core_mask = 0x03, + .trigger_panic = true, + }; + esp_task_wdt_reconfigure(&wdt_config); #else - esp_task_wdt_init(WDT_TIMEOUT_S, true); + esp_task_wdt_init(WDT_TIMEOUT_S, true); #endif App.feed_wdt(); #pragma GCC diagnostic push From d3634041da24b68edcbcfacabdae8a9b1970f7a6 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 25 Mar 2024 22:33:31 +0000 Subject: [PATCH 64/97] lint --- esphome/components/ota_http/ota_http_arduino.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index c0def77617..e50975e458 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -29,7 +29,7 @@ int OtaHttpArduino::http_init(char *url) { const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); #ifdef USE_ESP8266 - ESP.wdtEnable(WDT_TIMEOUT_S * 1000); + EspClass::wdtEnable(WDT_TIMEOUT_S * 1000); if (this->stream_ptr_ == nullptr && this->set_stream_ptr_()) { ESP_LOGE(TAG, "Unable to set client"); } From 2affb6b1bc305282b249c3aff6ec7b19b2e738dc Mon Sep 17 00:00:00 2001 From: oarcher Date: Tue, 26 Mar 2024 03:04:27 +0000 Subject: [PATCH 65/97] reduced url size (was too large for esp8266) --- esphome/components/ota_http/ota_http.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 977b0bcd84..ad56753285 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -27,8 +27,8 @@ static const uint32_t WDT_TIMEOUT_S = 20; struct OtaHttpGlobalPrefType { OtaHttpState ota_http_state; - char md5_url[512]; - char url[512]; + char md5_url[250]; + char url[250]; } PACKED; class OtaHttpComponent : public Component { From 57f32d9318480c701ddee7961088fdd36482979b Mon Sep 17 00:00:00 2001 From: oarcher Date: Wed, 27 Mar 2024 19:09:48 +0000 Subject: [PATCH 66/97] feed wdt more often --- esphome/components/ota_http/ota_http.cpp | 7 ++++--- esphome/components/ota_http/ota_http_arduino.cpp | 1 + esphome/components/ota_http/ota_http_idf.cpp | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index f85aece18a..b7c51ba0a3 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -87,6 +87,10 @@ void OtaHttpComponent::flash() { // read a maximum of chunk_size bytes into buf. (real read size returned) int bufsize = this->http_read(buf, this->http_recv_buffer_); + // feed watchdog and give other tasks a chance to run + App.feed_wdt(); + yield(); + if (bufsize < 0) { ESP_LOGE(TAG, "Stream closed"); this->cleanup_(); @@ -112,9 +116,6 @@ void OtaHttpComponent::flash() { if ((now - last_progress > 1000) or (this->bytes_read_ == this->body_length_)) { last_progress = now; ESP_LOGI(TAG, "Progress: %0.1f%%", this->bytes_read_ * 100. / this->body_length_); - // feed watchdog and give other tasks a chance to run - App.feed_wdt(); - yield(); } } // while diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index e50975e458..ccb1a8fbf7 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -115,6 +115,7 @@ int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { while (this->stream_ptr_->available() == 0) { // give other tasks a chance to run while waiting for some data: // ESP_LOGVV(TAG, "not enougth data available: %zu (total read: %zu)", streamPtr->available(), bytes_read); + App.feed_wdt(); yield(); delay(1); } diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 07e7637ac6..ee94f84370 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -80,6 +80,7 @@ int OtaHttpIDF::http_init(char *url) { int OtaHttpIDF::http_read(uint8_t *buf, const size_t max_len) { int bufsize = std::min(max_len, this->body_length_ - this->bytes_read_); + App.feed_wdt(); int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); if (read_len > 0) { this->bytes_read_ += bufsize; From 2c631d26d7e7e6d5a3f41b39d4794586bca48c75 Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 28 Mar 2024 10:19:13 +0000 Subject: [PATCH 67/97] watchdog improvements --- esphome/components/ota_http/__init__.py | 15 ++++ esphome/components/ota_http/ota_http.cpp | 11 ++- esphome/components/ota_http/ota_http.h | 1 - .../components/ota_http/ota_http_arduino.cpp | 21 +---- esphome/components/ota_http/ota_http_idf.cpp | 15 +--- esphome/components/ota_http/watchdog.cpp | 76 +++++++++++++++++++ esphome/components/ota_http/watchdog.h | 25 ++++++ 7 files changed, 131 insertions(+), 33 deletions(-) create mode 100644 esphome/components/ota_http/watchdog.cpp create mode 100644 esphome/components/ota_http/watchdog.h diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 21b9176d25..7bbff058b9 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -28,6 +28,7 @@ OtaHttpFlashAction = ota_http_ns.class_("OtaHttpFlashAction", automation.Action) CONF_EXCLUDE_CERTIFICATE_BUNDLE = "exclude_certificate_bundle" CONF_MD5_URL = "md5_url" +CONF_WDT = "watchdog_timeout" def validate_certificate_bundle(config): @@ -72,6 +73,12 @@ def validate_safe_mode(config): return config +def validate_wdt(config): + if CORE.is_esp8266: + raise cv.Invalid(f"{CONF_WDT} not available on 'esp8266'") + return config + + def _declare_request_class(value): if CORE.using_esp_idf: return cv.declare_id(OtaHttpIDF)(value) @@ -88,6 +95,9 @@ CONFIG_SCHEMA = cv.All( cv.Optional( CONF_TIMEOUT, default="5min" ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_WDT, default="0s" + ): cv.positive_time_period_milliseconds, cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( cv.only_on_esp8266, cv.boolean ), @@ -104,6 +114,7 @@ CONFIG_SCHEMA = cv.All( rp2040_arduino=cv.Version(0, 0, 0), ), validate_certificate_bundle, + validate_wdt, ) FINAL_VALIDATE_SCHEMA = cv.All(validate_safe_mode) @@ -114,6 +125,10 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_timeout(config[CONF_TIMEOUT])) + + if config[CONF_WDT].total_milliseconds > 0: + cg.add_define("CONFIG_WDT", config[CONF_WDT].total_milliseconds) + if CORE.is_esp8266 and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT]: cg.add_define("USE_HTTP_REQUEST_ESP8266_HTTPS") diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index b7c51ba0a3..519638316f 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -9,6 +9,10 @@ #include "esphome/components/ota/ota_backend.h" #include "ota_http.h" +#ifdef CONFIG_WDT +#include "watchdog.h" +#endif + namespace esphome { namespace ota_http { @@ -58,7 +62,9 @@ void OtaHttpComponent::flash() { App.safe_reboot(); } #endif - +#ifdef CONFIG_WDT + watchdog::Watchdog::set_timeout(CONFIG_WDT); +#endif uint32_t update_start_time = millis(); uint8_t buf[this->http_recv_buffer_ + 1]; int error_code = 0; @@ -166,6 +172,9 @@ void OtaHttpComponent::cleanup_() { this->pref_.ota_http_state = OTA_HTTP_STATE_ABORT; } this->pref_obj_.save(&this->pref_); +#ifdef CONFIG_WDT + watchdog::Watchdog::reset(); +#endif }; void OtaHttpComponent::check_upgrade() { diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index ad56753285..f1014ebff6 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -23,7 +23,6 @@ enum OtaHttpState { static const char *const TAG = "ota_http"; static const uint8_t MD5_SIZE = 32; -static const uint32_t WDT_TIMEOUT_S = 20; struct OtaHttpGlobalPrefType { OtaHttpState ota_http_state; diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index ccb1a8fbf7..50b0feb422 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -7,10 +7,6 @@ #include "esphome/core/application.h" #include "esphome/components/network/util.h" #include "esphome/components/md5/md5.h" -#ifdef USE_ESP32 -#include "esp_task_wdt.h" -#include "esp_idf_version.h" -#endif namespace esphome { namespace ota_http { @@ -29,30 +25,17 @@ int OtaHttpArduino::http_init(char *url) { const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); #ifdef USE_ESP8266 - EspClass::wdtEnable(WDT_TIMEOUT_S * 1000); + // EspClass::wdtEnable(WDT_TIMEOUT_S * 1000); if (this->stream_ptr_ == nullptr && this->set_stream_ptr_()) { ESP_LOGE(TAG, "Unable to set client"); } #endif // USE_ESP8266 -#ifdef USE_ESP32 -#if ESP_IDF_VERSION_MAJOR >= 5 - esp_task_wdt_config_t wdt_config = { - .timeout_ms = WDT_TIMEOUT_S * 1000, - .idle_core_mask = 0x03, - .trigger_panic = true, - }; - esp_task_wdt_reconfigure(&wdt_config); -#else - esp_task_wdt_init(WDT_TIMEOUT_S, true); -#endif // ESP_IDF_VERSION_MAJOR -#endif // USE_ESP32 - ESP_LOGD(TAG, "Connecting to %s", url); bool status = false; #ifdef USE_RP2040 - watchdog_enable(WDT_TIMEOUT_S * 1000, true); + // watchdog_enable(WDT_TIMEOUT_S * 1000, true); this->client_.setInsecure(); #endif diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index ee94f84370..1b2c96c55e 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -33,16 +33,6 @@ namespace esphome { namespace ota_http { int OtaHttpIDF::http_init(char *url) { -#if ESP_IDF_VERSION_MAJOR >= 5 - esp_task_wdt_config_t wdt_config = { - .timeout_ms = WDT_TIMEOUT_S * 1000, - .idle_core_mask = 0x03, - .trigger_panic = true, - }; - esp_task_wdt_reconfigure(&wdt_config); -#else - esp_task_wdt_init(WDT_TIMEOUT_S, true); -#endif App.feed_wdt(); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" @@ -60,6 +50,8 @@ int OtaHttpIDF::http_init(char *url) { #endif #pragma GCC diagnostic pop + ESP_LOGI(TAG, "Trying to connect to url: %s", url); + this->client_ = esp_http_client_init(&config); esp_err_t err; if ((err = esp_http_client_open(this->client_, 0)) != ESP_OK) { @@ -68,8 +60,7 @@ int OtaHttpIDF::http_init(char *url) { } this->body_length_ = esp_http_client_fetch_headers(this->client_); - ESP_LOGV(TAG, "body_length: %d , esp_http_client_get_content_length: %" PRId64, this->body_length_, - (int64_t) esp_http_client_get_content_length(this->client_)); + ESP_LOGV(TAG, "body_length: %d", this->body_length_); if (this->body_length_ <= 0) { ESP_LOGE(TAG, "Incorrect file size (%d) reported by HTTP server (status: %d). Aborting", this->body_length_, err); diff --git a/esphome/components/ota_http/watchdog.cpp b/esphome/components/ota_http/watchdog.cpp new file mode 100644 index 0000000000..6323b6355e --- /dev/null +++ b/esphome/components/ota_http/watchdog.cpp @@ -0,0 +1,76 @@ +#include "watchdog.h" + +#include "esphome/core/defines.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" + +#include +#include +#ifdef USE_ESP32 +#include "esp_task_wdt.h" +#include "esp_idf_version.h" +#endif +#ifdef USE_RP2040 +#include "pico/stdlib.h" +#include "hardware/watchdog.h" +#endif + +namespace esphome { +namespace ota_http { +namespace watchdog { + +uint32_t Watchdog::timeout_ms_ = 0; +uint32_t Watchdog::init_timeout_ms_ = Watchdog::get_timeout(); + +void Watchdog::set_timeout(uint32_t timeout_ms){ + ESP_LOGV(TAG, "set_timeout: %" PRId32 "ms", timeout_ms); +#ifdef USE_ESP8266 + EspClass::wdtEnable(timeout_ms); +#endif // USE_ESP8266 + +#ifdef USE_ESP32 +#if ESP_IDF_VERSION_MAJOR >= 5 + esp_task_wdt_config_t wdt_config = { + .timeout_ms = timeout_ms, + .idle_core_mask = 0x03, + .trigger_panic = true, + }; + esp_task_wdt_reconfigure(&wdt_config); +#else + esp_task_wdt_init(timeout_ms, true); +#endif // ESP_IDF_VERSION_MAJOR +#endif // USE_ESP32 + +#ifdef USE_RP2040 + watchdog_enable(timeout_ms, true); +#endif + Watchdog::timeout_ms_ = timeout_ms; +} + +uint32_t Watchdog::get_timeout() { + + uint32_t timeout_ms = 0; + +#ifdef USE_ESP32 + timeout_ms = std::max((uint32_t)CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000, Watchdog::timeout_ms_); +#endif // USE_ESP32 + +#ifdef USE_RP2040 + timeout_ms = watchdog_get_count() / 1000; +#endif + + if (timeout_ms == 0) { + // fallback to stored timeout + timeout_ms = Watchdog::timeout_ms_; + } + ESP_LOGVV(TAG, "get_timeout: %" PRId32 "ms", timeout_ms); + + return timeout_ms; +} + +void Watchdog::reset() { Watchdog::set_timeout(Watchdog::init_timeout_ms_); } + +} // namespace watchdog +} // namespace ota_http +} // namespace esphome + diff --git a/esphome/components/ota_http/watchdog.h b/esphome/components/ota_http/watchdog.h new file mode 100644 index 0000000000..8337491489 --- /dev/null +++ b/esphome/components/ota_http/watchdog.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace esphome { +namespace ota_http { +namespace watchdog { + +static const char *const TAG = "ota_http.watchdog"; + +class Watchdog { + public: + static uint32_t get_timeout(); + static void set_timeout(uint32_t timeout_ms); + static void reset(); + + private: + static uint32_t timeout_ms_; + static uint32_t init_timeout_ms_; + Watchdog() {} +}; + +} // namespace watchdog +} // namespace ota_http +} // namespace esphome From 74afb07ad2255a00ab6f4ab13fde46721bbd4c87 Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 28 Mar 2024 11:20:18 +0000 Subject: [PATCH 68/97] lint + validation fixes --- esphome/components/ota_http/__init__.py | 21 +++++++-------------- esphome/components/ota_http/ota_http.cpp | 12 ++++++------ esphome/components/ota_http/watchdog.cpp | 6 ++---- esphome/components/ota_http/watchdog.h | 16 ++++++++-------- 4 files changed, 23 insertions(+), 32 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 7bbff058b9..dc8f56bab6 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -28,7 +28,7 @@ OtaHttpFlashAction = ota_http_ns.class_("OtaHttpFlashAction", automation.Action) CONF_EXCLUDE_CERTIFICATE_BUNDLE = "exclude_certificate_bundle" CONF_MD5_URL = "md5_url" -CONF_WDT = "watchdog_timeout" +CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" def validate_certificate_bundle(config): @@ -73,12 +73,6 @@ def validate_safe_mode(config): return config -def validate_wdt(config): - if CORE.is_esp8266: - raise cv.Invalid(f"{CONF_WDT} not available on 'esp8266'") - return config - - def _declare_request_class(value): if CORE.using_esp_idf: return cv.declare_id(OtaHttpIDF)(value) @@ -95,9 +89,10 @@ CONFIG_SCHEMA = cv.All( cv.Optional( CONF_TIMEOUT, default="5min" ): cv.positive_time_period_milliseconds, - cv.Optional( - CONF_WDT, default="0s" - ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_WATCHDOG_TIMEOUT): cv.All( + cv.Any(cv.only_on_esp32, cv.only_on_rp2040), + cv.positive_time_period_milliseconds + ), cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( cv.only_on_esp8266, cv.boolean ), @@ -114,7 +109,6 @@ CONFIG_SCHEMA = cv.All( rp2040_arduino=cv.Version(0, 0, 0), ), validate_certificate_bundle, - validate_wdt, ) FINAL_VALIDATE_SCHEMA = cv.All(validate_safe_mode) @@ -125,9 +119,8 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_timeout(config[CONF_TIMEOUT])) - - if config[CONF_WDT].total_milliseconds > 0: - cg.add_define("CONFIG_WDT", config[CONF_WDT].total_milliseconds) + if config.get(CONF_WATCHDOG_TIMEOUT, None) and config[CONF_WATCHDOG_TIMEOUT].total_milliseconds > 0: + cg.add_define("CONFIG_WATCHDOG_TIMEOUT", config[CONF_WATCHDOG_TIMEOUT].total_milliseconds) if CORE.is_esp8266 and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT]: cg.add_define("USE_HTTP_REQUEST_ESP8266_HTTPS") diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 519638316f..6271ca3cf0 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -9,7 +9,7 @@ #include "esphome/components/ota/ota_backend.h" #include "ota_http.h" -#ifdef CONFIG_WDT +#ifdef CONFIG_WATCHDOG_TIMEOUT #include "watchdog.h" #endif @@ -62,8 +62,8 @@ void OtaHttpComponent::flash() { App.safe_reboot(); } #endif -#ifdef CONFIG_WDT - watchdog::Watchdog::set_timeout(CONFIG_WDT); +#ifdef CONFIG_WATCHDOG_TIMEOUT + watchdog::Watchdog::set_timeout(CONFIG_WATCHDOG_TIMEOUT); #endif uint32_t update_start_time = millis(); uint8_t buf[this->http_recv_buffer_ + 1]; @@ -94,8 +94,8 @@ void OtaHttpComponent::flash() { int bufsize = this->http_read(buf, this->http_recv_buffer_); // feed watchdog and give other tasks a chance to run - App.feed_wdt(); - yield(); + App.feed_wdt(); + yield(); if (bufsize < 0) { ESP_LOGE(TAG, "Stream closed"); @@ -172,7 +172,7 @@ void OtaHttpComponent::cleanup_() { this->pref_.ota_http_state = OTA_HTTP_STATE_ABORT; } this->pref_obj_.save(&this->pref_); -#ifdef CONFIG_WDT +#ifdef CONFIG_WATCHDOG_TIMEOUT watchdog::Watchdog::reset(); #endif }; diff --git a/esphome/components/ota_http/watchdog.cpp b/esphome/components/ota_http/watchdog.cpp index 6323b6355e..1686041838 100644 --- a/esphome/components/ota_http/watchdog.cpp +++ b/esphome/components/ota_http/watchdog.cpp @@ -22,7 +22,7 @@ namespace watchdog { uint32_t Watchdog::timeout_ms_ = 0; uint32_t Watchdog::init_timeout_ms_ = Watchdog::get_timeout(); -void Watchdog::set_timeout(uint32_t timeout_ms){ +void Watchdog::set_timeout(uint32_t timeout_ms) { ESP_LOGV(TAG, "set_timeout: %" PRId32 "ms", timeout_ms); #ifdef USE_ESP8266 EspClass::wdtEnable(timeout_ms); @@ -48,11 +48,10 @@ void Watchdog::set_timeout(uint32_t timeout_ms){ } uint32_t Watchdog::get_timeout() { - uint32_t timeout_ms = 0; #ifdef USE_ESP32 - timeout_ms = std::max((uint32_t)CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000, Watchdog::timeout_ms_); + timeout_ms = std::max((uint32_t) CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000, Watchdog::timeout_ms_); #endif // USE_ESP32 #ifdef USE_RP2040 @@ -73,4 +72,3 @@ void Watchdog::reset() { Watchdog::set_timeout(Watchdog::init_timeout_ms_); } } // namespace watchdog } // namespace ota_http } // namespace esphome - diff --git a/esphome/components/ota_http/watchdog.h b/esphome/components/ota_http/watchdog.h index 8337491489..0046ec6810 100644 --- a/esphome/components/ota_http/watchdog.h +++ b/esphome/components/ota_http/watchdog.h @@ -9,15 +9,15 @@ namespace watchdog { static const char *const TAG = "ota_http.watchdog"; class Watchdog { - public: - static uint32_t get_timeout(); - static void set_timeout(uint32_t timeout_ms); - static void reset(); + public: + static uint32_t get_timeout(); + static void set_timeout(uint32_t timeout_ms); + static void reset(); - private: - static uint32_t timeout_ms_; - static uint32_t init_timeout_ms_; - Watchdog() {} + private: + static uint32_t timeout_ms_; + static uint32_t init_timeout_ms_; + Watchdog() {} }; } // namespace watchdog From 88c234c581340cd62b8f3e0ad6d5fde8d310c46d Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 28 Mar 2024 11:36:03 +0000 Subject: [PATCH 69/97] lint + 8266 tests --- esphome/components/ota_http/__init__.py | 11 ++++++++--- esphome/components/ota_http/watchdog.cpp | 3 +++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index dc8f56bab6..431af09975 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -91,7 +91,7 @@ CONFIG_SCHEMA = cv.All( ): cv.positive_time_period_milliseconds, cv.Optional(CONF_WATCHDOG_TIMEOUT): cv.All( cv.Any(cv.only_on_esp32, cv.only_on_rp2040), - cv.positive_time_period_milliseconds + cv.positive_time_period_milliseconds, ), cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( cv.only_on_esp8266, cv.boolean @@ -119,8 +119,13 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_timeout(config[CONF_TIMEOUT])) - if config.get(CONF_WATCHDOG_TIMEOUT, None) and config[CONF_WATCHDOG_TIMEOUT].total_milliseconds > 0: - cg.add_define("CONFIG_WATCHDOG_TIMEOUT", config[CONF_WATCHDOG_TIMEOUT].total_milliseconds) + if ( + config.get(CONF_WATCHDOG_TIMEOUT, None) + and config[CONF_WATCHDOG_TIMEOUT].total_milliseconds > 0 + ): + cg.add_define( + "CONFIG_WATCHDOG_TIMEOUT", config[CONF_WATCHDOG_TIMEOUT].total_milliseconds + ) if CORE.is_esp8266 and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT]: cg.add_define("USE_HTTP_REQUEST_ESP8266_HTTPS") diff --git a/esphome/components/ota_http/watchdog.cpp b/esphome/components/ota_http/watchdog.cpp index 1686041838..2ad36972e2 100644 --- a/esphome/components/ota_http/watchdog.cpp +++ b/esphome/components/ota_http/watchdog.cpp @@ -14,6 +14,9 @@ #include "pico/stdlib.h" #include "hardware/watchdog.h" #endif +#ifdef USE_ESP8266 +#include "Esp.h" +#endif namespace esphome { namespace ota_http { From 0e211a64104370c8fd520eaf59c43c4e302eae98 Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 28 Mar 2024 11:53:39 +0000 Subject: [PATCH 70/97] lint --- esphome/components/ota_http/watchdog.cpp | 16 ++++++++-------- esphome/components/ota_http/watchdog.h | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/esphome/components/ota_http/watchdog.cpp b/esphome/components/ota_http/watchdog.cpp index 2ad36972e2..f7cfc6f6c6 100644 --- a/esphome/components/ota_http/watchdog.cpp +++ b/esphome/components/ota_http/watchdog.cpp @@ -4,8 +4,8 @@ #include "esphome/core/log.h" #include "esphome/core/application.h" -#include -#include +#include +#include #ifdef USE_ESP32 #include "esp_task_wdt.h" #include "esp_idf_version.h" @@ -22,8 +22,8 @@ namespace esphome { namespace ota_http { namespace watchdog { -uint32_t Watchdog::timeout_ms_ = 0; -uint32_t Watchdog::init_timeout_ms_ = Watchdog::get_timeout(); +uint32_t Watchdog::timeout_ms = 0; +uint32_t Watchdog::init_timeout_ms = Watchdog::get_timeout(); void Watchdog::set_timeout(uint32_t timeout_ms) { ESP_LOGV(TAG, "set_timeout: %" PRId32 "ms", timeout_ms); @@ -47,14 +47,14 @@ void Watchdog::set_timeout(uint32_t timeout_ms) { #ifdef USE_RP2040 watchdog_enable(timeout_ms, true); #endif - Watchdog::timeout_ms_ = timeout_ms; + Watchdog::timeout_ms = timeout_ms; } uint32_t Watchdog::get_timeout() { uint32_t timeout_ms = 0; #ifdef USE_ESP32 - timeout_ms = std::max((uint32_t) CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000, Watchdog::timeout_ms_); + timeout_ms = std::max((uint32_t) CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000, Watchdog::timeout_ms); #endif // USE_ESP32 #ifdef USE_RP2040 @@ -63,14 +63,14 @@ uint32_t Watchdog::get_timeout() { if (timeout_ms == 0) { // fallback to stored timeout - timeout_ms = Watchdog::timeout_ms_; + timeout_ms = Watchdog::timeout_ms; } ESP_LOGVV(TAG, "get_timeout: %" PRId32 "ms", timeout_ms); return timeout_ms; } -void Watchdog::reset() { Watchdog::set_timeout(Watchdog::init_timeout_ms_); } +void Watchdog::reset() { Watchdog::set_timeout(Watchdog::init_timeout_ms); } } // namespace watchdog } // namespace ota_http diff --git a/esphome/components/ota_http/watchdog.h b/esphome/components/ota_http/watchdog.h index 0046ec6810..30200da5d5 100644 --- a/esphome/components/ota_http/watchdog.h +++ b/esphome/components/ota_http/watchdog.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace esphome { namespace ota_http { @@ -15,8 +15,8 @@ class Watchdog { static void reset(); private: - static uint32_t timeout_ms_; - static uint32_t init_timeout_ms_; + static uint32_t timeout_ms; + static uint32_t init_timeout_ms; Watchdog() {} }; From 01672cf74af3f80bdf812ad531173cdeae77ff83 Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 28 Mar 2024 13:03:07 +0000 Subject: [PATCH 71/97] lint --- esphome/components/ota_http/watchdog.cpp | 4 ++-- esphome/components/ota_http/watchdog.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/ota_http/watchdog.cpp b/esphome/components/ota_http/watchdog.cpp index f7cfc6f6c6..1b76e6630d 100644 --- a/esphome/components/ota_http/watchdog.cpp +++ b/esphome/components/ota_http/watchdog.cpp @@ -22,8 +22,8 @@ namespace esphome { namespace ota_http { namespace watchdog { -uint32_t Watchdog::timeout_ms = 0; -uint32_t Watchdog::init_timeout_ms = Watchdog::get_timeout(); +uint32_t Watchdog::timeout_ms = 0; // NOLINT +uint32_t Watchdog::init_timeout_ms = Watchdog::get_timeout(); // NOLINT void Watchdog::set_timeout(uint32_t timeout_ms) { ESP_LOGV(TAG, "set_timeout: %" PRId32 "ms", timeout_ms); diff --git a/esphome/components/ota_http/watchdog.h b/esphome/components/ota_http/watchdog.h index 30200da5d5..e6b0847c49 100644 --- a/esphome/components/ota_http/watchdog.h +++ b/esphome/components/ota_http/watchdog.h @@ -15,8 +15,8 @@ class Watchdog { static void reset(); private: - static uint32_t timeout_ms; - static uint32_t init_timeout_ms; + static uint32_t timeout_ms; // NOLINT + static uint32_t init_timeout_ms; // NOLINT Watchdog() {} }; From 1328f35585a1e632aed28d1a4c86b97f6edbd19f Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 28 Mar 2024 13:07:44 +0000 Subject: [PATCH 72/97] lint --- esphome/components/ota_http/watchdog.cpp | 4 ++-- esphome/components/ota_http/watchdog.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/ota_http/watchdog.cpp b/esphome/components/ota_http/watchdog.cpp index 1b76e6630d..2d7ba0bf35 100644 --- a/esphome/components/ota_http/watchdog.cpp +++ b/esphome/components/ota_http/watchdog.cpp @@ -22,8 +22,8 @@ namespace esphome { namespace ota_http { namespace watchdog { -uint32_t Watchdog::timeout_ms = 0; // NOLINT -uint32_t Watchdog::init_timeout_ms = Watchdog::get_timeout(); // NOLINT +uint32_t Watchdog::timeout_ms = 0; // NOLINT +uint32_t Watchdog::init_timeout_ms = Watchdog::get_timeout(); // NOLINT void Watchdog::set_timeout(uint32_t timeout_ms) { ESP_LOGV(TAG, "set_timeout: %" PRId32 "ms", timeout_ms); diff --git a/esphome/components/ota_http/watchdog.h b/esphome/components/ota_http/watchdog.h index e6b0847c49..3bf89817e2 100644 --- a/esphome/components/ota_http/watchdog.h +++ b/esphome/components/ota_http/watchdog.h @@ -15,8 +15,8 @@ class Watchdog { static void reset(); private: - static uint32_t timeout_ms; // NOLINT - static uint32_t init_timeout_ms; // NOLINT + static uint32_t timeout_ms; // NOLINT + static uint32_t init_timeout_ms; // NOLINT Watchdog() {} }; From f3aaa751ae8183db36c5a67680d4c7b79858bd43 Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 28 Mar 2024 22:40:17 +0000 Subject: [PATCH 73/97] check url lenght --- esphome/components/ota_http/ota_http.h | 44 +++++++++++++++----------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index f1014ebff6..172a3a72c3 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -3,6 +3,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/defines.h" +#include "esphome/core/log.h" #include "esphome/components/ota/ota_backend.h" #include @@ -23,29 +24,20 @@ enum OtaHttpState { static const char *const TAG = "ota_http"; static const uint8_t MD5_SIZE = 32; +static const size_t MAX_URL_LEN = 250; struct OtaHttpGlobalPrefType { OtaHttpState ota_http_state; - char md5_url[250]; - char url[250]; + char md5_url[MAX_URL_LEN]; + char url[MAX_URL_LEN]; } PACKED; class OtaHttpComponent : public Component { public: void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } - void set_md5_url(const std::string &md5_url) { - size_t length = std::min(md5_url.length(), static_cast(sizeof(this->pref_.md5_url) - 1)); - strncpy(this->pref_.md5_url, md5_url.c_str(), length); - this->pref_.md5_url[length] = 0; // null terminator - this->pref_obj_.save(&this->pref_); - } - void set_url(const std::string &url) { - size_t length = std::min(url.length(), static_cast(sizeof(this->pref_.url) - 1)); - strncpy(this->pref_.url, url.c_str(), length); - this->pref_.url[length] = 0; // null terminator - this->pref_obj_.save(&this->pref_); - } + bool set_md5_url(const std::string &md5_url) { return this->set_url_(md5_url, this->pref_.md5_url); } + bool set_url(const std::string &url) { return this->set_url_(url, this->pref_.url); } void set_timeout(uint64_t timeout) { this->timeout_ = timeout; } void flash(); void check_upgrade(); @@ -69,6 +61,18 @@ class OtaHttpComponent : public Component { OtaHttpGlobalPrefType pref_ = {OTA_HTTP_STATE_OK, "", ""}; ESPPreferenceObject pref_obj_ = global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); + + private: + bool set_url_(const std::string &value, char *url) { + if (value.length() > MAX_URL_LEN - 1) { + ESP_LOGE(TAG, "Url max lenght is %d, and attempted to set url with lenght %d: %s", MAX_URL_LEN, value.length(), value.c_str()); + return false; + } + strncpy(url, value.c_str(), value.length()); + url[value.length()] = '\0'; // null terminator + this->pref_obj_.save(&this->pref_); + return true; + } }; template class OtaHttpFlashAction : public Action { @@ -79,12 +83,14 @@ template class OtaHttpFlashAction : public Action { TEMPLATABLE_VALUE(uint64_t, timeout) void play(Ts... x) override { - this->parent_->set_md5_url(this->md5_url_.value(x...)); - this->parent_->set_url(this->url_.value(x...)); - if (this->timeout_.has_value()) { - this->parent_->set_timeout(this->timeout_.value(x...)); + if (this->parent_->set_md5_url(this->md5_url_.value(x...)) && this->parent_->set_url(this->url_.value(x...))) { + if (this->timeout_.has_value()) { + this->parent_->set_timeout(this->timeout_.value(x...)); + } + this->parent_->flash(); + // Normaly never reached (device rebooted) } - this->parent_->flash(); + ESP_LOGE(TAG, "Aborted"); } protected: From ef5510c23a3fe5ce21ea956c0274d863c18bd211 Mon Sep 17 00:00:00 2001 From: oarcher Date: Thu, 28 Mar 2024 23:02:19 +0000 Subject: [PATCH 74/97] move ESP_LOG to cpp --- esphome/components/ota_http/ota_http.cpp | 12 ++++++++++++ esphome/components/ota_http/ota_http.h | 13 +------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 6271ca3cf0..a6072b5dab 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -215,5 +215,17 @@ bool OtaHttpComponent::http_get_md5() { return read_len == MD5_SIZE; } +bool OtaHttpComponent::set_url_(const std::string &value, char *url) { + if (value.length() > MAX_URL_LEN - 1) { + ESP_LOGE(TAG, "Url max lenght is %d, and attempted to set url with lenght %d: %s", MAX_URL_LEN, value.length(), + value.c_str()); + return false; + } + strncpy(url, value.c_str(), value.length()); + url[value.length()] = '\0'; // null terminator + this->pref_obj_.save(&this->pref_); + return true; +} + } // namespace ota_http } // namespace esphome diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 172a3a72c3..3876324caa 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -3,7 +3,6 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/defines.h" -#include "esphome/core/log.h" #include "esphome/components/ota/ota_backend.h" #include @@ -63,16 +62,7 @@ class OtaHttpComponent : public Component { global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); private: - bool set_url_(const std::string &value, char *url) { - if (value.length() > MAX_URL_LEN - 1) { - ESP_LOGE(TAG, "Url max lenght is %d, and attempted to set url with lenght %d: %s", MAX_URL_LEN, value.length(), value.c_str()); - return false; - } - strncpy(url, value.c_str(), value.length()); - url[value.length()] = '\0'; // null terminator - this->pref_obj_.save(&this->pref_); - return true; - } + bool set_url_(const std::string &value, char *url); }; template class OtaHttpFlashAction : public Action { @@ -90,7 +80,6 @@ template class OtaHttpFlashAction : public Action { this->parent_->flash(); // Normaly never reached (device rebooted) } - ESP_LOGE(TAG, "Aborted"); } protected: From b708f50ccc44bf742e766da9158fca0382aa6750 Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 29 Mar 2024 00:20:21 +0000 Subject: [PATCH 75/97] updated dump_config --- esphome/components/ota_http/ota_http.cpp | 26 ++++++++++++++++++++++-- esphome/components/ota_http/ota_http.h | 1 + 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index a6072b5dab..7c45c651ac 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -43,8 +43,29 @@ std::unique_ptr make_ota_backend() { const std::unique_ptr OtaHttpComponent::BACKEND = make_ota_backend(); void OtaHttpComponent::dump_config() { - ESP_LOGCONFIG(TAG, "ota_http:"); - ESP_LOGCONFIG(TAG, " Timeout: %llums", (uint64_t) this->timeout_); + ESP_LOGCONFIG(TAG, "OTA Update over http:"); + ESP_LOGCONFIG(TAG, " Max url lenght: %d", MAX_URL_LEN); + ESP_LOGCONFIG(TAG, " Timeout: %llus", this->timeout_ / 1000); +#ifdef CONFIG_WATCHDOG_TIMEOUT + ESP_LOGCONFIG(TAG, " Watchdog timeout: %ds", CONFIG_WATCHDOG_TIMEOUT / 1000); +#endif +#ifdef OTA_HTTP_ONLY_AT_BOOT + ESP_LOGCONFIG(TAG, " Safe mode: Yes"); +#else + ESP_LOGCONFIG(TAG, " Safe mode: %s", this->safe_mode_ ? "Fallback" : "No"); +#endif +#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + ESP_LOGCONFIG(TAG, " TLS server verification: Yes"); +#else + ESP_LOGCONFIG(TAG, " TLS server verification: No"); +#endif +#ifdef USE_ESP8266 +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS + ESP_LOGCONFIG(TAG, " ESP8266 SSL support: No"); +#else + ESP_LOGCONFIG(TAG, " ESP8266 SSL support: Yes"); +#endif +#endif }; void OtaHttpComponent::flash() { @@ -179,6 +200,7 @@ void OtaHttpComponent::cleanup_() { void OtaHttpComponent::check_upgrade() { // function called at boot time if CONF_SAFE_MODE is True or "fallback" + this->safe_mode_ = true; if (this->pref_obj_.load(&this->pref_)) { if (this->pref_.ota_http_state == OTA_HTTP_STATE_PROGRESS) { // progress at boot time means that there was a problem diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 3876324caa..3ffee3eae2 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -49,6 +49,7 @@ class OtaHttpComponent : public Component { bool secure_() { return strncmp(this->pref_.url, "https:", 6) == 0; }; size_t body_length_ = 0; size_t bytes_read_ = 0; + bool safe_mode_ = false; uint64_t timeout_; const uint16_t http_recv_buffer_ = 500; // the firmware GET chunk size const uint16_t max_http_recv_buffer_ = 512; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS From 536868be5bbc5f278fcad4a974d5dfc1492694fd Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 29 Mar 2024 00:50:26 +0000 Subject: [PATCH 76/97] add max_url_lenght yaml option --- esphome/components/ota_http/__init__.py | 4 +++- esphome/components/ota_http/ota_http.cpp | 6 +++--- esphome/components/ota_http/ota_http.h | 7 +++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 431af09975..d52cae3221 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -29,6 +29,7 @@ OtaHttpFlashAction = ota_http_ns.class_("OtaHttpFlashAction", automation.Action) CONF_EXCLUDE_CERTIFICATE_BUNDLE = "exclude_certificate_bundle" CONF_MD5_URL = "md5_url" CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" +CONF_MAX_URL_LENGHT = "max_url_lenght" def validate_certificate_bundle(config): @@ -100,6 +101,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_SAFE_MODE, default="fallback"): cv.Any( cv.boolean, "fallback" ), + cv.Optional(CONF_MAX_URL_LENGHT, default=240): cv.uint16_t, } ).extend(cv.COMPONENT_SCHEMA), cv.require_framework_version( @@ -118,7 +120,7 @@ FINAL_VALIDATE_SCHEMA = cv.All(validate_safe_mode) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_timeout(config[CONF_TIMEOUT])) - + cg.add_define("CONFIG_MAX_URL_LENGHT", config[CONF_MAX_URL_LENGHT]) if ( config.get(CONF_WATCHDOG_TIMEOUT, None) and config[CONF_WATCHDOG_TIMEOUT].total_milliseconds > 0 diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 7c45c651ac..250fc2a0ee 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -44,7 +44,7 @@ const std::unique_ptr OtaHttpComponent::BACKEND = make_ota_back void OtaHttpComponent::dump_config() { ESP_LOGCONFIG(TAG, "OTA Update over http:"); - ESP_LOGCONFIG(TAG, " Max url lenght: %d", MAX_URL_LEN); + ESP_LOGCONFIG(TAG, " Max url lenght: %d", CONFIG_MAX_URL_LENGHT); ESP_LOGCONFIG(TAG, " Timeout: %llus", this->timeout_ / 1000); #ifdef CONFIG_WATCHDOG_TIMEOUT ESP_LOGCONFIG(TAG, " Watchdog timeout: %ds", CONFIG_WATCHDOG_TIMEOUT / 1000); @@ -238,8 +238,8 @@ bool OtaHttpComponent::http_get_md5() { } bool OtaHttpComponent::set_url_(const std::string &value, char *url) { - if (value.length() > MAX_URL_LEN - 1) { - ESP_LOGE(TAG, "Url max lenght is %d, and attempted to set url with lenght %d: %s", MAX_URL_LEN, value.length(), + if (value.length() > CONFIG_MAX_URL_LENGHT - 1) { + ESP_LOGE(TAG, "Url max lenght is %d, and attempted to set url with lenght %d: %s", CONFIG_MAX_URL_LENGHT, value.length(), value.c_str()); return false; } diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 3ffee3eae2..a3dbe7d659 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -20,6 +20,9 @@ enum OtaHttpState { }; #define OTA_HTTP_PREF_SAFE_MODE_HASH 99380598UL +#ifndef CONFIG_MAX_URL_LENGHT +#define CONFIG_MAX_URL_LENGHT 128 +#endif static const char *const TAG = "ota_http"; static const uint8_t MD5_SIZE = 32; @@ -27,8 +30,8 @@ static const size_t MAX_URL_LEN = 250; struct OtaHttpGlobalPrefType { OtaHttpState ota_http_state; - char md5_url[MAX_URL_LEN]; - char url[MAX_URL_LEN]; + char md5_url[CONFIG_MAX_URL_LENGHT]; + char url[CONFIG_MAX_URL_LENGHT]; } PACKED; class OtaHttpComponent : public Component { From 30e1791a913f8870a5dde8f4e967fe2d903b1928 Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 29 Mar 2024 00:55:49 +0000 Subject: [PATCH 77/97] lint --- esphome/components/ota_http/ota_http.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index a3dbe7d659..95b57d0234 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -21,12 +21,11 @@ enum OtaHttpState { #define OTA_HTTP_PREF_SAFE_MODE_HASH 99380598UL #ifndef CONFIG_MAX_URL_LENGHT -#define CONFIG_MAX_URL_LENGHT 128 +static const uint16_t CONFIG_MAX_URL_LENGHT = 128; #endif static const char *const TAG = "ota_http"; static const uint8_t MD5_SIZE = 32; -static const size_t MAX_URL_LEN = 250; struct OtaHttpGlobalPrefType { OtaHttpState ota_http_state; From 029cc618c3d728f08da023c41575cf3a51a80454 Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 29 Mar 2024 00:57:13 +0000 Subject: [PATCH 78/97] lint --- esphome/components/ota_http/ota_http.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 250fc2a0ee..97001df9a8 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -239,8 +239,8 @@ bool OtaHttpComponent::http_get_md5() { bool OtaHttpComponent::set_url_(const std::string &value, char *url) { if (value.length() > CONFIG_MAX_URL_LENGHT - 1) { - ESP_LOGE(TAG, "Url max lenght is %d, and attempted to set url with lenght %d: %s", CONFIG_MAX_URL_LENGHT, value.length(), - value.c_str()); + ESP_LOGE(TAG, "Url max lenght is %d, and attempted to set url with lenght %d: %s", CONFIG_MAX_URL_LENGHT, + value.length(), value.c_str()); return false; } strncpy(url, value.c_str(), value.length()); From 30ec824f056a0205f1df746f07707c416870c988 Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 29 Mar 2024 09:49:32 +0000 Subject: [PATCH 79/97] spell --- esphome/components/ota_http/__init__.py | 6 +++--- esphome/components/ota_http/ota_http.cpp | 6 +++--- esphome/components/ota_http/ota_http.h | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index d52cae3221..96004c5697 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -29,7 +29,7 @@ OtaHttpFlashAction = ota_http_ns.class_("OtaHttpFlashAction", automation.Action) CONF_EXCLUDE_CERTIFICATE_BUNDLE = "exclude_certificate_bundle" CONF_MD5_URL = "md5_url" CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" -CONF_MAX_URL_LENGHT = "max_url_lenght" +CONF_MAX_URL_LENGTH = "max_url_length" def validate_certificate_bundle(config): @@ -101,7 +101,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_SAFE_MODE, default="fallback"): cv.Any( cv.boolean, "fallback" ), - cv.Optional(CONF_MAX_URL_LENGHT, default=240): cv.uint16_t, + cv.Optional(CONF_MAX_URL_LENGTH, default=240): cv.uint16_t, } ).extend(cv.COMPONENT_SCHEMA), cv.require_framework_version( @@ -120,7 +120,7 @@ FINAL_VALIDATE_SCHEMA = cv.All(validate_safe_mode) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_timeout(config[CONF_TIMEOUT])) - cg.add_define("CONFIG_MAX_URL_LENGHT", config[CONF_MAX_URL_LENGHT]) + cg.add_define("CONFIG_MAX_URL_LENGTH", config[CONF_MAX_URL_LENGTH]) if ( config.get(CONF_WATCHDOG_TIMEOUT, None) and config[CONF_WATCHDOG_TIMEOUT].total_milliseconds > 0 diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 97001df9a8..ae603f66e3 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -44,7 +44,7 @@ const std::unique_ptr OtaHttpComponent::BACKEND = make_ota_back void OtaHttpComponent::dump_config() { ESP_LOGCONFIG(TAG, "OTA Update over http:"); - ESP_LOGCONFIG(TAG, " Max url lenght: %d", CONFIG_MAX_URL_LENGHT); + ESP_LOGCONFIG(TAG, " Max url length: %d", CONFIG_MAX_URL_LENGTH); ESP_LOGCONFIG(TAG, " Timeout: %llus", this->timeout_ / 1000); #ifdef CONFIG_WATCHDOG_TIMEOUT ESP_LOGCONFIG(TAG, " Watchdog timeout: %ds", CONFIG_WATCHDOG_TIMEOUT / 1000); @@ -238,8 +238,8 @@ bool OtaHttpComponent::http_get_md5() { } bool OtaHttpComponent::set_url_(const std::string &value, char *url) { - if (value.length() > CONFIG_MAX_URL_LENGHT - 1) { - ESP_LOGE(TAG, "Url max lenght is %d, and attempted to set url with lenght %d: %s", CONFIG_MAX_URL_LENGHT, + if (value.length() > CONFIG_MAX_URL_LENGTH - 1) { + ESP_LOGE(TAG, "Url max length is %d, and attempted to set url with length %d: %s", CONFIG_MAX_URL_LENGTH, value.length(), value.c_str()); return false; } diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 95b57d0234..1aee61f9a0 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -20,8 +20,8 @@ enum OtaHttpState { }; #define OTA_HTTP_PREF_SAFE_MODE_HASH 99380598UL -#ifndef CONFIG_MAX_URL_LENGHT -static const uint16_t CONFIG_MAX_URL_LENGHT = 128; +#ifndef CONFIG_MAX_URL_LENGTH +static const uint16_t CONFIG_MAX_URL_LENGTH = 128; #endif static const char *const TAG = "ota_http"; @@ -29,8 +29,8 @@ static const uint8_t MD5_SIZE = 32; struct OtaHttpGlobalPrefType { OtaHttpState ota_http_state; - char md5_url[CONFIG_MAX_URL_LENGHT]; - char url[CONFIG_MAX_URL_LENGHT]; + char md5_url[CONFIG_MAX_URL_LENGTH]; + char url[CONFIG_MAX_URL_LENGTH]; } PACKED; class OtaHttpComponent : public Component { From efaefa92a9b29353714fc666e5951716b56e6862 Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 29 Mar 2024 21:29:36 +0000 Subject: [PATCH 80/97] fix http status for idf --- esphome/components/ota_http/ota_http_idf.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 1b2c96c55e..ee8af754b4 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -60,6 +60,12 @@ int OtaHttpIDF::http_init(char *url) { } this->body_length_ = esp_http_client_fetch_headers(this->client_); + int http_code = esp_http_client_get_status_code(this->client_); + if (http_code >= 310) { + ESP_LOGE(TAG, "HTTP error %d; URL: %s", http_code, url); + return -1; + } + ESP_LOGV(TAG, "body_length: %d", this->body_length_); if (this->body_length_ <= 0) { From 2f2dd6839fb373d0e5c9d01e8859de676391a92e Mon Sep 17 00:00:00 2001 From: oarcher Date: Fri, 29 Mar 2024 23:59:08 +0000 Subject: [PATCH 81/97] force_update option --- esphome/components/ota_http/__init__.py | 3 ++ esphome/components/ota_http/ota_http.cpp | 38 ++++++++++++++++++++++-- esphome/components/ota_http/ota_http.h | 7 ++++- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 96004c5697..82f8d66b98 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -30,6 +30,7 @@ CONF_EXCLUDE_CERTIFICATE_BUNDLE = "exclude_certificate_bundle" CONF_MD5_URL = "md5_url" CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" CONF_MAX_URL_LENGTH = "max_url_length" +CONF_FORCE_UPDATE = "force_update" def validate_certificate_bundle(config): @@ -102,6 +103,7 @@ CONFIG_SCHEMA = cv.All( cv.boolean, "fallback" ), cv.Optional(CONF_MAX_URL_LENGTH, default=240): cv.uint16_t, + cv.Optional(CONF_FORCE_UPDATE, default=False): cv.boolean, } ).extend(cv.COMPONENT_SCHEMA), cv.require_framework_version( @@ -121,6 +123,7 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_timeout(config[CONF_TIMEOUT])) cg.add_define("CONFIG_MAX_URL_LENGTH", config[CONF_MAX_URL_LENGTH]) + cg.add_define("CONFIG_FORCE_UPDATE", config[CONF_FORCE_UPDATE]); if ( config.get(CONF_WATCHDOG_TIMEOUT, None) and config[CONF_WATCHDOG_TIMEOUT].total_milliseconds > 0 diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index ae603f66e3..82d50d3f9e 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -42,8 +42,18 @@ std::unique_ptr make_ota_backend() { const std::unique_ptr OtaHttpComponent::BACKEND = make_ota_backend(); +OtaHttpComponent::OtaHttpComponent() { + this->pref_obj_.load(&this->pref_); + if (!this->pref_obj_.save(&this->pref_)) { + // error at 'load' might be caused by 1st usage, but error at 'save' is a real error. + ESP_LOGE(TAG, "Unable to use flash memory. Safe mode might be not available"); + } +} + void OtaHttpComponent::dump_config() { ESP_LOGCONFIG(TAG, "OTA Update over http:"); + pref_.last_md5[MD5_SIZE] = '\0'; + ESP_LOGCONFIG(TAG, " Last flashed md5: %s", pref_.last_md5); ESP_LOGCONFIG(TAG, " Max url length: %d", CONFIG_MAX_URL_LENGTH); ESP_LOGCONFIG(TAG, " Timeout: %llus", this->timeout_ / 1000); #ifdef CONFIG_WATCHDOG_TIMEOUT @@ -92,11 +102,27 @@ void OtaHttpComponent::flash() { uint32_t last_progress = 0; md5::MD5Digest md5_receive; std::unique_ptr md5_receive_str(new char[33]); - if (!this->http_get_md5() || !this->http_init(this->pref_.url)) { + if (!this->http_get_md5()) { return; } ESP_LOGD(TAG, "MD5 expected: %s", this->md5_expected_); + + if(!CONFIG_FORCE_UPDATE) { + if (strncmp(this->pref_.last_md5, this->md5_expected_, MD5_SIZE) == 0) { + this->http_end(); + ESP_LOGW(TAG, "OTA Update skipped: retrieved md5 %s match the last installed firmware", this->pref_.last_md5); +#ifdef CONFIG_WATCHDOG_TIMEOUT + watchdog::Watchdog::reset(); +#endif + return; + } + } + + if(!this->http_init(this->pref_.url)) { + return; + } + // we will compute MD5 on the fly for verification -- Arduino OTA seems to ignore it md5_receive.init(); ESP_LOGV(TAG, "MD5Digest initialized"); @@ -174,7 +200,9 @@ void OtaHttpComponent::flash() { } this->pref_.ota_http_state = OTA_HTTP_STATE_OK; + strncpy(this->pref_.last_md5, this->md5_expected_, MD5_SIZE); this->pref_obj_.save(&this->pref_); + global_preferences->sync(); delay(10); ESP_LOGI(TAG, "OTA update completed"); delay(10); @@ -225,9 +253,15 @@ void OtaHttpComponent::check_upgrade() { } bool OtaHttpComponent::http_get_md5() { - if (this->http_init(this->pref_.md5_url) < MD5_SIZE) { + int length = this->http_init(this->pref_.md5_url); + if (length < 0) { + this->http_end(); + return false; + } + if (length < MD5_SIZE) { ESP_LOGE(TAG, "MD5 file must be %u bytes; %u bytes reported by HTTP server. Aborting", MD5_SIZE, this->body_length_); + this->http_end(); return false; } diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 1aee61f9a0..b8572beb3b 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -23,18 +23,23 @@ enum OtaHttpState { #ifndef CONFIG_MAX_URL_LENGTH static const uint16_t CONFIG_MAX_URL_LENGTH = 128; #endif +#ifndef CONFIG_FORCE_UPDATE +static const bool CONFIG_FORCE_UPDATE = true; +#endif static const char *const TAG = "ota_http"; static const uint8_t MD5_SIZE = 32; struct OtaHttpGlobalPrefType { OtaHttpState ota_http_state; + char last_md5[MD5_SIZE + 1]; char md5_url[CONFIG_MAX_URL_LENGTH]; char url[CONFIG_MAX_URL_LENGTH]; } PACKED; class OtaHttpComponent : public Component { public: + OtaHttpComponent(); void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } bool set_md5_url(const std::string &md5_url) { return this->set_url_(md5_url, this->pref_.md5_url); } @@ -60,7 +65,7 @@ class OtaHttpComponent : public Component { static const std::unique_ptr BACKEND; void cleanup_(); char md5_expected_[MD5_SIZE]; - OtaHttpGlobalPrefType pref_ = {OTA_HTTP_STATE_OK, "", ""}; + OtaHttpGlobalPrefType pref_ = {OTA_HTTP_STATE_OK, "None", "", ""}; ESPPreferenceObject pref_obj_ = global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); From 1d5f39d8b18ac2e702da38ccf83d4bde41c460d3 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sat, 30 Mar 2024 00:04:10 +0000 Subject: [PATCH 82/97] lint --- esphome/components/ota_http/__init__.py | 4 ++-- esphome/components/ota_http/ota_http.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/ota_http/__init__.py b/esphome/components/ota_http/__init__.py index 82f8d66b98..dd05b8aa9c 100644 --- a/esphome/components/ota_http/__init__.py +++ b/esphome/components/ota_http/__init__.py @@ -10,6 +10,7 @@ from esphome.const import ( CONF_METHOD, CONF_ESP8266_DISABLE_SSL_SUPPORT, CONF_SAFE_MODE, + CONF_FORCE_UPDATE, ) from esphome.components import esp32 from esphome.core import CORE, coroutine_with_priority @@ -30,7 +31,6 @@ CONF_EXCLUDE_CERTIFICATE_BUNDLE = "exclude_certificate_bundle" CONF_MD5_URL = "md5_url" CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" CONF_MAX_URL_LENGTH = "max_url_length" -CONF_FORCE_UPDATE = "force_update" def validate_certificate_bundle(config): @@ -123,7 +123,7 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_timeout(config[CONF_TIMEOUT])) cg.add_define("CONFIG_MAX_URL_LENGTH", config[CONF_MAX_URL_LENGTH]) - cg.add_define("CONFIG_FORCE_UPDATE", config[CONF_FORCE_UPDATE]); + cg.add_define("CONFIG_FORCE_UPDATE", config[CONF_FORCE_UPDATE]) if ( config.get(CONF_WATCHDOG_TIMEOUT, None) and config[CONF_WATCHDOG_TIMEOUT].total_milliseconds > 0 diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 82d50d3f9e..770c64d20b 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -108,7 +108,7 @@ void OtaHttpComponent::flash() { ESP_LOGD(TAG, "MD5 expected: %s", this->md5_expected_); - if(!CONFIG_FORCE_UPDATE) { + if (!CONFIG_FORCE_UPDATE) { if (strncmp(this->pref_.last_md5, this->md5_expected_, MD5_SIZE) == 0) { this->http_end(); ESP_LOGW(TAG, "OTA Update skipped: retrieved md5 %s match the last installed firmware", this->pref_.last_md5); @@ -119,7 +119,7 @@ void OtaHttpComponent::flash() { } } - if(!this->http_init(this->pref_.url)) { + if (!this->http_init(this->pref_.url)) { return; } From 1af26318fc0ffed817cf6c3f8653e90812339fd1 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sat, 6 Apr 2024 19:35:04 +0000 Subject: [PATCH 83/97] safe url logging --- esphome/components/ota_http/ota_http.h | 5 +++++ esphome/components/ota_http/ota_http_arduino.cpp | 4 ++-- esphome/components/ota_http/ota_http_idf.cpp | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index b8572beb3b..d71d68fe82 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -8,6 +8,7 @@ #include #include #include +#include namespace esphome { namespace ota_http { @@ -44,6 +45,10 @@ class OtaHttpComponent : public Component { float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } bool set_md5_url(const std::string &md5_url) { return this->set_url_(md5_url, this->pref_.md5_url); } bool set_url(const std::string &url) { return this->set_url_(url, this->pref_.url); } + static std::string safe_url(const char* url) { + std::regex urlPattern(R"(^(https?:\/\/)([^:]+):([^@]+)@)"); + return std::regex_replace(url, urlPattern, "$1*****:*****@"); + } void set_timeout(uint64_t timeout) { this->timeout_ = timeout; } void flash(); void check_upgrade(); diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 50b0feb422..c5f54936f3 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -31,7 +31,7 @@ int OtaHttpArduino::http_init(char *url) { } #endif // USE_ESP8266 - ESP_LOGD(TAG, "Connecting to %s", url); + ESP_LOGD(TAG, "Connecting to %s", OtaHttpComponent::safe_url(url).c_str()); bool status = false; #ifdef USE_RP2040 @@ -70,7 +70,7 @@ int OtaHttpArduino::http_init(char *url) { ESP_LOGV(TAG, "HTTP GET finished"); if (http_code >= 310) { - ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s (%d); Duration: %u ms", url, + ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s (%d); Duration: %u ms", OtaHttpComponent::safe_url(url).c_str(), HTTPClient::errorToString(http_code).c_str(), http_code, duration); return -1; } diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index ee8af754b4..3af2b56a4f 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -50,7 +50,7 @@ int OtaHttpIDF::http_init(char *url) { #endif #pragma GCC diagnostic pop - ESP_LOGI(TAG, "Trying to connect to url: %s", url); + ESP_LOGI(TAG, "Trying to connect to url: %s", OtaHttpComponent::safe_url(url).c_str()); this->client_ = esp_http_client_init(&config); esp_err_t err; @@ -62,7 +62,7 @@ int OtaHttpIDF::http_init(char *url) { int http_code = esp_http_client_get_status_code(this->client_); if (http_code >= 310) { - ESP_LOGE(TAG, "HTTP error %d; URL: %s", http_code, url); + ESP_LOGE(TAG, "HTTP error %d; URL: %s", http_code, OtaHttpComponent::safe_url(url).c_str()); return -1; } From 9a1b8ab17862890b6fc159abd37696e244bf17d6 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sat, 6 Apr 2024 20:50:20 +0000 Subject: [PATCH 84/97] common logging --- esphome/components/ota_http/ota_http.cpp | 27 +++++++++++-- esphome/components/ota_http/ota_http.h | 5 ++- .../components/ota_http/ota_http_arduino.cpp | 38 ++----------------- esphome/components/ota_http/ota_http_idf.cpp | 25 +++--------- 4 files changed, 37 insertions(+), 58 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 770c64d20b..d070684822 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -119,7 +119,9 @@ void OtaHttpComponent::flash() { } } - if (!this->http_init(this->pref_.url)) { + ESP_LOGI(TAG, "Trying to connect to url: %s", OtaHttpComponent::safe_url(this->pref_.url).c_str()); + if(! this->check_status(this->http_init(this->pref_.url))) { + this->http_end(); return; } @@ -133,7 +135,7 @@ void OtaHttpComponent::flash() { this->cleanup_(); return; } - ESP_LOGV(TAG, "OTA backend begin"); + ESP_LOGI(TAG, "OTA backend begin"); this->bytes_read_ = 0; while (this->bytes_read_ != this->body_length_) { @@ -253,7 +255,12 @@ void OtaHttpComponent::check_upgrade() { } bool OtaHttpComponent::http_get_md5() { - int length = this->http_init(this->pref_.md5_url); + ESP_LOGI(TAG, "Trying to connect to url: %s", OtaHttpComponent::safe_url(this->pref_.md5_url).c_str()); + if(! this->check_status(this->http_init(this->pref_.md5_url))) { + this->http_end(); + return false; + } + int length = this->body_length_; if (length < 0) { this->http_end(); return false; @@ -283,5 +290,19 @@ bool OtaHttpComponent::set_url_(const std::string &value, char *url) { return true; } +bool OtaHttpComponent::check_status(int status){ + // status can be -1, or http status code + if(status < 100) { + ESP_LOGE(TAG, "No answer from http server (error %d). Network error?", status); + return false; + } + if (status >= 310) { + ESP_LOGE(TAG, "HTTP error %d", status); + return false; + } + ESP_LOGV(TAG, "HTTP status %d", status); + return true; +} + } // namespace ota_http } // namespace esphome diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index d71d68fe82..7d6d3cb360 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -46,13 +46,14 @@ class OtaHttpComponent : public Component { bool set_md5_url(const std::string &md5_url) { return this->set_url_(md5_url, this->pref_.md5_url); } bool set_url(const std::string &url) { return this->set_url_(url, this->pref_.url); } static std::string safe_url(const char* url) { - std::regex urlPattern(R"(^(https?:\/\/)([^:]+):([^@]+)@)"); - return std::regex_replace(url, urlPattern, "$1*****:*****@"); + std::regex url_pattern(R"(^(https?:\/\/)([^:]+):([^@]+)@)"); + return std::regex_replace(url, url_pattern, "$1*****:*****@"); } void set_timeout(uint64_t timeout) { this->timeout_ = timeout; } void flash(); void check_upgrade(); bool http_get_md5(); + bool check_status(int status); virtual int http_init(char *url) { return -1; }; virtual int http_read(uint8_t *buf, size_t len) { return 0; }; virtual void http_end(){}; diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index c5f54936f3..6017224064 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -17,25 +17,18 @@ struct Header { }; int OtaHttpArduino::http_init(char *url) { - int http_code; - uint32_t start_time; - uint32_t duration; const char *header_keys[] = {"Content-Length", "Content-Type"}; const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); #ifdef USE_ESP8266 - // EspClass::wdtEnable(WDT_TIMEOUT_S * 1000); if (this->stream_ptr_ == nullptr && this->set_stream_ptr_()) { ESP_LOGE(TAG, "Unable to set client"); } #endif // USE_ESP8266 - ESP_LOGD(TAG, "Connecting to %s", OtaHttpComponent::safe_url(url).c_str()); - - bool status = false; + int status; #ifdef USE_RP2040 - // watchdog_enable(WDT_TIMEOUT_S * 1000, true); this->client_.setInsecure(); #endif @@ -49,40 +42,19 @@ int OtaHttpArduino::http_init(char *url) { #endif if (!status) { - ESP_LOGE(TAG, "Unable to make HTTP connection"); this->client_.end(); - return -1; - } else { - ESP_LOGV(TAG, "HTTP begin successful"); + return status; } this->client_.setReuse(true); - ESP_LOGVV(TAG, "HTTP client setReuse"); // returned needed headers must be collected before the requests this->client_.collectHeaders(header_keys, header_count); - ESP_LOGV(TAG, "HTTP headers collected"); // HTTP GET - start_time = millis(); - http_code = this->client_.GET(); - duration = millis() - start_time; - ESP_LOGV(TAG, "HTTP GET finished"); - - if (http_code >= 310) { - ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s (%d); Duration: %u ms", OtaHttpComponent::safe_url(url).c_str(), - HTTPClient::errorToString(http_code).c_str(), http_code, duration); - return -1; - } - - if (this->client_.getSize() < 0) { - ESP_LOGE(TAG, "Incorrect file size (%d) reported by HTTP server (status: %d). Aborting", this->client_.getSize(), - http_code); - return -1; - } + status = this->client_.GET(); this->body_length_ = (size_t) this->client_.getSize(); - ESP_LOGV(TAG, "body_length: %d", this->body_length_); #if defined(USE_ESP32) || defined(USE_RP2040) if (this->stream_ptr_ == nullptr) { @@ -90,14 +62,13 @@ int OtaHttpArduino::http_init(char *url) { } #endif - return this->body_length_; + return status; } int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { // wait for the stream to be populated while (this->stream_ptr_->available() == 0) { // give other tasks a chance to run while waiting for some data: - // ESP_LOGVV(TAG, "not enougth data available: %zu (total read: %zu)", streamPtr->available(), bytes_read); App.feed_wdt(); yield(); delay(1); @@ -105,7 +76,6 @@ int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { int available_data = this->stream_ptr_->available(); int bufsize = std::min((int) max_len, available_data); if (bufsize > 0) { - // ESP_LOGVV(TAG, "data available: %zu", available_data); this->stream_ptr_->readBytes(buf, bufsize); this->bytes_read_ += bufsize; diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 3af2b56a4f..6eab42efe9 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -33,6 +33,8 @@ namespace esphome { namespace ota_http { int OtaHttpIDF::http_init(char *url) { + int status; + App.feed_wdt(); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" @@ -50,29 +52,15 @@ int OtaHttpIDF::http_init(char *url) { #endif #pragma GCC diagnostic pop - ESP_LOGI(TAG, "Trying to connect to url: %s", OtaHttpComponent::safe_url(url).c_str()); - this->client_ = esp_http_client_init(&config); - esp_err_t err; - if ((err = esp_http_client_open(this->client_, 0)) != ESP_OK) { - ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); - return 0; + if ((status = esp_http_client_open(this->client_, 0)) != ESP_OK) { + return status; } this->body_length_ = esp_http_client_fetch_headers(this->client_); - int http_code = esp_http_client_get_status_code(this->client_); - if (http_code >= 310) { - ESP_LOGE(TAG, "HTTP error %d; URL: %s", http_code, OtaHttpComponent::safe_url(url).c_str()); - return -1; - } + status = esp_http_client_get_status_code(this->client_); - ESP_LOGV(TAG, "body_length: %d", this->body_length_); - - if (this->body_length_ <= 0) { - ESP_LOGE(TAG, "Incorrect file size (%d) reported by HTTP server (status: %d). Aborting", this->body_length_, err); - return -1; - } - return this->body_length_; + return status; } int OtaHttpIDF::http_read(uint8_t *buf, const size_t max_len) { @@ -83,7 +71,6 @@ int OtaHttpIDF::http_read(uint8_t *buf, const size_t max_len) { this->bytes_read_ += bufsize; buf[bufsize] = '\0'; // not fed to ota } - // ESP_LOGVV(TAG, "Read %d bytes, %d remaining", read_len, this->body_length_ - this->bytes_read); return read_len; } From c0516af1b5ecec7cc1c58f88d5f3574063a66cd3 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sat, 6 Apr 2024 23:08:37 +0000 Subject: [PATCH 85/97] better http_init --- esphome/components/ota_http/ota_http.cpp | 44 ++++++++++++++----- esphome/components/ota_http/ota_http.h | 21 +++++---- .../components/ota_http/ota_http_arduino.cpp | 14 +++--- .../components/ota_http/ota_http_arduino.h | 2 +- esphome/components/ota_http/ota_http_idf.cpp | 13 +++--- esphome/components/ota_http/ota_http_idf.h | 2 +- 6 files changed, 58 insertions(+), 38 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index d070684822..75992092a3 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -119,8 +119,11 @@ void OtaHttpComponent::flash() { } } - ESP_LOGI(TAG, "Trying to connect to url: %s", OtaHttpComponent::safe_url(this->pref_.url).c_str()); - if(! this->check_status(this->http_init(this->pref_.url))) { + if( !this->set_url(this->pref_.url) ) + return; + ESP_LOGI(TAG, "Trying to connect to url: %s", this->get_safe_url().c_str()); + this->http_init(); + if (!this->check_status()) { this->http_end(); return; } @@ -255,8 +258,11 @@ void OtaHttpComponent::check_upgrade() { } bool OtaHttpComponent::http_get_md5() { - ESP_LOGI(TAG, "Trying to connect to url: %s", OtaHttpComponent::safe_url(this->pref_.md5_url).c_str()); - if(! this->check_status(this->http_init(this->pref_.md5_url))) { + if (!this->set_url(this->pref_.md5_url)) + return false; + ESP_LOGI(TAG, "Trying to connect to url: %s", this->get_safe_url().c_str()); + this->http_init(); + if (!this->check_status()) { this->http_end(); return false; } @@ -278,7 +284,23 @@ bool OtaHttpComponent::http_get_md5() { return read_len == MD5_SIZE; } -bool OtaHttpComponent::set_url_(const std::string &value, char *url) { +bool OtaHttpComponent::set_url(char *url) { + this->body_length_ = 0; + this->status_ = -1; + this->bytes_read_ = 0; + if (url == nullptr) { + ESP_LOGE(TAG, "Bad url: (nullptr)"); + return false; + } + if (strncmp(url, "http", 4) != 0) { + ESP_LOGE(TAG, "Bad url: %s", url); + return false; + } + this->url_ = url; + return true; + } + +bool OtaHttpComponent::save_url_(const std::string &value, char *url) { if (value.length() > CONFIG_MAX_URL_LENGTH - 1) { ESP_LOGE(TAG, "Url max length is %d, and attempted to set url with length %d: %s", CONFIG_MAX_URL_LENGTH, value.length(), value.c_str()); @@ -290,17 +312,17 @@ bool OtaHttpComponent::set_url_(const std::string &value, char *url) { return true; } -bool OtaHttpComponent::check_status(int status){ +bool OtaHttpComponent::check_status(){ // status can be -1, or http status code - if(status < 100) { - ESP_LOGE(TAG, "No answer from http server (error %d). Network error?", status); + if(this->status_ < 100) { + ESP_LOGE(TAG, "No answer from http server (error %d). Network error?", this->status_); return false; } - if (status >= 310) { - ESP_LOGE(TAG, "HTTP error %d", status); + if (this->status_ >= 310) { + ESP_LOGE(TAG, "HTTP error %d", this->status_); return false; } - ESP_LOGV(TAG, "HTTP status %d", status); + ESP_LOGV(TAG, "HTTP status %d", this->status_); return true; } diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 7d6d3cb360..264c984363 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -43,24 +43,27 @@ class OtaHttpComponent : public Component { OtaHttpComponent(); void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } - bool set_md5_url(const std::string &md5_url) { return this->set_url_(md5_url, this->pref_.md5_url); } - bool set_url(const std::string &url) { return this->set_url_(url, this->pref_.url); } - static std::string safe_url(const char* url) { + bool save_md5_url(const std::string &md5_url) { return this->save_url_(md5_url, this->pref_.md5_url); } + bool save_url(const std::string &url) { return this->save_url_(url, this->pref_.url); } + bool set_url(char *url); + std::string get_safe_url() { std::regex url_pattern(R"(^(https?:\/\/)([^:]+):([^@]+)@)"); - return std::regex_replace(url, url_pattern, "$1*****:*****@"); + return std::regex_replace(this->url_, url_pattern, "$1*****:*****@"); } void set_timeout(uint64_t timeout) { this->timeout_ = timeout; } void flash(); void check_upgrade(); bool http_get_md5(); - bool check_status(int status); - virtual int http_init(char *url) { return -1; }; + bool check_status(); + virtual void http_init(){}; virtual int http_read(uint8_t *buf, size_t len) { return 0; }; virtual void http_end(){}; protected: - bool secure_() { return strncmp(this->pref_.url, "https:", 6) == 0; }; + char *url_ = nullptr; + bool secure_() { return strncmp(this->url_, "https:", 6) == 0; }; size_t body_length_ = 0; + int status_ = -1; size_t bytes_read_ = 0; bool safe_mode_ = false; uint64_t timeout_; @@ -76,7 +79,7 @@ class OtaHttpComponent : public Component { global_preferences->make_preference(OTA_HTTP_PREF_SAFE_MODE_HASH, true); private: - bool set_url_(const std::string &value, char *url); + bool save_url_(const std::string &value, char *url); }; template class OtaHttpFlashAction : public Action { @@ -87,7 +90,7 @@ template class OtaHttpFlashAction : public Action { TEMPLATABLE_VALUE(uint64_t, timeout) void play(Ts... x) override { - if (this->parent_->set_md5_url(this->md5_url_.value(x...)) && this->parent_->set_url(this->url_.value(x...))) { + if (this->parent_->save_md5_url(this->md5_url_.value(x...)) && this->parent_->save_url(this->url_.value(x...))) { if (this->timeout_.has_value()) { this->parent_->set_timeout(this->timeout_.value(x...)); } diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 6017224064..61bbe2049c 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -16,7 +16,7 @@ struct Header { const char *value; }; -int OtaHttpArduino::http_init(char *url) { +void OtaHttpArduino::http_init() { const char *header_keys[] = {"Content-Length", "Content-Type"}; const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); @@ -27,7 +27,6 @@ int OtaHttpArduino::http_init(char *url) { } #endif // USE_ESP8266 - int status; #ifdef USE_RP2040 this->client_.setInsecure(); #endif @@ -35,15 +34,15 @@ int OtaHttpArduino::http_init(char *url) { App.feed_wdt(); #if defined(USE_ESP32) || defined(USE_RP2040) - status = this->client_.begin(url); + this->status_ = this->client_.begin(this->url_); #endif #ifdef USE_ESP8266 - status = this->client_.begin(*this->stream_ptr_, String(url)); + this->status_ = this->client_.begin(*this->stream_ptr_, String(url)); #endif - if (!status) { + if (!this->status_) { this->client_.end(); - return status; + return; } this->client_.setReuse(true); @@ -52,7 +51,7 @@ int OtaHttpArduino::http_init(char *url) { this->client_.collectHeaders(header_keys, header_count); // HTTP GET - status = this->client_.GET(); + this->status_ = this->client_.GET(); this->body_length_ = (size_t) this->client_.getSize(); @@ -62,7 +61,6 @@ int OtaHttpArduino::http_init(char *url) { } #endif - return status; } int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { diff --git a/esphome/components/ota_http/ota_http_arduino.h b/esphome/components/ota_http/ota_http_arduino.h index 7885bef97e..e679611d55 100644 --- a/esphome/components/ota_http/ota_http_arduino.h +++ b/esphome/components/ota_http/ota_http_arduino.h @@ -27,7 +27,7 @@ namespace ota_http { class OtaHttpArduino : public OtaHttpComponent { public: - int http_init(char *url) override; + void http_init() override; int http_read(uint8_t *buf, size_t len) override; void http_end() override; diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 6eab42efe9..65684f2dad 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -32,14 +32,13 @@ namespace esphome { namespace ota_http { -int OtaHttpIDF::http_init(char *url) { - int status; +void OtaHttpIDF::http_init() { App.feed_wdt(); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" esp_http_client_config_t config = {nullptr}; - config.url = url; + config.url = this->url_; config.method = HTTP_METHOD_GET; config.timeout_ms = (int) this->timeout_; config.buffer_size = this->max_http_recv_buffer_; @@ -53,14 +52,12 @@ int OtaHttpIDF::http_init(char *url) { #pragma GCC diagnostic pop this->client_ = esp_http_client_init(&config); - if ((status = esp_http_client_open(this->client_, 0)) != ESP_OK) { - return status; + if ((this->status_ = esp_http_client_open(this->client_, 0)) != ESP_OK) { + return; } this->body_length_ = esp_http_client_fetch_headers(this->client_); + this->status_ = esp_http_client_get_status_code(this->client_); - status = esp_http_client_get_status_code(this->client_); - - return status; } int OtaHttpIDF::http_read(uint8_t *buf, const size_t max_len) { diff --git a/esphome/components/ota_http/ota_http_idf.h b/esphome/components/ota_http/ota_http_idf.h index 5db1e4c0d1..5997a2b666 100644 --- a/esphome/components/ota_http/ota_http_idf.h +++ b/esphome/components/ota_http/ota_http_idf.h @@ -11,7 +11,7 @@ namespace ota_http { class OtaHttpIDF : public OtaHttpComponent { public: - int http_init(char *url) override; + void http_init() override; int http_read(uint8_t *buf, size_t len) override; void http_end() override; From 45fc7db453fe6e09bb14bbc5c2b9cd4cadcc8b1b Mon Sep 17 00:00:00 2001 From: oarcher Date: Sat, 6 Apr 2024 23:28:08 +0000 Subject: [PATCH 86/97] lint --- esphome/components/ota_http/ota_http.cpp | 32 +++++++++---------- .../components/ota_http/ota_http_arduino.cpp | 3 -- esphome/components/ota_http/ota_http_idf.cpp | 2 -- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 75992092a3..ed0ee5c98d 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -119,7 +119,7 @@ void OtaHttpComponent::flash() { } } - if( !this->set_url(this->pref_.url) ) + if (!this->set_url(this->pref_.url)) return; ESP_LOGI(TAG, "Trying to connect to url: %s", this->get_safe_url().c_str()); this->http_init(); @@ -285,20 +285,20 @@ bool OtaHttpComponent::http_get_md5() { } bool OtaHttpComponent::set_url(char *url) { - this->body_length_ = 0; - this->status_ = -1; - this->bytes_read_ = 0; - if (url == nullptr) { - ESP_LOGE(TAG, "Bad url: (nullptr)"); - return false; - } - if (strncmp(url, "http", 4) != 0) { - ESP_LOGE(TAG, "Bad url: %s", url); - return false; - } - this->url_ = url; - return true; + this->body_length_ = 0; + this->status_ = -1; + this->bytes_read_ = 0; + if (url == nullptr) { + ESP_LOGE(TAG, "Bad url: (nullptr)"); + return false; } + if (strncmp(url, "http", 4) != 0) { + ESP_LOGE(TAG, "Bad url: %s", url); + return false; + } + this->url_ = url; + return true; +} bool OtaHttpComponent::save_url_(const std::string &value, char *url) { if (value.length() > CONFIG_MAX_URL_LENGTH - 1) { @@ -312,9 +312,9 @@ bool OtaHttpComponent::save_url_(const std::string &value, char *url) { return true; } -bool OtaHttpComponent::check_status(){ +bool OtaHttpComponent::check_status() { // status can be -1, or http status code - if(this->status_ < 100) { + if (this->status_ < 100) { ESP_LOGE(TAG, "No answer from http server (error %d). Network error?", this->status_); return false; } diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 61bbe2049c..29ce027583 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -17,7 +17,6 @@ struct Header { }; void OtaHttpArduino::http_init() { - const char *header_keys[] = {"Content-Length", "Content-Type"}; const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); @@ -60,7 +59,6 @@ void OtaHttpArduino::http_init() { this->set_stream_ptr_(); } #endif - } int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { @@ -74,7 +72,6 @@ int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { int available_data = this->stream_ptr_->available(); int bufsize = std::min((int) max_len, available_data); if (bufsize > 0) { - this->stream_ptr_->readBytes(buf, bufsize); this->bytes_read_ += bufsize; buf[bufsize] = '\0'; // not fed to ota diff --git a/esphome/components/ota_http/ota_http_idf.cpp b/esphome/components/ota_http/ota_http_idf.cpp index 65684f2dad..6b6fd92a88 100644 --- a/esphome/components/ota_http/ota_http_idf.cpp +++ b/esphome/components/ota_http/ota_http_idf.cpp @@ -33,7 +33,6 @@ namespace esphome { namespace ota_http { void OtaHttpIDF::http_init() { - App.feed_wdt(); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" @@ -57,7 +56,6 @@ void OtaHttpIDF::http_init() { } this->body_length_ = esp_http_client_fetch_headers(this->client_); this->status_ = esp_http_client_get_status_code(this->client_); - } int OtaHttpIDF::http_read(uint8_t *buf, const size_t max_len) { From e3b697737af8647a5b8ae878711fb4e92ff2ad03 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sun, 7 Apr 2024 03:37:05 +0000 Subject: [PATCH 87/97] fix url for 8266 --- esphome/components/ota_http/ota_http_arduino.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 29ce027583..ffe58912dd 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -36,7 +36,7 @@ void OtaHttpArduino::http_init() { this->status_ = this->client_.begin(this->url_); #endif #ifdef USE_ESP8266 - this->status_ = this->client_.begin(*this->stream_ptr_, String(url)); + this->status_ = this->client_.begin(*this->stream_ptr_, String(this->url_)); #endif if (!this->status_) { From 39e684976003c77d47b7b8624c941e8f758a3822 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sun, 7 Apr 2024 04:33:31 +0000 Subject: [PATCH 88/97] remove regex that makes 8266 unstable --- esphome/components/ota_http/ota_http.cpp | 5 +++-- esphome/components/ota_http/ota_http.h | 25 +++++++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index ed0ee5c98d..572e2b9131 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -121,7 +121,7 @@ void OtaHttpComponent::flash() { if (!this->set_url(this->pref_.url)) return; - ESP_LOGI(TAG, "Trying to connect to url: %s", this->get_safe_url().c_str()); + ESP_LOGI(TAG, "Trying to connect to url: %s", this->safe_url_); this->http_init(); if (!this->check_status()) { this->http_end(); @@ -260,7 +260,7 @@ void OtaHttpComponent::check_upgrade() { bool OtaHttpComponent::http_get_md5() { if (!this->set_url(this->pref_.md5_url)) return false; - ESP_LOGI(TAG, "Trying to connect to url: %s", this->get_safe_url().c_str()); + ESP_LOGI(TAG, "Trying to connect to url: %s", this->safe_url_); this->http_init(); if (!this->check_status()) { this->http_end(); @@ -297,6 +297,7 @@ bool OtaHttpComponent::set_url(char *url) { return false; } this->url_ = url; + this->set_safe_url_(); return true; } diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 264c984363..b7ce62a927 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -8,7 +8,6 @@ #include #include #include -#include namespace esphome { namespace ota_http { @@ -46,10 +45,6 @@ class OtaHttpComponent : public Component { bool save_md5_url(const std::string &md5_url) { return this->save_url_(md5_url, this->pref_.md5_url); } bool save_url(const std::string &url) { return this->save_url_(url, this->pref_.url); } bool set_url(char *url); - std::string get_safe_url() { - std::regex url_pattern(R"(^(https?:\/\/)([^:]+):([^@]+)@)"); - return std::regex_replace(this->url_, url_pattern, "$1*****:*****@"); - } void set_timeout(uint64_t timeout) { this->timeout_ = timeout; } void flash(); void check_upgrade(); @@ -61,6 +56,7 @@ class OtaHttpComponent : public Component { protected: char *url_ = nullptr; + char safe_url_[CONFIG_MAX_URL_LENGTH]; bool secure_() { return strncmp(this->url_, "https:", 6) == 0; }; size_t body_length_ = 0; int status_ = -1; @@ -80,6 +76,25 @@ class OtaHttpComponent : public Component { private: bool save_url_(const std::string &value, char *url); + void set_safe_url_() { + // using regex makes 8266 unstable later + const char* prefix_end = strstr(this->url_, "://"); + if (!prefix_end) { + strcpy(this->safe_url_, this->url_); + return; + } + const char* at = strchr(prefix_end, '@'); + if (!at) { + strcpy(this->safe_url_, this->url_); + return; + } + size_t prefix_len = prefix_end - this->url_ + 3; + strncpy(this->safe_url_, this->url_, prefix_len); + this->safe_url_[prefix_len] = '\0'; + + strcat(this->safe_url_, "****:****@"); + strcat(this->safe_url_, at + 1); +} }; template class OtaHttpFlashAction : public Action { From 600cba7efebe3a6b404b894a6e916655f14758e8 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sun, 7 Apr 2024 04:38:33 +0000 Subject: [PATCH 89/97] return on https disbable on 8266 --- esphome/components/ota_http/ota_http_arduino.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index ffe58912dd..094a03d026 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -23,6 +23,7 @@ void OtaHttpArduino::http_init() { #ifdef USE_ESP8266 if (this->stream_ptr_ == nullptr && this->set_stream_ptr_()) { ESP_LOGE(TAG, "Unable to set client"); + return; } #endif // USE_ESP8266 From 9dc79a3bc0c9ae87b7711ef88dec0da6f684d2a8 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sun, 7 Apr 2024 10:35:01 +0200 Subject: [PATCH 90/97] lint --- esphome/components/ota_http/ota_http.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index b7ce62a927..36b2502581 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -78,15 +78,15 @@ class OtaHttpComponent : public Component { bool save_url_(const std::string &value, char *url); void set_safe_url_() { // using regex makes 8266 unstable later - const char* prefix_end = strstr(this->url_, "://"); + const char *prefix_end = strstr(this->url_, "://"); if (!prefix_end) { - strcpy(this->safe_url_, this->url_); - return; + strcpy(this->safe_url_, this->url_); + return; } - const char* at = strchr(prefix_end, '@'); + const char *at = strchr(prefix_end, '@'); if (!at) { - strcpy(this->safe_url_, this->url_); - return; + strcpy(this->safe_url_, this->url_); + return; } size_t prefix_len = prefix_end - this->url_ + 3; strncpy(this->safe_url_, this->url_, prefix_len); @@ -94,7 +94,7 @@ class OtaHttpComponent : public Component { strcat(this->safe_url_, "****:****@"); strcat(this->safe_url_, at + 1); -} + } }; template class OtaHttpFlashAction : public Action { From d9e34a1240f5deb706e065961175ce033153b5c9 Mon Sep 17 00:00:00 2001 From: oarcher Date: Sun, 7 Apr 2024 09:36:55 +0000 Subject: [PATCH 91/97] check char bounds --- esphome/components/ota_http/ota_http.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/esphome/components/ota_http/ota_http.h b/esphome/components/ota_http/ota_http.h index 36b2502581..9eb7ab2099 100644 --- a/esphome/components/ota_http/ota_http.h +++ b/esphome/components/ota_http/ota_http.h @@ -80,20 +80,20 @@ class OtaHttpComponent : public Component { // using regex makes 8266 unstable later const char *prefix_end = strstr(this->url_, "://"); if (!prefix_end) { - strcpy(this->safe_url_, this->url_); + strlcpy(this->safe_url_, this->url_, sizeof(this->safe_url_)); return; } const char *at = strchr(prefix_end, '@'); if (!at) { - strcpy(this->safe_url_, this->url_); + strlcpy(this->safe_url_, this->url_, sizeof(this->safe_url_)); return; } - size_t prefix_len = prefix_end - this->url_ + 3; - strncpy(this->safe_url_, this->url_, prefix_len); - this->safe_url_[prefix_len] = '\0'; - strcat(this->safe_url_, "****:****@"); - strcat(this->safe_url_, at + 1); + size_t prefix_len = prefix_end - this->url_ + 3; + strlcpy(this->safe_url_, this->url_, prefix_len + 1); + strlcat(this->safe_url_, "****:****@", sizeof(this->safe_url_)); + + strlcat(this->safe_url_, at + 1, sizeof(this->safe_url_)); } }; From 6d999de2033457f9ba7503d14c805e49864935ae Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 8 Apr 2024 18:14:36 +0200 Subject: [PATCH 92/97] fix http 8266 for arduino 3.1 --- esphome/components/ota_http/ota_http_arduino.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 094a03d026..29baddb567 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -63,6 +63,16 @@ void OtaHttpArduino::http_init() { } int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { +#ifdef USE_ESP8266 +#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 1, 0) // && USE_ARDUINO_VERSION_CODE < VERSION_CODE(?, ?, ?) + if( ! this->secure_()) { + // needed for http and arduino > 3.1 until https://github.com/esp8266/Arduino/issues/9035 is closed + ESP_LOGVV(TAG, "Resetting WiFiClient stream for arduino > 3.1"); + this->stream_ptr_.reset(this->client_.getStreamPtr()); + } +#endif // USE_ARDUINO_VERSION_CODE +#endif // USE_ESP8266 + // wait for the stream to be populated while (this->stream_ptr_->available() == 0) { // give other tasks a chance to run while waiting for some data: From 3468b5393a83635ce51b4c39a6f9031e40a55053 Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 8 Apr 2024 18:22:44 +0200 Subject: [PATCH 93/97] lint --- esphome/components/ota_http/ota_http_arduino.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 29baddb567..a4cf788e83 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -64,14 +64,14 @@ void OtaHttpArduino::http_init() { int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { #ifdef USE_ESP8266 -#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 1, 0) // && USE_ARDUINO_VERSION_CODE < VERSION_CODE(?, ?, ?) - if( ! this->secure_()) { +#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 1, 0) // && USE_ARDUINO_VERSION_CODE < VERSION_CODE(?, ?, ?) + if (!this->secure_()) { // needed for http and arduino > 3.1 until https://github.com/esp8266/Arduino/issues/9035 is closed ESP_LOGVV(TAG, "Resetting WiFiClient stream for arduino > 3.1"); this->stream_ptr_.reset(this->client_.getStreamPtr()); } -#endif // USE_ARDUINO_VERSION_CODE -#endif // USE_ESP8266 +#endif // USE_ARDUINO_VERSION_CODE +#endif // USE_ESP8266 // wait for the stream to be populated while (this->stream_ptr_->available() == 0) { From c8d39bbc53b41b7e74aa7985b4346bac39d67ebd Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 8 Apr 2024 19:18:39 +0000 Subject: [PATCH 94/97] warn slow on arduino 8266 > 3.1 --- esphome/components/ota_http/ota_http_arduino.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index a4cf788e83..51cc52c714 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -66,21 +66,22 @@ int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { #ifdef USE_ESP8266 #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 1, 0) // && USE_ARDUINO_VERSION_CODE < VERSION_CODE(?, ?, ?) if (!this->secure_()) { - // needed for http and arduino > 3.1 until https://github.com/esp8266/Arduino/issues/9035 is closed - ESP_LOGVV(TAG, "Resetting WiFiClient stream for arduino > 3.1"); - this->stream_ptr_.reset(this->client_.getStreamPtr()); + ESP_LOGW(TAG, "Using arduino version >= 3.1 is **very** slow. Consider setting framework version to 3.0.2 in your yaml"); } #endif // USE_ARDUINO_VERSION_CODE #endif // USE_ESP8266 + // Since arduino8266 >= 3.1 using this->stream_ptr_ is broken (https://github.com/esp8266/Arduino/issues/9035) + WiFiClient *stream_ptr = this->client_.getStreamPtr(); + // wait for the stream to be populated - while (this->stream_ptr_->available() == 0) { + while (stream_ptr->available() == 0) { // give other tasks a chance to run while waiting for some data: App.feed_wdt(); yield(); delay(1); } - int available_data = this->stream_ptr_->available(); + int available_data = stream_ptr->available(); int bufsize = std::min((int) max_len, available_data); if (bufsize > 0) { this->stream_ptr_->readBytes(buf, bufsize); From 80c08e388331a27f8fa006afe88a290ab99ba1bc Mon Sep 17 00:00:00 2001 From: oarcher Date: Mon, 8 Apr 2024 19:52:11 +0000 Subject: [PATCH 95/97] lint --- esphome/components/ota_http/ota_http_arduino.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http_arduino.cpp b/esphome/components/ota_http/ota_http_arduino.cpp index 51cc52c714..b739740358 100644 --- a/esphome/components/ota_http/ota_http_arduino.cpp +++ b/esphome/components/ota_http/ota_http_arduino.cpp @@ -66,7 +66,8 @@ int OtaHttpArduino::http_read(uint8_t *buf, const size_t max_len) { #ifdef USE_ESP8266 #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 1, 0) // && USE_ARDUINO_VERSION_CODE < VERSION_CODE(?, ?, ?) if (!this->secure_()) { - ESP_LOGW(TAG, "Using arduino version >= 3.1 is **very** slow. Consider setting framework version to 3.0.2 in your yaml"); + ESP_LOGW(TAG, + "Using arduino version >= 3.1 is **very** slow. Consider setting framework version to 3.0.2 in your yaml"); } #endif // USE_ARDUINO_VERSION_CODE #endif // USE_ESP8266 From f33ad471f9044d9453c6870626ed0193d832671a Mon Sep 17 00:00:00 2001 From: oarcher Date: Sun, 21 Apr 2024 13:44:06 +0200 Subject: [PATCH 96/97] disable preferences_prevent_write before sync prefs on 8266 and 2040 --- esphome/components/ota_http/ota_http.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 572e2b9131..2c53a171c1 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -9,6 +9,13 @@ #include "esphome/components/ota/ota_backend.h" #include "ota_http.h" +#ifdef USE_ESP8266 +#include "esphome/components/esp8266/preferences.h" +#endif +#ifdef USE_RP2040 +#include "esphome/components/rp2040/preferences.h" +#endif + #ifdef CONFIG_WATCHDOG_TIMEOUT #include "watchdog.h" #endif @@ -207,6 +214,13 @@ void OtaHttpComponent::flash() { this->pref_.ota_http_state = OTA_HTTP_STATE_OK; strncpy(this->pref_.last_md5, this->md5_expected_, MD5_SIZE); this->pref_obj_.save(&this->pref_); + // on rp2040 and esp8266, reenable write to flash that was disabled by OTA +#ifdef USE_ESP8266 + esp8266::preferences_prevent_write(false); +#endif +#ifdef USE_RP2040 + rp2040::preferences_prevent_write(false); +#endif global_preferences->sync(); delay(10); ESP_LOGI(TAG, "OTA update completed"); From 7965d2184065e2bfa92b8507ef5d04d9a3f3bc0e Mon Sep 17 00:00:00 2001 From: oarcher Date: Sun, 21 Apr 2024 13:59:46 +0200 Subject: [PATCH 97/97] lint --- esphome/components/ota_http/ota_http.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ota_http/ota_http.cpp b/esphome/components/ota_http/ota_http.cpp index 2c53a171c1..0656fbb616 100644 --- a/esphome/components/ota_http/ota_http.cpp +++ b/esphome/components/ota_http/ota_http.cpp @@ -214,7 +214,7 @@ void OtaHttpComponent::flash() { this->pref_.ota_http_state = OTA_HTTP_STATE_OK; strncpy(this->pref_.last_md5, this->md5_expected_, MD5_SIZE); this->pref_obj_.save(&this->pref_); - // on rp2040 and esp8266, reenable write to flash that was disabled by OTA + // on rp2040 and esp8266, reenable write to flash that was disabled by OTA #ifdef USE_ESP8266 esp8266::preferences_prevent_write(false); #endif