Commit Graph

14391 Commits

Author SHA1 Message Date
J. Nick Koston 08c09fbe36 [esphome.ota] TEMP: add shim call counter to pinpoint C->C++ wake break 2026-04-10 16:20:03 -10:00
J. Nick Koston 9c70986909 [esphome.ota] TEMP: log server_->ready() after setup + add global rcvplus counter 2026-04-10 16:13:56 -10:00
J. Nick Koston e820d485e2 [esphome.ota] TEMP: keep loop enabled to trace wake/ready flow 2026-04-10 16:08:00 -10:00
J. Nick Koston f92c745ae9 [esphome.ota] TEMP: debug logging to diagnose wake/accept race 2026-04-10 16:01:07 -10:00
J. Nick Koston 06285dbb75 [esphome.ota] Comment host wake path as currently dead code 2026-04-10 15:43:10 -10:00
J. Nick Koston ae54f3e071 [esphome.ota] Drop explicit disable_loop() from setup, let loop() self-disable 2026-04-10 15:42:32 -10:00
J. Nick Koston ffbd0dcbfc [esphome.ota] Set pending-enable flags before main-loop wake (fix race)
The wake-hook call (esphome_wake_ota_component_any_context / App.wake_ota_component_any_context)
was placed AFTER xTaskNotifyGive()/wake_loop_any_context() in both the fast-select callback and
the raw-TCP accept callback. That opened a race: the main task could wake, run a full iteration
(draining has_pending_enable_loop_requests_), and finish before the flag-set ran — losing the
pending-enable request until the next unrelated socket event happened to re-trigger the path.

Swap the order so the pending-enable flags are set first, then the main task is woken. The
main-loop iteration triggered by the wake is now guaranteed to see the pending request.

Note: host's yield_with_select_ path already sets and consumes the flag on the main thread
with no cross-task wake in between, so it has no race and is unchanged.
2026-04-10 15:41:57 -10:00
J. Nick Koston 903a159344 [esphome.ota] Fix loop() docstring to reflect cleanup no longer disables 2026-04-10 14:52:12 -10:00
J. Nick Koston 92f93e128f [esphome.ota] Drop unnecessary IRAM_ATTR from wake hook
The wake hook is called only from:
  - esphome_socket_event_callback (lwip fast select, LwIP TCP/IP task context)
  - LWIPRawListenImpl::accept_fn_ (raw TCP accept callback)
  - Application::yield_with_select_ (host select fallback, main thread)

None of those contexts require IRAM-resident code. The LwIP fast-select
event callback itself is not IRAM_ATTR; the raw-TCP accept callback runs
from a low-priority user IRQ on RP2040 where IRAM_ATTR is a no-op anyway
(it's an ESP32-specific section attribute for code that must run while
flash cache is disabled). This is not a real ISR path the way
enable_loop_soon_any_context() is (which is called from GPIO ISRs and
genuinely does need IRAM).

Removing IRAM_ATTR frees scarce IRAM on ESP32.
2026-04-10 14:47:52 -10:00
J. Nick Koston af8fd1d060 [esphome.ota] Fix cleanup race, tighten error message and comments, add tests
Addresses copilot review on #15636.

1. Fix cleanup_connection_() race with queued listener events.
   While an OTA session was active, a second incoming connection would
   fire esphome_socket_event_callback → esphome_wake_ota_component_any_context,
   which sets pending_enable_loop_ on the (still-active) OTA component.
   enable_pending_loops_() only scans the inactive section, so that flag
   goes invisible. When cleanup_connection_() then called disable_loop(),
   the component dropped to LOOP_DONE with a stale pending flag and
   nothing to re-trigger the scan — the queued client sat forever until
   some unrelated socket activity woke the main loop.

   Fix: don't call disable_loop() from cleanup_connection_(). loop() has
   the idempotent idle check at its top; one more dispatch after cleanup
   is cheap and guarantees we re-read server_->ready() and either accept
   the queued client or disable cleanly.

2. Tighten the multi-port error message. Merging is fine — the constraint
   is single-port. Reworded: "Only a single port is supported for 'ota'
   'platform: esphome'. Got ports [...]. Consolidate onto a single port;
   configs sharing a port are merged automatically."

3. Comment drift: three call sites and the fast-select extern declaration
   still referred to enable_loop_soon_any_context() and implied the hook
   wakes the main loop. Updated to reflect the current mechanism (sets
   pending-enable flags only; callers have already woken the main loop).
   Also clarified that esphome_wake_ota_component_any_context fires on
   every RCVPLUS event across all monitored sockets, so false wakes are
   expected and OTA::loop() disables itself again when idle.

