From 58329c52de78f1097d5e552d3517c1b2b48abec4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 5 Mar 2026 00:37:42 -1000 Subject: [PATCH] bump --- .clang-tidy.hash | 2 +- esphome/components/rp2040/__init__.py | 6 +-- .../components/wifi/wifi_component_pico_w.cpp | 44 +++++++++++++++++-- platformio.ini | 2 +- 4 files changed, 45 insertions(+), 9 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 767da3f33e..adcebadeb4 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -b97e16a84153b2a4cfc51137cd6121db3c32374504b2bea55144413b3e573052 +b6f8c16c1ddd222134bf4a71910b4c832e764e23caf49f9bce3280b079955fcf diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index ea269a47c5..1442a0a7f7 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -91,7 +91,7 @@ def _parse_platform_version(value): # The default/recommended arduino framework version # - https://github.com/earlephilhower/arduino-pico/releases # - https://api.registry.platformio.org/v3/packages/earlephilhower/tool/framework-arduinopico -RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(5, 5, 0) +RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(5, 5, 1) # The raspberrypi platform version to use for arduino frameworks # - https://github.com/maxgerhardt/platform-raspberrypi/tags @@ -101,8 +101,8 @@ RECOMMENDED_ARDUINO_PLATFORM_VERSION = "v1.4.0-gcc14-arduinopico460" def _arduino_check_versions(value): value = value.copy() lookups = { - "dev": (cv.Version(5, 5, 0), "https://github.com/earlephilhower/arduino-pico"), - "latest": (cv.Version(5, 5, 0), None), + "dev": (cv.Version(5, 5, 1), "https://github.com/earlephilhower/arduino-pico"), + "latest": (cv.Version(5, 5, 1), None), "recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None), } diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index b9758b6963..dd56170493 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -23,7 +23,19 @@ static const char *const TAG = "wifi_pico_w"; // unconditionally return true regardless of STA state, causing false positives // when the fallback AP is active. static bool wifi_sta_connected() { - return cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA) == CYW43_LINK_JOIN && WiFi.localIP().isSet(); + int link = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA); + bool ip_set = WiFi.localIP().isSet(); + if (link == CYW43_LINK_JOIN && ip_set) { + // Verify the IP is a real STA IP, not the AP's IP leaking through + IPAddress local = WiFi.localIP(); + IPAddress ap_ip = WiFi.softAPIP(); + if (local == ap_ip) { + ESP_LOGV(TAG, "wifi_sta_connected: localIP %s matches AP IP, ignoring", local.toString().c_str()); + return false; + } + return true; + } + return false; } // Track previous state for detecting changes @@ -32,6 +44,8 @@ static bool s_sta_had_ip = false; // NOLINT(cppcoreguidelines-avoid-non- static size_t s_scan_result_count = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) bool WiFiComponent::wifi_mode_(optional sta, optional ap) { + ESP_LOGD(TAG, "wifi_mode_(sta=%s, ap=%s)", sta.has_value() ? (sta.value() ? "true" : "false") : "nullopt", + ap.has_value() ? (ap.value() ? "true" : "false") : "nullopt"); if (sta.has_value()) { if (sta.value()) { cyw43_wifi_set_up(&cyw43_state, CYW43_ITF_STA, true, CYW43_COUNTRY_WORLDWIDE); @@ -86,12 +100,19 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { return false; #endif + ESP_LOGD(TAG, "wifi_sta_connect_: STA link=%d, WiFi.status()=%d, mode=%d, localIP=%s, softAPIP=%s", + cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA), WiFi.status(), (int) WiFi.getMode(), + WiFi.localIP().toString().c_str(), WiFi.softAPIP().toString().c_str()); + // Use beginNoBlock to avoid WiFi.begin()'s additional 2x timeout wait loop on top of // CYW43::begin()'s internal blocking join. CYW43::begin() blocks for up to 10 seconds // (default timeout) to complete the join - this is required because the LwipIntfDev netif // setup depends on begin() succeeding. beginNoBlock() skips the outer wait loop, saving // up to 20 additional seconds of blocking per attempt. auto ret = WiFi.beginNoBlock(ap.ssid_.c_str(), ap.password_.c_str()); + ESP_LOGD(TAG, "wifi_sta_connect_: beginNoBlock returned %d, STA link=%d, mode=%d, localIP=%s", ret, + cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA), (int) WiFi.getMode(), + WiFi.localIP().toString().c_str()); if (ret == WL_IDLE_STATUS) return false; @@ -135,6 +156,9 @@ WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { // flags and would only fall through to cyw43_wifi_link_status when the flags aren't set. // Using cyw43_wifi_link_status directly gives us the actual WiFi radio join state. int status = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA); + int ap_status = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_AP); + ESP_LOGV(TAG, "connect_status: STA link=%d, AP link=%d, localIP=%s, softAPIP=%s, WiFi.status()=%d", status, ap_status, + WiFi.localIP().toString().c_str(), WiFi.softAPIP().toString().c_str(), WiFi.status()); switch (status) { case CYW43_LINK_JOIN: // WiFi joined, check if STA has an IP address via wifi_sta_connected() @@ -205,6 +229,9 @@ bool WiFiComponent::wifi_ap_ip_config_(const optional &manual_ip) { } bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { + ESP_LOGD(TAG, "wifi_start_ap_: STA link=%d, AP link=%d, WiFi.status()=%d, mode=%d, localIP=%s", + cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA), cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_AP), + WiFi.status(), (int) WiFi.getMode(), WiFi.localIP().toString().c_str()); if (!this->wifi_mode_({}, true)) return false; #ifdef USE_WIFI_MANUAL_IP @@ -220,6 +247,8 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { #endif WiFi.beginAP(ap.ssid_.c_str(), ap.password_.c_str(), ap.has_channel() ? ap.get_channel() : 1); + ESP_LOGD(TAG, "wifi_start_ap_: after beginAP, WiFi.status()=%d, mode=%d, softAPIP=%s, localIP=%s", WiFi.status(), + (int) WiFi.getMode(), WiFi.softAPIP().toString().c_str(), WiFi.localIP().toString().c_str()); return true; } @@ -228,9 +257,16 @@ network::IPAddress WiFiComponent::wifi_soft_ap_ip() { return {(const ip_addr_t * #endif // USE_WIFI_AP bool WiFiComponent::wifi_disconnect_() { - // Use Arduino WiFi.disconnect() instead of raw cyw43_wifi_leave() to properly - // clean up the lwIP netif, DHCP client, and internal Arduino state. - WiFi.disconnect(); + // Use cyw43_wifi_leave() directly instead of WiFi.disconnect(). + // WiFi.disconnect() sets _wifiHWInitted=false and _mode=WIFI_OFF in the Arduino + // framework, which causes WiFi.beginAP() to enter AP-only mode (IP 192.168.42.1) + // instead of AP_STA mode (IP 192.168.4.1). In AP-only mode, _beginInternal() + // redirects all subsequent STA connect attempts to beginAP() via the ESP8266 + // compat hack, creating an infinite connect/disconnect loop. + ESP_LOGD(TAG, "wifi_disconnect_: STA link=%d, AP link=%d, WiFi.status()=%d, mode=%d", + cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA), cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_AP), + WiFi.status(), (int) WiFi.getMode()); + cyw43_wifi_leave(&cyw43_state, CYW43_ITF_STA); return true; } diff --git a/platformio.ini b/platformio.ini index 16a1b18211..87f992759c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -196,7 +196,7 @@ board_build.filesystem_size = 0.5m platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.4.0-gcc14-arduinopico460 platform_packages = ; earlephilhower/framework-arduinopico@~1.20602.0 ; Cannot use the platformio package until old releases stop getting deleted - earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/5.5.0/rp2040-5.5.0.zip + earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/5.5.1/rp2040-5.5.1.zip framework = arduino lib_deps =