diff --git a/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp b/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp index 19eaa703f501ac..e1e26ba982e192 100644 --- a/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp +++ b/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp @@ -56,7 +56,9 @@ ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMod if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled) { wifi_mode_t curWiFiMode; - mWiFiStationMode = (esp_wifi_get_mode(&curWiFiMode) == ESP_OK && (curWiFiMode == WIFI_MODE_STA)) + mWiFiStationMode = + (esp_wifi_get_mode(&curWiFiMode) == ESP_OK && (curWiFiMode == WIFI_MODE_APSTA || curWiFiMode == WIFI_MODE_STA)) + ? kWiFiStationMode_Enabled : kWiFiStationMode_Disabled; } @@ -76,6 +78,8 @@ CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(WiFiStationMode val) if (val != kWiFiStationMode_ApplicationControlled) { + ReturnErrorOnFailure(Internal::ESP32Utils::EnableStationMode()); + DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); } @@ -332,6 +336,9 @@ CHIP_ERROR ConnectivityManagerImpl::InitWiFi() // TODO Initialize the Chip Addressing and Routing Module. + // Ensure that ESP station mode is enabled. + ReturnErrorOnFailure(Internal::ESP32Utils::EnableStationMode()); + // If there is no persistent station provision... if (!IsWiFiStationProvisioned()) { @@ -366,6 +373,7 @@ CHIP_ERROR ConnectivityManagerImpl::InitWiFi() } } + ReturnErrorOnFailure(Internal::ESP32Utils::MapError(esp_wifi_set_mode(WIFI_MODE_STA))); // Queue work items to bootstrap the AP and station state machines once the Chip event loop is running. ReturnErrorOnFailure(DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL)); @@ -469,6 +477,9 @@ void ConnectivityManagerImpl::DriveStationState() { // Ensure that the ESP WiFi layer is started. ReturnOnFailure(Internal::ESP32Utils::StartWiFiLayer()); + + // Ensure that station mode is enabled in the ESP WiFi layer. + ReturnOnFailure(Internal::ESP32Utils::EnableStationMode()); } // Determine if the ESP WiFi layer thinks the station interface is currently connected. diff --git a/src/platform/ESP32/ESP32Utils.cpp b/src/platform/ESP32/ESP32Utils.cpp index 1e45a31bf89c90..9aef5c706610d4 100644 --- a/src/platform/ESP32/ESP32Utils.cpp +++ b/src/platform/ESP32/ESP32Utils.cpp @@ -53,6 +53,36 @@ CHIP_ERROR ESP32Utils::IsStationEnabled(bool & staEnabled) return CHIP_NO_ERROR; } +CHIP_ERROR ESP32Utils::EnableStationMode(void) +{ + wifi_mode_t curWiFiMode; + + // Get the current ESP WiFI mode. + esp_err_t err = esp_wifi_get_mode(&curWiFiMode); + if (err != ESP_OK) + { + ChipLogError(DeviceLayer, "esp_wifi_get_mode() failed: %s", esp_err_to_name(err)); + return ESP32Utils::MapError(err); + } + + // If station mode is not already enabled (implying the current mode is WIFI_MODE_AP), change + // the mode to WIFI_MODE_APSTA. + if (curWiFiMode == WIFI_MODE_AP) + { + ChipLogProgress(DeviceLayer, "Changing ESP WiFi mode: %s -> %s", WiFiModeToStr(WIFI_MODE_AP), + WiFiModeToStr(WIFI_MODE_APSTA)); + + err = esp_wifi_set_mode(WIFI_MODE_APSTA); + if (err != ESP_OK) + { + ChipLogError(DeviceLayer, "esp_wifi_set_mode() failed: %s", esp_err_to_name(err)); + return ESP32Utils::MapError(err); + } + } + + return CHIP_NO_ERROR; +} + bool ESP32Utils::IsStationProvisioned(void) { wifi_config_t stationConfig; @@ -126,6 +156,10 @@ const char * ESP32Utils::WiFiModeToStr(wifi_mode_t wifiMode) return "NULL"; case WIFI_MODE_STA: return "STA"; + case WIFI_MODE_AP: + return "AP"; + case WIFI_MODE_APSTA: + return "STA+AP"; default: return "(unknown)"; } @@ -173,6 +207,10 @@ CHIP_ERROR ESP32Utils::SetWiFiStationProvision(const Internal::DeviceNetworkInfo char wifiSSID[kMaxWiFiSSIDLength + 1]; size_t netInfoSSIDLen = strlen(netInfo.WiFiSSID); + // Ensure that ESP station mode is enabled. This is required before esp_wifi_set_config(ESP_IF_WIFI_STA,...) + // can be called. + ReturnErrorOnFailure(ESP32Utils::EnableStationMode()); + // Enforce that wifiSSID is null terminated before copying it memcpy(wifiSSID, netInfo.WiFiSSID, min(netInfoSSIDLen + 1, sizeof(wifiSSID))); if (netInfoSSIDLen + 1 < sizeof(wifiSSID)) @@ -244,18 +282,6 @@ CHIP_ERROR ESP32Utils::InitWiFiStack(void) return ESP32Utils::MapError(err); } - esp_wifi_get_mode(&mode); - if (mode == WIFI_MODE_AP) - { - esp_fill_random(ap_mac, sizeof(ap_mac)); - /* Bit 0 of the first octet of MAC Address should always be 0 */ - ap_mac[0] &= (uint8_t) ~0x01; - err = esp_wifi_set_mac(WIFI_IF_AP, ap_mac); - if (err != ESP_OK) - { - return ESP32Utils::MapError(err); - } - } err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, PlatformManagerImpl::HandleESPSystemEvent, NULL); if (err != ESP_OK) { diff --git a/src/platform/ESP32/ESP32Utils.h b/src/platform/ESP32/ESP32Utils.h index 2bbbe851b097b2..498a41033335b9 100644 --- a/src/platform/ESP32/ESP32Utils.h +++ b/src/platform/ESP32/ESP32Utils.h @@ -33,6 +33,7 @@ class ESP32Utils static bool IsStationProvisioned(void); static CHIP_ERROR IsStationConnected(bool & connected); static CHIP_ERROR StartWiFiLayer(void); + static CHIP_ERROR EnableStationMode(void); static int OrderScanResultsByRSSI(const void * _res1, const void * _res2); static const char * WiFiModeToStr(wifi_mode_t wifiMode); static struct netif * GetNetif(const char * ifKey);