From e160fcce0ea26b062edeb3a86050ad1120b5f4fd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 10 Dec 2025 03:51:20 +0100 Subject: [PATCH] fixes --- .../components/socket/lwip_raw_tcp_impl.cpp | 23 ++++++++++++++++--- esphome/components/socket/socket.h | 9 ++++++++ esphome/core/application.cpp | 7 ++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 197acb8030..9e3392bf6e 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -21,6 +21,24 @@ namespace esphome { namespace socket { +#ifdef USE_ESP8266 +// Flag to signal socket activity - checked by socket_delay() to exit early +static volatile bool s_socket_woke = false; + +void socket_delay(uint32_t ms) { + // Use esp_delay with a callback that checks if socket data arrived. + // This allows the delay to exit early when socket_wake() is called by + // lwip recv_fn/accept_fn callbacks, reducing socket latency. + s_socket_woke = false; + esp_delay(ms, []() { return !s_socket_woke; }); +} + +void socket_wake() { + s_socket_woke = true; + esp_schedule(); +} +#endif + static const char *const TAG = "socket.lwip"; // set to 1 to enable verbose lwip logging @@ -483,8 +501,7 @@ class LWIPRawImpl : public Socket { } #ifdef USE_ESP8266 // Wake the main loop immediately so it can process the received data. - // esp_schedule() wakes the context blocked in delay() -> esp_suspend(). - esp_schedule(); + socket_wake(); #endif return ERR_OK; } @@ -648,7 +665,7 @@ class LWIPRawListenImpl : public LWIPRawImpl { LWIP_LOG("Accepted connection, queue size: %d", accepted_socket_count_); #ifdef USE_ESP8266 // Wake the main loop immediately so it can accept the new connection. - esp_schedule(); + socket_wake(); #endif return ERR_OK; } diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index 78a89fe008..8936b2cd10 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -82,6 +82,15 @@ socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::stri /// Set a sockaddr to the any address and specified port for the IP version used by socket_ip(). socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port); +#if defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) +/// Delay that can be woken early by socket activity. +/// On ESP8266, lwip callbacks set a flag and call esp_schedule() to wake the delay. +void socket_delay(uint32_t ms); + +/// Called by lwip callbacks to signal socket activity and wake delay. +void socket_wake(); +#endif + } // namespace socket } // namespace esphome #endif diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 75814ae253..a85d671a07 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -12,6 +12,10 @@ #include "esphome/components/status_led/status_led.h" #endif +#if defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) +#include "esphome/components/socket/socket.h" +#endif + #ifdef USE_SOCKET_SELECT_SUPPORT #include @@ -627,6 +631,9 @@ void Application::yield_with_select_(uint32_t delay_ms) { // No sockets registered, use regular delay delay(delay_ms); } +#elif defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) + // No select support but can wake on socket activity via esp_schedule() + socket::socket_delay(delay_ms); #else // No select support, use regular delay delay(delay_ms);