diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index ce5ee8875a8229..336b693a244de8 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -30,6 +30,10 @@ if(NOT CHIP_ROOT) endif() set(CHIP_REQURIE_COMPONENTS freertos lwip bt mdns mbedtls fatfs) +if(${IDF_TARGET} STREQUAL "esp32h2") + list(APPEND CHIP_REQURIE_COMPONENTS openthread) +endif() + if (CONFIG_ENABLE_CHIP_SHELL) list(APPEND CHIP_REQURIE_COMPONENTS console) endif() @@ -84,6 +88,9 @@ if (CONFIG_ENABLE_CHIP_SHELL) chip_gn_arg_append("chip_build_libshell" "true") endif() +if (CONFIG_OPENTHREAD_ENABLED) + chip_gn_arg_append("chip_enable_openthread" "true") +endif() set(args_gn_input "${CMAKE_CURRENT_BINARY_DIR}/args.gn.in") file(GENERATE OUTPUT "${args_gn_input}" CONTENT "${chip_gn_args}") @@ -160,6 +167,7 @@ target_include_directories(${COMPONENT_LIB} PRIVATE target_include_directories(${COMPONENT_LIB} INTERFACE "${CHIP_ROOT}/src/platform/ESP32" + "${CHIP_ROOT}/src/platform/OpenThread" "${CHIP_ROOT}/src/include" "${CHIP_ROOT}/src/lib" "${CHIP_ROOT}/src" @@ -173,8 +181,15 @@ target_include_directories(${COMPONENT_LIB} INTERFACE idf_component_get_property(esp32_mbedtls_lib esp32_mbedtls COMPONENT_LIB) if(CONFIG_BT_ENABLED) - idf_component_get_property(bt_lib bt COMPONENT_LIB) - list(APPEND chip_libraries $ -lbtdm_app) + if("${CONFIG_IDF_TARGET}" STREQUAL "esp32h2") + idf_component_get_property(bt_lib bt COMPONENT_LIB) + idf_component_get_property(bt_dir bt COMPONENT_DIR) + list(APPEND chip_libraries $) + list(APPEND chip_libraries ${bt_dir}/controller/lib/esp32h2beta/libcontroller_5p0_seq.a) + else() + idf_component_get_property(bt_lib bt COMPONENT_LIB) + list(APPEND chip_libraries $ -lbtdm_app) + endif() endif() if (CONFIG_ENABLE_CHIP_SHELL) @@ -182,6 +197,11 @@ if (CONFIG_ENABLE_CHIP_SHELL) list(APPEND chip_libraries $) endif() +if(CONFIG_OPENTHREAD_ENABLED) + idf_component_get_property(openthread_lib openthread COMPONENT_LIB) + list(APPEND chip_libraries $) +endif() + if(NOT CONFIG_USE_MINIMAL_MDNS) idf_component_get_property(mdns_lib mdns COMPONENT_LIB) list(APPEND chip_libraries $) diff --git a/src/platform/ESP32/BUILD.gn b/src/platform/ESP32/BUILD.gn index b0edb65c6af00c..f664bfa68034db 100644 --- a/src/platform/ESP32/BUILD.gn +++ b/src/platform/ESP32/BUILD.gn @@ -26,7 +26,6 @@ static_library("ESP32") { "CHIPDevicePlatformEvent.h", "ConfigurationManagerImpl.cpp", "ConfigurationManagerImpl.h", - "ConnectivityManagerImpl.cpp", "ConnectivityManagerImpl.h", "DeviceNetworkProvisioningDelegateImpl.cpp", "DeviceNetworkProvisioningDelegateImpl.h", @@ -38,11 +37,8 @@ static_library("ESP32") { "KeyValueStoreManagerImpl.h", "Logging.cpp", "LwIPCoreLock.cpp", - "MdnsImpl.cpp", "PlatformManagerImpl.cpp", "PlatformManagerImpl.h", - "ServiceProvisioning.cpp", - "ServiceProvisioning.h", "SoftwareUpdateManagerImpl.h", "SystemTimeSupport.cpp", "bluedroid/BLEManagerImpl.cpp", @@ -55,4 +51,23 @@ static_library("ESP32") { "${chip_root}/src/crypto", "${chip_root}/src/platform:platform_base", ] + if (chip_enable_openthread) { + sources += [ + "../OpenThread/MdnsImpl.cpp", + "../OpenThread/OpenThreadUtils.cpp", + "ConnectivityManagerImpl_Thread.cpp", + "ConnectivityManagerImpl_Thread.h", + "ESPThreadConfig.h", + "ThreadStackManagerImpl.cpp", + "ThreadStackManagerImpl.h", + ] + } else { + sources += [ + "ConnectivityManagerImpl_WiFi.cpp", + "ConnectivityManagerImpl_WiFi.h", + "MdnsImpl.cpp", + "ServiceProvisioning.cpp", + "ServiceProvisioning.h", + ] + } } diff --git a/src/platform/ESP32/CHIPDevicePlatformConfig.h b/src/platform/ESP32/CHIPDevicePlatformConfig.h index e79a922b46b39b..0c533e40ad9d8a 100644 --- a/src/platform/ESP32/CHIPDevicePlatformConfig.h +++ b/src/platform/ESP32/CHIPDevicePlatformConfig.h @@ -41,6 +41,12 @@ #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID CONFIG_DEVICE_PRODUCT_ID #define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_PRODUCT_REVISION CONFIG_DEFAULT_DEVICE_PRODUCT_REVISION #define CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION_STRING CONFIG_DEVICE_FIRMWARE_REVISION + +#if CONFIG_IDF_TARGET_ESP32H2 +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD CONFIG_OPENTHREAD_ENABLED +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT CONFIG_OPENTHREAD_SRP_CLIENT +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI !CONFIG_OPENTHREAD_ENABLED +#else #define CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL CONFIG_WIFI_STATION_RECONNECT_INTERVAL #define CHIP_DEVICE_CONFIG_MAX_SCAN_NETWORKS_RESULTS CONFIG_MAX_SCAN_NETWORKS_RESULTS #define CHIP_DEVICE_CONFIG_WIFI_SCAN_COMPLETION_TIMEOUT CONFIG_WIFI_SCAN_COMPLETION_TIMEOUT @@ -50,6 +56,10 @@ #define CHIP_DEVICE_CONFIG_WIFI_AP_MAX_STATIONS CONFIG_WIFI_AP_MAX_STATIONS #define CHIP_DEVICE_CONFIG_WIFI_AP_BEACON_INTERVAL CONFIG_WIFI_AP_BEACON_INTERVAL #define CHIP_DEVICE_CONFIG_WIFI_AP_IDLE_TIMEOUT CONFIG_WIFI_AP_IDLE_TIMEOUT +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_TELEMETRY CONFIG_ENABLE_WIFI_TELEMETRY +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP | CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION +#endif // CONFIG_IDF_TARGET_ESP32H2 + #define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE CONFIG_ENABLE_CHIPOBLE #define CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX CONFIG_BLE_DEVICE_NAME_PREFIX #define CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN @@ -70,7 +80,6 @@ #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR CONFIG_USE_TEST_SETUP_DISCRIMINATOR #define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER CONFIG_USE_TEST_SERIAL_NUMBER #define CHIP_DEVICE_CONFIG_ENABLE_TRAIT_MANAGER CONFIG_ENABLE_TRAIT_MANAGER -#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_TELEMETRY CONFIG_ENABLE_WIFI_TELEMETRY #define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY CONFIG_ENABLE_THREAD_TELEMETRY #define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY_FULL CONFIG_ENABLE_THREAD_TELEMETRY_FULL #define CHIP_DEVICE_CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE diff --git a/src/platform/ESP32/ConfigurationManagerImpl.cpp b/src/platform/ESP32/ConfigurationManagerImpl.cpp index b1543790e4a335..b3814d72937fa4 100644 --- a/src/platform/ESP32/ConfigurationManagerImpl.cpp +++ b/src/platform/ESP32/ConfigurationManagerImpl.cpp @@ -102,12 +102,16 @@ CHIP_ERROR ConfigurationManagerImpl::_Init() CHIP_ERROR ConfigurationManagerImpl::_GetPrimaryWiFiMACAddress(uint8_t * buf) { +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI wifi_mode_t mode; esp_wifi_get_mode(&mode); if ((mode == WIFI_MODE_AP) || (mode == WIFI_MODE_APSTA)) return MapConfigError(esp_wifi_get_mac(WIFI_IF_AP, buf)); else return MapConfigError(esp_wifi_get_mac(WIFI_IF_STA, buf)); +#else + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +#endif } CHIP_ERROR ConfigurationManagerImpl::MapConfigError(esp_err_t error) @@ -169,12 +173,15 @@ void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) } // Restore WiFi persistent settings to default values. +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI esp_err_t error = esp_wifi_restore(); if (error != ESP_OK) { ChipLogError(DeviceLayer, "esp_wifi_restore() failed: %s", esp_err_to_name(error)); } - +#elif CHIP_DEVICE_CONFIG_ENABLE_THREAD + ThreadStackMgr().ErasePersistentInfo(); +#endif // Restart the system. ChipLogProgress(DeviceLayer, "System restarting"); esp_restart(); diff --git a/src/platform/ESP32/ConnectivityManagerImpl.h b/src/platform/ESP32/ConnectivityManagerImpl.h index f379c78dbeadf4..7ee462fc3033d7 100644 --- a/src/platform/ESP32/ConnectivityManagerImpl.h +++ b/src/platform/ESP32/ConnectivityManagerImpl.h @@ -19,192 +19,8 @@ #pragma once -#include -#include -#include -#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE -#include +#if CONFIG_IDF_TARGET_ESP32H2 +#include #else -#include +#include #endif -#include -#include - -#include "esp_event.h" - -namespace Inet { -class IPAddress; -} // namespace Inet - -namespace chip { -namespace DeviceLayer { - -class PlatformManagerImpl; - -/** - * Concrete implementation of the ConnectivityManager singleton object for the ESP32 platform. - */ -class ConnectivityManagerImpl final : public ConnectivityManager, - public Internal::GenericConnectivityManagerImpl, - public Internal::GenericConnectivityManagerImpl_WiFi, -#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE - public Internal::GenericConnectivityManagerImpl_BLE, -#else - public Internal::GenericConnectivityManagerImpl_NoBLE, -#endif - public Internal::GenericConnectivityManagerImpl_NoThread -{ - - // Allow the ConnectivityManager interface class to delegate method calls to - // the implementation methods provided by this class. - friend class ConnectivityManager; - -private: - using Flags = GenericConnectivityManagerImpl_WiFi::ConnectivityFlags; - // ===== Members that implement the ConnectivityManager abstract interface. - - WiFiStationMode _GetWiFiStationMode(void); - CHIP_ERROR _SetWiFiStationMode(WiFiStationMode val); - bool _IsWiFiStationEnabled(void); - bool _IsWiFiStationApplicationControlled(void); - bool _IsWiFiStationConnected(void); - uint32_t _GetWiFiStationReconnectIntervalMS(void); - CHIP_ERROR _SetWiFiStationReconnectIntervalMS(uint32_t val); - bool _IsWiFiStationProvisioned(void); - void _ClearWiFiStationProvision(void); - WiFiAPMode _GetWiFiAPMode(void); - CHIP_ERROR _SetWiFiAPMode(WiFiAPMode val); - bool _IsWiFiAPActive(void); - bool _IsWiFiAPApplicationControlled(void); - void _DemandStartWiFiAP(void); - void _StopOnDemandWiFiAP(void); - void _MaintainOnDemandWiFiAP(void); - uint32_t _GetWiFiAPIdleTimeoutMS(void); - void _SetWiFiAPIdleTimeoutMS(uint32_t val); - CHIP_ERROR _GetAndLogWifiStatsCounters(void); - bool _HaveIPv4InternetConnectivity(void); - bool _HaveIPv6InternetConnectivity(void); - bool _HaveServiceConnectivity(void); - CHIP_ERROR _Init(void); - void _OnPlatformEvent(const ChipDeviceEvent * event); - bool _CanStartWiFiScan(); - void _OnWiFiScanDone(); - void _OnWiFiStationProvisionChange(); - - // ===== Members for internal use by the following friends. - - friend ConnectivityManager & ConnectivityMgr(void); - friend ConnectivityManagerImpl & ConnectivityMgrImpl(void); - - static ConnectivityManagerImpl sInstance; - - // ===== Private members reserved for use by this class only. - - uint64_t mLastStationConnectFailTime; - uint64_t mLastAPDemandTime; - WiFiStationMode mWiFiStationMode; - WiFiStationState mWiFiStationState; - WiFiAPMode mWiFiAPMode; - WiFiAPState mWiFiAPState; - uint32_t mWiFiStationReconnectIntervalMS; - uint32_t mWiFiAPIdleTimeoutMS; - BitFlags mFlags; - - void DriveStationState(void); - void OnStationConnected(void); - void OnStationDisconnected(void); - void ChangeWiFiStationState(WiFiStationState newState); - static void DriveStationState(::chip::System::Layer * aLayer, void * aAppState); - - void DriveAPState(void); - CHIP_ERROR ConfigureWiFiAP(void); - void ChangeWiFiAPState(WiFiAPState newState); - static void DriveAPState(::chip::System::Layer * aLayer, void * aAppState); - - void UpdateInternetConnectivityState(void); - void OnStationIPv4AddressAvailable(const ip_event_got_ip_t & got_ip); - void OnStationIPv4AddressLost(void); - void OnIPv6AddressAvailable(const ip_event_got_ip6_t & got_ip); - - static void RefreshMessageLayer(void); -}; - -inline bool ConnectivityManagerImpl::_IsWiFiStationApplicationControlled(void) -{ - return mWiFiStationMode == kWiFiStationMode_ApplicationControlled; -} - -inline bool ConnectivityManagerImpl::_IsWiFiStationConnected(void) -{ - return mWiFiStationState == kWiFiStationState_Connected; -} - -inline bool ConnectivityManagerImpl::_IsWiFiAPApplicationControlled(void) -{ - return mWiFiAPMode == kWiFiAPMode_ApplicationControlled; -} - -inline uint32_t ConnectivityManagerImpl::_GetWiFiStationReconnectIntervalMS(void) -{ - return mWiFiStationReconnectIntervalMS; -} - -inline ConnectivityManager::WiFiAPMode ConnectivityManagerImpl::_GetWiFiAPMode(void) -{ - return mWiFiAPMode; -} - -inline bool ConnectivityManagerImpl::_IsWiFiAPActive(void) -{ - return mWiFiAPState == kWiFiAPState_Active; -} - -inline uint32_t ConnectivityManagerImpl::_GetWiFiAPIdleTimeoutMS(void) -{ - return mWiFiAPIdleTimeoutMS; -} - -inline bool ConnectivityManagerImpl::_HaveIPv4InternetConnectivity(void) -{ - return mFlags.Has(Flags::kHaveIPv4InternetConnectivity); -} - -inline bool ConnectivityManagerImpl::_HaveIPv6InternetConnectivity(void) -{ - return mFlags.Has(Flags::kHaveIPv6InternetConnectivity); -} - -inline bool ConnectivityManagerImpl::_CanStartWiFiScan() -{ - return mWiFiStationState != kWiFiStationState_Connecting; -} - -inline bool ConnectivityManagerImpl::_HaveServiceConnectivity(void) -{ - return HaveServiceConnectivityViaThread(); -} - -/** - * Returns the public interface of the ConnectivityManager singleton object. - * - * Chip applications should use this to access features of the ConnectivityManager object - * that are common to all platforms. - */ -inline ConnectivityManager & ConnectivityMgr(void) -{ - return ConnectivityManagerImpl::sInstance; -} - -/** - * Returns the platform-specific implementation of the ConnectivityManager singleton object. - * - * Chip applications can use this to gain access to features of the ConnectivityManager - * that are specific to the ESP32 platform. - */ -inline ConnectivityManagerImpl & ConnectivityMgrImpl(void) -{ - return ConnectivityManagerImpl::sInstance; -} - -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/ESP32/ConnectivityManagerImpl_Thread.cpp b/src/platform/ESP32/ConnectivityManagerImpl_Thread.cpp new file mode 100644 index 00000000000000..117088f78513bd --- /dev/null +++ b/src/platform/ESP32/ConnectivityManagerImpl_Thread.cpp @@ -0,0 +1,56 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include +#endif + +#include + +#include +#include +#include + +using namespace ::chip; +using namespace ::chip::Inet; +using namespace ::chip::System; +using namespace ::chip::TLV; + +namespace chip { +namespace DeviceLayer { + +ConnectivityManagerImpl ConnectivityManagerImpl::sInstance; +// ==================== ConnectivityManager Platform Internal Methods ==================== + +CHIP_ERROR ConnectivityManagerImpl::_Init() +{ + GenericConnectivityManagerImpl_Thread::_Init(); + return CHIP_NO_ERROR; +} + +void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) +{ + GenericConnectivityManagerImpl_Thread::_OnPlatformEvent(event); +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ESP32/ConnectivityManagerImpl_Thread.h b/src/platform/ESP32/ConnectivityManagerImpl_Thread.h new file mode 100644 index 00000000000000..86f4e8d0eeb365 --- /dev/null +++ b/src/platform/ESP32/ConnectivityManagerImpl_Thread.h @@ -0,0 +1,112 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include +#else +#include +#endif +#include + +namespace Inet { +class IPAddress; +} // namespace Inet + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the ConnectivityManager singleton object for the ESP32 platform. + */ +class ConnectivityManagerImpl final : public ConnectivityManager, + public Internal::GenericConnectivityManagerImpl_NoWiFi, +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + public Internal::GenericConnectivityManagerImpl_BLE, +#else + public Internal::GenericConnectivityManagerImpl_NoBLE, +#endif + public Internal::GenericConnectivityManagerImpl_Thread, + public Internal::GenericConnectivityManagerImpl +{ + + // Allow the ConnectivityManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ConnectivityManager; + +private: + // ===== Members that implement the ConnectivityManager abstract interface. + + CHIP_ERROR _Init(void); + void _OnPlatformEvent(const ChipDeviceEvent * event); + bool _HaveIPv4InternetConnectivity(void); + bool _HaveIPv6InternetConnectivity(void); + bool _HaveServiceConnectivity(void); + // ===== Members for internal use by the following friends. + + friend ConnectivityManager & ConnectivityMgr(void); + friend ConnectivityManagerImpl & ConnectivityMgrImpl(void); + + static ConnectivityManagerImpl sInstance; +}; + +inline bool ConnectivityManagerImpl::_HaveServiceConnectivity(void) +{ + return HaveServiceConnectivityViaThread(); +} + +inline bool ConnectivityManagerImpl::_HaveIPv4InternetConnectivity(void) +{ + return false; +} + +inline bool ConnectivityManagerImpl::_HaveIPv6InternetConnectivity(void) +{ + return false; +} + +/** + * Returns the public interface of the ConnectivityManager singleton object. + * + * Chip applications should use this to access features of the ConnectivityManager object + * that are common to all platforms. + */ +inline ConnectivityManager & ConnectivityMgr(void) +{ + return ConnectivityManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the ConnectivityManager singleton object. + * + * Chip applications can use this to gain access to features of the ConnectivityManager + * that are specific to the ESP32 platform. + */ +inline ConnectivityManagerImpl & ConnectivityMgrImpl(void) +{ + return ConnectivityManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ESP32/ConnectivityManagerImpl.cpp b/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp similarity index 100% rename from src/platform/ESP32/ConnectivityManagerImpl.cpp rename to src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp diff --git a/src/platform/ESP32/ConnectivityManagerImpl_WiFi.h b/src/platform/ESP32/ConnectivityManagerImpl_WiFi.h new file mode 100644 index 00000000000000..f379c78dbeadf4 --- /dev/null +++ b/src/platform/ESP32/ConnectivityManagerImpl_WiFi.h @@ -0,0 +1,210 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include +#else +#include +#endif +#include +#include + +#include "esp_event.h" + +namespace Inet { +class IPAddress; +} // namespace Inet + +namespace chip { +namespace DeviceLayer { + +class PlatformManagerImpl; + +/** + * Concrete implementation of the ConnectivityManager singleton object for the ESP32 platform. + */ +class ConnectivityManagerImpl final : public ConnectivityManager, + public Internal::GenericConnectivityManagerImpl, + public Internal::GenericConnectivityManagerImpl_WiFi, +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + public Internal::GenericConnectivityManagerImpl_BLE, +#else + public Internal::GenericConnectivityManagerImpl_NoBLE, +#endif + public Internal::GenericConnectivityManagerImpl_NoThread +{ + + // Allow the ConnectivityManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ConnectivityManager; + +private: + using Flags = GenericConnectivityManagerImpl_WiFi::ConnectivityFlags; + // ===== Members that implement the ConnectivityManager abstract interface. + + WiFiStationMode _GetWiFiStationMode(void); + CHIP_ERROR _SetWiFiStationMode(WiFiStationMode val); + bool _IsWiFiStationEnabled(void); + bool _IsWiFiStationApplicationControlled(void); + bool _IsWiFiStationConnected(void); + uint32_t _GetWiFiStationReconnectIntervalMS(void); + CHIP_ERROR _SetWiFiStationReconnectIntervalMS(uint32_t val); + bool _IsWiFiStationProvisioned(void); + void _ClearWiFiStationProvision(void); + WiFiAPMode _GetWiFiAPMode(void); + CHIP_ERROR _SetWiFiAPMode(WiFiAPMode val); + bool _IsWiFiAPActive(void); + bool _IsWiFiAPApplicationControlled(void); + void _DemandStartWiFiAP(void); + void _StopOnDemandWiFiAP(void); + void _MaintainOnDemandWiFiAP(void); + uint32_t _GetWiFiAPIdleTimeoutMS(void); + void _SetWiFiAPIdleTimeoutMS(uint32_t val); + CHIP_ERROR _GetAndLogWifiStatsCounters(void); + bool _HaveIPv4InternetConnectivity(void); + bool _HaveIPv6InternetConnectivity(void); + bool _HaveServiceConnectivity(void); + CHIP_ERROR _Init(void); + void _OnPlatformEvent(const ChipDeviceEvent * event); + bool _CanStartWiFiScan(); + void _OnWiFiScanDone(); + void _OnWiFiStationProvisionChange(); + + // ===== Members for internal use by the following friends. + + friend ConnectivityManager & ConnectivityMgr(void); + friend ConnectivityManagerImpl & ConnectivityMgrImpl(void); + + static ConnectivityManagerImpl sInstance; + + // ===== Private members reserved for use by this class only. + + uint64_t mLastStationConnectFailTime; + uint64_t mLastAPDemandTime; + WiFiStationMode mWiFiStationMode; + WiFiStationState mWiFiStationState; + WiFiAPMode mWiFiAPMode; + WiFiAPState mWiFiAPState; + uint32_t mWiFiStationReconnectIntervalMS; + uint32_t mWiFiAPIdleTimeoutMS; + BitFlags mFlags; + + void DriveStationState(void); + void OnStationConnected(void); + void OnStationDisconnected(void); + void ChangeWiFiStationState(WiFiStationState newState); + static void DriveStationState(::chip::System::Layer * aLayer, void * aAppState); + + void DriveAPState(void); + CHIP_ERROR ConfigureWiFiAP(void); + void ChangeWiFiAPState(WiFiAPState newState); + static void DriveAPState(::chip::System::Layer * aLayer, void * aAppState); + + void UpdateInternetConnectivityState(void); + void OnStationIPv4AddressAvailable(const ip_event_got_ip_t & got_ip); + void OnStationIPv4AddressLost(void); + void OnIPv6AddressAvailable(const ip_event_got_ip6_t & got_ip); + + static void RefreshMessageLayer(void); +}; + +inline bool ConnectivityManagerImpl::_IsWiFiStationApplicationControlled(void) +{ + return mWiFiStationMode == kWiFiStationMode_ApplicationControlled; +} + +inline bool ConnectivityManagerImpl::_IsWiFiStationConnected(void) +{ + return mWiFiStationState == kWiFiStationState_Connected; +} + +inline bool ConnectivityManagerImpl::_IsWiFiAPApplicationControlled(void) +{ + return mWiFiAPMode == kWiFiAPMode_ApplicationControlled; +} + +inline uint32_t ConnectivityManagerImpl::_GetWiFiStationReconnectIntervalMS(void) +{ + return mWiFiStationReconnectIntervalMS; +} + +inline ConnectivityManager::WiFiAPMode ConnectivityManagerImpl::_GetWiFiAPMode(void) +{ + return mWiFiAPMode; +} + +inline bool ConnectivityManagerImpl::_IsWiFiAPActive(void) +{ + return mWiFiAPState == kWiFiAPState_Active; +} + +inline uint32_t ConnectivityManagerImpl::_GetWiFiAPIdleTimeoutMS(void) +{ + return mWiFiAPIdleTimeoutMS; +} + +inline bool ConnectivityManagerImpl::_HaveIPv4InternetConnectivity(void) +{ + return mFlags.Has(Flags::kHaveIPv4InternetConnectivity); +} + +inline bool ConnectivityManagerImpl::_HaveIPv6InternetConnectivity(void) +{ + return mFlags.Has(Flags::kHaveIPv6InternetConnectivity); +} + +inline bool ConnectivityManagerImpl::_CanStartWiFiScan() +{ + return mWiFiStationState != kWiFiStationState_Connecting; +} + +inline bool ConnectivityManagerImpl::_HaveServiceConnectivity(void) +{ + return HaveServiceConnectivityViaThread(); +} + +/** + * Returns the public interface of the ConnectivityManager singleton object. + * + * Chip applications should use this to access features of the ConnectivityManager object + * that are common to all platforms. + */ +inline ConnectivityManager & ConnectivityMgr(void) +{ + return ConnectivityManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the ConnectivityManager singleton object. + * + * Chip applications can use this to gain access to features of the ConnectivityManager + * that are specific to the ESP32 platform. + */ +inline ConnectivityManagerImpl & ConnectivityMgrImpl(void) +{ + return ConnectivityManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ESP32/DeviceNetworkProvisioningDelegateImpl.cpp b/src/platform/ESP32/DeviceNetworkProvisioningDelegateImpl.cpp index 0bc90aebdc5b30..2cabe05d785746 100644 --- a/src/platform/ESP32/DeviceNetworkProvisioningDelegateImpl.cpp +++ b/src/platform/ESP32/DeviceNetworkProvisioningDelegateImpl.cpp @@ -26,16 +26,33 @@ namespace DeviceLayer { CHIP_ERROR DeviceNetworkProvisioningDelegateImpl::_ProvisionWiFiNetwork(const char * ssid, const char * key) { +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI CHIP_ERROR err = CHIP_NO_ERROR; - ChipLogProgress(NetworkProvisioning, "ESP32NetworkProvisioningDelegate: SSID: %s", ssid); err = SetWiFiStationProvisioning(ssid, key); if (err != CHIP_NO_ERROR) { ChipLogError(NetworkProvisioning, "Failed to connect to WiFi network: %s", chip::ErrorStr(err)); } + return err; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +CHIP_ERROR DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(ByteSpan threadData) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + CHIP_ERROR err = CHIP_NO_ERROR; + SuccessOrExit(err = ThreadStackMgr().SetThreadEnabled(false)); + SuccessOrExit(err = ThreadStackMgr().SetThreadProvision(threadData)); + SuccessOrExit(err = ThreadStackMgr().SetThreadEnabled(true)); +exit: return err; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif } } // namespace DeviceLayer diff --git a/src/platform/ESP32/DeviceNetworkProvisioningDelegateImpl.h b/src/platform/ESP32/DeviceNetworkProvisioningDelegateImpl.h index 6e89a78e2110b2..102699448bd6bc 100644 --- a/src/platform/ESP32/DeviceNetworkProvisioningDelegateImpl.h +++ b/src/platform/ESP32/DeviceNetworkProvisioningDelegateImpl.h @@ -36,7 +36,7 @@ class DeviceNetworkProvisioningDelegateImpl final friend class GenericDeviceNetworkProvisioningDelegateImpl; CHIP_ERROR _ProvisionWiFiNetwork(const char * ssid, const char * passwd); - CHIP_ERROR _ProvisionThreadNetwork(ByteSpan threadData) { return CHIP_ERROR_NOT_IMPLEMENTED; } + CHIP_ERROR _ProvisionThreadNetwork(ByteSpan threadData); }; } // namespace DeviceLayer diff --git a/src/platform/ESP32/ESPThreadConfig.h b/src/platform/ESP32/ESPThreadConfig.h new file mode 100644 index 00000000000000..a000e8ccff98d2 --- /dev/null +++ b/src/platform/ESP32/ESPThreadConfig.h @@ -0,0 +1,40 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provide Default Config for ESP Thread Device + */ +#pragma once + +#include "esp_openthread_types.h" + +#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \ + { \ + .radio_mode = RADIO_MODE_NATIVE, \ + } + +#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ + { \ + .host_connection_mode = HOST_CONNECTION_MODE_NONE, \ + } + +#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ + { \ + .storage_partition_name = "ot_storage", .netif_queue_size = 10, .task_queue_size = 10, \ + } diff --git a/src/platform/ESP32/PlatformManagerImpl.cpp b/src/platform/ESP32/PlatformManagerImpl.cpp index 48ecb5e6ab81dc..a5b5992c8085fc 100644 --- a/src/platform/ESP32/PlatformManagerImpl.cpp +++ b/src/platform/ESP32/PlatformManagerImpl.cpp @@ -57,22 +57,21 @@ static int app_entropy_source(void * data, unsigned char * output, size_t len, s CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) { esp_err_t err; - wifi_init_config_t cfg; - uint8_t ap_mac[6]; - wifi_mode_t mode; - // Arrange for CHIP-encapsulated ESP32 errors to be translated to text Internal::ESP32Utils::RegisterESP32ErrorFormatter(); +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + wifi_init_config_t cfg; + uint8_t ap_mac[6]; + wifi_mode_t mode; // Make sure the LwIP core lock has been initialized ReturnErrorOnFailure(Internal::InitLwIPCoreLock()); - err = esp_netif_init(); if (err != ESP_OK) { goto exit; } - +#endif // Arrange for the ESP event loop to deliver events into the CHIP Device layer. err = esp_event_loop_create_default(); if (err != ESP_OK) @@ -80,6 +79,7 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) goto exit; } +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI esp_netif_create_default_wifi_ap(); esp_netif_create_default_wifi_sta(); @@ -106,6 +106,7 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) goto exit; } } +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI ReturnErrorOnFailure(chip::Crypto::add_entropy_source(app_entropy_source, NULL, 16)); diff --git a/src/platform/ESP32/ThreadStackManagerImpl.cpp b/src/platform/ESP32/ThreadStackManagerImpl.cpp new file mode 100644 index 00000000000000..5e23fe606749b8 --- /dev/null +++ b/src/platform/ESP32/ThreadStackManagerImpl.cpp @@ -0,0 +1,133 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides an implementation of the ThreadStackManager object for + * ESP32 platform. + * + */ +/* this file behaves like a config.h, comes first */ +#include + +#include +#include +#include + +#include "driver/uart.h" +#include "esp_err.h" +#include "esp_netif.h" +#include "esp_openthread.h" +#include "esp_openthread_lock.h" +#include "esp_openthread_netif_glue.h" +#include "esp_openthread_types.h" +#include "esp_vfs_eventfd.h" +#include +#include +#include + +namespace chip { +namespace DeviceLayer { + +using namespace ::chip::DeviceLayer::Internal; + +ThreadStackManagerImpl ThreadStackManagerImpl::sInstance; + +CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + esp_netif_t * openthread_netif = NULL; + esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); + esp_openthread_platform_config_t config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }; + + esp_vfs_eventfd_config_t eventfd_config = { + .max_fds = 3, + }; + VerifyOrExit(esp_netif_init() == ESP_OK, err = CHIP_ERROR_INTERNAL); + VerifyOrExit(esp_vfs_eventfd_register(&eventfd_config) == ESP_OK, err = CHIP_ERROR_INTERNAL); + VerifyOrExit(esp_openthread_init(&config) == ESP_OK, err = CHIP_ERROR_INTERNAL); + openthread_netif = esp_netif_new(&netif_cfg); + VerifyOrExit(openthread_netif != NULL, err = CHIP_ERROR_INTERNAL); + VerifyOrExit(esp_netif_attach(openthread_netif, esp_openthread_netif_glue_init(&config)) == ESP_OK, err = CHIP_ERROR_INTERNAL); + err = GenericThreadStackManagerImpl_OpenThread::DoInit(NULL); +exit: + return err; +} + +CHIP_ERROR ThreadStackManagerImpl::_StartThreadTask() +{ + if (mThreadTask != NULL) + { + return CHIP_ERROR_INCORRECT_STATE; + } + xTaskCreate(ESPThreadTask, CHIP_DEVICE_CONFIG_THREAD_TASK_NAME, CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE / sizeof(StackType_t), + this, CHIP_DEVICE_CONFIG_THREAD_TASK_PRIORITY, &mThreadTask); + if (mThreadTask == NULL) + { + return CHIP_ERROR_NO_MEMORY; + } + return CHIP_NO_ERROR; +} + +void ThreadStackManagerImpl::_LockThreadStack() +{ + esp_openthread_lock_acquire(portMAX_DELAY); +} + +bool ThreadStackManagerImpl::_TryLockThreadStack() +{ + return esp_openthread_lock_acquire(0); +} + +void ThreadStackManagerImpl::_UnlockThreadStack() +{ + esp_openthread_lock_release(); +} + +void ThreadStackManagerImpl::_ProcessThreadActivity() +{ + // Intentionally empty. +} +void ThreadStackManagerImpl::_OnCHIPoBLEAdvertisingStart() +{ + // Intentionally empty. +} + +void ThreadStackManagerImpl::_OnCHIPoBLEAdvertisingStop() +{ + // Intentionally empty. +} + +void ThreadStackManagerImpl::ESPThreadTask(void * arg) +{ + esp_openthread_launch_mainloop(); + esp_openthread_netif_glue_deinit(); + esp_vfs_eventfd_unregister(); + vTaskDelete(NULL); +} + +} // namespace DeviceLayer +} // namespace chip + +extern "C" void otTaskletsSignalPending(otInstance * p_instance) +{ + // Intentionally empty +} diff --git a/src/platform/ESP32/ThreadStackManagerImpl.h b/src/platform/ESP32/ThreadStackManagerImpl.h new file mode 100644 index 00000000000000..69a42c69004ab2 --- /dev/null +++ b/src/platform/ESP32/ThreadStackManagerImpl.h @@ -0,0 +1,105 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides an implementation of the ThreadStackManager object + * for the ESP32 platform. + */ + +#pragma once + +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/task.h" + +#include + +#include +#include +#include + +#include + +#include + +namespace chip { +namespace DeviceLayer { + +class ThreadStackManager; +class ThreadStackManagerImpl; + +/** + * Concrate implementation of the ThreadStackManager singleton object for ESP32 platform. + */ +class ThreadStackManagerImpl final : public ThreadStackManager, + public Internal::GenericThreadStackManagerImpl_OpenThread +{ + friend class ThreadStackManager; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + friend Internal::GenericThreadStackManagerImpl_OpenThread; +#endif + friend void ::otTaskletsSignalPending(otInstance * otInst); + +public: + CHIP_ERROR _InitThreadStack(); + +protected: + CHIP_ERROR _StartThreadTask(); + void _LockThreadStack(); + bool _TryLockThreadStack(); + void _UnlockThreadStack(); + void _ProcessThreadActivity(); + void _OnCHIPoBLEAdvertisingStart(); + void _OnCHIPoBLEAdvertisingStop(); + TaskHandle_t mThreadTask; + +private: + friend ThreadStackManager & ::chip::DeviceLayer::ThreadStackMgr(void); + friend ThreadStackManagerImpl & ::chip::DeviceLayer::ThreadStackMgrImpl(void); + static ThreadStackManagerImpl sInstance; + ThreadStackManagerImpl() = default; + static void ESPThreadTask(void * arg); +}; + +/** + * Returns the public interface of the ThreadStackManager singleton object. + * + * chip applications should use this to access features of the ThreadStackManager object + * that are common to all platforms. + */ +inline ThreadStackManager & ThreadStackMgr(void) +{ + return ThreadStackManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the ThreadStackManager singleton object. + * + * chip applications can use this to gain access to features of the ThreadStackManager + * that are specific to ESP32 platform. + */ +inline ThreadStackManagerImpl & ThreadStackMgrImpl(void) +{ + return ThreadStackManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip