diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index 0d6e9b0007c1b9..94c5bd15476d60 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -21,6 +21,7 @@ set(PRIV_INCLUDE_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/all-clusters-app" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/include" "${CMAKE_CURRENT_LIST_DIR}/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" ) set(SRC_DIRS_LIST "${CMAKE_CURRENT_LIST_DIR}" @@ -28,6 +29,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/route_hook" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" diff --git a/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp b/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp index 156bb28d706af0..9d73baddc68a4a 100644 --- a/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp +++ b/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp @@ -46,6 +46,7 @@ #include #include #include +#include static const char * TAG = "app-devicecallbacks"; @@ -55,7 +56,8 @@ using namespace ::chip::System; using namespace ::chip::DeviceLayer; using namespace chip::app; -constexpr uint32_t kIdentifyTimerDelayMS = 250; +constexpr uint32_t kIdentifyTimerDelayMS = 250; +constexpr uint32_t kInitOTARequestorDelaySec = 3; void OnIdentifyTriggerEffect(Identify * identify) { @@ -200,13 +202,26 @@ void DeviceCallbacks::PostAttributeChangeCallback(EndpointId endpointId, Cluster ESP_LOGI(TAG, "Current free heap: %u\n", static_cast(heap_caps_get_free_size(MALLOC_CAP_8BIT))); } +void InitOTARequestorHandler(System::Layer * systemLayer, void * appState) +{ + OTAHelpers::Instance().InitOTARequestor(); +} + void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event) { + static bool isOTAInitialized = false; if (event->InternetConnectivityChange.IPv4 == kConnectivity_Established) { ESP_LOGI(TAG, "Server ready at: %s:%d", event->InternetConnectivityChange.address, CHIP_PORT); wifiLED.Set(true); chip::app::DnssdServer::Instance().StartServer(); + + if (!isOTAInitialized) + { + chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(kInitOTARequestorDelaySec), + InitOTARequestorHandler, nullptr); + isOTAInitialized = true; + } } else if (event->InternetConnectivityChange.IPv4 == kConnectivity_Lost) { @@ -217,6 +232,12 @@ void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event { ESP_LOGI(TAG, "IPv6 Server ready..."); chip::app::DnssdServer::Instance().StartServer(); + if (!isOTAInitialized) + { + chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(kInitOTARequestorDelaySec), + InitOTARequestorHandler, nullptr); + isOTAInitialized = true; + } } else if (event->InternetConnectivityChange.IPv6 == kConnectivity_Lost) { diff --git a/examples/all-clusters-app/esp32/main/main.cpp b/examples/all-clusters-app/esp32/main/main.cpp index 55e08b595d94fa..0638b838d77e9d 100644 --- a/examples/all-clusters-app/esp32/main/main.cpp +++ b/examples/all-clusters-app/esp32/main/main.cpp @@ -37,17 +37,12 @@ #include "shell_extension/launch.h" #include -#include -#include -#include -#include #include #include #include #include #include #include -#include #if CONFIG_HAVE_DISPLAY #include "DeviceWithDisplay.h" @@ -76,14 +71,6 @@ static DeviceCallbacks EchoCallbacks; namespace { -#if CONFIG_ENABLE_OTA_REQUESTOR -DefaultOTARequestor gRequestorCore; -DefaultOTARequestorStorage gRequestorStorage; -DefaultOTARequestorDriver gRequestorUser; -BDXDownloader gDownloader; -OTAImageProcessorImpl gImageProcessor; -#endif - app::Clusters::NetworkCommissioning::Instance sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::ESPWiFiDriver::GetInstance())); @@ -126,18 +113,6 @@ static void InitServer(intptr_t context) #endif } -static void InitOTARequestor(void) -{ -#if CONFIG_ENABLE_OTA_REQUESTOR - SetRequestorInstance(&gRequestorCore); - gRequestorStorage.Init(Server::GetInstance().GetPersistentStorage()); - gRequestorCore.Init(Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); - gImageProcessor.SetOTADownloader(&gDownloader); - gDownloader.SetImageProcessorDelegate(&gImageProcessor); - gRequestorUser.Init(&gRequestorCore, &gImageProcessor); -#endif -} - extern "C" void app_main() { // Initialize the ESP NVS layer. @@ -174,8 +149,6 @@ extern "C" void app_main() return; } - InitOTARequestor(); - ESP_LOGI(TAG, "------------------------Starting App Task---------------------------"); error = GetAppTask().StartAppTask(); if (error != CHIP_NO_ERROR) diff --git a/examples/lighting-app/esp32/main/CMakeLists.txt b/examples/lighting-app/esp32/main/CMakeLists.txt index 3a81faaf0f0394..efbabfd9b5f678 100644 --- a/examples/lighting-app/esp32/main/CMakeLists.txt +++ b/examples/lighting-app/esp32/main/CMakeLists.txt @@ -20,12 +20,14 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/lighting-app" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/lighting-app/lighting-common/color_format" "${CMAKE_CURRENT_LIST_DIR}/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" SRC_DIRS "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/lighting-app/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/route_hook" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/lighting-app/lighting-common/color_format" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" diff --git a/examples/lighting-app/esp32/main/DeviceCallbacks.cpp b/examples/lighting-app/esp32/main/DeviceCallbacks.cpp index 2ecbe8dcf9ea8f..1353598daa6554 100644 --- a/examples/lighting-app/esp32/main/DeviceCallbacks.cpp +++ b/examples/lighting-app/esp32/main/DeviceCallbacks.cpp @@ -38,8 +38,10 @@ #include #include #include +#include -static const char * TAG = "light-app-callbacks"; +static const char * TAG = "light-app-callbacks"; +constexpr uint32_t kInitOTARequestorDelaySec = 3; extern LEDWidget AppLED; @@ -149,12 +151,25 @@ void DeviceCallbacks::PostAttributeChangeCallback(EndpointId endpointId, Cluster ESP_LOGI(TAG, "Current free heap: %u\n", static_cast(heap_caps_get_free_size(MALLOC_CAP_8BIT))); } +void InitOTARequestorHandler(System::Layer * systemLayer, void * appState) +{ + OTAHelpers::Instance().InitOTARequestor(); +} + void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event) { + static bool isOTAInitialized = false; if (event->InternetConnectivityChange.IPv4 == kConnectivity_Established) { ESP_LOGI(TAG, "Server ready at: %s:%d", event->InternetConnectivityChange.address, CHIP_PORT); chip::app::DnssdServer::Instance().StartServer(); + + if (!isOTAInitialized) + { + chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(kInitOTARequestorDelaySec), + InitOTARequestorHandler, nullptr); + isOTAInitialized = true; + } } else if (event->InternetConnectivityChange.IPv4 == kConnectivity_Lost) { @@ -164,6 +179,13 @@ void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event { ESP_LOGI(TAG, "IPv6 Server ready..."); chip::app::DnssdServer::Instance().StartServer(); + + if (!isOTAInitialized) + { + chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(kInitOTARequestorDelaySec), + InitOTARequestorHandler, nullptr); + isOTAInitialized = true; + } } else if (event->InternetConnectivityChange.IPv6 == kConnectivity_Lost) { diff --git a/examples/lighting-app/esp32/main/main.cpp b/examples/lighting-app/esp32/main/main.cpp index 7004f6c576d7a6..838b77a1234d09 100644 --- a/examples/lighting-app/esp32/main/main.cpp +++ b/examples/lighting-app/esp32/main/main.cpp @@ -27,17 +27,12 @@ #include "nvs_flash.h" #include "shell_extension/launch.h" #include -#include -#include -#include -#include #include #include #include #include #include #include -#include #if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER #include @@ -48,14 +43,6 @@ using namespace ::chip::Credentials; using namespace ::chip::DeviceManager; using namespace ::chip::DeviceLayer; -#if CONFIG_ENABLE_OTA_REQUESTOR -DefaultOTARequestor gRequestorCore; -DefaultOTARequestorStorage gRequestorStorage; -DefaultOTARequestorDriver gRequestorUser; -BDXDownloader gDownloader; -OTAImageProcessorImpl gImageProcessor; -#endif - LEDWidget AppLED; static const char * TAG = "light-app"; @@ -72,18 +59,6 @@ ESP32FactoryDataProvider sFactoryDataProvider; #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER } // namespace -static void InitOTARequestor(void) -{ -#if CONFIG_ENABLE_OTA_REQUESTOR - SetRequestorInstance(&gRequestorCore); - gRequestorStorage.Init(Server::GetInstance().GetPersistentStorage()); - gRequestorCore.Init(Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); - gImageProcessor.SetOTADownloader(&gDownloader); - gDownloader.SetImageProcessorDelegate(&gImageProcessor); - gRequestorUser.Init(&gRequestorCore, &gImageProcessor); -#endif -} - static void InitServer(intptr_t context) { // Print QR Code URL @@ -111,7 +86,6 @@ static void InitServer(intptr_t context) chip::app::DnssdServer::Instance().StartServer(); } #endif - InitOTARequestor(); } extern "C" void app_main() diff --git a/examples/ota-requestor-app/esp32/main/CMakeLists.txt b/examples/ota-requestor-app/esp32/main/CMakeLists.txt index 08f878c56b683f..f89b111d538656 100644 --- a/examples/ota-requestor-app/esp32/main/CMakeLists.txt +++ b/examples/ota-requestor-app/esp32/main/CMakeLists.txt @@ -20,7 +20,8 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/include" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/ota-requestor-app/" - SRC_DIRS + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" + SRC_DIRS "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/ota-requestor-app/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" @@ -49,7 +50,8 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - PRIV_REQUIRES chip QRCode bt console app_update) + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" + PRIV_REQUIRES chip QRCode bt console app_update) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 14) target_compile_options(${COMPONENT_LIB} PRIVATE "-DLWIP_IPV6_SCOPES=0" "-DCHIP_HAVE_CONFIG_H") diff --git a/examples/ota-requestor-app/esp32/main/DeviceCallbacks.cpp b/examples/ota-requestor-app/esp32/main/DeviceCallbacks.cpp index 043d452011e7a4..6807e16cde0bb9 100644 --- a/examples/ota-requestor-app/esp32/main/DeviceCallbacks.cpp +++ b/examples/ota-requestor-app/esp32/main/DeviceCallbacks.cpp @@ -30,8 +30,10 @@ #include #include #include +#include -static const char * TAG = "echo-devicecallbacks"; +static const char * TAG = "echo-devicecallbacks"; +constexpr uint32_t kInitOTARequestorDelaySec = 3; using namespace ::chip; using namespace ::chip::Inet; @@ -78,12 +80,24 @@ void DeviceCallbacks::PostAttributeChangeCallback(EndpointId endpointId, Cluster ESP_LOGI(TAG, "Current free heap: %d\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); } +void InitOTARequestorHandler(System::Layer * systemLayer, void * appState) +{ + OTAHelpers::Instance().InitOTARequestor(); +} + void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event) { + static bool isOTAInitialized = false; if (event->InternetConnectivityChange.IPv4 == kConnectivity_Established) { ESP_LOGI(TAG, "Server ready at: %s:%d", event->InternetConnectivityChange.address, CHIP_PORT); chip::app::DnssdServer::Instance().StartServer(); + if (!isOTAInitialized) + { + chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(kInitOTARequestorDelaySec), + InitOTARequestorHandler, nullptr); + isOTAInitialized = true; + } } else if (event->InternetConnectivityChange.IPv4 == kConnectivity_Lost) { @@ -93,6 +107,12 @@ void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event { ESP_LOGI(TAG, "IPv6 Server ready..."); chip::app::DnssdServer::Instance().StartServer(); + if (!isOTAInitialized) + { + chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(kInitOTARequestorDelaySec), + InitOTARequestorHandler, nullptr); + isOTAInitialized = true; + } } else if (event->InternetConnectivityChange.IPv6 == kConnectivity_Lost) { diff --git a/examples/ota-requestor-app/esp32/main/main.cpp b/examples/ota-requestor-app/esp32/main/main.cpp index 5f962d712d8db1..02adf0680655ae 100644 --- a/examples/ota-requestor-app/esp32/main/main.cpp +++ b/examples/ota-requestor-app/esp32/main/main.cpp @@ -29,10 +29,6 @@ #include "freertos/task.h" #include "nvs_flash.h" #include -#include -#include -#include -#include #include #include @@ -41,8 +37,6 @@ #include -#include "OTAImageProcessorImpl.h" - using namespace ::chip; using namespace ::chip::System; using namespace ::chip::Credentials; @@ -53,12 +47,6 @@ namespace { const char * TAG = "ota-requester-app"; static DeviceCallbacks EchoCallbacks; -DefaultOTARequestor gRequestorCore; -DefaultOTARequestorStorage gRequestorStorage; -DefaultOTARequestorDriver gRequestorUser; -BDXDownloader gDownloader; -OTAImageProcessorImpl gImageProcessor; - app::Clusters::NetworkCommissioning::Instance sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::ESPWiFiDriver::GetInstance())); @@ -72,13 +60,6 @@ static void InitServer(intptr_t context) SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); sWiFiNetworkCommissioningInstance.Init(); - - SetRequestorInstance(&gRequestorCore); - gRequestorStorage.Init(Server::GetInstance().GetPersistentStorage()); - gRequestorCore.Init(Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); - gImageProcessor.SetOTADownloader(&gDownloader); - gDownloader.SetImageProcessorDelegate(&gImageProcessor); - gRequestorUser.Init(&gRequestorCore, &gImageProcessor); } } // namespace diff --git a/examples/platform/esp32/ota/OTAHelper.cpp b/examples/platform/esp32/ota/OTAHelper.cpp new file mode 100644 index 00000000000000..d561a09ad815e6 --- /dev/null +++ b/examples/platform/esp32/ota/OTAHelper.cpp @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2022 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. + */ + +#include "OTAHelper.h" + +#include +#include +#include +#include +#include + +using namespace chip::DeviceLayer; +using namespace chip; + +namespace { + +#if CONFIG_ENABLE_OTA_REQUESTOR +DefaultOTARequestor gRequestorCore; +DefaultOTARequestorStorage gRequestorStorage; +DefaultOTARequestorDriver gRequestorUser; +BDXDownloader gDownloader; +OTAImageProcessorImpl gImageProcessor; +#endif +} // namespace +void OTAHelpers::InitOTARequestor() +{ + +#if CONFIG_ENABLE_OTA_REQUESTOR + SetRequestorInstance(&gRequestorCore); + gRequestorStorage.Init(Server::GetInstance().GetPersistentStorage()); + gRequestorCore.Init(Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); + gImageProcessor.SetOTADownloader(&gDownloader); + gDownloader.SetImageProcessorDelegate(&gImageProcessor); + gRequestorUser.Init(&gRequestorCore, &gImageProcessor); +#endif +} diff --git a/examples/platform/esp32/ota/OTAHelper.h b/examples/platform/esp32/ota/OTAHelper.h new file mode 100644 index 00000000000000..521c5b39532b6d --- /dev/null +++ b/examples/platform/esp32/ota/OTAHelper.h @@ -0,0 +1,27 @@ +/* + * + * Copyright (c) 2022 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. + */ + +class OTAHelpers +{ +public: + static OTAHelpers & Instance(void) + { + static OTAHelpers sInitOTA; + return sInitOTA; + } + void InitOTARequestor(void); +}; diff --git a/src/platform/ESP32/OTAImageProcessorImpl.cpp b/src/platform/ESP32/OTAImageProcessorImpl.cpp index 6f8d5d07dda0d3..62fbe55410bef2 100644 --- a/src/platform/ESP32/OTAImageProcessorImpl.cpp +++ b/src/platform/ESP32/OTAImageProcessorImpl.cpp @@ -16,6 +16,7 @@ */ #include +#include #include #include "OTAImageProcessorImpl.h" @@ -38,6 +39,35 @@ void HandleRestart(Layer * systemLayer, void * appState) } } // namespace +bool OTAImageProcessorImpl::IsFirstImageRun() +{ + OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor == nullptr) + { + return false; + } + + return requestor->GetCurrentUpdateState() == OTARequestorInterface::OTAUpdateStateEnum::kApplying; +} + +CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage() +{ + OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor == nullptr) + { + return CHIP_ERROR_INTERNAL; + } + + uint32_t currentVersion; + ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSoftwareVersion(currentVersion)); + if (currentVersion != requestor->GetTargetVersion()) + { + return CHIP_ERROR_INCORRECT_STATE; + } + + return CHIP_NO_ERROR; +} + CHIP_ERROR OTAImageProcessorImpl::PrepareDownload() { DeviceLayer::PlatformMgr().ScheduleWork(HandlePrepareDownload, reinterpret_cast(this)); diff --git a/src/platform/ESP32/OTAImageProcessorImpl.h b/src/platform/ESP32/OTAImageProcessorImpl.h index 64ba8e8f51f557..5d0775c4392f13 100644 --- a/src/platform/ESP32/OTAImageProcessorImpl.h +++ b/src/platform/ESP32/OTAImageProcessorImpl.h @@ -35,8 +35,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface CHIP_ERROR Abort() override; CHIP_ERROR ProcessBlock(ByteSpan & block) override; void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }; - bool IsFirstImageRun() override { return false; } - CHIP_ERROR ConfirmCurrentImage() override { return CHIP_NO_ERROR; } + bool IsFirstImageRun() override; + CHIP_ERROR ConfirmCurrentImage() override; private: static void HandlePrepareDownload(intptr_t context);