Replace the poll-based busy-wait introduced in #15662 with a call to
Arduino's 1-arg esp_delay(), which uses os_timer + esp_suspend to
properly suspend the cont task for the requested duration.
The busy-wait only yielded via optimistic_yield(1000) once 1 ms had
elapsed since the last task switch, so short waits like delay(1) often
finished without ever yielding. That starved the SDK and extended
interrupt latency, breaking timing sensitive interrupt-driven code such
as the ESP8266 software-serial RX path used by fingerprint_grow.
esp_delay()'s 1-arg form does not itself call millis(), so the slow
Arduino millis() body is not pulled into IRAM by this path; the
--wrap=millis goal of #15662 is preserved.
Fixes#16558
The ESP8266 software serial GPIO ISR decodes a full byte into the
RX buffer, then returns. With the 2026.5.0 loop cadence change the
byte may sit unread for up to one loop_interval_ tick (~16 ms),
which breaks timing-sensitive components (e.g. fingerprint_grow)
that poll read() in a tight setup() loop and time out before bytes
appear.
Call wake_loop_isrsafe() from the ISR after the byte is buffered,
mirroring the ESP-IDF UART path (and the same pattern ratgdo uses
via SoftwareSerial::onReceive). The wake call is a single inline
flag set plus esp_schedule(); IRAM-safe and essentially free.
Gated on USE_UART_WAKE_LOOP_ON_RX, now enabled by default for
ESP8266 (in addition to ESP32) when networking is configured.
Pull encode_to_buffer and get_batch_delay_ms_ out of the tail of
api_server.h into a dedicated api_connection_buffer.h so api_server.h no
longer carries APIConnection method bodies. api_connection.cpp includes
api_connection_buffer.h instead of api_server.h; the new header pulls
api_server.h in to keep APIServer complete at the inline-definition site.
No behavioral change; just file organisation on top of the previous
include-cycle break.
api_connection.h now forward-declares APIServer instead of including
api_server.h, and api_server.h includes api_connection.h before clients_
is declared. With APIConnection complete at that point, libc++ no longer
trips the incomplete-type assert in default_delete<APIConnection> when
parsing std::array<unique_ptr<APIConnection>, MAX_API_CONNECTIONS>, so
the custom APIConnectionDeleter introduced in #16050 is no longer needed.
The two APIConnection inline methods that touched APIServer
(encode_to_buffer, get_batch_delay_ms_) are now defined at the bottom of
api_server.h, where APIServer is complete; api_connection.cpp gains a
direct include of api_server.h so those definitions are visible there.
Verified locally on macOS host platform with python3.14 -m esphome
compile (the path that reproduces the libc++ error). Noise and plaintext
integration tests pass.