mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Merge branch 'ota_base_extract' into integration
This commit is contained in:
		| @@ -327,6 +327,7 @@ esphome/components/opentherm/* @olegtarasov | ||||
| esphome/components/openthread/* @mrene | ||||
| esphome/components/opt3001/* @ccutrer | ||||
| esphome/components/ota/* @esphome/core | ||||
| esphome/components/ota_base/* @esphome/core | ||||
| esphome/components/output/* @esphome/core | ||||
| esphome/components/packet_transport/* @clydebarrow | ||||
| esphome/components/pca6416a/* @Mat931 | ||||
|   | ||||
| @@ -15,8 +15,7 @@ namespace adc { | ||||
|  | ||||
| #ifdef USE_ESP32 | ||||
| // clang-format off | ||||
| #if (ESP_IDF_VERSION_MAJOR == 4 && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 7)) || \ | ||||
|     (ESP_IDF_VERSION_MAJOR == 5 && \ | ||||
| #if (ESP_IDF_VERSION_MAJOR == 5 && \ | ||||
|      ((ESP_IDF_VERSION_MINOR == 0 && ESP_IDF_VERSION_PATCH >= 5) || \ | ||||
|       (ESP_IDF_VERSION_MINOR == 1 && ESP_IDF_VERSION_PATCH >= 3) || \ | ||||
|       (ESP_IDF_VERSION_MINOR >= 2)) \ | ||||
| @@ -100,11 +99,7 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage | ||||
|   adc1_channel_t channel1_{ADC1_CHANNEL_MAX}; | ||||
|   adc2_channel_t channel2_{ADC2_CHANNEL_MAX}; | ||||
|   bool autorange_{false}; | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|   esp_adc_cal_characteristics_t cal_characteristics_[SOC_ADC_ATTEN_NUM] = {}; | ||||
| #else | ||||
|   esp_adc_cal_characteristics_t cal_characteristics_[ADC_ATTEN_MAX] = {}; | ||||
| #endif  // ESP_IDF_VERSION_MAJOR | ||||
| #endif  // USE_ESP32 | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -411,8 +411,8 @@ def _esp_idf_check_versions(value): | ||||
|         version = cv.Version.parse(cv.version_number(value[CONF_VERSION])) | ||||
|         source = value.get(CONF_SOURCE, None) | ||||
|  | ||||
|     if version < cv.Version(4, 0, 0): | ||||
|         raise cv.Invalid("Only ESP-IDF 4.0+ is supported.") | ||||
|     if version < cv.Version(5, 0, 0): | ||||
|         raise cv.Invalid("Only ESP-IDF 5.0+ is supported.") | ||||
|  | ||||
|     # flag this for later *before* we set value[CONF_PLATFORM_VERSION] below | ||||
|     has_platform_ver = CONF_PLATFORM_VERSION in value | ||||
| @@ -422,20 +422,15 @@ def _esp_idf_check_versions(value): | ||||
|     ) | ||||
|  | ||||
|     if ( | ||||
|         (is_platformio := _platform_is_platformio(value[CONF_PLATFORM_VERSION])) | ||||
|         and version.major >= 5 | ||||
|         and version not in SUPPORTED_PLATFORMIO_ESP_IDF_5X | ||||
|     ): | ||||
|         is_platformio := _platform_is_platformio(value[CONF_PLATFORM_VERSION]) | ||||
|     ) and version not in SUPPORTED_PLATFORMIO_ESP_IDF_5X: | ||||
|         raise cv.Invalid( | ||||
|             f"ESP-IDF {str(version)} not supported by platformio/espressif32" | ||||
|         ) | ||||
|  | ||||
|     if ( | ||||
|         version.major < 5 | ||||
|         or ( | ||||
|             version in SUPPORTED_PLATFORMIO_ESP_IDF_5X | ||||
|             and version not in SUPPORTED_PIOARDUINO_ESP_IDF_5X | ||||
|         ) | ||||
|         version in SUPPORTED_PLATFORMIO_ESP_IDF_5X | ||||
|         and version not in SUPPORTED_PIOARDUINO_ESP_IDF_5X | ||||
|     ) and not has_platform_ver: | ||||
|         raise cv.Invalid( | ||||
|             f"ESP-IDF {value[CONF_VERSION]} may be supported by platformio/espressif32; please specify '{CONF_PLATFORM_VERSION}'" | ||||
| @@ -801,14 +796,9 @@ async def to_code(config): | ||||
|  | ||||
|         if advanced.get(CONF_IGNORE_EFUSE_MAC_CRC): | ||||
|             add_idf_sdkconfig_option("CONFIG_ESP_MAC_IGNORE_MAC_CRC_ERROR", True) | ||||
|             if (framework_ver.major, framework_ver.minor) >= (4, 4): | ||||
|                 add_idf_sdkconfig_option( | ||||
|                     "CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE", False | ||||
|                 ) | ||||
|             else: | ||||
|                 add_idf_sdkconfig_option( | ||||
|                     "CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE", False | ||||
|                 ) | ||||
|             add_idf_sdkconfig_option( | ||||
|                 "CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE", False | ||||
|             ) | ||||
|         if advanced.get(CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES): | ||||
|             _LOGGER.warning( | ||||
|                 "Using experimental features in ESP-IDF may result in unexpected failures." | ||||
|   | ||||
| @@ -56,11 +56,7 @@ void arch_init() { | ||||
| void IRAM_ATTR HOT arch_feed_wdt() { esp_task_wdt_reset(); } | ||||
|  | ||||
| uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
| uint32_t arch_get_cpu_cycle_count() { return esp_cpu_get_cycle_count(); } | ||||
| #else | ||||
| uint32_t arch_get_cpu_cycle_count() { return cpu_hal_get_cycle_count(); } | ||||
| #endif | ||||
| uint32_t arch_get_cpu_freq_hz() { | ||||
|   uint32_t freq = 0; | ||||
| #ifdef USE_ESP_IDF | ||||
|   | ||||
| @@ -29,8 +29,6 @@ from esphome.const import ( | ||||
|     CONF_ON_BLE_SERVICE_DATA_ADVERTISE, | ||||
|     CONF_SERVICE_UUID, | ||||
|     CONF_TRIGGER_ID, | ||||
|     KEY_CORE, | ||||
|     KEY_FRAMEWORK_VERSION, | ||||
| ) | ||||
| from esphome.core import CORE | ||||
|  | ||||
| @@ -323,10 +321,7 @@ async def to_code(config): | ||||
|         # https://github.com/espressif/esp-idf/issues/2503 | ||||
|         # Match arduino CONFIG_BTU_TASK_STACK_SIZE | ||||
|         # https://github.com/espressif/arduino-esp32/blob/fd72cf46ad6fc1a6de99c1d83ba8eba17d80a4ee/tools/sdk/esp32/sdkconfig#L1866 | ||||
|         if CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version(4, 4, 6): | ||||
|             add_idf_sdkconfig_option("CONFIG_BT_BTU_TASK_STACK_SIZE", 8192) | ||||
|         else: | ||||
|             add_idf_sdkconfig_option("CONFIG_BTU_TASK_STACK_SIZE", 8192) | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_BTU_TASK_STACK_SIZE", 8192) | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_ACL_CONNECTIONS", 9) | ||||
|         add_idf_sdkconfig_option( | ||||
|             "CONFIG_BTDM_CTRL_BLE_MAX_CONN", config[CONF_MAX_CONNECTIONS] | ||||
| @@ -335,8 +330,7 @@ async def to_code(config): | ||||
|         # max notifications in 5.x, setting CONFIG_BT_ACL_CONNECTIONS | ||||
|         # is enough in 4.x | ||||
|         # https://github.com/esphome/issues/issues/6808 | ||||
|         if CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version(5, 0, 0): | ||||
|             add_idf_sdkconfig_option("CONFIG_BT_GATTC_NOTIF_REG_MAX", 9) | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_GATTC_NOTIF_REG_MAX", 9) | ||||
|  | ||||
|     cg.add_define("USE_OTA_STATE_CALLBACK")  # To be notified when an OTA update starts | ||||
|     cg.add_define("USE_ESP32_BLE_CLIENT") | ||||
|   | ||||
| @@ -18,7 +18,7 @@ | ||||
| #include <cinttypes> | ||||
|  | ||||
| #ifdef USE_OTA | ||||
| #include "esphome/components/ota/ota_backend.h" | ||||
| #include "esphome/components/ota_base/ota_backend.h" | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE | ||||
| @@ -61,9 +61,9 @@ void ESP32BLETracker::setup() { | ||||
|   global_esp32_ble_tracker = this; | ||||
|  | ||||
| #ifdef USE_OTA | ||||
|   ota::get_global_ota_callback()->add_on_state_callback( | ||||
|       [this](ota::OTAState state, float progress, uint8_t error, ota::OTAComponent *comp) { | ||||
|         if (state == ota::OTA_STARTED) { | ||||
|   ota_base::get_global_ota_callback()->add_on_state_callback( | ||||
|       [this](ota_base::OTAState state, float progress, uint8_t error, ota_base::OTAComponent *comp) { | ||||
|         if (state == ota_base::OTA_STARTED) { | ||||
|           this->stop_scan(); | ||||
|           for (auto *client : this->clients_) { | ||||
|             client->disconnect(); | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| import logging | ||||
|  | ||||
| import esphome.codegen as cg | ||||
| from esphome.components.ota import BASE_OTA_SCHEMA, OTAComponent, ota_to_code | ||||
| from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code | ||||
| from esphome.components.ota_base import OTAComponent | ||||
| from esphome.config_helpers import merge_config | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import ( | ||||
|   | ||||
| @@ -2,12 +2,12 @@ | ||||
| #ifdef USE_OTA | ||||
| #include "esphome/components/md5/md5.h" | ||||
| #include "esphome/components/network/util.h" | ||||
| #include "esphome/components/ota/ota_backend.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_libretiny.h" | ||||
| #include "esphome/components/ota/ota_backend_arduino_rp2040.h" | ||||
| #include "esphome/components/ota/ota_backend_esp_idf.h" | ||||
| #include "esphome/components/ota_base/ota_backend.h"  // For OTAComponent and callbacks | ||||
| #include "esphome/components/ota_base/ota_backend_arduino_esp32.h" | ||||
| #include "esphome/components/ota_base/ota_backend_arduino_esp8266.h" | ||||
| #include "esphome/components/ota_base/ota_backend_arduino_libretiny.h" | ||||
| #include "esphome/components/ota_base/ota_backend_arduino_rp2040.h" | ||||
| #include "esphome/components/ota_base/ota_backend_esp_idf.h" | ||||
| #include "esphome/core/application.h" | ||||
| #include "esphome/core/hal.h" | ||||
| #include "esphome/core/log.h" | ||||
| @@ -23,7 +23,7 @@ static constexpr u_int16_t OTA_BLOCK_SIZE = 8192; | ||||
|  | ||||
| void ESPHomeOTAComponent::setup() { | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|   ota::register_ota_platform(this); | ||||
|   ota_base::register_ota_platform(this); | ||||
| #endif | ||||
|  | ||||
|   this->server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0);  // monitored for incoming connections | ||||
| @@ -94,7 +94,7 @@ void ESPHomeOTAComponent::loop() { | ||||
| static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01; | ||||
|  | ||||
| void ESPHomeOTAComponent::handle_() { | ||||
|   ota::OTAResponseTypes error_code = ota::OTA_RESPONSE_ERROR_UNKNOWN; | ||||
|   ota_base::OTAResponseTypes error_code = ota_base::OTA_RESPONSE_ERROR_UNKNOWN; | ||||
|   bool update_started = false; | ||||
|   size_t total = 0; | ||||
|   uint32_t last_progress = 0; | ||||
| @@ -102,7 +102,7 @@ void ESPHomeOTAComponent::handle_() { | ||||
|   char *sbuf = reinterpret_cast<char *>(buf); | ||||
|   size_t ota_size; | ||||
|   uint8_t ota_features; | ||||
|   std::unique_ptr<ota::OTABackend> backend; | ||||
|   std::unique_ptr<ota_base::OTABackend> backend; | ||||
|   (void) ota_features; | ||||
| #if USE_OTA_VERSION == 2 | ||||
|   size_t size_acknowledged = 0; | ||||
| @@ -129,7 +129,7 @@ void ESPHomeOTAComponent::handle_() { | ||||
|   ESP_LOGD(TAG, "Starting update from %s", this->client_->getpeername().c_str()); | ||||
|   this->status_set_warning(); | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|   this->state_callback_.call(ota::OTA_STARTED, 0.0f, 0); | ||||
|   this->state_callback_.call(ota_base::OTA_STARTED, 0.0f, 0); | ||||
| #endif | ||||
|  | ||||
|   if (!this->readall_(buf, 5)) { | ||||
| @@ -140,16 +140,16 @@ void ESPHomeOTAComponent::handle_() { | ||||
|   if (buf[0] != 0x6C || buf[1] != 0x26 || buf[2] != 0xF7 || buf[3] != 0x5C || buf[4] != 0x45) { | ||||
|     ESP_LOGW(TAG, "Magic bytes do not match! 0x%02X-0x%02X-0x%02X-0x%02X-0x%02X", buf[0], buf[1], buf[2], buf[3], | ||||
|              buf[4]); | ||||
|     error_code = ota::OTA_RESPONSE_ERROR_MAGIC; | ||||
|     error_code = ota_base::OTA_RESPONSE_ERROR_MAGIC; | ||||
|     goto error;  // NOLINT(cppcoreguidelines-avoid-goto) | ||||
|   } | ||||
|  | ||||
|   // Send OK and version - 2 bytes | ||||
|   buf[0] = ota::OTA_RESPONSE_OK; | ||||
|   buf[0] = ota_base::OTA_RESPONSE_OK; | ||||
|   buf[1] = USE_OTA_VERSION; | ||||
|   this->writeall_(buf, 2); | ||||
|  | ||||
|   backend = ota::make_ota_backend(); | ||||
|   backend = ota_base::make_ota_backend(); | ||||
|  | ||||
|   // Read features - 1 byte | ||||
|   if (!this->readall_(buf, 1)) { | ||||
| @@ -160,16 +160,16 @@ void ESPHomeOTAComponent::handle_() { | ||||
|   ESP_LOGV(TAG, "Features: 0x%02X", ota_features); | ||||
|  | ||||
|   // Acknowledge header - 1 byte | ||||
|   buf[0] = ota::OTA_RESPONSE_HEADER_OK; | ||||
|   buf[0] = ota_base::OTA_RESPONSE_HEADER_OK; | ||||
|   if ((ota_features & FEATURE_SUPPORTS_COMPRESSION) != 0 && backend->supports_compression()) { | ||||
|     buf[0] = ota::OTA_RESPONSE_SUPPORTS_COMPRESSION; | ||||
|     buf[0] = ota_base::OTA_RESPONSE_SUPPORTS_COMPRESSION; | ||||
|   } | ||||
|  | ||||
|   this->writeall_(buf, 1); | ||||
|  | ||||
| #ifdef USE_OTA_PASSWORD | ||||
|   if (!this->password_.empty()) { | ||||
|     buf[0] = ota::OTA_RESPONSE_REQUEST_AUTH; | ||||
|     buf[0] = ota_base::OTA_RESPONSE_REQUEST_AUTH; | ||||
|     this->writeall_(buf, 1); | ||||
|     md5::MD5Digest md5{}; | ||||
|     md5.init(); | ||||
| @@ -220,14 +220,14 @@ void ESPHomeOTAComponent::handle_() { | ||||
|  | ||||
|     if (!matches) { | ||||
|       ESP_LOGW(TAG, "Auth failed! Passwords do not match"); | ||||
|       error_code = ota::OTA_RESPONSE_ERROR_AUTH_INVALID; | ||||
|       error_code = ota_base::OTA_RESPONSE_ERROR_AUTH_INVALID; | ||||
|       goto error;  // NOLINT(cppcoreguidelines-avoid-goto) | ||||
|     } | ||||
|   } | ||||
| #endif  // USE_OTA_PASSWORD | ||||
|  | ||||
|   // Acknowledge auth OK - 1 byte | ||||
|   buf[0] = ota::OTA_RESPONSE_AUTH_OK; | ||||
|   buf[0] = ota_base::OTA_RESPONSE_AUTH_OK; | ||||
|   this->writeall_(buf, 1); | ||||
|  | ||||
|   // Read size, 4 bytes MSB first | ||||
| @@ -243,12 +243,12 @@ void ESPHomeOTAComponent::handle_() { | ||||
|   ESP_LOGV(TAG, "Size is %u bytes", ota_size); | ||||
|  | ||||
|   error_code = backend->begin(ota_size); | ||||
|   if (error_code != ota::OTA_RESPONSE_OK) | ||||
|   if (error_code != ota_base::OTA_RESPONSE_OK) | ||||
|     goto error;  // NOLINT(cppcoreguidelines-avoid-goto) | ||||
|   update_started = true; | ||||
|  | ||||
|   // Acknowledge prepare OK - 1 byte | ||||
|   buf[0] = ota::OTA_RESPONSE_UPDATE_PREPARE_OK; | ||||
|   buf[0] = ota_base::OTA_RESPONSE_UPDATE_PREPARE_OK; | ||||
|   this->writeall_(buf, 1); | ||||
|  | ||||
|   // Read binary MD5, 32 bytes | ||||
| @@ -261,7 +261,7 @@ void ESPHomeOTAComponent::handle_() { | ||||
|   backend->set_update_md5(sbuf); | ||||
|  | ||||
|   // Acknowledge MD5 OK - 1 byte | ||||
|   buf[0] = ota::OTA_RESPONSE_BIN_MD5_OK; | ||||
|   buf[0] = ota_base::OTA_RESPONSE_BIN_MD5_OK; | ||||
|   this->writeall_(buf, 1); | ||||
|  | ||||
|   while (total < ota_size) { | ||||
| @@ -285,14 +285,14 @@ void ESPHomeOTAComponent::handle_() { | ||||
|     } | ||||
|  | ||||
|     error_code = backend->write(buf, read); | ||||
|     if (error_code != ota::OTA_RESPONSE_OK) { | ||||
|     if (error_code != ota_base::OTA_RESPONSE_OK) { | ||||
|       ESP_LOGW(TAG, "Error writing binary data to flash!, error_code: %d", error_code); | ||||
|       goto error;  // NOLINT(cppcoreguidelines-avoid-goto) | ||||
|     } | ||||
|     total += read; | ||||
| #if USE_OTA_VERSION == 2 | ||||
|     while (size_acknowledged + OTA_BLOCK_SIZE <= total || (total == ota_size && size_acknowledged < ota_size)) { | ||||
|       buf[0] = ota::OTA_RESPONSE_CHUNK_OK; | ||||
|       buf[0] = ota_base::OTA_RESPONSE_CHUNK_OK; | ||||
|       this->writeall_(buf, 1); | ||||
|       size_acknowledged += OTA_BLOCK_SIZE; | ||||
|     } | ||||
| @@ -304,7 +304,7 @@ void ESPHomeOTAComponent::handle_() { | ||||
|       float percentage = (total * 100.0f) / ota_size; | ||||
|       ESP_LOGD(TAG, "Progress: %0.1f%%", percentage); | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|       this->state_callback_.call(ota::OTA_IN_PROGRESS, percentage, 0); | ||||
|       this->state_callback_.call(ota_base::OTA_IN_PROGRESS, percentage, 0); | ||||
| #endif | ||||
|       // feed watchdog and give other tasks a chance to run | ||||
|       App.feed_wdt(); | ||||
| @@ -313,21 +313,21 @@ void ESPHomeOTAComponent::handle_() { | ||||
|   } | ||||
|  | ||||
|   // Acknowledge receive OK - 1 byte | ||||
|   buf[0] = ota::OTA_RESPONSE_RECEIVE_OK; | ||||
|   buf[0] = ota_base::OTA_RESPONSE_RECEIVE_OK; | ||||
|   this->writeall_(buf, 1); | ||||
|  | ||||
|   error_code = backend->end(); | ||||
|   if (error_code != ota::OTA_RESPONSE_OK) { | ||||
|   if (error_code != ota_base::OTA_RESPONSE_OK) { | ||||
|     ESP_LOGW(TAG, "Error ending update! error_code: %d", error_code); | ||||
|     goto error;  // NOLINT(cppcoreguidelines-avoid-goto) | ||||
|   } | ||||
|  | ||||
|   // Acknowledge Update end OK - 1 byte | ||||
|   buf[0] = ota::OTA_RESPONSE_UPDATE_END_OK; | ||||
|   buf[0] = ota_base::OTA_RESPONSE_UPDATE_END_OK; | ||||
|   this->writeall_(buf, 1); | ||||
|  | ||||
|   // Read ACK | ||||
|   if (!this->readall_(buf, 1) || buf[0] != ota::OTA_RESPONSE_OK) { | ||||
|   if (!this->readall_(buf, 1) || buf[0] != ota_base::OTA_RESPONSE_OK) { | ||||
|     ESP_LOGW(TAG, "Reading back acknowledgement failed"); | ||||
|     // do not go to error, this is not fatal | ||||
|   } | ||||
| @@ -338,7 +338,7 @@ void ESPHomeOTAComponent::handle_() { | ||||
|   ESP_LOGI(TAG, "Update complete"); | ||||
|   this->status_clear_warning(); | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|   this->state_callback_.call(ota::OTA_COMPLETED, 100.0f, 0); | ||||
|   this->state_callback_.call(ota_base::OTA_COMPLETED, 100.0f, 0); | ||||
| #endif | ||||
|   delay(100);  // NOLINT | ||||
|   App.safe_reboot(); | ||||
| @@ -355,7 +355,7 @@ error: | ||||
|  | ||||
|   this->status_momentary_error("onerror", 5000); | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|   this->state_callback_.call(ota::OTA_ERROR, 0.0f, static_cast<uint8_t>(error_code)); | ||||
|   this->state_callback_.call(ota_base::OTA_ERROR, 0.0f, static_cast<uint8_t>(error_code)); | ||||
| #endif | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -4,13 +4,13 @@ | ||||
| #ifdef USE_OTA | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/preferences.h" | ||||
| #include "esphome/components/ota/ota_backend.h" | ||||
| #include "esphome/components/ota_base/ota_backend.h" | ||||
| #include "esphome/components/socket/socket.h" | ||||
|  | ||||
| namespace esphome { | ||||
|  | ||||
| /// ESPHomeOTAComponent provides a simple way to integrate Over-the-Air updates into your app using ArduinoOTA. | ||||
| class ESPHomeOTAComponent : public ota::OTAComponent { | ||||
| class ESPHomeOTAComponent : public ota_base::OTAComponent { | ||||
|  public: | ||||
| #ifdef USE_OTA_PASSWORD | ||||
|   void set_auth_password(const std::string &password) { password_ = password; } | ||||
|   | ||||
| @@ -19,11 +19,7 @@ | ||||
| #include <sys/cdefs.h> | ||||
| #include "esp_log.h" | ||||
| #include "esp_eth.h" | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
| #include "esp_eth_phy_802_3.h" | ||||
| #else | ||||
| #include "eth_phy_regs_struct.h" | ||||
| #endif | ||||
| #include "freertos/FreeRTOS.h" | ||||
| #include "freertos/task.h" | ||||
| #include "driver/gpio.h" | ||||
| @@ -174,11 +170,7 @@ static esp_err_t jl1101_reset_hw(esp_eth_phy_t *phy) { | ||||
|   return ESP_OK; | ||||
| } | ||||
|  | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
| static esp_err_t jl1101_negotiate(esp_eth_phy_t *phy, eth_phy_autoneg_cmd_t cmd, bool *nego_state) { | ||||
| #else | ||||
| static esp_err_t jl1101_negotiate(esp_eth_phy_t *phy) { | ||||
| #endif | ||||
|   phy_jl1101_t *jl1101 = __containerof(phy, phy_jl1101_t, parent); | ||||
|   esp_eth_mediator_t *eth = jl1101->eth; | ||||
|   /* in case any link status has changed, let's assume we're in link down status */ | ||||
| @@ -293,11 +285,7 @@ static esp_err_t jl1101_init(esp_eth_phy_t *phy) { | ||||
|   esp_eth_mediator_t *eth = jl1101->eth; | ||||
|   // Detect PHY address | ||||
|   if (jl1101->addr == ESP_ETH_PHY_ADDR_AUTO) { | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|     PHY_CHECK(esp_eth_phy_802_3_detect_phy_addr(eth, &jl1101->addr) == ESP_OK, "Detect PHY address failed", err); | ||||
| #else | ||||
|     PHY_CHECK(esp_eth_detect_phy_addr(eth, &jl1101->addr) == ESP_OK, "Detect PHY address failed", err); | ||||
| #endif | ||||
|   } | ||||
|   /* Power on Ethernet PHY */ | ||||
|   PHY_CHECK(jl1101_pwrctl(phy, true) == ESP_OK, "power control failed", err); | ||||
| @@ -336,11 +324,7 @@ esp_eth_phy_t *esp_eth_phy_new_jl1101(const eth_phy_config_t *config) { | ||||
|   jl1101->parent.init = jl1101_init; | ||||
|   jl1101->parent.deinit = jl1101_deinit; | ||||
|   jl1101->parent.set_mediator = jl1101_set_mediator; | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|   jl1101->parent.autonego_ctrl = jl1101_negotiate; | ||||
| #else | ||||
|   jl1101->parent.negotiate = jl1101_negotiate; | ||||
| #endif | ||||
|   jl1101->parent.get_link = jl1101_get_link; | ||||
|   jl1101->parent.pwrctl = jl1101_pwrctl; | ||||
|   jl1101->parent.get_addr = jl1101_get_addr; | ||||
|   | ||||
| @@ -122,25 +122,12 @@ void EthernetComponent::setup() { | ||||
|       .post_cb = nullptr, | ||||
|   }; | ||||
|  | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
| #if CONFIG_ETH_SPI_ETHERNET_W5500 | ||||
|   eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(host, &devcfg); | ||||
| #endif | ||||
| #if CONFIG_ETH_SPI_ETHERNET_DM9051 | ||||
|   eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(host, &devcfg); | ||||
| #endif | ||||
| #else | ||||
|   spi_device_handle_t spi_handle = nullptr; | ||||
|   err = spi_bus_add_device(host, &devcfg, &spi_handle); | ||||
|   ESPHL_ERROR_CHECK(err, "SPI bus add device error"); | ||||
|  | ||||
| #if CONFIG_ETH_SPI_ETHERNET_W5500 | ||||
|   eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle); | ||||
| #endif | ||||
| #if CONFIG_ETH_SPI_ETHERNET_DM9051 | ||||
|   eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle); | ||||
| #endif | ||||
| #endif  // ESP_IDF_VERSION_MAJOR >= 5 | ||||
|  | ||||
| #if CONFIG_ETH_SPI_ETHERNET_W5500 | ||||
|   w5500_config.int_gpio_num = this->interrupt_pin_; | ||||
| @@ -211,11 +198,7 @@ void EthernetComponent::setup() { | ||||
|     } | ||||
|     case ETHERNET_TYPE_KSZ8081: | ||||
|     case ETHERNET_TYPE_KSZ8081RNA: { | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|       this->phy_ = esp_eth_phy_new_ksz80xx(&phy_config); | ||||
| #else | ||||
|       this->phy_ = esp_eth_phy_new_ksz8081(&phy_config); | ||||
| #endif | ||||
|       break; | ||||
|     } | ||||
| #endif | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| from esphome import automation | ||||
| import esphome.codegen as cg | ||||
| from esphome.components.ota import BASE_OTA_SCHEMA, OTAComponent, ota_to_code | ||||
| from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import CONF_ID, CONF_PASSWORD, CONF_URL, CONF_USERNAME | ||||
| from esphome.core import coroutine_with_priority | ||||
| @@ -15,6 +15,9 @@ DEPENDENCIES = ["network", "http_request"] | ||||
| CONF_MD5 = "md5" | ||||
| CONF_MD5_URL = "md5_url" | ||||
|  | ||||
| ota_base_ns = cg.esphome_ns.namespace("ota_base") | ||||
| OTAComponent = ota_base_ns.class_("OTAComponent", cg.Component) | ||||
|  | ||||
| OtaHttpRequestComponent = http_request_ns.class_( | ||||
|     "OtaHttpRequestComponent", OTAComponent | ||||
| ) | ||||
|   | ||||
| @@ -6,11 +6,11 @@ | ||||
|  | ||||
| #include "esphome/components/md5/md5.h" | ||||
| #include "esphome/components/watchdog/watchdog.h" | ||||
| #include "esphome/components/ota/ota_backend.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_base/ota_backend.h" | ||||
| #include "esphome/components/ota_base/ota_backend_arduino_esp32.h" | ||||
| #include "esphome/components/ota_base/ota_backend_arduino_esp8266.h" | ||||
| #include "esphome/components/ota_base/ota_backend_arduino_rp2040.h" | ||||
| #include "esphome/components/ota_base/ota_backend_esp_idf.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace http_request { | ||||
| @@ -19,7 +19,7 @@ static const char *const TAG = "http_request.ota"; | ||||
|  | ||||
| void OtaHttpRequestComponent::setup() { | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|   ota::register_ota_platform(this); | ||||
|   ota_base::register_ota_platform(this); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| @@ -50,15 +50,15 @@ void OtaHttpRequestComponent::flash() { | ||||
|  | ||||
|   ESP_LOGI(TAG, "Starting update"); | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|   this->state_callback_.call(ota::OTA_STARTED, 0.0f, 0); | ||||
|   this->state_callback_.call(ota_base::OTA_STARTED, 0.0f, 0); | ||||
| #endif | ||||
|  | ||||
|   auto ota_status = this->do_ota_(); | ||||
|  | ||||
|   switch (ota_status) { | ||||
|     case ota::OTA_RESPONSE_OK: | ||||
|     case ota_base::OTA_RESPONSE_OK: | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|       this->state_callback_.call(ota::OTA_COMPLETED, 100.0f, ota_status); | ||||
|       this->state_callback_.call(ota_base::OTA_COMPLETED, 100.0f, ota_status); | ||||
| #endif | ||||
|       delay(10); | ||||
|       App.safe_reboot(); | ||||
| @@ -66,7 +66,7 @@ void OtaHttpRequestComponent::flash() { | ||||
|  | ||||
|     default: | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|       this->state_callback_.call(ota::OTA_ERROR, 0.0f, ota_status); | ||||
|       this->state_callback_.call(ota_base::OTA_ERROR, 0.0f, ota_status); | ||||
| #endif | ||||
|       this->md5_computed_.clear();  // will be reset at next attempt | ||||
|       this->md5_expected_.clear();  // will be reset at next attempt | ||||
| @@ -74,7 +74,7 @@ void OtaHttpRequestComponent::flash() { | ||||
|   } | ||||
| } | ||||
|  | ||||
| void OtaHttpRequestComponent::cleanup_(std::unique_ptr<ota::OTABackend> backend, | ||||
| void OtaHttpRequestComponent::cleanup_(std::unique_ptr<ota_base::OTABackend> backend, | ||||
|                                        const std::shared_ptr<HttpContainer> &container) { | ||||
|   if (this->update_started_) { | ||||
|     ESP_LOGV(TAG, "Aborting OTA backend"); | ||||
| @@ -115,9 +115,9 @@ uint8_t OtaHttpRequestComponent::do_ota_() { | ||||
|   ESP_LOGV(TAG, "MD5Digest initialized"); | ||||
|  | ||||
|   ESP_LOGV(TAG, "OTA backend begin"); | ||||
|   auto backend = ota::make_ota_backend(); | ||||
|   auto backend = ota_base::make_ota_backend(); | ||||
|   auto error_code = backend->begin(container->content_length); | ||||
|   if (error_code != ota::OTA_RESPONSE_OK) { | ||||
|   if (error_code != ota_base::OTA_RESPONSE_OK) { | ||||
|     ESP_LOGW(TAG, "backend->begin error: %d", error_code); | ||||
|     this->cleanup_(std::move(backend), container); | ||||
|     return error_code; | ||||
| @@ -144,7 +144,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() { | ||||
|       // write bytes to OTA backend | ||||
|       this->update_started_ = true; | ||||
|       error_code = backend->write(buf, bufsize); | ||||
|       if (error_code != ota::OTA_RESPONSE_OK) { | ||||
|       if (error_code != ota_base::OTA_RESPONSE_OK) { | ||||
|         // error code explanation available at | ||||
|         // https://github.com/esphome/esphome/blob/dev/esphome/components/ota/ota_backend.h | ||||
|         ESP_LOGE(TAG, "Error code (%02X) writing binary data to flash at offset %d and size %d", error_code, | ||||
| @@ -160,7 +160,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() { | ||||
|       float percentage = container->get_bytes_read() * 100.0f / container->content_length; | ||||
|       ESP_LOGD(TAG, "Progress: %0.1f%%", percentage); | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|       this->state_callback_.call(ota::OTA_IN_PROGRESS, percentage, 0); | ||||
|       this->state_callback_.call(ota_base::OTA_IN_PROGRESS, percentage, 0); | ||||
| #endif | ||||
|     } | ||||
|   }  // while | ||||
| @@ -174,7 +174,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() { | ||||
|   if (strncmp(this->md5_computed_.c_str(), this->md5_expected_.c_str(), MD5_SIZE) != 0) { | ||||
|     ESP_LOGE(TAG, "MD5 computed: %s - Aborting due to MD5 mismatch", this->md5_computed_.c_str()); | ||||
|     this->cleanup_(std::move(backend), container); | ||||
|     return ota::OTA_RESPONSE_ERROR_MD5_MISMATCH; | ||||
|     return ota_base::OTA_RESPONSE_ERROR_MD5_MISMATCH; | ||||
|   } else { | ||||
|     backend->set_update_md5(md5_receive_str.get()); | ||||
|   } | ||||
| @@ -187,14 +187,14 @@ uint8_t OtaHttpRequestComponent::do_ota_() { | ||||
|   delay(100);  // NOLINT | ||||
|  | ||||
|   error_code = backend->end(); | ||||
|   if (error_code != ota::OTA_RESPONSE_OK) { | ||||
|   if (error_code != ota_base::OTA_RESPONSE_OK) { | ||||
|     ESP_LOGW(TAG, "Error ending update! error_code: %d", error_code); | ||||
|     this->cleanup_(std::move(backend), container); | ||||
|     return error_code; | ||||
|   } | ||||
|  | ||||
|   ESP_LOGI(TAG, "Update complete"); | ||||
|   return ota::OTA_RESPONSE_OK; | ||||
|   return ota_base::OTA_RESPONSE_OK; | ||||
| } | ||||
|  | ||||
| std::string OtaHttpRequestComponent::get_url_with_auth_(const std::string &url) { | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/components/ota/ota_backend.h" | ||||
| #include "esphome/components/ota_base/ota_backend.h" | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/core/defines.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| @@ -22,7 +22,7 @@ enum OtaHttpRequestError : uint8_t { | ||||
|   OTA_CONNECTION_ERROR = 0x12, | ||||
| }; | ||||
|  | ||||
| class OtaHttpRequestComponent : public ota::OTAComponent, public Parented<HttpRequestComponent> { | ||||
| class OtaHttpRequestComponent : public ota_base::OTAComponent, public Parented<HttpRequestComponent> { | ||||
|  public: | ||||
|   void setup() override; | ||||
|   void dump_config() override; | ||||
| @@ -40,7 +40,7 @@ class OtaHttpRequestComponent : public ota::OTAComponent, public Parented<HttpRe | ||||
|   void flash(); | ||||
|  | ||||
|  protected: | ||||
|   void cleanup_(std::unique_ptr<ota::OTABackend> backend, const std::shared_ptr<HttpContainer> &container); | ||||
|   void cleanup_(std::unique_ptr<ota_base::OTABackend> backend, const std::shared_ptr<HttpContainer> &container); | ||||
|   uint8_t do_ota_(); | ||||
|   std::string get_url_with_auth_(const std::string &url); | ||||
|   bool http_get_md5_(); | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
|  | ||||
| #include "esphome/components/json/json_util.h" | ||||
| #include "esphome/components/network/util.h" | ||||
| #include "esphome/components/ota_base/ota_backend.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace http_request { | ||||
| @@ -21,13 +22,13 @@ static const char *const TAG = "http_request.update"; | ||||
| static const size_t MAX_READ_SIZE = 256; | ||||
|  | ||||
| void HttpRequestUpdate::setup() { | ||||
|   this->ota_parent_->add_on_state_callback([this](ota::OTAState state, float progress, uint8_t err) { | ||||
|     if (state == ota::OTAState::OTA_IN_PROGRESS) { | ||||
|   this->ota_parent_->add_on_state_callback([this](ota_base::OTAState state, float progress, uint8_t err) { | ||||
|     if (state == ota_base::OTAState::OTA_IN_PROGRESS) { | ||||
|       this->state_ = update::UPDATE_STATE_INSTALLING; | ||||
|       this->update_info_.has_progress = true; | ||||
|       this->update_info_.progress = progress; | ||||
|       this->publish_state(); | ||||
|     } else if (state == ota::OTAState::OTA_ABORT || state == ota::OTAState::OTA_ERROR) { | ||||
|     } else if (state == ota_base::OTAState::OTA_ABORT || state == ota_base::OTAState::OTA_ERROR) { | ||||
|       this->state_ = update::UPDATE_STATE_AVAILABLE; | ||||
|       this->status_set_error("Failed to install firmware"); | ||||
|       this->publish_state(); | ||||
|   | ||||
| @@ -9,14 +9,7 @@ from esphome.components.esp32.const import ( | ||||
|     VARIANT_ESP32S3, | ||||
| ) | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import ( | ||||
|     CONF_BITS_PER_SAMPLE, | ||||
|     CONF_CHANNEL, | ||||
|     CONF_ID, | ||||
|     CONF_SAMPLE_RATE, | ||||
|     KEY_CORE, | ||||
|     KEY_FRAMEWORK_VERSION, | ||||
| ) | ||||
| from esphome.const import CONF_BITS_PER_SAMPLE, CONF_CHANNEL, CONF_ID, CONF_SAMPLE_RATE | ||||
| from esphome.core import CORE | ||||
| from esphome.cpp_generator import MockObjClass | ||||
| import esphome.final_validate as fv | ||||
| @@ -250,8 +243,7 @@ def _final_validate(_): | ||||
|  | ||||
|  | ||||
| def use_legacy(): | ||||
|     framework_version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] | ||||
|     if CORE.using_esp_idf and framework_version >= cv.Version(5, 0, 0): | ||||
|     if CORE.using_esp_idf: | ||||
|         if not _use_legacy_driver: | ||||
|             return False | ||||
|     return True | ||||
|   | ||||
| @@ -9,15 +9,11 @@ namespace i2s_audio { | ||||
|  | ||||
| static const char *const TAG = "i2s_audio"; | ||||
|  | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
| static const uint8_t I2S_NUM_MAX = SOC_I2S_NUM;  // because IDF 5+ took this away :( | ||||
| #endif | ||||
|  | ||||
| void I2SAudioComponent::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "Running setup"); | ||||
|  | ||||
|   static i2s_port_t next_port_num = I2S_NUM_0; | ||||
|   if (next_port_num >= I2S_NUM_MAX) { | ||||
|   if (next_port_num >= SOC_I2S_NUM) { | ||||
|     ESP_LOGE(TAG, "Too many components"); | ||||
|     this->mark_failed(); | ||||
|     return; | ||||
|   | ||||
| @@ -59,11 +59,7 @@ optional<uint8_t> ImprovSerialComponent::read_byte_() { | ||||
|       break; | ||||
| #if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC) | ||||
|     case logger::UART_SELECTION_USB_CDC: | ||||
| #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) | ||||
|       if (esp_usb_console_available_for_read()) { | ||||
| #else | ||||
|       if (esp_usb_console_read_available()) { | ||||
| #endif | ||||
|         esp_usb_console_read_buf((char *) &data, 1); | ||||
|         byte = data; | ||||
|       } | ||||
|   | ||||
| @@ -10,11 +10,7 @@ uint8_t temprature_sens_read(); | ||||
| #elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || \ | ||||
|     defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || \ | ||||
|     defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32P4) | ||||
| #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) | ||||
| #include "driver/temp_sensor.h" | ||||
| #else | ||||
| #include "driver/temperature_sensor.h" | ||||
| #endif  // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) | ||||
| #endif  // USE_ESP32_VARIANT | ||||
| #endif  // USE_ESP32 | ||||
| #ifdef USE_RP2040 | ||||
| @@ -31,12 +27,11 @@ namespace internal_temperature { | ||||
|  | ||||
| static const char *const TAG = "internal_temperature"; | ||||
| #ifdef USE_ESP32 | ||||
| #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) && \ | ||||
|     (defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S2) || \ | ||||
|      defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32C2) || \ | ||||
|      defined(USE_ESP32_VARIANT_ESP32P4)) | ||||
| #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S2) || \ | ||||
|     defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32C2) || \ | ||||
|     defined(USE_ESP32_VARIANT_ESP32P4) | ||||
| static temperature_sensor_handle_t tsensNew = NULL; | ||||
| #endif  // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) && USE_ESP32_VARIANT | ||||
| #endif  // USE_ESP32_VARIANT | ||||
| #endif  // USE_ESP32 | ||||
|  | ||||
| void InternalTemperatureSensor::update() { | ||||
| @@ -51,24 +46,11 @@ void InternalTemperatureSensor::update() { | ||||
| #elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || \ | ||||
|     defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || \ | ||||
|     defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32P4) | ||||
| #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) | ||||
|   temp_sensor_config_t tsens = TSENS_CONFIG_DEFAULT(); | ||||
|   temp_sensor_set_config(tsens); | ||||
|   temp_sensor_start(); | ||||
| #if defined(USE_ESP32_VARIANT_ESP32S3) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 3)) | ||||
| #error \ | ||||
|     "ESP32-S3 internal temperature sensor requires ESP IDF V4.4.3 or higher. See https://github.com/esphome/issues/issues/4271" | ||||
| #endif | ||||
|   esp_err_t result = temp_sensor_read_celsius(&temperature); | ||||
|   temp_sensor_stop(); | ||||
|   success = (result == ESP_OK); | ||||
| #else | ||||
|   esp_err_t result = temperature_sensor_get_celsius(tsensNew, &temperature); | ||||
|   success = (result == ESP_OK); | ||||
|   if (!success) { | ||||
|     ESP_LOGE(TAG, "Reading failed (%d)", result); | ||||
|   } | ||||
| #endif  // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) | ||||
| #endif  // USE_ESP32_VARIANT | ||||
| #endif  // USE_ESP32 | ||||
| #ifdef USE_RP2040 | ||||
| @@ -99,10 +81,9 @@ void InternalTemperatureSensor::update() { | ||||
|  | ||||
| void InternalTemperatureSensor::setup() { | ||||
| #ifdef USE_ESP32 | ||||
| #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) && \ | ||||
|     (defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S2) || \ | ||||
|      defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32C2) || \ | ||||
|      defined(USE_ESP32_VARIANT_ESP32P4)) | ||||
| #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S2) || \ | ||||
|     defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32C2) || \ | ||||
|     defined(USE_ESP32_VARIANT_ESP32P4) | ||||
|   ESP_LOGCONFIG(TAG, "Running setup"); | ||||
|  | ||||
|   temperature_sensor_config_t tsens_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80); | ||||
| @@ -120,7 +101,7 @@ void InternalTemperatureSensor::setup() { | ||||
|     this->mark_failed(); | ||||
|     return; | ||||
|   } | ||||
| #endif  // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) && USE_ESP32_VARIANT | ||||
| #endif  // USE_ESP32_VARIANT | ||||
| #endif  // USE_ESP32 | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,46 +1,21 @@ | ||||
| import esphome.codegen as cg | ||||
| from esphome.components import sensor | ||||
| from esphome.components.esp32 import get_esp32_variant | ||||
| from esphome.components.esp32.const import VARIANT_ESP32S3 | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import ( | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     ENTITY_CATEGORY_DIAGNOSTIC, | ||||
|     KEY_CORE, | ||||
|     KEY_FRAMEWORK_VERSION, | ||||
|     PLATFORM_BK72XX, | ||||
|     PLATFORM_ESP32, | ||||
|     PLATFORM_RP2040, | ||||
|     STATE_CLASS_MEASUREMENT, | ||||
|     UNIT_CELSIUS, | ||||
| ) | ||||
| from esphome.core import CORE | ||||
|  | ||||
| internal_temperature_ns = cg.esphome_ns.namespace("internal_temperature") | ||||
| InternalTemperatureSensor = internal_temperature_ns.class_( | ||||
|     "InternalTemperatureSensor", sensor.Sensor, cg.PollingComponent | ||||
| ) | ||||
|  | ||||
|  | ||||
| def validate_config(config): | ||||
|     if CORE.is_esp32: | ||||
|         variant = get_esp32_variant() | ||||
|         if variant == VARIANT_ESP32S3: | ||||
|             if CORE.using_arduino and CORE.data[KEY_CORE][ | ||||
|                 KEY_FRAMEWORK_VERSION | ||||
|             ] < cv.Version(2, 0, 6): | ||||
|                 raise cv.Invalid( | ||||
|                     "ESP32-S3 Internal Temperature Sensor requires framework version 2.0.6 or higher. See <https://github.com/esphome/issues/issues/4271>." | ||||
|                 ) | ||||
|             if CORE.using_esp_idf and CORE.data[KEY_CORE][ | ||||
|                 KEY_FRAMEWORK_VERSION | ||||
|             ] < cv.Version(4, 4, 3): | ||||
|                 raise cv.Invalid( | ||||
|                     "ESP32-S3 Internal Temperature Sensor requires framework version 4.4.3 or higher. See <https://github.com/esphome/issues/issues/4271>." | ||||
|                 ) | ||||
|     return config | ||||
|  | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     sensor.sensor_schema( | ||||
|         InternalTemperatureSensor, | ||||
| @@ -51,7 +26,6 @@ CONFIG_SCHEMA = cv.All( | ||||
|         entity_category=ENTITY_CATEGORY_DIAGNOSTIC, | ||||
|     ).extend(cv.polling_component_schema("60s")), | ||||
|     cv.only_on([PLATFORM_ESP32, PLATFORM_RP2040, PLATFORM_BK72XX]), | ||||
|     validate_config, | ||||
| ) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -83,9 +83,7 @@ void init_uart(uart_port_t uart_num, uint32_t baud_rate, int tx_buffer_size) { | ||||
|   uart_config.parity = UART_PARITY_DISABLE; | ||||
|   uart_config.stop_bits = UART_STOP_BITS_1; | ||||
|   uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; | ||||
| #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) | ||||
|   uart_config.source_clk = UART_SCLK_DEFAULT; | ||||
| #endif | ||||
|   uart_param_config(uart_num, &uart_config); | ||||
|   const int uart_buffer_size = tx_buffer_size; | ||||
|   // Install UART driver using an event queue here | ||||
|   | ||||
| @@ -8,8 +8,6 @@ from esphome.const import ( | ||||
|     CONF_PROTOCOL, | ||||
|     CONF_SERVICE, | ||||
|     CONF_SERVICES, | ||||
|     KEY_CORE, | ||||
|     KEY_FRAMEWORK_VERSION, | ||||
| ) | ||||
| from esphome.core import CORE, coroutine_with_priority | ||||
|  | ||||
| @@ -85,9 +83,7 @@ async def to_code(config): | ||||
|         elif CORE.is_rp2040: | ||||
|             cg.add_library("LEAmDNS", None) | ||||
|  | ||||
|     if CORE.using_esp_idf and CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version( | ||||
|         5, 0, 0 | ||||
|     ): | ||||
|     if CORE.using_esp_idf: | ||||
|         add_idf_component(name="espressif/mdns", ref="1.8.2") | ||||
|  | ||||
|     cg.add_define("USE_MDNS") | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
| #include "esphome/components/audio/audio_transfer_buffer.h" | ||||
|  | ||||
| #ifdef USE_OTA | ||||
| #include "esphome/components/ota/ota_backend.h" | ||||
| #include "esphome/components/ota_base/ota_backend.h" | ||||
| #endif | ||||
|  | ||||
| namespace esphome { | ||||
| @@ -121,11 +121,11 @@ void MicroWakeWord::setup() { | ||||
|   }); | ||||
|  | ||||
| #ifdef USE_OTA | ||||
|   ota::get_global_ota_callback()->add_on_state_callback( | ||||
|       [this](ota::OTAState state, float progress, uint8_t error, ota::OTAComponent *comp) { | ||||
|         if (state == ota::OTA_STARTED) { | ||||
|   ota_base::get_global_ota_callback()->add_on_state_callback( | ||||
|       [this](ota_base::OTAState state, float progress, uint8_t error, ota_base::OTAComponent *comp) { | ||||
|         if (state == ota_base::OTA_STARTED) { | ||||
|           this->suspend_task_(); | ||||
|         } else if (state == ota::OTA_ERROR) { | ||||
|         } else if (state == ota_base::OTA_ERROR) { | ||||
|           this->resume_task_(); | ||||
|         } | ||||
|       }); | ||||
|   | ||||
| @@ -14,49 +14,6 @@ namespace mqtt { | ||||
| static const char *const TAG = "mqtt.idf"; | ||||
|  | ||||
| bool MQTTBackendESP32::initialize_() { | ||||
| #if ESP_IDF_VERSION_MAJOR < 5 | ||||
|   mqtt_cfg_.user_context = (void *) this; | ||||
|   mqtt_cfg_.buffer_size = MQTT_BUFFER_SIZE; | ||||
|  | ||||
|   mqtt_cfg_.host = this->host_.c_str(); | ||||
|   mqtt_cfg_.port = this->port_; | ||||
|   mqtt_cfg_.keepalive = this->keep_alive_; | ||||
|   mqtt_cfg_.disable_clean_session = !this->clean_session_; | ||||
|  | ||||
|   if (!this->username_.empty()) { | ||||
|     mqtt_cfg_.username = this->username_.c_str(); | ||||
|     if (!this->password_.empty()) { | ||||
|       mqtt_cfg_.password = this->password_.c_str(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (!this->lwt_topic_.empty()) { | ||||
|     mqtt_cfg_.lwt_topic = this->lwt_topic_.c_str(); | ||||
|     this->mqtt_cfg_.lwt_qos = this->lwt_qos_; | ||||
|     this->mqtt_cfg_.lwt_retain = this->lwt_retain_; | ||||
|  | ||||
|     if (!this->lwt_message_.empty()) { | ||||
|       mqtt_cfg_.lwt_msg = this->lwt_message_.c_str(); | ||||
|       mqtt_cfg_.lwt_msg_len = this->lwt_message_.size(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (!this->client_id_.empty()) { | ||||
|     mqtt_cfg_.client_id = this->client_id_.c_str(); | ||||
|   } | ||||
|   if (ca_certificate_.has_value()) { | ||||
|     mqtt_cfg_.cert_pem = ca_certificate_.value().c_str(); | ||||
|     mqtt_cfg_.skip_cert_common_name_check = skip_cert_cn_check_; | ||||
|     mqtt_cfg_.transport = MQTT_TRANSPORT_OVER_SSL; | ||||
|  | ||||
|     if (this->cl_certificate_.has_value() && this->cl_key_.has_value()) { | ||||
|       mqtt_cfg_.client_cert_pem = this->cl_certificate_.value().c_str(); | ||||
|       mqtt_cfg_.client_key_pem = this->cl_key_.value().c_str(); | ||||
|     } | ||||
|   } else { | ||||
|     mqtt_cfg_.transport = MQTT_TRANSPORT_OVER_TCP; | ||||
|   } | ||||
| #else | ||||
|   mqtt_cfg_.broker.address.hostname = this->host_.c_str(); | ||||
|   mqtt_cfg_.broker.address.port = this->port_; | ||||
|   mqtt_cfg_.session.keepalive = this->keep_alive_; | ||||
| @@ -95,7 +52,7 @@ bool MQTTBackendESP32::initialize_() { | ||||
|   } else { | ||||
|     mqtt_cfg_.broker.address.transport = MQTT_TRANSPORT_OVER_TCP; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   auto *mqtt_client = esp_mqtt_client_init(&mqtt_cfg_); | ||||
|   if (mqtt_client) { | ||||
|     handler_.reset(mqtt_client); | ||||
|   | ||||
| @@ -272,18 +272,13 @@ bool OpenTherm::init_esp32_timer_() { | ||||
|   this->timer_idx_ = timer_idx; | ||||
|  | ||||
|   timer_config_t const config = { | ||||
|     .alarm_en = TIMER_ALARM_EN, | ||||
|     .counter_en = TIMER_PAUSE, | ||||
|     .intr_type = TIMER_INTR_LEVEL, | ||||
|     .counter_dir = TIMER_COUNT_UP, | ||||
|     .auto_reload = TIMER_AUTORELOAD_EN, | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|     .clk_src = TIMER_SRC_CLK_DEFAULT, | ||||
| #endif | ||||
|     .divider = 80, | ||||
| #if defined(SOC_TIMER_GROUP_SUPPORT_XTAL) && ESP_IDF_VERSION_MAJOR < 5 | ||||
|     .clk_src = TIMER_SRC_CLK_APB | ||||
| #endif | ||||
|       .alarm_en = TIMER_ALARM_EN, | ||||
|       .counter_en = TIMER_PAUSE, | ||||
|       .intr_type = TIMER_INTR_LEVEL, | ||||
|       .counter_dir = TIMER_COUNT_UP, | ||||
|       .auto_reload = TIMER_AUTORELOAD_EN, | ||||
|       .clk_src = TIMER_SRC_CLK_DEFAULT, | ||||
|       .divider = 80, | ||||
|   }; | ||||
|  | ||||
|   esp_err_t result; | ||||
|   | ||||
| @@ -8,10 +8,12 @@ from esphome.const import ( | ||||
|     CONF_PLATFORM, | ||||
|     CONF_TRIGGER_ID, | ||||
| ) | ||||
| from esphome.core import CORE, coroutine_with_priority | ||||
| from esphome.core import coroutine_with_priority | ||||
|  | ||||
| from ..ota_base import OTAState | ||||
|  | ||||
| CODEOWNERS = ["@esphome/core"] | ||||
| AUTO_LOAD = ["md5", "safe_mode"] | ||||
| AUTO_LOAD = ["safe_mode", "ota_base"] | ||||
|  | ||||
| IS_PLATFORM_COMPONENT = True | ||||
|  | ||||
| @@ -23,8 +25,6 @@ CONF_ON_STATE_CHANGE = "on_state_change" | ||||
|  | ||||
|  | ||||
| ota_ns = cg.esphome_ns.namespace("ota") | ||||
| OTAComponent = ota_ns.class_("OTAComponent", cg.Component) | ||||
| OTAState = ota_ns.enum("OTAState") | ||||
| OTAAbortTrigger = ota_ns.class_("OTAAbortTrigger", automation.Trigger.template()) | ||||
| OTAEndTrigger = ota_ns.class_("OTAEndTrigger", automation.Trigger.template()) | ||||
| OTAErrorTrigger = ota_ns.class_("OTAErrorTrigger", automation.Trigger.template()) | ||||
| @@ -84,12 +84,6 @@ BASE_OTA_SCHEMA = cv.Schema( | ||||
| async def to_code(config): | ||||
|     cg.add_define("USE_OTA") | ||||
|  | ||||
|     if CORE.is_esp32 and CORE.using_arduino: | ||||
|         cg.add_library("Update", None) | ||||
|  | ||||
|     if CORE.is_rp2040 and CORE.using_arduino: | ||||
|         cg.add_library("Updater", None) | ||||
|  | ||||
|  | ||||
| async def ota_to_code(var, config): | ||||
|     await cg.past_safe_mode() | ||||
|   | ||||
| @@ -1,12 +1,16 @@ | ||||
| #pragma once | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
| #include "ota_backend.h" | ||||
| #include "esphome/components/ota_base/ota_backend.h" | ||||
|  | ||||
| #include "esphome/core/automation.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
|  | ||||
| // Import types from ota_base for the automation triggers | ||||
| using ota_base::OTAComponent; | ||||
| using ota_base::OTAState; | ||||
|  | ||||
| class OTAStateChangeTrigger : public Trigger<OTAState> { | ||||
|  public: | ||||
|   explicit OTAStateChangeTrigger(OTAComponent *parent) { | ||||
| @@ -22,7 +26,7 @@ class OTAStartTrigger : public Trigger<> { | ||||
|  public: | ||||
|   explicit OTAStartTrigger(OTAComponent *parent) { | ||||
|     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { | ||||
|       if (state == OTA_STARTED && !parent->is_failed()) { | ||||
|       if (state == ota_base::OTA_STARTED && !parent->is_failed()) { | ||||
|         trigger(); | ||||
|       } | ||||
|     }); | ||||
| @@ -33,7 +37,7 @@ class OTAProgressTrigger : public Trigger<float> { | ||||
|  public: | ||||
|   explicit OTAProgressTrigger(OTAComponent *parent) { | ||||
|     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { | ||||
|       if (state == OTA_IN_PROGRESS && !parent->is_failed()) { | ||||
|       if (state == ota_base::OTA_IN_PROGRESS && !parent->is_failed()) { | ||||
|         trigger(progress); | ||||
|       } | ||||
|     }); | ||||
| @@ -44,7 +48,7 @@ class OTAEndTrigger : public Trigger<> { | ||||
|  public: | ||||
|   explicit OTAEndTrigger(OTAComponent *parent) { | ||||
|     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { | ||||
|       if (state == OTA_COMPLETED && !parent->is_failed()) { | ||||
|       if (state == ota_base::OTA_COMPLETED && !parent->is_failed()) { | ||||
|         trigger(); | ||||
|       } | ||||
|     }); | ||||
| @@ -55,7 +59,7 @@ class OTAAbortTrigger : public Trigger<> { | ||||
|  public: | ||||
|   explicit OTAAbortTrigger(OTAComponent *parent) { | ||||
|     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { | ||||
|       if (state == OTA_ABORT && !parent->is_failed()) { | ||||
|       if (state == ota_base::OTA_ABORT && !parent->is_failed()) { | ||||
|         trigger(); | ||||
|       } | ||||
|     }); | ||||
| @@ -66,7 +70,7 @@ class OTAErrorTrigger : public Trigger<uint8_t> { | ||||
|  public: | ||||
|   explicit OTAErrorTrigger(OTAComponent *parent) { | ||||
|     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { | ||||
|       if (state == OTA_ERROR && !parent->is_failed()) { | ||||
|       if (state == ota_base::OTA_ERROR && !parent->is_failed()) { | ||||
|         trigger(error); | ||||
|       } | ||||
|     }); | ||||
|   | ||||
							
								
								
									
										23
									
								
								esphome/components/ota_base/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								esphome/components/ota_base/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| import esphome.codegen as cg | ||||
| from esphome.core import CORE, coroutine_with_priority | ||||
|  | ||||
| CODEOWNERS = ["@esphome/core"] | ||||
| AUTO_LOAD = ["md5"] | ||||
|  | ||||
| ota_base_ns = cg.esphome_ns.namespace("ota_base") | ||||
| OTAComponent = ota_base_ns.class_("OTAComponent", cg.Component) | ||||
| OTAState = ota_base_ns.enum("OTAState") | ||||
|  | ||||
|  | ||||
| @coroutine_with_priority(52.0) | ||||
| async def to_code(config): | ||||
|     # Note: USE_OTA_STATE_CALLBACK is not defined here | ||||
|     # Components that need OTA callbacks (like esp32_ble_tracker, speaker, etc.) | ||||
|     # define USE_OTA_STATE_CALLBACK themselves in their own __init__.py files | ||||
|     # This ensures the callback functionality is only compiled when actually needed | ||||
|  | ||||
|     if CORE.is_esp32 and CORE.using_arduino: | ||||
|         cg.add_library("Update", None) | ||||
|  | ||||
|     if CORE.is_rp2040 and CORE.using_arduino: | ||||
|         cg.add_library("Updater", None) | ||||
| @@ -1,7 +1,9 @@ | ||||
| #include "ota_backend.h" | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
| namespace ota_base { | ||||
| 
 | ||||
| // The make_ota_backend() implementation is provided by each platform-specific backend
 | ||||
| 
 | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
| OTAGlobalCallback *global_ota_callback{nullptr};  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
 | ||||
| @@ -16,5 +18,5 @@ OTAGlobalCallback *get_global_ota_callback() { | ||||
| void register_ota_platform(OTAComponent *ota_caller) { get_global_ota_callback()->register_ota(ota_caller); } | ||||
| #endif | ||||
| 
 | ||||
| }  // namespace ota
 | ||||
| }  // namespace ota_base
 | ||||
| }  // namespace esphome
 | ||||
| @@ -9,7 +9,7 @@ | ||||
| #endif | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
| namespace ota_base { | ||||
| 
 | ||||
| enum OTAResponseTypes { | ||||
|   OTA_RESPONSE_OK = 0x00, | ||||
| @@ -59,15 +59,38 @@ class OTABackend { | ||||
|   virtual bool supports_compression() = 0; | ||||
| }; | ||||
| 
 | ||||
| std::unique_ptr<OTABackend> make_ota_backend(); | ||||
| 
 | ||||
| class OTAComponent : public Component { | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|  public: | ||||
|   void add_on_state_callback(std::function<void(ota::OTAState, float, uint8_t)> &&callback) { | ||||
|   void add_on_state_callback(std::function<void(OTAState, float, uint8_t)> &&callback) { | ||||
|     this->state_callback_.add(std::move(callback)); | ||||
|   } | ||||
| 
 | ||||
|  protected: | ||||
|   CallbackManager<void(ota::OTAState, float, uint8_t)> state_callback_{}; | ||||
|   /** Extended callback manager with deferred call support.
 | ||||
|    * | ||||
|    * This adds a call_deferred() method for thread-safe execution from other tasks. | ||||
|    */ | ||||
|   class StateCallbackManager : public CallbackManager<void(OTAState, float, uint8_t)> { | ||||
|    public: | ||||
|     StateCallbackManager(OTAComponent *component) : component_(component) {} | ||||
| 
 | ||||
|     /** Call callbacks with deferral to main loop (for thread safety).
 | ||||
|      * | ||||
|      * This should be used by OTA implementations that run in separate tasks | ||||
|      * (like web_server OTA) to ensure callbacks execute in the main loop. | ||||
|      */ | ||||
|     void call_deferred(OTAState state, float progress, uint8_t error) { | ||||
|       component_->defer([this, state, progress, error]() { this->call(state, progress, error); }); | ||||
|     } | ||||
| 
 | ||||
|    private: | ||||
|     OTAComponent *component_; | ||||
|   }; | ||||
| 
 | ||||
|   StateCallbackManager state_callback_{this}; | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| @@ -89,8 +112,12 @@ class OTAGlobalCallback { | ||||
| 
 | ||||
| OTAGlobalCallback *get_global_ota_callback(); | ||||
| void register_ota_platform(OTAComponent *ota_caller); | ||||
| #endif | ||||
| std::unique_ptr<ota::OTABackend> make_ota_backend(); | ||||
| 
 | ||||
| }  // namespace ota
 | ||||
| // OTA implementations should use:
 | ||||
| // - state_callback_.call() when already in main loop (e.g., esphome OTA)
 | ||||
| // - state_callback_.call_deferred() when in separate task (e.g., web_server OTA)
 | ||||
| // This ensures proper callback execution in all contexts.
 | ||||
| #endif | ||||
| 
 | ||||
| }  // namespace ota_base
 | ||||
| }  // namespace esphome
 | ||||
| @@ -8,13 +8,18 @@ | ||||
| #include <Update.h> | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
| namespace ota_base { | ||||
| 
 | ||||
| static const char *const TAG = "ota.arduino_esp32"; | ||||
| 
 | ||||
| std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoESP32OTABackend>(); } | ||||
| std::unique_ptr<OTABackend> make_ota_backend() { return make_unique<ArduinoESP32OTABackend>(); } | ||||
| 
 | ||||
| OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) { | ||||
|   // Handle UPDATE_SIZE_UNKNOWN (0) which is used by web server OTA
 | ||||
|   // where the exact firmware size is unknown due to multipart encoding
 | ||||
|   if (image_size == 0) { | ||||
|     image_size = UPDATE_SIZE_UNKNOWN; | ||||
|   } | ||||
|   bool ret = Update.begin(image_size, U_FLASH); | ||||
|   if (ret) { | ||||
|     return OTA_RESPONSE_OK; | ||||
| @@ -29,7 +34,10 @@ OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) { | ||||
|   return OTA_RESPONSE_ERROR_UNKNOWN; | ||||
| } | ||||
| 
 | ||||
| void ArduinoESP32OTABackend::set_update_md5(const char *md5) { Update.setMD5(md5); } | ||||
| void ArduinoESP32OTABackend::set_update_md5(const char *md5) { | ||||
|   Update.setMD5(md5); | ||||
|   this->md5_set_ = true; | ||||
| } | ||||
| 
 | ||||
| OTAResponseTypes ArduinoESP32OTABackend::write(uint8_t *data, size_t len) { | ||||
|   size_t written = Update.write(data, len); | ||||
| @@ -44,7 +52,9 @@ OTAResponseTypes ArduinoESP32OTABackend::write(uint8_t *data, size_t len) { | ||||
| } | ||||
| 
 | ||||
| OTAResponseTypes ArduinoESP32OTABackend::end() { | ||||
|   if (Update.end()) { | ||||
|   // Use strict validation (false) when MD5 is set, lenient validation (true) when no MD5
 | ||||
|   // This matches the behavior of the old web_server OTA implementation
 | ||||
|   if (Update.end(!this->md5_set_)) { | ||||
|     return OTA_RESPONSE_OK; | ||||
|   } | ||||
| 
 | ||||
| @@ -56,7 +66,7 @@ OTAResponseTypes ArduinoESP32OTABackend::end() { | ||||
| 
 | ||||
| void ArduinoESP32OTABackend::abort() { Update.abort(); } | ||||
| 
 | ||||
| }  // namespace ota
 | ||||
| }  // namespace ota_base
 | ||||
| }  // namespace esphome
 | ||||
| 
 | ||||
| #endif  // USE_ESP32_FRAMEWORK_ARDUINO
 | ||||
| @@ -6,7 +6,7 @@ | ||||
| #include "esphome/core/helpers.h" | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
| namespace ota_base { | ||||
| 
 | ||||
| class ArduinoESP32OTABackend : public OTABackend { | ||||
|  public: | ||||
| @@ -16,9 +16,12 @@ class ArduinoESP32OTABackend : public OTABackend { | ||||
|   OTAResponseTypes end() override; | ||||
|   void abort() override; | ||||
|   bool supports_compression() override { return false; } | ||||
| 
 | ||||
|  private: | ||||
|   bool md5_set_{false}; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace ota
 | ||||
| }  // namespace ota_base
 | ||||
| }  // namespace esphome
 | ||||
| 
 | ||||
| #endif  // USE_ESP32_FRAMEWORK_ARDUINO
 | ||||
| @@ -10,13 +10,18 @@ | ||||
| #include <Updater.h> | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
| namespace ota_base { | ||||
| 
 | ||||
| static const char *const TAG = "ota.arduino_esp8266"; | ||||
| 
 | ||||
| std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoESP8266OTABackend>(); } | ||||
| std::unique_ptr<OTABackend> make_ota_backend() { return make_unique<ArduinoESP8266OTABackend>(); } | ||||
| 
 | ||||
| OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) { | ||||
|   // Handle UPDATE_SIZE_UNKNOWN (0) by calculating available space
 | ||||
|   if (image_size == 0) { | ||||
|     // NOLINTNEXTLINE(readability-static-accessed-through-instance)
 | ||||
|     image_size = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; | ||||
|   } | ||||
|   bool ret = Update.begin(image_size, U_FLASH); | ||||
|   if (ret) { | ||||
|     esp8266::preferences_prevent_write(true); | ||||
| @@ -38,7 +43,10 @@ OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) { | ||||
|   return OTA_RESPONSE_ERROR_UNKNOWN; | ||||
| } | ||||
| 
 | ||||
| void ArduinoESP8266OTABackend::set_update_md5(const char *md5) { Update.setMD5(md5); } | ||||
| void ArduinoESP8266OTABackend::set_update_md5(const char *md5) { | ||||
|   Update.setMD5(md5); | ||||
|   this->md5_set_ = true; | ||||
| } | ||||
| 
 | ||||
| OTAResponseTypes ArduinoESP8266OTABackend::write(uint8_t *data, size_t len) { | ||||
|   size_t written = Update.write(data, len); | ||||
| @@ -53,13 +61,19 @@ OTAResponseTypes ArduinoESP8266OTABackend::write(uint8_t *data, size_t len) { | ||||
| } | ||||
| 
 | ||||
| OTAResponseTypes ArduinoESP8266OTABackend::end() { | ||||
|   if (Update.end()) { | ||||
|   // Use strict validation (false) when MD5 is set, lenient validation (true) when no MD5
 | ||||
|   // This matches the behavior of the old web_server OTA implementation
 | ||||
|   bool success = Update.end(!this->md5_set_); | ||||
| 
 | ||||
|   // On ESP8266, Update.end() might return false even with error code 0
 | ||||
|   // Check the actual error code to determine success
 | ||||
|   uint8_t error = Update.getError(); | ||||
| 
 | ||||
|   if (success || error == UPDATE_ERROR_OK) { | ||||
|     return OTA_RESPONSE_OK; | ||||
|   } | ||||
| 
 | ||||
|   uint8_t error = Update.getError(); | ||||
|   ESP_LOGE(TAG, "End error: %d", error); | ||||
| 
 | ||||
|   return OTA_RESPONSE_ERROR_UPDATE_END; | ||||
| } | ||||
| 
 | ||||
| @@ -68,7 +82,7 @@ void ArduinoESP8266OTABackend::abort() { | ||||
|   esp8266::preferences_prevent_write(false); | ||||
| } | ||||
| 
 | ||||
| }  // namespace ota
 | ||||
| }  // namespace ota_base
 | ||||
| }  // namespace esphome
 | ||||
| 
 | ||||
| #endif | ||||
| @@ -7,7 +7,7 @@ | ||||
| #include "esphome/core/macros.h" | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
| namespace ota_base { | ||||
| 
 | ||||
| class ArduinoESP8266OTABackend : public OTABackend { | ||||
|  public: | ||||
| @@ -21,9 +21,12 @@ class ArduinoESP8266OTABackend : public OTABackend { | ||||
| #else | ||||
|   bool supports_compression() override { return false; } | ||||
| #endif | ||||
| 
 | ||||
|  private: | ||||
|   bool md5_set_{false}; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace ota
 | ||||
| }  // namespace ota_base
 | ||||
| }  // namespace esphome
 | ||||
| 
 | ||||
| #endif | ||||
| @@ -8,13 +8,18 @@ | ||||
| #include <Update.h> | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
| namespace ota_base { | ||||
| 
 | ||||
| static const char *const TAG = "ota.arduino_libretiny"; | ||||
| 
 | ||||
| std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoLibreTinyOTABackend>(); } | ||||
| std::unique_ptr<OTABackend> make_ota_backend() { return make_unique<ArduinoLibreTinyOTABackend>(); } | ||||
| 
 | ||||
| OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) { | ||||
|   // Handle UPDATE_SIZE_UNKNOWN (0) which is used by web server OTA
 | ||||
|   // where the exact firmware size is unknown due to multipart encoding
 | ||||
|   if (image_size == 0) { | ||||
|     image_size = UPDATE_SIZE_UNKNOWN; | ||||
|   } | ||||
|   bool ret = Update.begin(image_size, U_FLASH); | ||||
|   if (ret) { | ||||
|     return OTA_RESPONSE_OK; | ||||
| @@ -29,7 +34,10 @@ OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) { | ||||
|   return OTA_RESPONSE_ERROR_UNKNOWN; | ||||
| } | ||||
| 
 | ||||
| void ArduinoLibreTinyOTABackend::set_update_md5(const char *md5) { Update.setMD5(md5); } | ||||
| void ArduinoLibreTinyOTABackend::set_update_md5(const char *md5) { | ||||
|   Update.setMD5(md5); | ||||
|   this->md5_set_ = true; | ||||
| } | ||||
| 
 | ||||
| OTAResponseTypes ArduinoLibreTinyOTABackend::write(uint8_t *data, size_t len) { | ||||
|   size_t written = Update.write(data, len); | ||||
| @@ -44,7 +52,9 @@ OTAResponseTypes ArduinoLibreTinyOTABackend::write(uint8_t *data, size_t len) { | ||||
| } | ||||
| 
 | ||||
| OTAResponseTypes ArduinoLibreTinyOTABackend::end() { | ||||
|   if (Update.end()) { | ||||
|   // Use strict validation (false) when MD5 is set, lenient validation (true) when no MD5
 | ||||
|   // This matches the behavior of the old web_server OTA implementation
 | ||||
|   if (Update.end(!this->md5_set_)) { | ||||
|     return OTA_RESPONSE_OK; | ||||
|   } | ||||
| 
 | ||||
| @@ -56,7 +66,7 @@ OTAResponseTypes ArduinoLibreTinyOTABackend::end() { | ||||
| 
 | ||||
| void ArduinoLibreTinyOTABackend::abort() { Update.abort(); } | ||||
| 
 | ||||
| }  // namespace ota
 | ||||
| }  // namespace ota_base
 | ||||
| }  // namespace esphome
 | ||||
| 
 | ||||
| #endif  // USE_LIBRETINY
 | ||||
| @@ -5,7 +5,7 @@ | ||||
| #include "esphome/core/defines.h" | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
| namespace ota_base { | ||||
| 
 | ||||
| class ArduinoLibreTinyOTABackend : public OTABackend { | ||||
|  public: | ||||
| @@ -15,9 +15,12 @@ class ArduinoLibreTinyOTABackend : public OTABackend { | ||||
|   OTAResponseTypes end() override; | ||||
|   void abort() override; | ||||
|   bool supports_compression() override { return false; } | ||||
| 
 | ||||
|  private: | ||||
|   bool md5_set_{false}; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace ota
 | ||||
| }  // namespace ota_base
 | ||||
| }  // namespace esphome
 | ||||
| 
 | ||||
| #endif  // USE_LIBRETINY
 | ||||
| @@ -10,13 +10,24 @@ | ||||
| #include <Updater.h> | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
| namespace ota_base { | ||||
| 
 | ||||
| static const char *const TAG = "ota.arduino_rp2040"; | ||||
| 
 | ||||
| std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoRP2040OTABackend>(); } | ||||
| std::unique_ptr<OTABackend> make_ota_backend() { return make_unique<ArduinoRP2040OTABackend>(); } | ||||
| 
 | ||||
| OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) { | ||||
|   // Handle UPDATE_SIZE_UNKNOWN (0) by calculating available space
 | ||||
|   if (image_size == 0) { | ||||
|     // Similar to ESP8266, calculate available space from flash layout
 | ||||
|     extern uint8_t _FS_start; | ||||
|     extern uint8_t _FS_end; | ||||
|     // Calculate the size of the filesystem area which will be used for OTA
 | ||||
|     size_t fs_size = &_FS_end - &_FS_start; | ||||
|     // Reserve some space for filesystem overhead
 | ||||
|     image_size = (fs_size - 0x1000) & 0xFFFFF000; | ||||
|     ESP_LOGD(TAG, "OTA size unknown, using filesystem size: %u bytes", image_size); | ||||
|   } | ||||
|   bool ret = Update.begin(image_size, U_FLASH); | ||||
|   if (ret) { | ||||
|     rp2040::preferences_prevent_write(true); | ||||
| @@ -38,7 +49,10 @@ OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) { | ||||
|   return OTA_RESPONSE_ERROR_UNKNOWN; | ||||
| } | ||||
| 
 | ||||
| void ArduinoRP2040OTABackend::set_update_md5(const char *md5) { Update.setMD5(md5); } | ||||
| void ArduinoRP2040OTABackend::set_update_md5(const char *md5) { | ||||
|   Update.setMD5(md5); | ||||
|   this->md5_set_ = true; | ||||
| } | ||||
| 
 | ||||
| OTAResponseTypes ArduinoRP2040OTABackend::write(uint8_t *data, size_t len) { | ||||
|   size_t written = Update.write(data, len); | ||||
| @@ -53,7 +67,9 @@ OTAResponseTypes ArduinoRP2040OTABackend::write(uint8_t *data, size_t len) { | ||||
| } | ||||
| 
 | ||||
| OTAResponseTypes ArduinoRP2040OTABackend::end() { | ||||
|   if (Update.end()) { | ||||
|   // Use strict validation (false) when MD5 is set, lenient validation (true) when no MD5
 | ||||
|   // This matches the behavior of the old web_server OTA implementation
 | ||||
|   if (Update.end(!this->md5_set_)) { | ||||
|     return OTA_RESPONSE_OK; | ||||
|   } | ||||
| 
 | ||||
| @@ -68,7 +84,7 @@ void ArduinoRP2040OTABackend::abort() { | ||||
|   rp2040::preferences_prevent_write(false); | ||||
| } | ||||
| 
 | ||||
| }  // namespace ota
 | ||||
| }  // namespace ota_base
 | ||||
| }  // namespace esphome
 | ||||
| 
 | ||||
| #endif  // USE_RP2040
 | ||||
| @@ -7,7 +7,7 @@ | ||||
| #include "esphome/core/macros.h" | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
| namespace ota_base { | ||||
| 
 | ||||
| class ArduinoRP2040OTABackend : public OTABackend { | ||||
|  public: | ||||
| @@ -17,9 +17,12 @@ class ArduinoRP2040OTABackend : public OTABackend { | ||||
|   OTAResponseTypes end() override; | ||||
|   void abort() override; | ||||
|   bool supports_compression() override { return false; } | ||||
| 
 | ||||
|  private: | ||||
|   bool md5_set_{false}; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace ota
 | ||||
| }  // namespace ota_base
 | ||||
| }  // namespace esphome
 | ||||
| 
 | ||||
| #endif  // USE_RP2040
 | ||||
| @@ -6,15 +6,12 @@ | ||||
| 
 | ||||
| #include <esp_ota_ops.h> | ||||
| #include <esp_task_wdt.h> | ||||
| 
 | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
| #include <spi_flash_mmap.h> | ||||
| #endif | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
| namespace ota_base { | ||||
| 
 | ||||
| std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::IDFOTABackend>(); } | ||||
| std::unique_ptr<OTABackend> make_ota_backend() { return make_unique<IDFOTABackend>(); } | ||||
| 
 | ||||
| OTAResponseTypes IDFOTABackend::begin(size_t image_size) { | ||||
|   this->partition_ = esp_ota_get_next_update_partition(nullptr); | ||||
| @@ -24,7 +21,6 @@ OTAResponseTypes IDFOTABackend::begin(size_t image_size) { | ||||
| 
 | ||||
| #if CONFIG_ESP_TASK_WDT_TIMEOUT_S < 15 | ||||
|   // The following function takes longer than the 5 seconds timeout of WDT
 | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|   esp_task_wdt_config_t wdtc; | ||||
|   wdtc.idle_core_mask = 0; | ||||
| #if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 | ||||
| @@ -36,21 +32,14 @@ OTAResponseTypes IDFOTABackend::begin(size_t image_size) { | ||||
|   wdtc.timeout_ms = 15000; | ||||
|   wdtc.trigger_panic = false; | ||||
|   esp_task_wdt_reconfigure(&wdtc); | ||||
| #else | ||||
|   esp_task_wdt_init(15, false); | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
|   esp_err_t err = esp_ota_begin(this->partition_, image_size, &this->update_handle_); | ||||
| 
 | ||||
| #if CONFIG_ESP_TASK_WDT_TIMEOUT_S < 15 | ||||
|   // Set the WDT back to the configured timeout
 | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|   wdtc.timeout_ms = CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000; | ||||
|   esp_task_wdt_reconfigure(&wdtc); | ||||
| #else | ||||
|   esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false); | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
|   if (err != ESP_OK) { | ||||
| @@ -67,7 +56,10 @@ OTAResponseTypes IDFOTABackend::begin(size_t image_size) { | ||||
|   return OTA_RESPONSE_OK; | ||||
| } | ||||
| 
 | ||||
| void IDFOTABackend::set_update_md5(const char *expected_md5) { memcpy(this->expected_bin_md5_, expected_md5, 32); } | ||||
| void IDFOTABackend::set_update_md5(const char *expected_md5) { | ||||
|   memcpy(this->expected_bin_md5_, expected_md5, 32); | ||||
|   this->md5_set_ = true; | ||||
| } | ||||
| 
 | ||||
| OTAResponseTypes IDFOTABackend::write(uint8_t *data, size_t len) { | ||||
|   esp_err_t err = esp_ota_write(this->update_handle_, data, len); | ||||
| @@ -84,10 +76,12 @@ OTAResponseTypes IDFOTABackend::write(uint8_t *data, size_t len) { | ||||
| } | ||||
| 
 | ||||
| OTAResponseTypes IDFOTABackend::end() { | ||||
|   this->md5_.calculate(); | ||||
|   if (!this->md5_.equals_hex(this->expected_bin_md5_)) { | ||||
|     this->abort(); | ||||
|     return OTA_RESPONSE_ERROR_MD5_MISMATCH; | ||||
|   if (this->md5_set_) { | ||||
|     this->md5_.calculate(); | ||||
|     if (!this->md5_.equals_hex(this->expected_bin_md5_)) { | ||||
|       this->abort(); | ||||
|       return OTA_RESPONSE_ERROR_MD5_MISMATCH; | ||||
|     } | ||||
|   } | ||||
|   esp_err_t err = esp_ota_end(this->update_handle_); | ||||
|   this->update_handle_ = 0; | ||||
| @@ -111,6 +105,6 @@ void IDFOTABackend::abort() { | ||||
|   this->update_handle_ = 0; | ||||
| } | ||||
| 
 | ||||
| }  // namespace ota
 | ||||
| }  // namespace ota_base
 | ||||
| }  // namespace esphome
 | ||||
| #endif | ||||
| @@ -8,7 +8,7 @@ | ||||
| #include <esp_ota_ops.h> | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace ota { | ||||
| namespace ota_base { | ||||
| 
 | ||||
| class IDFOTABackend : public OTABackend { | ||||
|  public: | ||||
| @@ -24,8 +24,9 @@ class IDFOTABackend : public OTABackend { | ||||
|   const esp_partition_t *partition_; | ||||
|   md5::MD5Digest md5_{}; | ||||
|   char expected_bin_md5_[32]; | ||||
|   bool md5_set_{false}; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace ota
 | ||||
| }  // namespace ota_base
 | ||||
| }  // namespace esphome
 | ||||
| #endif | ||||
| @@ -2,9 +2,7 @@ | ||||
| #ifdef USE_ESP32 | ||||
| #include "psram.h" | ||||
| #include <esp_idf_version.h> | ||||
| #if defined(USE_ESP_IDF) && ESP_IDF_VERSION_MAJOR >= 5 | ||||
| #include <esp_psram.h> | ||||
| #endif  // USE_ESP_IDF | ||||
|  | ||||
| #include "esphome/core/log.h" | ||||
|  | ||||
| @@ -16,7 +14,6 @@ static const char *const TAG = "psram"; | ||||
|  | ||||
| void PsramComponent::dump_config() { | ||||
|   ESP_LOGCONFIG(TAG, "PSRAM:"); | ||||
| #if defined(USE_ESP_IDF) && ESP_IDF_VERSION_MAJOR >= 5 | ||||
|   bool available = esp_psram_is_initialized(); | ||||
|  | ||||
|   ESP_LOGCONFIG(TAG, "  Available: %s", YESNO(available)); | ||||
| @@ -26,23 +23,6 @@ void PsramComponent::dump_config() { | ||||
|     ESP_LOGCONFIG(TAG, "  ECC enabled: YES"); | ||||
| #endif | ||||
|   } | ||||
| #else | ||||
|   // Technically this can be false if the PSRAM is full, but heap_caps_get_total_size() isn't always available, and it's | ||||
|   // very unlikely for the PSRAM to be full. | ||||
|   bool available = heap_caps_get_free_size(MALLOC_CAP_SPIRAM) > 0; | ||||
|   ESP_LOGCONFIG(TAG, "  Available: %s", YESNO(available)); | ||||
|  | ||||
|   if (available) { | ||||
|     const size_t psram_total_size_bytes = heap_caps_get_total_size(MALLOC_CAP_SPIRAM); | ||||
|     const float psram_total_size_kb = psram_total_size_bytes / 1024.0f; | ||||
|  | ||||
|     if (abs(std::round(psram_total_size_kb) - psram_total_size_kb) < 0.05f) { | ||||
|       ESP_LOGCONFIG(TAG, "  Size: %.0f KB", psram_total_size_kb); | ||||
|     } else { | ||||
|       ESP_LOGCONFIG(TAG, "  Size: %zu bytes", psram_total_size_bytes); | ||||
|     } | ||||
|   } | ||||
| #endif  // USE_ESP_IDF | ||||
| } | ||||
|  | ||||
| }  // namespace psram | ||||
|   | ||||
| @@ -146,11 +146,7 @@ void PVVXDisplay::sync_time_() { | ||||
|   } | ||||
|   time.recalc_timestamp_utc(true);  // calculate timestamp of local time | ||||
|   uint8_t blk[5] = {}; | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|   ESP_LOGD(TAG, "[%s] Sync time with timestamp %" PRIu64 ".", this->parent_->address_str().c_str(), time.timestamp); | ||||
| #else | ||||
|   ESP_LOGD(TAG, "[%s] Sync time with timestamp %lu.", this->parent_->address_str().c_str(), time.timestamp); | ||||
| #endif | ||||
|   blk[0] = 0x23; | ||||
|   blk[1] = time.timestamp & 0xff; | ||||
|   blk[2] = (time.timestamp >> 8) & 0xff; | ||||
|   | ||||
| @@ -10,10 +10,8 @@ void RpiDpiRgb::setup() { | ||||
|   this->reset_display_(); | ||||
|   esp_lcd_rgb_panel_config_t config{}; | ||||
|   config.flags.fb_in_psram = 1; | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|   config.bounce_buffer_size_px = this->width_ * 10; | ||||
|   config.num_fbs = 1; | ||||
| #endif  // ESP_IDF_VERSION_MAJOR | ||||
|   config.timings.h_res = this->width_; | ||||
|   config.timings.v_res = this->height_; | ||||
|   config.timings.hsync_pulse_width = this->hsync_pulse_width_; | ||||
| @@ -47,10 +45,8 @@ void RpiDpiRgb::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "RPI_DPI_RGB setup complete"); | ||||
| } | ||||
| void RpiDpiRgb::loop() { | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|   if (this->handle_ != nullptr) | ||||
|     esp_lcd_rgb_panel_restart(this->handle_); | ||||
| #endif  // ESP_IDF_VERSION_MAJOR | ||||
| } | ||||
|  | ||||
| void RpiDpiRgb::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order, | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
|  | ||||
| #include "esphome/components/audio/audio.h" | ||||
| #ifdef USE_OTA | ||||
| #include "esphome/components/ota/ota_backend.h" | ||||
| #include "esphome/components/ota_base/ota_backend.h" | ||||
| #endif | ||||
|  | ||||
| namespace esphome { | ||||
| @@ -67,16 +67,16 @@ void SpeakerMediaPlayer::setup() { | ||||
|   } | ||||
|  | ||||
| #ifdef USE_OTA | ||||
|   ota::get_global_ota_callback()->add_on_state_callback( | ||||
|       [this](ota::OTAState state, float progress, uint8_t error, ota::OTAComponent *comp) { | ||||
|         if (state == ota::OTA_STARTED) { | ||||
|   ota_base::get_global_ota_callback()->add_on_state_callback( | ||||
|       [this](ota_base::OTAState state, float progress, uint8_t error, ota_base::OTAComponent *comp) { | ||||
|         if (state == ota_base::OTA_STARTED) { | ||||
|           if (this->media_pipeline_ != nullptr) { | ||||
|             this->media_pipeline_->suspend_tasks(); | ||||
|           } | ||||
|           if (this->announcement_pipeline_ != nullptr) { | ||||
|             this->announcement_pipeline_->suspend_tasks(); | ||||
|           } | ||||
|         } else if (state == ota::OTA_ERROR) { | ||||
|         } else if (state == ota_base::OTA_ERROR) { | ||||
|           if (this->media_pipeline_ != nullptr) { | ||||
|             this->media_pipeline_->resume_tasks(); | ||||
|           } | ||||
|   | ||||
| @@ -12,10 +12,8 @@ void ST7701S::setup() { | ||||
|  | ||||
|   esp_lcd_rgb_panel_config_t config{}; | ||||
|   config.flags.fb_in_psram = 1; | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|   config.bounce_buffer_size_px = this->width_ * 10; | ||||
|   config.num_fbs = 1; | ||||
| #endif  // ESP_IDF_VERSION_MAJOR | ||||
|   config.timings.h_res = this->width_; | ||||
|   config.timings.v_res = this->height_; | ||||
|   config.timings.hsync_pulse_width = this->hsync_pulse_width_; | ||||
| @@ -48,10 +46,8 @@ void ST7701S::setup() { | ||||
| } | ||||
|  | ||||
| void ST7701S::loop() { | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|   if (this->handle_ != nullptr) | ||||
|     esp_lcd_rgb_panel_restart(this->handle_); | ||||
| #endif  // ESP_IDF_VERSION_MAJOR | ||||
| } | ||||
|  | ||||
| void ST7701S::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order, | ||||
|   | ||||
| @@ -48,11 +48,7 @@ uart_config_t IDFUARTComponent::get_config_() { | ||||
|   uart_config.parity = parity; | ||||
|   uart_config.stop_bits = this->stop_bits_ == 1 ? UART_STOP_BITS_1 : UART_STOP_BITS_2; | ||||
|   uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; | ||||
| #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) | ||||
|   uart_config.source_clk = UART_SCLK_DEFAULT; | ||||
| #else | ||||
|   uart_config.source_clk = UART_SCLK_APB; | ||||
| #endif | ||||
|   uart_config.rx_flow_ctrl_thresh = 122; | ||||
|  | ||||
|   return uart_config; | ||||
|   | ||||
| @@ -38,16 +38,12 @@ WatchdogManager::~WatchdogManager() { | ||||
| void WatchdogManager::set_timeout_(uint32_t timeout_ms) { | ||||
|   ESP_LOGV(TAG, "Adjusting WDT to %" PRIu32 "ms", timeout_ms); | ||||
| #ifdef USE_ESP32 | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|   esp_task_wdt_config_t wdt_config = { | ||||
|       .timeout_ms = timeout_ms, | ||||
|       .idle_core_mask = (1 << SOC_CPU_CORES_NUM) - 1, | ||||
|       .trigger_panic = true, | ||||
|   }; | ||||
|   esp_task_wdt_reconfigure(&wdt_config); | ||||
| #else | ||||
|   esp_task_wdt_init(timeout_ms / 1000, true); | ||||
| #endif  // ESP_IDF_VERSION_MAJOR | ||||
| #endif  // USE_ESP32 | ||||
|  | ||||
| #ifdef USE_RP2040 | ||||
|   | ||||
| @@ -34,7 +34,7 @@ from esphome.const import ( | ||||
| from esphome.core import CORE, coroutine_with_priority | ||||
| import esphome.final_validate as fv | ||||
|  | ||||
| AUTO_LOAD = ["json", "web_server_base"] | ||||
| AUTO_LOAD = ["json", "web_server_base", "ota_base"] | ||||
|  | ||||
| CONF_SORTING_GROUP_ID = "sorting_group_id" | ||||
| CONF_SORTING_GROUPS = "sorting_groups" | ||||
| @@ -274,7 +274,7 @@ async def to_code(config): | ||||
|     cg.add(var.set_allow_ota(config[CONF_OTA])) | ||||
|     if config[CONF_OTA]: | ||||
|         # Define USE_WEBSERVER_OTA based only on web_server OTA config | ||||
|         # This allows web server OTA to work without loading the OTA component | ||||
|         # Web server OTA now uses ota_base backend for consistency | ||||
|         cg.add_define("USE_WEBSERVER_OTA") | ||||
|     cg.add(var.set_expose_log(config[CONF_LOG])) | ||||
|     if config[CONF_ENABLE_PRIVATE_NETWORK_ACCESS]: | ||||
|   | ||||
| @@ -4,19 +4,16 @@ | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/log.h" | ||||
|  | ||||
| #ifdef USE_ARDUINO | ||||
| #include <StreamString.h> | ||||
| #if defined(USE_ESP32) || defined(USE_LIBRETINY) | ||||
| #include <Update.h> | ||||
| #endif | ||||
| #ifdef USE_ESP8266 | ||||
| #include <Updater.h> | ||||
| #endif | ||||
| #ifdef USE_WEBSERVER_OTA | ||||
| #include "esphome/components/ota_base/ota_backend.h" | ||||
| #endif | ||||
|  | ||||
| #if defined(USE_ESP_IDF) && defined(USE_WEBSERVER_OTA) | ||||
| #include <esp_ota_ops.h> | ||||
| #include <esp_task_wdt.h> | ||||
| #ifdef USE_ARDUINO | ||||
| #ifdef USE_ESP8266 | ||||
| #include <Updater.h> | ||||
| #elif defined(USE_ESP32) || defined(USE_LIBRETINY) | ||||
| #include <Update.h> | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| namespace esphome { | ||||
| @@ -24,104 +21,6 @@ namespace web_server_base { | ||||
|  | ||||
| static const char *const TAG = "web_server_base"; | ||||
|  | ||||
| #if defined(USE_ESP_IDF) && defined(USE_WEBSERVER_OTA) | ||||
| // Minimal OTA backend implementation for web server | ||||
| // This allows OTA updates via web server without requiring the OTA component | ||||
| // TODO: In the future, this should be refactored into a common ota_base component | ||||
| // that both web_server and ota components can depend on, avoiding code duplication | ||||
| // while keeping the components independent. This would allow both ESP-IDF and Arduino | ||||
| // implementations to share the base OTA functionality without requiring the full OTA component. | ||||
| // The IDFWebServerOTABackend class is intentionally designed with the same interface | ||||
| // as OTABackend to make it easy to swap to using OTABackend when the ota component | ||||
| // is split into ota and ota_base in the future. | ||||
| class IDFWebServerOTABackend { | ||||
|  public: | ||||
|   bool begin() { | ||||
|     this->partition_ = esp_ota_get_next_update_partition(nullptr); | ||||
|     if (this->partition_ == nullptr) { | ||||
|       ESP_LOGE(TAG, "No OTA partition available"); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
| #if CONFIG_ESP_TASK_WDT_TIMEOUT_S < 15 | ||||
|     // The following function takes longer than the default timeout of WDT due to flash erase | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|     esp_task_wdt_config_t wdtc; | ||||
|     wdtc.idle_core_mask = 0; | ||||
| #if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 | ||||
|     wdtc.idle_core_mask |= (1 << 0); | ||||
| #endif | ||||
| #if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 | ||||
|     wdtc.idle_core_mask |= (1 << 1); | ||||
| #endif | ||||
|     wdtc.timeout_ms = 15000; | ||||
|     wdtc.trigger_panic = false; | ||||
|     esp_task_wdt_reconfigure(&wdtc); | ||||
| #else | ||||
|     esp_task_wdt_init(15, false); | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
|     esp_err_t err = esp_ota_begin(this->partition_, 0, &this->update_handle_); | ||||
|  | ||||
| #if CONFIG_ESP_TASK_WDT_TIMEOUT_S < 15 | ||||
|     // Set the WDT back to the configured timeout | ||||
| #if ESP_IDF_VERSION_MAJOR >= 5 | ||||
|     wdtc.timeout_ms = CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000; | ||||
|     esp_task_wdt_reconfigure(&wdtc); | ||||
| #else | ||||
|     esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false); | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
|     if (err != ESP_OK) { | ||||
|       esp_ota_abort(this->update_handle_); | ||||
|       this->update_handle_ = 0; | ||||
|       ESP_LOGE(TAG, "esp_ota_begin failed: %s", esp_err_to_name(err)); | ||||
|       return false; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   bool write(uint8_t *data, size_t len) { | ||||
|     esp_err_t err = esp_ota_write(this->update_handle_, data, len); | ||||
|     if (err != ESP_OK) { | ||||
|       ESP_LOGE(TAG, "esp_ota_write failed: %s", esp_err_to_name(err)); | ||||
|       return false; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   bool end() { | ||||
|     esp_err_t err = esp_ota_end(this->update_handle_); | ||||
|     this->update_handle_ = 0; | ||||
|     if (err != ESP_OK) { | ||||
|       ESP_LOGE(TAG, "esp_ota_end failed: %s", esp_err_to_name(err)); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     err = esp_ota_set_boot_partition(this->partition_); | ||||
|     if (err != ESP_OK) { | ||||
|       ESP_LOGE(TAG, "esp_ota_set_boot_partition failed: %s", esp_err_to_name(err)); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   void abort() { | ||||
|     if (this->update_handle_ != 0) { | ||||
|       esp_ota_abort(this->update_handle_); | ||||
|       this->update_handle_ = 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   esp_ota_handle_t update_handle_{0}; | ||||
|   const esp_partition_t *partition_{nullptr}; | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| void WebServerBase::add_handler(AsyncWebHandler *handler) { | ||||
|   // remove all handlers | ||||
|  | ||||
| @@ -138,12 +37,21 @@ void WebServerBase::add_handler(AsyncWebHandler *handler) { | ||||
| void OTARequestHandler::report_ota_progress_(AsyncWebServerRequest *request) { | ||||
|   const uint32_t now = millis(); | ||||
|   if (now - this->last_ota_progress_ > 1000) { | ||||
|     float percentage = 0.0f; | ||||
|     if (request->contentLength() != 0) { | ||||
|       float percentage = (this->ota_read_length_ * 100.0f) / request->contentLength(); | ||||
|       // Note: Using contentLength() for progress calculation is technically wrong as it includes | ||||
|       // multipart headers/boundaries, but it's only off by a small amount and we don't have | ||||
|       // access to the actual firmware size until the upload is complete. This is intentional | ||||
|       // as it still gives the user a reasonable progress indication. | ||||
|       percentage = (this->ota_read_length_ * 100.0f) / request->contentLength(); | ||||
|       ESP_LOGD(TAG, "OTA in progress: %0.1f%%", percentage); | ||||
|     } else { | ||||
|       ESP_LOGD(TAG, "OTA in progress: %u bytes read", this->ota_read_length_); | ||||
|     } | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|     // Report progress - use call_deferred since we're in web server task | ||||
|     this->parent_->state_callback_.call_deferred(ota_base::OTA_IN_PROGRESS, percentage, 0); | ||||
| #endif | ||||
|     this->last_ota_progress_ = now; | ||||
|   } | ||||
| } | ||||
| @@ -159,87 +67,72 @@ void OTARequestHandler::schedule_ota_reboot_() { | ||||
| void OTARequestHandler::ota_init_(const char *filename) { | ||||
|   ESP_LOGI(TAG, "OTA Update Start: %s", filename); | ||||
|   this->ota_read_length_ = 0; | ||||
| } | ||||
|  | ||||
| void report_ota_error() { | ||||
| #ifdef USE_ARDUINO | ||||
|   StreamString ss; | ||||
|   Update.printError(ss); | ||||
|   ESP_LOGW(TAG, "OTA Update failed! Error: %s", ss.c_str()); | ||||
| #endif | ||||
|   this->ota_success_ = false; | ||||
| } | ||||
|  | ||||
| void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const String &filename, size_t index, | ||||
|                                      uint8_t *data, size_t len, bool final) { | ||||
| #ifdef USE_ARDUINO | ||||
|   bool success; | ||||
|   if (index == 0) { | ||||
|   ota_base::OTAResponseTypes error_code = ota_base::OTA_RESPONSE_OK; | ||||
|  | ||||
|   if (index == 0 && !this->ota_backend_) { | ||||
|     // Initialize OTA on first call | ||||
|     this->ota_init_(filename.c_str()); | ||||
|  | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|     // Notify OTA started - use call_deferred since we're in web server task | ||||
|     this->parent_->state_callback_.call_deferred(ota_base::OTA_STARTED, 0.0f, 0); | ||||
| #endif | ||||
|  | ||||
|     // Platform-specific pre-initialization | ||||
| #ifdef USE_ARDUINO | ||||
| #ifdef USE_ESP8266 | ||||
|     Update.runAsync(true); | ||||
|     // NOLINTNEXTLINE(readability-static-accessed-through-instance) | ||||
|     success = Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000); | ||||
| #endif | ||||
| #if defined(USE_ESP32_FRAMEWORK_ARDUINO) || defined(USE_LIBRETINY) | ||||
|     if (Update.isRunning()) { | ||||
|       Update.abort(); | ||||
|     } | ||||
|     success = Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH); | ||||
| #endif | ||||
|     if (!success) { | ||||
|       report_ota_error(); | ||||
|       return; | ||||
|     } | ||||
|   } else if (Update.hasError()) { | ||||
|     // don't spam logs with errors if something failed at start | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   success = Update.write(data, len) == len; | ||||
|   if (!success) { | ||||
|     report_ota_error(); | ||||
|     return; | ||||
|   } | ||||
|   this->ota_read_length_ += len; | ||||
|   this->report_ota_progress_(request); | ||||
|  | ||||
|   if (final) { | ||||
|     if (Update.end(true)) { | ||||
|       this->schedule_ota_reboot_(); | ||||
|     } else { | ||||
|       report_ota_error(); | ||||
|     } | ||||
|   } | ||||
| #endif  // USE_ARDUINO | ||||
|  | ||||
| #ifdef USE_ESP_IDF | ||||
|   // ESP-IDF implementation | ||||
|   if (index == 0 && !this->ota_backend_) { | ||||
|     // Initialize OTA on first call | ||||
|     this->ota_init_(filename.c_str()); | ||||
|     this->ota_success_ = false; | ||||
|  | ||||
|     auto *backend = new IDFWebServerOTABackend(); | ||||
|     if (!backend->begin()) { | ||||
|       ESP_LOGE(TAG, "OTA begin failed"); | ||||
|       delete backend; | ||||
|     this->ota_backend_ = ota_base::make_ota_backend(); | ||||
|     if (!this->ota_backend_) { | ||||
|       ESP_LOGE(TAG, "Failed to create OTA backend"); | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|       this->parent_->state_callback_.call_deferred(ota_base::OTA_ERROR, 0.0f, | ||||
|                                                    static_cast<uint8_t>(ota_base::OTA_RESPONSE_ERROR_UNKNOWN)); | ||||
| #endif | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     // Web server OTA uses multipart uploads where the actual firmware size | ||||
|     // is unknown (contentLength includes multipart overhead) | ||||
|     // Pass 0 to indicate unknown size | ||||
|     error_code = this->ota_backend_->begin(0); | ||||
|     if (error_code != ota_base::OTA_RESPONSE_OK) { | ||||
|       ESP_LOGE(TAG, "OTA begin failed: %d", error_code); | ||||
|       this->ota_backend_.reset(); | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|       this->parent_->state_callback_.call_deferred(ota_base::OTA_ERROR, 0.0f, static_cast<uint8_t>(error_code)); | ||||
| #endif | ||||
|       return; | ||||
|     } | ||||
|     this->ota_backend_ = backend; | ||||
|   } | ||||
|  | ||||
|   auto *backend = static_cast<IDFWebServerOTABackend *>(this->ota_backend_); | ||||
|   if (!backend) { | ||||
|   if (!this->ota_backend_) { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   // Process data | ||||
|   if (len > 0) { | ||||
|     if (!backend->write(data, len)) { | ||||
|       ESP_LOGE(TAG, "OTA write failed"); | ||||
|       backend->abort(); | ||||
|       delete backend; | ||||
|       this->ota_backend_ = nullptr; | ||||
|     error_code = this->ota_backend_->write(data, len); | ||||
|     if (error_code != ota_base::OTA_RESPONSE_OK) { | ||||
|       ESP_LOGE(TAG, "OTA write failed: %d", error_code); | ||||
|       this->ota_backend_->abort(); | ||||
|       this->ota_backend_.reset(); | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|       this->parent_->state_callback_.call_deferred(ota_base::OTA_ERROR, 0.0f, static_cast<uint8_t>(error_code)); | ||||
| #endif | ||||
|       return; | ||||
|     } | ||||
|     this->ota_read_length_ += len; | ||||
| @@ -248,40 +141,45 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Strin | ||||
|  | ||||
|   // Finalize | ||||
|   if (final) { | ||||
|     this->ota_success_ = backend->end(); | ||||
|     if (this->ota_success_) { | ||||
|     ESP_LOGD(TAG, "OTA final chunk: index=%u, len=%u, total_read=%u, contentLength=%u", index, len, | ||||
|              this->ota_read_length_, request->contentLength()); | ||||
|  | ||||
|     // For Arduino framework, the Update library tracks expected size from firmware header | ||||
|     // If we haven't received enough data, calling end() will fail | ||||
|     // This can happen if the upload is interrupted or the client disconnects | ||||
|     error_code = this->ota_backend_->end(); | ||||
|     if (error_code == ota_base::OTA_RESPONSE_OK) { | ||||
|       this->ota_success_ = true; | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|       // Report completion before reboot - use call_deferred since we're in web server task | ||||
|       this->parent_->state_callback_.call_deferred(ota_base::OTA_COMPLETED, 100.0f, 0); | ||||
| #endif | ||||
|       this->schedule_ota_reboot_(); | ||||
|     } else { | ||||
|       ESP_LOGE(TAG, "OTA end failed"); | ||||
|       ESP_LOGE(TAG, "OTA end failed: %d", error_code); | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|       this->parent_->state_callback_.call_deferred(ota_base::OTA_ERROR, 0.0f, static_cast<uint8_t>(error_code)); | ||||
| #endif | ||||
|     } | ||||
|     delete backend; | ||||
|     this->ota_backend_ = nullptr; | ||||
|     this->ota_backend_.reset(); | ||||
|   } | ||||
| #endif  // USE_ESP_IDF | ||||
| } | ||||
|  | ||||
| void OTARequestHandler::handleRequest(AsyncWebServerRequest *request) { | ||||
|   AsyncWebServerResponse *response; | ||||
| #ifdef USE_ARDUINO | ||||
|   if (!Update.hasError()) { | ||||
|     response = request->beginResponse(200, "text/plain", "Update Successful!"); | ||||
|   } else { | ||||
|     StreamString ss; | ||||
|     ss.print("Update Failed: "); | ||||
|     Update.printError(ss); | ||||
|     response = request->beginResponse(200, "text/plain", ss); | ||||
|   } | ||||
| #endif  // USE_ARDUINO | ||||
| #ifdef USE_ESP_IDF | ||||
|   // Send response based on the OTA result | ||||
|   response = request->beginResponse(200, "text/plain", this->ota_success_ ? "Update Successful!" : "Update Failed!"); | ||||
| #endif  // USE_ESP_IDF | ||||
|   // Use the ota_success_ flag to determine the actual result | ||||
|   const char *msg = this->ota_success_ ? "Update Successful!" : "Update Failed!"; | ||||
|   response = request->beginResponse(200, "text/plain", msg); | ||||
|   response->addHeader("Connection", "close"); | ||||
|   request->send(response); | ||||
| } | ||||
|  | ||||
| void WebServerBase::add_ota_handler() { | ||||
|   this->add_handler(new OTARequestHandler(this));  // NOLINT | ||||
| #ifdef USE_OTA_STATE_CALLBACK | ||||
|   // Register with global OTA callback system | ||||
|   ota_base::register_ota_platform(this); | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -14,6 +14,10 @@ | ||||
| #include "esphome/components/web_server_idf/web_server_idf.h" | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_WEBSERVER_OTA | ||||
| #include "esphome/components/ota_base/ota_backend.h" | ||||
| #endif | ||||
|  | ||||
| namespace esphome { | ||||
| namespace web_server_base { | ||||
|  | ||||
| @@ -79,7 +83,11 @@ class AuthMiddlewareHandler : public MiddlewareHandler { | ||||
|  | ||||
| }  // namespace internal | ||||
|  | ||||
| #ifdef USE_WEBSERVER_OTA | ||||
| class WebServerBase : public ota_base::OTAComponent { | ||||
| #else | ||||
| class WebServerBase : public Component { | ||||
| #endif | ||||
|  public: | ||||
|   void init() { | ||||
|     if (this->initialized_) { | ||||
| @@ -151,12 +159,10 @@ class OTARequestHandler : public AsyncWebHandler { | ||||
|   uint32_t last_ota_progress_{0}; | ||||
|   uint32_t ota_read_length_{0}; | ||||
|   WebServerBase *parent_; | ||||
|   bool ota_success_{false}; | ||||
|  | ||||
|  private: | ||||
| #ifdef USE_ESP_IDF | ||||
|   void *ota_backend_{nullptr}; | ||||
|   bool ota_success_{false}; | ||||
| #endif | ||||
|   std::unique_ptr<ota_base::OTABackend> ota_backend_{nullptr}; | ||||
| }; | ||||
| #endif  // USE_WEBSERVER_OTA | ||||
|  | ||||
|   | ||||
| @@ -6,14 +6,7 @@ import esphome.codegen as cg | ||||
| from esphome.components import time | ||||
| from esphome.components.esp32 import CORE, add_idf_sdkconfig_option | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import ( | ||||
|     CONF_ADDRESS, | ||||
|     CONF_ID, | ||||
|     CONF_REBOOT_TIMEOUT, | ||||
|     CONF_TIME_ID, | ||||
|     KEY_CORE, | ||||
|     KEY_FRAMEWORK_VERSION, | ||||
| ) | ||||
| from esphome.const import CONF_ADDRESS, CONF_ID, CONF_REBOOT_TIMEOUT, CONF_TIME_ID | ||||
| from esphome.core import TimePeriod | ||||
|  | ||||
| CONF_NETMASK = "netmask" | ||||
| @@ -125,9 +118,7 @@ async def to_code(config): | ||||
|  | ||||
|     # Workaround for crash on IDF 5+ | ||||
|     # See https://github.com/trombik/esp_wireguard/issues/33#issuecomment-1568503651 | ||||
|     if CORE.using_esp_idf and CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version( | ||||
|         5, 0, 0 | ||||
|     ): | ||||
|     if CORE.using_esp_idf: | ||||
|         add_idf_sdkconfig_option("CONFIG_LWIP_PPP_SUPPORT", True) | ||||
|  | ||||
|     # This flag is added here because the esp_wireguard library statically | ||||
|   | ||||
							
								
								
									
										10
									
								
								tests/components/ota_base/common.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/components/ota_base/common.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| # Test that ota_base compiles correctly as a dependency | ||||
| # This component is typically auto-loaded by other components | ||||
|  | ||||
| wifi: | ||||
|   ssid: MySSID | ||||
|   password: password1 | ||||
|  | ||||
| ota: | ||||
|   - platform: esphome | ||||
|     password: "test1234" | ||||
							
								
								
									
										1
									
								
								tests/components/ota_base/test.esp32-idf.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/components/ota_base/test.esp32-idf.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| <<: !include common.yaml | ||||
		Reference in New Issue
	
	Block a user