4. Added tests/component_tests/ota/test_esphome_ota.py covering
   ota_esphome_final_validate: single instance accepted, same-port
   configs merge, different-port configs rejected with cv.Invalid,
   non-esphome platforms unaffected.
2026-04-10 14:29:32 -10:00
J. Nick Koston ae9c5bab80 [esphome.ota] Drop narrative comment from multi-port validator 2026-04-10 14:11:19 -10:00
J. Nick Koston 0f8419f97d [esphome.ota] Reject multi-port esphome OTA, drop redundant wake
Address copilot review on #15636.

1. Enforce single ESPHome OTA instance (BREAKING CHANGE).
   The `ota_esphome_final_validate` hook has always merged multiple
   `ota: - platform: esphome` configs by port so a user config and a
   remote package that both define OTA would merge rather than break.
   That merge behavior is preserved. But if two configs survive on
   *different* ports they produce two independent listening sockets,
   which is not a sane deployment: it creates ambiguity for safe_mode
   coordination and for the socket wake hook added in this PR.
   Raise cv.Invalid when more than one port remains after merging.

2. Drop redundant main-loop wake in Application::wake_ota_component_any_context.
   Every caller (lwip fast-select callback already calls xTaskNotifyGive,
   raw-tcp accept callback already calls wake_loop_any_context(), host
   path is already running post-select in the main loop) has woken the
   main loop by the time we reach this hook. Calling
   enable_loop_soon_any_context() would re-wake it. Application is a
   friend of Component, so set pending_enable_loop_ and
   has_pending_enable_loop_requests_ directly instead.
2026-04-10 14:09:27 -10:00
J. Nick Koston 5b84ad5926 [esphome.ota] Disable loop while idle, wake on listening-socket activity
ESPHomeOTAComponent::loop() previously ran every main-loop tick just to
check `client_ != nullptr || server_->ready()` — a wasted dispatch on
every device, since OTA is idle the vast majority of the time.

OTA now disables its own loop after setup() and after cleanup_connection_().
A single 4-byte Component* slot in Application (only compiled in under
USE_OTA) lets the existing socket-wake paths call
enable_loop_soon_any_context() on the registered OTA component:

  - ESP32 / LibreTiny (lwip fast select): hooked in
    esphome_socket_event_callback on NETCONN_EVT_RCVPLUS.
  - ESP8266 / RP2040 (raw TCP): hooked in LWIPRawListenImpl::accept_fn_
    right after the existing wake_loop_any_context() call.
  - Host (select fallback): called after select() returns ready in
    Application::yield_with_select_.

False wakes (e.g. an API-socket event firing the fast-select callback)
land in ESPHomeOTAComponent::loop(), which re-disables itself immediately
when idle. Net cost is still far below running every tick.

