diff --git a/esphome/components/esphome/ota/__init__.py b/esphome/components/esphome/ota/__init__.py index a852d8d001..86006e3e18 100644 --- a/esphome/components/esphome/ota/__init__.py +++ b/esphome/components/esphome/ota/__init__.py @@ -1,10 +1,9 @@ import logging import esphome.codegen as cg -import esphome.config_validation as cv -import esphome.final_validate as fv -from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent +from esphome.components.ota import BASE_OTA_SCHEMA, OTAComponent, ota_to_code from esphome.config_helpers import merge_config +import esphome.config_validation as cv from esphome.const import ( CONF_ESPHOME, CONF_ID, @@ -18,6 +17,7 @@ from esphome.const import ( CONF_VERSION, ) from esphome.core import coroutine_with_priority +import esphome.final_validate as fv _LOGGER = logging.getLogger(__name__) @@ -124,7 +124,6 @@ FINAL_VALIDATE_SCHEMA = ota_esphome_final_validate @coroutine_with_priority(52.0) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - await ota_to_code(var, config) cg.add(var.set_port(config[CONF_PORT])) if CONF_PASSWORD in config: cg.add(var.set_auth_password(config[CONF_PASSWORD])) @@ -132,3 +131,4 @@ async def to_code(config): cg.add_define("USE_OTA_VERSION", config[CONF_VERSION]) await cg.register_component(var, config) + await ota_to_code(var, config) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 4ed2c834f8..b2ce718ec4 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -189,7 +189,7 @@ template class HttpRequestSendAction : public Action { if (container == nullptr) { for (auto *trigger : this->error_triggers_) - trigger->trigger(x...); + trigger->trigger(); return; } diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index af1eb6f459..85a1312aaa 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -104,7 +104,9 @@ std::shared_ptr HttpRequestArduino::start(std::string url, std::s static const size_t HEADER_COUNT = sizeof(header_keys) / sizeof(header_keys[0]); container->client_.collectHeaders(header_keys, HEADER_COUNT); + App.feed_wdt(); container->status_code = container->client_.sendRequest(method.c_str(), body.c_str()); + App.feed_wdt(); if (container->status_code < 0) { ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s", url.c_str(), HTTPClient::errorToString(container->status_code).c_str()); diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index c6c567b620..b449f046ee 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -117,8 +117,11 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin return nullptr; } + App.feed_wdt(); container->content_length = esp_http_client_fetch_headers(client); + App.feed_wdt(); container->status_code = esp_http_client_get_status_code(client); + App.feed_wdt(); if (is_success(container->status_code)) { container->duration_ms = millis() - start; return container; @@ -148,8 +151,11 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin return nullptr; } + App.feed_wdt(); container->content_length = esp_http_client_fetch_headers(client); + App.feed_wdt(); container->status_code = esp_http_client_get_status_code(client); + App.feed_wdt(); if (is_success(container->status_code)) { container->duration_ms = millis() - start; return container; diff --git a/esphome/components/nextion/automation.h b/esphome/components/nextion/automation.h index f51fe6b4f8..5182e07229 100644 --- a/esphome/components/nextion/automation.h +++ b/esphome/components/nextion/automation.h @@ -42,5 +42,12 @@ class TouchTrigger : public Trigger { } }; +class BufferOverflowTrigger : public Trigger<> { + public: + explicit BufferOverflowTrigger(Nextion *nextion) { + nextion->add_buffer_overflow_event_callback([this]() { this->trigger(); }); + } +}; + } // namespace nextion } // namespace esphome diff --git a/esphome/components/nextion/base_component.py b/esphome/components/nextion/base_component.py index 2924f66d3c..9708379861 100644 --- a/esphome/components/nextion/base_component.py +++ b/esphome/components/nextion/base_component.py @@ -18,6 +18,7 @@ CONF_ON_SLEEP = "on_sleep" CONF_ON_WAKE = "on_wake" CONF_ON_SETUP = "on_setup" CONF_ON_PAGE = "on_page" +CONF_ON_BUFFER_OVERFLOW = "on_buffer_overflow" CONF_TOUCH_SLEEP_TIMEOUT = "touch_sleep_timeout" CONF_WAKE_UP_PAGE = "wake_up_page" CONF_START_UP_PAGE = "start_up_page" diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index e403ba7ae8..6f284376af 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -13,6 +13,7 @@ from esphome.const import ( from esphome.core import CORE from . import Nextion, nextion_ns, nextion_ref from .base_component import ( + CONF_ON_BUFFER_OVERFLOW, CONF_ON_SLEEP, CONF_ON_WAKE, CONF_ON_SETUP, @@ -36,6 +37,9 @@ SleepTrigger = nextion_ns.class_("SleepTrigger", automation.Trigger.template()) WakeTrigger = nextion_ns.class_("WakeTrigger", automation.Trigger.template()) PageTrigger = nextion_ns.class_("PageTrigger", automation.Trigger.template()) TouchTrigger = nextion_ns.class_("TouchTrigger", automation.Trigger.template()) +BufferOverflowTrigger = nextion_ns.class_( + "BufferOverflowTrigger", automation.Trigger.template() +) CONFIG_SCHEMA = ( display.BASIC_DISPLAY_SCHEMA.extend( @@ -68,6 +72,13 @@ CONFIG_SCHEMA = ( cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TouchTrigger), } ), + cv.Optional(CONF_ON_BUFFER_OVERFLOW): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + BufferOverflowTrigger + ), + } + ), cv.Optional(CONF_TOUCH_SLEEP_TIMEOUT): cv.int_range(min=3, max=65535), cv.Optional(CONF_WAKE_UP_PAGE): cv.uint8_t, cv.Optional(CONF_START_UP_PAGE): cv.uint8_t, @@ -151,3 +162,7 @@ async def to_code(config): ], conf, ) + + for conf in config.get(CONF_ON_BUFFER_OVERFLOW, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index a80f6efc91..984db09c57 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -190,6 +190,10 @@ void Nextion::add_touch_event_callback(std::functiontouch_callback_.add(std::move(callback)); } +void Nextion::add_buffer_overflow_event_callback(std::function &&callback) { + this->buffer_overflow_callback_.add(std::move(callback)); +} + void Nextion::update_all_components() { if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping()) return; @@ -458,7 +462,9 @@ void Nextion::process_nextion_commands_() { this->remove_from_q_(); break; case 0x24: // Serial Buffer overflow occurs - ESP_LOGW(TAG, "Nextion reported Serial Buffer overflow!"); + // Buffer will continue to receive the current instruction, all previous instructions are lost. + ESP_LOGE(TAG, "Nextion reported Serial Buffer overflow!"); + this->buffer_overflow_callback_.call(); break; case 0x65: { // touch event return data if (to_process_length != 3) { diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 732ee9b455..f539c79718 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -1134,6 +1134,12 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ void add_touch_event_callback(std::function &&callback); + /** Add a callback to be notified when the nextion reports a buffer overflow. + * + * @param callback The void() callback. + */ + void add_buffer_overflow_event_callback(std::function &&callback); + void update_all_components(); /** @@ -1323,6 +1329,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe CallbackManager wake_callback_{}; CallbackManager page_callback_{}; CallbackManager touch_callback_{}; + CallbackManager buffer_overflow_callback_{}; optional writer_; float brightness_{1.0}; diff --git a/esphome/components/online_image/__init__.py b/esphome/components/online_image/__init__.py index dfb10137aa..be1bfb4a00 100644 --- a/esphome/components/online_image/__init__.py +++ b/esphome/components/online_image/__init__.py @@ -98,6 +98,7 @@ CONFIG_SCHEMA = cv.Schema( # esp8266_arduino=cv.Version(2, 7, 0), esp32_arduino=cv.Version(0, 0, 0), esp_idf=cv.Version(4, 0, 0), + rp2040_arduino=cv.Version(0, 0, 0), ), ) ) diff --git a/esphome/components/ota/__init__.py b/esphome/components/ota/__init__.py index d9917a2aae..627c55e910 100644 --- a/esphome/components/ota/__init__.py +++ b/esphome/components/ota/__init__.py @@ -92,6 +92,7 @@ async def to_code(config): async def ota_to_code(var, config): + await cg.past_safe_mode() use_state_callback = False for conf in config.get(CONF_ON_STATE_CHANGE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) diff --git a/esphome/components/qspi_dbi/models.py b/esphome/components/qspi_dbi/models.py index 071ea72d73..cbd9c4663f 100644 --- a/esphome/components/qspi_dbi/models.py +++ b/esphome/components/qspi_dbi/models.py @@ -55,6 +55,7 @@ chip.cmd(PAGESEL, 0x00) chip.cmd(0xC2, 0x00) chip.delay(10) chip.cmd(TEON, 0x00) +chip.cmd(PIXFMT, 0x55) chip = DriverChip("AXS15231") chip.cmd(0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xA5) diff --git a/esphome/components/remote_base/raw_protocol.cpp b/esphome/components/remote_base/raw_protocol.cpp index bdeb935dc4..ef0cb8454e 100644 --- a/esphome/components/remote_base/raw_protocol.cpp +++ b/esphome/components/remote_base/raw_protocol.cpp @@ -28,7 +28,7 @@ bool RawDumper::dump(RemoteReceiveData src) { ESP_LOGI(TAG, "%s", buffer); buffer_offset = 0; written = sprintf(buffer, " "); - if (i + 1 < src.size()) { + if (i + 1 < src.size() - 1) { written += sprintf(buffer + written, "%" PRId32 ", ", value); } else { written += sprintf(buffer + written, "%" PRId32, value); diff --git a/esphome/components/rtttl/rtttl.h b/esphome/components/rtttl/rtttl.h index 10c290c5fb..420948bfbf 100644 --- a/esphome/components/rtttl/rtttl.h +++ b/esphome/components/rtttl/rtttl.h @@ -40,13 +40,7 @@ class Rtttl : public Component { void set_speaker(speaker::Speaker *speaker) { this->speaker_ = speaker; } #endif float get_gain() { return gain_; } - void set_gain(float gain) { - if (gain < 0.1f) - gain = 0.1f; - if (gain > 1.0f) - gain = 1.0f; - this->gain_ = gain; - } + void set_gain(float gain) { this->gain_ = clamp(gain, 0.0f, 1.0f); } void play(std::string rtttl); void stop(); void dump_config() override; diff --git a/esphome/components/speaker/__init__.py b/esphome/components/speaker/__init__.py index 7a668dc2f3..948fe4b534 100644 --- a/esphome/components/speaker/__init__.py +++ b/esphome/components/speaker/__init__.py @@ -7,6 +7,7 @@ from esphome.const import CONF_DATA, CONF_ID, CONF_VOLUME from esphome.core import CORE from esphome.coroutine import coroutine_with_priority +AUTO_LOAD = ["audio"] CODEOWNERS = ["@jesserockz", "@kahrendt"] IS_PLATFORM_COMPONENT = True diff --git a/esphome/core/config.py b/esphome/core/config.py index 8c130eb6db..367e61c413 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -184,6 +184,9 @@ PRELOAD_CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_ESP8266_RESTORE_FROM_FLASH): cv.valid, cv.Optional(CONF_BOARD_FLASH_MODE): cv.valid, cv.Optional(CONF_ARDUINO_VERSION): cv.valid, + cv.Optional(CONF_MIN_VERSION, default=ESPHOME_VERSION): cv.All( + cv.version_number, cv.validate_esphome_version + ), }, extra=cv.ALLOW_EXTRA, ) diff --git a/esphome/dashboard/core.py b/esphome/dashboard/core.py index 563ca1506d..f53cb7ffb1 100644 --- a/esphome/dashboard/core.py +++ b/esphome/dashboard/core.py @@ -103,7 +103,7 @@ class ESPHomeDashboard: self.loop = asyncio.get_running_loop() self.ping_request = asyncio.Event() self.entries = DashboardEntries(self) - self.load_ignored_devices() + await self.loop.run_in_executor(None, self.load_ignored_devices) def load_ignored_devices(self) -> None: storage_path = Path(ignored_devices_storage_path()) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index 07f7f019f8..0fed8e9c53 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -544,7 +544,7 @@ class ImportRequestHandler(BaseHandler): class IgnoreDeviceRequestHandler(BaseHandler): @authenticated - def post(self) -> None: + async def post(self) -> None: dashboard = DASHBOARD try: args = json.loads(self.request.body.decode()) @@ -576,7 +576,8 @@ class IgnoreDeviceRequestHandler(BaseHandler): else: dashboard.ignored_devices.discard(ignored_device.device_name) - dashboard.save_ignored_devices() + loop = asyncio.get_running_loop() + await loop.run_in_executor(None, dashboard.save_ignored_devices) self.set_status(204) self.finish() diff --git a/requirements.txt b/requirements.txt index 4bea8cf4ef..7bc1c895df 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ pyserial==3.5 platformio==6.1.16 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 -esphome-dashboard==20241118.0 +esphome-dashboard==20241120.0 aioesphomeapi==24.6.2 zeroconf==0.132.2 puremagic==1.27 diff --git a/tests/components/http_request/common.yaml b/tests/components/http_request/common.yaml index 593b85e435..8408f27a05 100644 --- a/tests/components/http_request/common.yaml +++ b/tests/components/http_request/common.yaml @@ -39,6 +39,14 @@ http_request: timeout: 10s verify_ssl: ${verify_ssl} +script: + - id: does_not_compile + parameters: + api_url: string + then: + - http_request.get: + url: "http://google.com" + ota: - platform: http_request on_begin: diff --git a/tests/components/nextion/test.esp32-ard.yaml b/tests/components/nextion/test.esp32-ard.yaml index 27568ebc2a..ba76236fc6 100644 --- a/tests/components/nextion/test.esp32-ard.yaml +++ b/tests/components/nextion/test.esp32-ard.yaml @@ -58,3 +58,6 @@ display: on_page: then: lambda: 'ESP_LOGD("display","Display shows new page %u", x);' + on_buffer_overflow: + then: + logger.log: "Nextion reported a buffer overflow!" diff --git a/tests/components/nextion/test.esp32-c3-ard.yaml b/tests/components/nextion/test.esp32-c3-ard.yaml index 5881d6e165..5d253268f8 100644 --- a/tests/components/nextion/test.esp32-c3-ard.yaml +++ b/tests/components/nextion/test.esp32-c3-ard.yaml @@ -58,3 +58,6 @@ display: on_page: then: lambda: 'ESP_LOGD("display","Display shows new page %u", x);' + on_buffer_overflow: + then: + logger.log: "Nextion reported a buffer overflow!" diff --git a/tests/components/nextion/test.esp32-c3-idf.yaml b/tests/components/nextion/test.esp32-c3-idf.yaml index 5881d6e165..5d253268f8 100644 --- a/tests/components/nextion/test.esp32-c3-idf.yaml +++ b/tests/components/nextion/test.esp32-c3-idf.yaml @@ -58,3 +58,6 @@ display: on_page: then: lambda: 'ESP_LOGD("display","Display shows new page %u", x);' + on_buffer_overflow: + then: + logger.log: "Nextion reported a buffer overflow!" diff --git a/tests/components/nextion/test.esp32-idf.yaml b/tests/components/nextion/test.esp32-idf.yaml index 27568ebc2a..ba76236fc6 100644 --- a/tests/components/nextion/test.esp32-idf.yaml +++ b/tests/components/nextion/test.esp32-idf.yaml @@ -58,3 +58,6 @@ display: on_page: then: lambda: 'ESP_LOGD("display","Display shows new page %u", x);' + on_buffer_overflow: + then: + logger.log: "Nextion reported a buffer overflow!" diff --git a/tests/components/nextion/test.esp8266-ard.yaml b/tests/components/nextion/test.esp8266-ard.yaml index 5881d6e165..5d253268f8 100644 --- a/tests/components/nextion/test.esp8266-ard.yaml +++ b/tests/components/nextion/test.esp8266-ard.yaml @@ -58,3 +58,6 @@ display: on_page: then: lambda: 'ESP_LOGD("display","Display shows new page %u", x);' + on_buffer_overflow: + then: + logger.log: "Nextion reported a buffer overflow!" diff --git a/tests/components/nextion/test.rp2040-ard.yaml b/tests/components/nextion/test.rp2040-ard.yaml index a1c5848ce6..9b04433095 100644 --- a/tests/components/nextion/test.rp2040-ard.yaml +++ b/tests/components/nextion/test.rp2040-ard.yaml @@ -53,3 +53,6 @@ display: on_page: then: lambda: 'ESP_LOGD("display","Display shows new page %u", x);' + on_buffer_overflow: + then: + logger.log: "Nextion reported a buffer overflow!" diff --git a/tests/components/online_image/common-rp2040.yaml b/tests/components/online_image/common-rp2040.yaml new file mode 100644 index 0000000000..16bb2b2c44 --- /dev/null +++ b/tests/components/online_image/common-rp2040.yaml @@ -0,0 +1,19 @@ +<<: !include common.yaml + +spi: + - id: spi_main_lcd + clk_pin: 18 + mosi_pin: 19 + miso_pin: 16 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 20 + dc_pin: 17 + reset_pin: 21 + invert_colors: true + lambda: |- + it.fill(Color(0, 0, 0)); + it.image(0, 0, id(online_rgba_image)); diff --git a/tests/components/online_image/test.rp2040-ard.yaml b/tests/components/online_image/test.rp2040-ard.yaml new file mode 100644 index 0000000000..d10f36b4e9 --- /dev/null +++ b/tests/components/online_image/test.rp2040-ard.yaml @@ -0,0 +1,4 @@ +<<: !include common-rp2040.yaml + +http_request: + verify_ssl: false