3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2018 Nest Labs, Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 /* this file behaves like a config.h, comes first */
20 #include <platform/internal/CHIPDeviceLayerInternal.h>
22 #include <platform/ConnectivityManager.h>
23 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
24 #include <platform/internal/GenericConnectivityManagerImpl_BLE.cpp>
26 #include <platform/internal/GenericConnectivityManagerImpl_WiFi.cpp>
28 #include <platform/ESP32/ESP32Utils.h>
29 #include <platform/internal/BLEManager.h>
30 #include <support/CodeUtils.h>
31 #include <support/logging/CHIPLogging.h>
33 #include "esp_event.h"
34 #include "esp_netif.h"
38 #include <lwip/ip_addr.h>
40 #include <lwip/netif.h>
42 #include <type_traits>
44 #if !CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
45 #error "WiFi Station support must be enabled when building for ESP32"
48 #if !CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
49 #error "WiFi AP support must be enabled when building for ESP32"
52 using namespace ::chip;
53 using namespace ::chip::Inet;
54 using namespace ::chip::System;
55 using namespace ::chip::TLV;
58 namespace DeviceLayer {
60 ConnectivityManagerImpl ConnectivityManagerImpl::sInstance;
62 ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMode(void)
64 if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled)
66 wifi_mode_t curWiFiMode;
68 (esp_wifi_get_mode(&curWiFiMode) == ESP_OK && (curWiFiMode == WIFI_MODE_APSTA || curWiFiMode == WIFI_MODE_STA))
69 ? kWiFiStationMode_Enabled
70 : kWiFiStationMode_Disabled;
72 return mWiFiStationMode;
75 bool ConnectivityManagerImpl::_IsWiFiStationEnabled(void)
77 return GetWiFiStationMode() == kWiFiStationMode_Enabled;
80 CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(WiFiStationMode val)
82 CHIP_ERROR err = CHIP_NO_ERROR;
84 VerifyOrExit(val != kWiFiStationMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
86 if (val != kWiFiStationMode_ApplicationControlled)
88 bool autoConnect = (val == kWiFiStationMode_Enabled);
89 err = Internal::ESP32Utils::SetAPMode(autoConnect);
92 SystemLayer.ScheduleWork(DriveStationState, NULL);
95 if (mWiFiStationMode != val)
97 ChipLogProgress(DeviceLayer, "WiFi station mode change: %s -> %s", WiFiStationModeToStr(mWiFiStationMode),
98 WiFiStationModeToStr(val));
101 mWiFiStationMode = val;
107 bool ConnectivityManagerImpl::_IsWiFiStationProvisioned(void)
109 return Internal::ESP32Utils::IsStationProvisioned();
112 void ConnectivityManagerImpl::_ClearWiFiStationProvision(void)
114 if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled)
116 wifi_config_t stationConfig;
118 memset(&stationConfig, 0, sizeof(stationConfig));
119 esp_wifi_set_config(WIFI_IF_STA, &stationConfig);
121 SystemLayer.ScheduleWork(DriveStationState, NULL);
122 SystemLayer.ScheduleWork(DriveAPState, NULL);
126 CHIP_ERROR ConnectivityManagerImpl::_SetWiFiAPMode(WiFiAPMode val)
128 CHIP_ERROR err = CHIP_NO_ERROR;
130 VerifyOrExit(val != kWiFiAPMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
132 if (mWiFiAPMode != val)
134 ChipLogProgress(DeviceLayer, "WiFi AP mode change: %s -> %s", WiFiAPModeToStr(mWiFiAPMode), WiFiAPModeToStr(val));
139 SystemLayer.ScheduleWork(DriveAPState, NULL);
145 void ConnectivityManagerImpl::_DemandStartWiFiAP(void)
147 if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
149 mLastAPDemandTime = System::Layer::GetClock_MonotonicMS();
150 SystemLayer.ScheduleWork(DriveAPState, NULL);
154 void ConnectivityManagerImpl::_StopOnDemandWiFiAP(void)
156 if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
158 mLastAPDemandTime = 0;
159 SystemLayer.ScheduleWork(DriveAPState, NULL);
163 void ConnectivityManagerImpl::_MaintainOnDemandWiFiAP(void)
165 if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
167 if (mWiFiAPState == kWiFiAPState_Activating || mWiFiAPState == kWiFiAPState_Active)
169 mLastAPDemandTime = System::Layer::GetClock_MonotonicMS();
174 void ConnectivityManagerImpl::_SetWiFiAPIdleTimeoutMS(uint32_t val)
176 mWiFiAPIdleTimeoutMS = val;
177 SystemLayer.ScheduleWork(DriveAPState, NULL);
180 #define WIFI_BAND_2_4GHZ 2400
181 #define WIFI_BAND_5_0GHZ 5000
183 static uint16_t Map2400MHz(const uint8_t inChannel)
185 uint16_t frequency = 0;
187 if (inChannel >= 1 && inChannel <= 13)
189 // Cast is OK because we definitely fit in 16 bits.
190 frequency = static_cast<uint16_t>(2412 + ((inChannel - 1) * 5));
192 else if (inChannel == 14)
200 static uint16_t Map5000MHz(const uint8_t inChannel)
202 uint16_t frequency = 0;
338 static uint16_t MapFrequency(const uint16_t inBand, const uint8_t inChannel)
340 uint16_t frequency = 0;
342 if (inBand == WIFI_BAND_2_4GHZ)
344 frequency = Map2400MHz(inChannel);
346 else if (inBand == WIFI_BAND_5_0GHZ)
348 frequency = Map5000MHz(inChannel);
354 CHIP_ERROR ConnectivityManagerImpl::_GetAndLogWifiStatsCounters(void)
357 wifi_config_t wifiConfig;
358 uint8_t primaryChannel;
359 wifi_second_chan_t secondChannel;
363 err = esp_wifi_get_config(WIFI_IF_STA, &wifiConfig);
366 ChipLogError(DeviceLayer, "esp_wifi_get_config() failed: %s", ErrorStr(err));
370 err = esp_wifi_get_channel(&primaryChannel, &secondChannel);
373 ChipLogError(DeviceLayer, "esp_wifi_get_channel() failed: %s", ErrorStr(err));
377 freq = MapFrequency(WIFI_BAND_2_4GHZ, primaryChannel);
378 static_assert(std::is_same<std::remove_reference<decltype(wifiConfig.sta.bssid[5])>::type, uint8_t>::value,
379 "Our bits are going to start overlapping");
380 bssid = static_cast<uint16_t>((wifiConfig.sta.bssid[4] << 8) | wifiConfig.sta.bssid[5]);
381 ChipLogProgress(DeviceLayer,
387 return CHIP_NO_ERROR;
390 // ==================== ConnectivityManager Platform Internal Methods ====================
392 CHIP_ERROR ConnectivityManagerImpl::_Init()
396 mLastStationConnectFailTime = 0;
397 mLastAPDemandTime = 0;
398 mWiFiStationMode = kWiFiStationMode_Disabled;
399 mWiFiStationState = kWiFiStationState_NotConnected;
400 mWiFiAPMode = kWiFiAPMode_Disabled;
401 mWiFiAPState = kWiFiAPState_NotActive;
402 mWiFiStationReconnectIntervalMS = CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL;
403 mWiFiAPIdleTimeoutMS = CHIP_DEVICE_CONFIG_WIFI_AP_IDLE_TIMEOUT;
406 // TODO Initialize the Chip Addressing and Routing Module.
408 // Ensure that ESP station mode is enabled.
409 err = Internal::ESP32Utils::EnableStationMode();
412 // If there is no persistent station provision...
413 if (!IsWiFiStationProvisioned())
415 // If the code has been compiled with a default WiFi station provision, configure that now.
416 if (CONFIG_DEFAULT_WIFI_SSID[0] != 0)
418 ChipLogProgress(DeviceLayer, "Setting default WiFi station configuration (SSID: %s)", CONFIG_DEFAULT_WIFI_SSID);
420 // Set a default station configuration.
421 wifi_config_t wifiConfig;
422 memset(&wifiConfig, 0, sizeof(wifiConfig));
423 memcpy(wifiConfig.sta.ssid, CONFIG_DEFAULT_WIFI_SSID, strlen(CONFIG_DEFAULT_WIFI_SSID) + 1);
424 memcpy(wifiConfig.sta.password, CONFIG_DEFAULT_WIFI_PASSWORD, strlen(CONFIG_DEFAULT_WIFI_PASSWORD) + 1);
425 wifiConfig.sta.scan_method = WIFI_ALL_CHANNEL_SCAN;
426 wifiConfig.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL;
427 err = esp_wifi_set_config(WIFI_IF_STA, &wifiConfig);
430 ChipLogError(DeviceLayer, "esp_wifi_set_config() failed: %s", chip::ErrorStr(err));
434 // Enable WiFi station mode.
435 err = SetWiFiStationMode(kWiFiStationMode_Enabled);
439 // Otherwise, ensure WiFi station mode is disabled.
442 err = SetWiFiStationMode(kWiFiStationMode_Disabled);
447 // Force AP mode off for now.
448 err = Internal::ESP32Utils::SetAPMode(false);
451 // Queue work items to bootstrap the AP and station state machines once the Chip event loop is running.
452 err = SystemLayer.ScheduleWork(DriveStationState, NULL);
454 err = SystemLayer.ScheduleWork(DriveAPState, NULL);
461 void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
463 // Handle ESP system events...
464 if (event->Type == DeviceEventType::kESPSystemEvent)
466 if (event->Platform.ESPSystemEvent.Base == WIFI_EVENT)
468 switch (event->Platform.ESPSystemEvent.Id)
470 case WIFI_EVENT_STA_START:
471 ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_START");
474 case WIFI_EVENT_STA_CONNECTED:
475 ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_CONNECTED");
476 if (mWiFiStationState == kWiFiStationState_Connecting)
478 ChangeWiFiStationState(kWiFiStationState_Connecting_Succeeded);
482 case WIFI_EVENT_STA_DISCONNECTED:
483 ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_DISCONNECTED");
484 if (mWiFiStationState == kWiFiStationState_Connecting)
486 ChangeWiFiStationState(kWiFiStationState_Connecting_Failed);
490 case WIFI_EVENT_STA_STOP:
491 ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_STOP");
494 case WIFI_EVENT_AP_START:
495 ChipLogProgress(DeviceLayer, "WIFI_EVENT_AP_START");
496 ChangeWiFiAPState(kWiFiAPState_Active);
499 case WIFI_EVENT_AP_STOP:
500 ChipLogProgress(DeviceLayer, "WIFI_EVENT_AP_STOP");
501 ChangeWiFiAPState(kWiFiAPState_NotActive);
504 case WIFI_EVENT_AP_STACONNECTED:
505 ChipLogProgress(DeviceLayer, "WIFI_EVENT_AP_STACONNECTED");
506 MaintainOnDemandWiFiAP();
513 if (event->Platform.ESPSystemEvent.Base == IP_EVENT)
515 switch (event->Platform.ESPSystemEvent.Id)
517 case IP_EVENT_STA_GOT_IP:
518 ChipLogProgress(DeviceLayer, "IP_EVENT_STA_GOT_IP");
519 OnStationIPv4AddressAvailable(event->Platform.ESPSystemEvent.Data.IpGotIp);
521 case IP_EVENT_STA_LOST_IP:
522 ChipLogProgress(DeviceLayer, "IP_EVENT_STA_LOST_IP");
523 OnStationIPv4AddressLost();
525 case IP_EVENT_GOT_IP6:
526 ChipLogProgress(DeviceLayer, "IP_EVENT_GOT_IP6");
527 OnIPv6AddressAvailable(event->Platform.ESPSystemEvent.Data.IpGotIp6);
536 void ConnectivityManagerImpl::_OnWiFiScanDone()
538 // Schedule a call to DriveStationState method in case a station connect attempt was
539 // deferred because the scan was in progress.
540 SystemLayer.ScheduleWork(DriveStationState, NULL);
543 void ConnectivityManagerImpl::_OnWiFiStationProvisionChange()
545 // Schedule a call to the DriveStationState method to adjust the station state as needed.
546 SystemLayer.ScheduleWork(DriveStationState, NULL);
549 // ==================== ConnectivityManager Private Methods ====================
551 void ConnectivityManagerImpl::DriveStationState()
553 CHIP_ERROR err = CHIP_NO_ERROR;
554 bool stationConnected;
556 // Refresh the current station mode. Specifically, this reads the ESP auto_connect flag,
557 // which determine whether the WiFi station mode is kWiFiStationMode_Enabled or
558 // kWiFiStationMode_Disabled.
559 GetWiFiStationMode();
561 // If the station interface is NOT under application control...
562 if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled)
564 // Ensure that the ESP WiFi layer is started.
565 err = Internal::ESP32Utils::StartWiFiLayer();
568 // Ensure that station mode is enabled in the ESP WiFi layer.
569 err = Internal::ESP32Utils::EnableStationMode();
573 // Determine if the ESP WiFi layer thinks the station interface is currently connected.
574 err = Internal::ESP32Utils::IsStationConnected(stationConnected);
577 // If the station interface is currently connected ...
578 if (stationConnected)
580 // Advance the station state to Connected if it was previously NotConnected or
581 // a previously initiated connect attempt succeeded.
582 if (mWiFiStationState == kWiFiStationState_NotConnected || mWiFiStationState == kWiFiStationState_Connecting_Succeeded)
584 ChangeWiFiStationState(kWiFiStationState_Connected);
585 ChipLogProgress(DeviceLayer, "WiFi station interface connected");
586 mLastStationConnectFailTime = 0;
587 OnStationConnected();
590 // If the WiFi station interface is no longer enabled, or no longer provisioned,
591 // disconnect the station from the AP, unless the WiFi station mode is currently
592 // under application control.
593 if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled &&
594 (mWiFiStationMode != kWiFiStationMode_Enabled || !IsWiFiStationProvisioned()))
596 ChipLogProgress(DeviceLayer, "Disconnecting WiFi station interface");
597 err = esp_wifi_disconnect();
600 ChipLogError(DeviceLayer, "esp_wifi_disconnect() failed: %s", chip::ErrorStr(err));
604 ChangeWiFiStationState(kWiFiStationState_Disconnecting);
608 // Otherwise the station interface is NOT connected to an AP, so...
611 uint64_t now = System::Layer::GetClock_MonotonicMS();
613 // Advance the station state to NotConnected if it was previously Connected or Disconnecting,
614 // or if a previous initiated connect attempt failed.
615 if (mWiFiStationState == kWiFiStationState_Connected || mWiFiStationState == kWiFiStationState_Disconnecting ||
616 mWiFiStationState == kWiFiStationState_Connecting_Failed)
618 WiFiStationState prevState = mWiFiStationState;
619 ChangeWiFiStationState(kWiFiStationState_NotConnected);
620 if (prevState != kWiFiStationState_Connecting_Failed)
622 ChipLogProgress(DeviceLayer, "WiFi station interface disconnected");
623 mLastStationConnectFailTime = 0;
624 OnStationDisconnected();
628 mLastStationConnectFailTime = now;
632 // If the WiFi station interface is now enabled and provisioned (and by implication,
633 // not presently under application control), AND the system is not in the process of
635 if (mWiFiStationMode == kWiFiStationMode_Enabled && IsWiFiStationProvisioned())
637 // Initiate a connection to the AP if we haven't done so before, or if enough
638 // time has passed since the last attempt.
639 if (mLastStationConnectFailTime == 0 || now >= mLastStationConnectFailTime + mWiFiStationReconnectIntervalMS)
641 ChipLogProgress(DeviceLayer, "Attempting to connect WiFi station interface");
642 err = esp_wifi_connect();
645 ChipLogError(DeviceLayer, "esp_wifi_connect() failed: %s", chip::ErrorStr(err));
649 ChangeWiFiStationState(kWiFiStationState_Connecting);
652 // Otherwise arrange another connection attempt at a suitable point in the future.
655 uint32_t timeToNextConnect = (uint32_t)((mLastStationConnectFailTime + mWiFiStationReconnectIntervalMS) - now);
657 ChipLogProgress(DeviceLayer, "Next WiFi station reconnect in %" PRIu32 " ms", timeToNextConnect);
659 err = SystemLayer.StartTimer(timeToNextConnect, DriveStationState, NULL);
667 ChipLogProgress(DeviceLayer, "Done driving station state, nothing else to do...");
668 // Kick-off any pending network scan that might have been deferred due to the activity
669 // of the WiFi station.
672 void ConnectivityManagerImpl::OnStationConnected()
676 // Assign an IPv6 link local address to the station interface.
677 err = esp_netif_create_ip6_linklocal(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"));
680 ChipLogError(DeviceLayer, "esp_netif_create_ip6_linklocal() failed for WIFI_STA_DEF interface: %s", chip::ErrorStr(err));
683 // TODO Invoke WARM to perform actions that occur when the WiFi station interface comes up.
685 // Alert other components of the new state.
686 ChipDeviceEvent event;
687 event.Type = DeviceEventType::kWiFiConnectivityChange;
688 event.WiFiConnectivityChange.Result = kConnectivity_Established;
689 PlatformMgr().PostEvent(&event);
691 UpdateInternetConnectivityState();
694 void ConnectivityManagerImpl::OnStationDisconnected()
696 // TODO Invoke WARM to perform actions that occur when the WiFi station interface goes down.
698 // Alert other components of the new state.
699 ChipDeviceEvent event;
700 event.Type = DeviceEventType::kWiFiConnectivityChange;
701 event.WiFiConnectivityChange.Result = kConnectivity_Lost;
702 PlatformMgr().PostEvent(&event);
704 UpdateInternetConnectivityState();
707 void ConnectivityManagerImpl::ChangeWiFiStationState(WiFiStationState newState)
709 if (mWiFiStationState != newState)
711 ChipLogProgress(DeviceLayer, "WiFi station state change: %s -> %s", WiFiStationStateToStr(mWiFiStationState),
712 WiFiStationStateToStr(newState));
713 mWiFiStationState = newState;
717 void ConnectivityManagerImpl::DriveStationState(::chip::System::Layer * aLayer, void * aAppState, ::chip::System::Error aError)
719 sInstance.DriveStationState();
722 void ConnectivityManagerImpl::DriveAPState()
724 CHIP_ERROR err = CHIP_NO_ERROR;
725 WiFiAPState targetState;
728 bool espAPModeEnabled;
730 // Determine if AP mode is currently enabled in the ESP WiFi layer.
731 err = Internal::ESP32Utils::IsAPEnabled(espAPModeEnabled);
734 // Adjust the Connectivity Manager's AP state to match the state in the WiFi layer.
735 if (espAPModeEnabled && (mWiFiAPState == kWiFiAPState_NotActive || mWiFiAPState == kWiFiAPState_Deactivating))
737 ChangeWiFiAPState(kWiFiAPState_Activating);
739 if (!espAPModeEnabled && (mWiFiAPState == kWiFiAPState_Active || mWiFiAPState == kWiFiAPState_Activating))
741 ChangeWiFiAPState(kWiFiAPState_Deactivating);
744 // If the AP interface is not under application control...
745 if (mWiFiAPMode != kWiFiAPMode_ApplicationControlled)
747 // Ensure the ESP WiFi layer is started.
748 err = Internal::ESP32Utils::StartWiFiLayer();
751 // Determine the target (desired) state for AP interface...
753 // The target state is 'NotActive' if the application has expressly disabled the AP interface.
754 if (mWiFiAPMode == kWiFiAPMode_Disabled)
756 targetState = kWiFiAPState_NotActive;
759 // The target state is 'Active' if the application has expressly enabled the AP interface.
760 else if (mWiFiAPMode == kWiFiAPMode_Enabled)
762 targetState = kWiFiAPState_Active;
765 // The target state is 'Active' if the AP mode is 'On demand, when no station is available'
766 // and the station interface is not provisioned or the application has disabled the station
768 else if (mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision &&
769 (!IsWiFiStationProvisioned() || GetWiFiStationMode() == kWiFiStationMode_Disabled))
771 targetState = kWiFiAPState_Active;
774 // The target state is 'Active' if the AP mode is one of the 'On demand' modes and there
775 // has been demand for the AP within the idle timeout period.
776 else if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
778 now = System::Layer::GetClock_MonotonicMS();
780 if (mLastAPDemandTime != 0 && now < (mLastAPDemandTime + mWiFiAPIdleTimeoutMS))
782 targetState = kWiFiAPState_Active;
784 // Compute the amount of idle time before the AP should be deactivated and
785 // arm a timer to fire at that time.
786 apTimeout = (uint32_t)((mLastAPDemandTime + mWiFiAPIdleTimeoutMS) - now);
787 err = SystemLayer.StartTimer(apTimeout, DriveAPState, NULL);
789 ChipLogProgress(DeviceLayer, "Next WiFi AP timeout in %" PRIu32 " ms", apTimeout);
793 targetState = kWiFiAPState_NotActive;
797 // Otherwise the target state is 'NotActive'.
800 targetState = kWiFiAPState_NotActive;
803 // If the current AP state does not match the target state...
804 if (mWiFiAPState != targetState)
806 // If the target state is 'Active' and the current state is NOT 'Activating', enable
807 // and configure the AP interface, and then enter the 'Activating' state. Eventually
808 // a SYSTEM_EVENT_AP_START event will be received from the ESP WiFi layer which will
809 // cause the state to transition to 'Active'.
810 if (targetState == kWiFiAPState_Active)
812 if (mWiFiAPState != kWiFiAPState_Activating)
814 err = Internal::ESP32Utils::SetAPMode(true);
817 err = ConfigureWiFiAP();
820 ChangeWiFiAPState(kWiFiAPState_Activating);
824 // Otherwise, if the target state is 'NotActive' and the current state is not 'Deactivating',
825 // disable the AP interface and enter the 'Deactivating' state. Later a SYSTEM_EVENT_AP_STOP
826 // event will move the AP state to 'NotActive'.
829 if (mWiFiAPState != kWiFiAPState_Deactivating)
831 err = Internal::ESP32Utils::SetAPMode(false);
834 ChangeWiFiAPState(kWiFiAPState_Deactivating);
840 // If AP is active, but the interface doesn't have an IPv6 link-local
841 // address, assign one now.
842 if (mWiFiAPState == kWiFiAPState_Active && Internal::ESP32Utils::IsInterfaceUp("WIFI_AP_DEF") &&
843 !Internal::ESP32Utils::HasIPv6LinkLocalAddress("WIFI_AP_DEF"))
845 err = esp_netif_create_ip6_linklocal(esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"));
848 ChipLogError(DeviceLayer, "esp_netif_create_ip6_linklocal() failed for WIFI_AP_DEF interface: %s", chip::ErrorStr(err));
854 if (err != CHIP_NO_ERROR && mWiFiAPMode != kWiFiAPMode_ApplicationControlled)
856 SetWiFiAPMode(kWiFiAPMode_Disabled);
857 Internal::ESP32Utils::SetAPMode(false);
861 CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP()
863 CHIP_ERROR err = CHIP_NO_ERROR;
864 wifi_config_t wifiConfig;
866 memset(&wifiConfig, 0, sizeof(wifiConfig));
868 uint16_t discriminator;
869 SuccessOrExit(err = ConfigurationMgr().GetSetupDiscriminator(discriminator));
871 snprintf((char *) wifiConfig.ap.ssid, sizeof(wifiConfig.ap.ssid), "%s%04u", CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX,
873 wifiConfig.ap.channel = CHIP_DEVICE_CONFIG_WIFI_AP_CHANNEL;
874 wifiConfig.ap.authmode = WIFI_AUTH_OPEN;
875 wifiConfig.ap.max_connection = CHIP_DEVICE_CONFIG_WIFI_AP_MAX_STATIONS;
876 wifiConfig.ap.beacon_interval = CHIP_DEVICE_CONFIG_WIFI_AP_BEACON_INTERVAL;
877 ChipLogProgress(DeviceLayer, "Configuring WiFi AP: SSID %s, channel %u", wifiConfig.ap.ssid, wifiConfig.ap.channel);
878 err = esp_wifi_set_config(WIFI_IF_AP, &wifiConfig);
881 ChipLogError(DeviceLayer, "esp_wifi_set_config(WIFI_IF_AP) failed: %s", chip::ErrorStr(err));
889 void ConnectivityManagerImpl::ChangeWiFiAPState(WiFiAPState newState)
891 if (mWiFiAPState != newState)
893 ChipLogProgress(DeviceLayer, "WiFi AP state change: %s -> %s", WiFiAPStateToStr(mWiFiAPState), WiFiAPStateToStr(newState));
894 mWiFiAPState = newState;
898 void ConnectivityManagerImpl::DriveAPState(::chip::System::Layer * aLayer, void * aAppState, ::chip::System::Error aError)
900 sInstance.DriveAPState();
903 void ConnectivityManagerImpl::UpdateInternetConnectivityState(void)
905 bool haveIPv4Conn = false;
906 bool haveIPv6Conn = false;
907 bool hadIPv4Conn = GetFlag(mFlags, kFlag_HaveIPv4InternetConnectivity);
908 bool hadIPv6Conn = GetFlag(mFlags, kFlag_HaveIPv6InternetConnectivity);
911 // If the WiFi station is currently in the connected state...
912 if (mWiFiStationState == kWiFiStationState_Connected)
914 // Get the LwIP netif for the WiFi station interface.
915 struct netif * netif = Internal::ESP32Utils::GetStationNetif();
917 // If the WiFi station interface is up...
918 if (netif != NULL && netif_is_up(netif) && netif_is_link_up(netif))
920 // Check if a DNS server is currently configured. If so...
921 ip_addr_t dnsServerAddr = *dns_getserver(0);
922 if (!ip_addr_isany_val(dnsServerAddr))
924 // If the station interface has been assigned an IPv4 address, and has
925 // an IPv4 gateway, then presume that the device has IPv4 Internet
927 if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) && !ip4_addr_isany_val(*netif_ip4_gw(netif)))
931 esp_netif_ip_info_t ipInfo;
932 if (esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &ipInfo) == ESP_OK)
934 char addrStr[INET_ADDRSTRLEN];
935 // ToDo: change the code to using IPv6 address
936 esp_ip4addr_ntoa(&ipInfo.ip, addrStr, sizeof(addrStr));
937 IPAddress::FromString(addrStr, addr);
941 // Search among the IPv6 addresses assigned to the interface for a Global Unicast
942 // address (2000::/3) that is in the valid state. If such an address is found...
943 for (uint8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++)
945 if (ip6_addr_isglobal(netif_ip6_addr(netif, i)) && ip6_addr_isvalid(netif_ip6_addr_state(netif, i)))
947 // Determine if there is a default IPv6 router that is currently reachable
948 // via the station interface. If so, presume for now that the device has
949 // IPv6 connectivity.
950 struct netif * found_if = nd6_find_route(IP6_ADDR_ANY6);
951 if (found_if && netif->num == found_if->num)
961 // If the internet connectivity state has changed...
962 if (haveIPv4Conn != hadIPv4Conn || haveIPv6Conn != hadIPv6Conn)
964 // Update the current state.
965 SetFlag(mFlags, kFlag_HaveIPv4InternetConnectivity, haveIPv4Conn);
966 SetFlag(mFlags, kFlag_HaveIPv6InternetConnectivity, haveIPv6Conn);
968 // Alert other components of the state change.
969 ChipDeviceEvent event;
970 event.Type = DeviceEventType::kInternetConnectivityChange;
971 event.InternetConnectivityChange.IPv4 = GetConnectivityChange(hadIPv4Conn, haveIPv4Conn);
972 event.InternetConnectivityChange.IPv6 = GetConnectivityChange(hadIPv6Conn, haveIPv6Conn);
973 addr.ToString(event.InternetConnectivityChange.address);
974 PlatformMgr().PostEvent(&event);
976 if (haveIPv4Conn != hadIPv4Conn)
978 ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv4", (haveIPv4Conn) ? "ESTABLISHED" : "LOST");
981 if (haveIPv6Conn != hadIPv6Conn)
983 ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv6", (haveIPv6Conn) ? "ESTABLISHED" : "LOST");
988 void ConnectivityManagerImpl::OnStationIPv4AddressAvailable(const ip_event_got_ip_t & got_ip)
990 #if CHIP_PROGRESS_LOGGING
992 ChipLogProgress(DeviceLayer, "IPv4 address %s on WiFi station interface: " IPSTR "/" IPSTR " gateway " IPSTR,
993 (got_ip.ip_changed) ? "changed" : "ready", IP2STR(&got_ip.ip_info.ip), IP2STR(&got_ip.ip_info.netmask),
994 IP2STR(&got_ip.ip_info.gw));
996 #endif // CHIP_PROGRESS_LOGGING
998 RefreshMessageLayer();
1000 UpdateInternetConnectivityState();
1002 ChipDeviceEvent event;
1003 event.Type = DeviceEventType::kInterfaceIpAddressChanged;
1004 event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV4_Assigned;
1005 PlatformMgr().PostEvent(&event);
1008 void ConnectivityManagerImpl::OnStationIPv4AddressLost(void)
1010 ChipLogProgress(DeviceLayer, "IPv4 address lost on WiFi station interface");
1012 RefreshMessageLayer();
1014 UpdateInternetConnectivityState();
1016 ChipDeviceEvent event;
1017 event.Type = DeviceEventType::kInterfaceIpAddressChanged;
1018 event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV4_Lost;
1019 PlatformMgr().PostEvent(&event);
1022 void ConnectivityManagerImpl::OnIPv6AddressAvailable(const ip_event_got_ip6_t & got_ip)
1024 #if CHIP_PROGRESS_LOGGING
1026 ChipLogProgress(DeviceLayer, "IPv6 addr available. Ready on %s interface: " IPV6STR, esp_netif_get_ifkey(got_ip.esp_netif),
1027 IPV62STR(got_ip.ip6_info.ip));
1029 #endif // CHIP_PROGRESS_LOGGING
1031 RefreshMessageLayer();
1033 UpdateInternetConnectivityState();
1035 ChipDeviceEvent event;
1036 event.Type = DeviceEventType::kInterfaceIpAddressChanged;
1037 event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV6_Assigned;
1038 PlatformMgr().PostEvent(&event);
1041 void ConnectivityManagerImpl::RefreshMessageLayer(void) {}
1043 } // namespace DeviceLayer