This is deliberately an OTA-only hook: OTA is the only component that
benefits, and a single global slot avoids adding per-socket Component*
storage, wake-callback lists, or any new API churn to the socket layer.
2026-04-10 13:24:32 -10:00
J. Nick Koston 40081e5ae7 [rp2040] Fix W5500 Ethernet pbuf corruption by mirroring LWIPMutex semantics (#15624)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-10 13:13:05 -10:00
Jonathan Swoboda a7c5b0ab46 [sx127x][cc1101][sx126x] Use GPIO interrupt to wake loop (#15627) 2026-04-10 16:26:09 -04:00
dependabot[bot] e1a813e11f Bump peter-evans/create-pull-request from 8.1.0 to 8.1.1 (#15630)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 10:21:01 -10:00
dependabot[bot] 1dfeef0265 Bump actions/github-script from 8.0.0 to 9.0.0 (#15632)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 10:20:43 -10:00
dependabot[bot] 395610c117 Bump docker/build-push-action from 7.0.0 to 7.1.0 in /.github/actions/build-image (#15633)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 10:20:17 -10:00
dependabot[bot] ae96f82b82 Bump actions/upload-artifact from 7.0.0 to 7.0.1 (#15631)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 10:20:04 -10:00
dependabot[bot] 2c610abcd0 Bump resvg-py from 0.2.6 to 0.3.0 (#15629)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 10:19:52 -10:00
Kevin Ahrendt d3591c8d9e [micro_wake_word] Pin esp-nn version (#15628) 2026-04-10 15:21:26 -04:00
J. Nick Koston ec420d5792 [api] Add (inline_encode) proto option for sub-message inlining (#15599) 2026-04-10 15:33:56 +12:00
J. Nick Koston 17209df7b5 [mcp23016] Add interrupt pin support (#15616) 2026-04-10 15:29:52 +12:00
J. Nick Koston 9cf9b02ba2 [pca6416a] Add interrupt pin support (#15614) 2026-04-10 15:29:26 +12:00
J. Nick Koston c90fa2378a [tca9555] Add interrupt pin support (#15613) 2026-04-10 15:29:00 +12:00
Jesse Hills c04dfa922e [hbridge] Move light pin switching to loop (#15615) 2026-04-10 14:02:49 +12:00
Jesse Hills 668007707d [CI] Add org fork detection warning to auto-label PR workflow (#15588) 2026-04-10 12:13:22 +12:00
dependabot[bot] ab71f5276f Bump ruff from 0.15.9 to 0.15.10 (#15609)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-04-09 19:36:25 +00:00
Jonathan Swoboda d062f62656 [sx127x][cc1101] Disable loop when packet mode is inactive (#15606) 2026-04-09 15:00:52 -04:00
J. Nick Koston 03db32d045 [core] Add CodSpeed benchmarks for hot helper functions (#15593) 2026-04-09 07:48:32 -10:00
J. Nick Koston 8f6d489a9a [ci] Use --base-only for memory impact builds (#15598) 2026-04-09 11:48:33 -04:00
J. Nick Koston dd07fba943 [socket] Document ready() contract: callers must drain or track (#15590) 2026-04-09 11:48:18 -04:00
J. Nick Koston 6f5d642a31 [gdk101] Increase reset retries for slow-booting sensor MCU (#15584) 2026-04-09 11:48:10 -04:00
dependabot[bot] 2721f08bcc Bump aioesphomeapi from 44.12.0 to 44.13.1 (#15600)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-09 10:03:58 +00:00
J. Nick Koston eafc5df3f2 [safe_mode] Combine related OTA rollback log messages (#15592) 2026-04-09 05:30:39 +00:00
J. Nick Koston 46d0c29be5 [safe_mode] Use loop component start time instead of millis() (#15591) 2026-04-09 05:20:32 +00:00
J. Nick Koston abdbbf4dd2 [api] Fix ListEntitiesRequest not read due to LWIP rcvevent tracking (#15589) 2026-04-09 02:14:01 +00:00
Jesse Hills 4dc0599a7d Merge branch 'beta' into dev 2026-04-09 13:41:27 +12:00
Jesse Hills ded0936b2a Merge pull request #15587 from esphome/bump-2026.4.0b1
2026.4.0b1
2026.4.0b1
2026-04-09 13:40:37 +12:00
Jesse Hills 52c35ec09c Bump version to 2026.5.0-dev 2026-04-09 11:28:48 +12:00
J. Nick Koston 76490e45bc [ci] Fix status-check-labels workflow flooding CI queue (#15585) 2026-04-08 13:08:29 -10:00
Angel Nunez Mencias 0a8130858c [ade7953_spi] Fix SPI mode on esp-idf (#14824)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-04-08 22:57:53 +00:00
Jesse Hills ff5ba99d16 Bump version to 2026.4.0b1 2026-04-09 10:39:13 +12:00
Clyde Stubbs 14ec82084b [rpi_dpi_rgb][qspi_dbi] Add deprecation warnings (#15583) 2026-04-09 10:35:09 +12:00
J. Nick Koston 8e02d0a20e [fan] Store preset mode vector on Fan entity to eliminate heap allocation (#15209) 2026-04-09 10:25:37 +12:00
J. Nick Koston faa05031a7 [climate] Store custom mode vectors on Climate entity to eliminate heap allocation (#15206) 2026-04-09 10:25:29 +12:00
J. Nick Koston d4cce142c5 [api] Fix batch messages stuck in Nagle buffer (#15581) 2026-04-08 21:11:31 +00:00
J. Nick Koston 576d89a82a [api] Peel first write iteration, inline socket writes, zero-gap batch encoding (#15063) 2026-04-08 11:05:53 -10:00
J. Nick Koston 4a18ef87d7 [codegen] Fix templatable float type to use cg.float_ (#15568) 2026-04-08 20:23:36 +00:00
Jonathan Swoboda 2cd92a311b [esp32] Capture both cores' backtraces in crash handler (#15559)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-04-08 20:14:18 +00:00