diff --git a/config/nrfconnect/chip-module/Kconfig.features b/config/nrfconnect/chip-module/Kconfig.features index 6486d19506bab9..54e3244f65f938 100644 --- a/config/nrfconnect/chip-module/Kconfig.features +++ b/config/nrfconnect/chip-module/Kconfig.features @@ -230,4 +230,39 @@ config CHIP_WIFI_CONNECTION_RECOVERY_JITTER a random jitter interval is added to it to avoid periodicity. The random jitter is selected within range [-JITTER; +JITTER]. +choice CHIP_LAST_FABRIC_REMOVED_ACTION + prompt "An action to perform after removing the last fabric" + default CHIP_LAST_FABRIC_REMOVED_ERASE_AND_REBOOT + + config CHIP_LAST_FABRIC_REMOVED_NONE + bool "After removing the last fabric do not perform any action" + help + After removing the last fabric the device will not perform factory reset + or reboot. The current state will be left as it is and the BLE advertising + will not start automatically. + + config CHIP_LAST_FABRIC_REMOVED_ERASE_AND_REBOOT + bool "After removing the last fabric erase NVS and reboot" + help + After removing the last fabric the device will perform the factory reset and + then reboot. The current RAM state will be removed and the new commissioning to + the new fabric will use the initial fabric index. This option is the most safe. + + config CHIP_LAST_FABRIC_REMOVED_ERASE_AND_PAIRING_START + bool "After removing the last fabric erase NVS and start Bluetooth LE advertising" + help + After removing the last fabric the device will perform the factory reset without + rebooting and start the Bluetooth LE advertisement automatically. + The current RAM state will be saved and the new commissioning to the next + fabric will use the next possible fabric index. + + config CHIP_LAST_FABRIC_REMOVED_ERASE_ONLY + bool "After removing the last fabric erase NVS only" + help + After removing the last fabric the device will perform the factory reset only without + rebooting. The current RAM state will be saved and the new commissioning to the next + fabric will use the next possible fabric index. + +endchoice + endif # CHIP diff --git a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp index 217748c218519f..9f471943406c80 100644 --- a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp +++ b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp @@ -18,6 +18,7 @@ #include "AppTask.h" #include "AppConfig.h" #include "AppEvent.h" +#include "FabricTableDelegate.h" #include "LEDUtil.h" #include "binding-handler.h" @@ -207,6 +208,7 @@ CHIP_ERROR AppTask::Init() (void) initParams.InitializeStaticResourcesBeforeServerInit(); initParams.testEventTriggerDelegate = &testEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); + AppFabricTableDelegate::Init(); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); diff --git a/examples/all-clusters-app/nrfconnect/main/include/AppTask.h b/examples/all-clusters-app/nrfconnect/main/include/AppTask.h index 4db18dba683c0e..12489d037dfd50 100644 --- a/examples/all-clusters-app/nrfconnect/main/include/AppTask.h +++ b/examples/all-clusters-app/nrfconnect/main/include/AppTask.h @@ -37,6 +37,8 @@ struct Identify; class AppTask { + friend class FabricTableDelegate; + public: static AppTask & Instance(void) { diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp index 6ec81dfd5c363b..02f0704f080a58 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp +++ b/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp @@ -18,6 +18,7 @@ #include "AppTask.h" #include "AppConfig.h" #include "AppEvent.h" +#include "FabricTableDelegate.h" #include "LEDUtil.h" #include "binding-handler.h" @@ -156,6 +157,7 @@ CHIP_ERROR AppTask::Init() static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); + AppFabricTableDelegate::Init(); // We only have network commissioning on endpoint 0. emberAfEndpointEnableDisable(kNetworkCommissioningEndpointSecondary, false); diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/include/AppTask.h b/examples/all-clusters-minimal-app/nrfconnect/main/include/AppTask.h index 0d5a9f1f1dc84f..9abc025f745da9 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/main/include/AppTask.h +++ b/examples/all-clusters-minimal-app/nrfconnect/main/include/AppTask.h @@ -37,6 +37,8 @@ struct Identify; class AppTask { + friend class FabricTableDelegate; + public: static AppTask & Instance(void) { diff --git a/examples/light-switch-app/nrfconnect/main/AppTask.cpp b/examples/light-switch-app/nrfconnect/main/AppTask.cpp index 2716458175b20c..a4b5ac5b47b318 100644 --- a/examples/light-switch-app/nrfconnect/main/AppTask.cpp +++ b/examples/light-switch-app/nrfconnect/main/AppTask.cpp @@ -19,6 +19,7 @@ #include "AppTask.h" #include "AppConfig.h" #include "BoardUtil.h" +#include "FabricTableDelegate.h" #include "LEDUtil.h" #include "LightSwitch.h" @@ -218,6 +219,7 @@ CHIP_ERROR AppTask::Init() (void) initParams.InitializeStaticResourcesBeforeServerInit(); initParams.testEventTriggerDelegate = &testEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); + AppFabricTableDelegate::Init(); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); diff --git a/examples/light-switch-app/nrfconnect/main/include/AppTask.h b/examples/light-switch-app/nrfconnect/main/include/AppTask.h index c4018152e23da5..2d960b639cc886 100644 --- a/examples/light-switch-app/nrfconnect/main/include/AppTask.h +++ b/examples/light-switch-app/nrfconnect/main/include/AppTask.h @@ -40,6 +40,8 @@ struct Identify; class AppTask { + friend class FabricTableDelegate; + public: static AppTask & Instance() { diff --git a/examples/lighting-app/nrfconnect/main/AppTask.cpp b/examples/lighting-app/nrfconnect/main/AppTask.cpp index 8bbddd6b47774f..44a58ec5d1009e 100644 --- a/examples/lighting-app/nrfconnect/main/AppTask.cpp +++ b/examples/lighting-app/nrfconnect/main/AppTask.cpp @@ -20,6 +20,7 @@ #include "AppConfig.h" #include "AppEvent.h" +#include "FabricTableDelegate.h" #include "LEDUtil.h" #include "PWMDevice.h" @@ -246,6 +247,7 @@ CHIP_ERROR AppTask::Init() (void) initParams.InitializeStaticResourcesBeforeServerInit(); initParams.testEventTriggerDelegate = &testEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); + AppFabricTableDelegate::Init(); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); diff --git a/examples/lighting-app/nrfconnect/main/include/AppTask.h b/examples/lighting-app/nrfconnect/main/include/AppTask.h index 37be9a0334847c..3b8197c82464dd 100644 --- a/examples/lighting-app/nrfconnect/main/include/AppTask.h +++ b/examples/lighting-app/nrfconnect/main/include/AppTask.h @@ -45,6 +45,8 @@ struct Identify; class AppTask { + friend class FabricTableDelegate; + public: static AppTask & Instance() { diff --git a/examples/lock-app/nrfconnect/main/AppTask.cpp b/examples/lock-app/nrfconnect/main/AppTask.cpp index 3ef85657363043..25a23ddb80249c 100644 --- a/examples/lock-app/nrfconnect/main/AppTask.cpp +++ b/examples/lock-app/nrfconnect/main/AppTask.cpp @@ -19,6 +19,7 @@ #include "AppTask.h" #include "AppConfig.h" #include "BoltLockManager.h" +#include "FabricTableDelegate.h" #include "LEDUtil.h" #include "LEDWidget.h" @@ -212,6 +213,7 @@ CHIP_ERROR AppTask::Init() (void) initParams.InitializeStaticResourcesBeforeServerInit(); initParams.testEventTriggerDelegate = &testEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); + AppFabricTableDelegate::Init(); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); diff --git a/examples/lock-app/nrfconnect/main/include/AppTask.h b/examples/lock-app/nrfconnect/main/include/AppTask.h index a0a50da9ed23db..7d0feaf78ac696 100644 --- a/examples/lock-app/nrfconnect/main/include/AppTask.h +++ b/examples/lock-app/nrfconnect/main/include/AppTask.h @@ -40,6 +40,8 @@ struct Identify; class AppTask { + friend class FabricTableDelegate; + public: static AppTask & Instance() { @@ -67,8 +69,8 @@ class AppTask static void FunctionHandler(const AppEvent & event); static void StartBLEAdvertisementAndLockActionEventHandler(const AppEvent & event); static void LockActionEventHandler(const AppEvent & event); - static void StartBLEAdvertisementHandler(const AppEvent & event); static void UpdateLedStateEventHandler(const AppEvent & event); + static void StartBLEAdvertisementHandler(const AppEvent & event); static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); static void ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged); diff --git a/examples/platform/nrfconnect/util/include/FabricTableDelegate.h b/examples/platform/nrfconnect/util/include/FabricTableDelegate.h new file mode 100644 index 00000000000000..43d3edd05ccd8a --- /dev/null +++ b/examples/platform/nrfconnect/util/include/FabricTableDelegate.h @@ -0,0 +1,74 @@ +/* + * + * Copyright (c) 2023 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. + */ + +#pragma once + +#include "AppTask.h" + +#include +#include + +namespace chip { + +class AppFabricTableDelegate : public FabricTable::Delegate +{ +public: + ~AppFabricTableDelegate() { Server::GetInstance().GetFabricTable().RemoveFabricDelegate(this); } + + /** + * @brief Initialize module and add a delegation to the Fabric Table. + * + * To use the OnFabricRemoved method defined within this class and allow to react on the last fabric removal + * this method should be called in the application code. + */ + static void Init() + { +#ifndef CONFIG_CHIP_LAST_FABRIC_NONE + static AppFabricTableDelegate sAppFabricDelegate; + Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAppFabricDelegate); +#endif // CONFIG_CHIP_LAST_FABRIC_NONE + } + +private: + void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) + { +#ifndef CONFIG_CHIP_LAST_FABRIC_NONE + if (Server::GetInstance().GetFabricTable().FabricCount() == 0) + { +#ifdef CONFIG_CHIP_LAST_FABRIC_REMOVED_ERASE_AND_REBOOT + Server::GetInstance().ScheduleFactoryReset(); +#elif defined(CONFIG_CHIP_LAST_FABRIC_REMOVED_ERASE_ONLY) || defined(CONFIG_CHIP_LAST_FABRIC_REMOVED_ERASE_AND_PAIRING_START) + DeviceLayer::PlatformMgr().ScheduleWork([](intptr_t) { + /* Erase Matter data */ + DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().DoFactoryReset(); + /* Erase Network credentials and disconnect */ + DeviceLayer::ConnectivityMgr().ErasePersistentInfo(); + DeviceLayer::ConnectivityMgr().ClearWiFiStationProvision(); +#ifdef CONFIG_CHIP_LAST_FABRIC_REMOVED_ERASE_AND_PAIRING_START + /* Start the New BLE advertising */ + AppEvent event; + event.Handler = AppTask::StartBLEAdvertisementHandler; + AppTask::Instance().PostEvent(event); +#endif // CONFIG_CHIP_LAST_FABRIC_REMOVED_ERASE_AND_PAIRING_START + }); +#endif // CONFIG_CHIP_LAST_FABRIC_REMOVED_ERASE_AND_REBOOT + } +#endif // CONFIG_CHIP_LAST_FABRIC_NONE + } +}; +} // namespace chip diff --git a/examples/pump-app/nrfconnect/main/AppTask.cpp b/examples/pump-app/nrfconnect/main/AppTask.cpp index b2406ed56cf29d..c8fc9c73b8daae 100644 --- a/examples/pump-app/nrfconnect/main/AppTask.cpp +++ b/examples/pump-app/nrfconnect/main/AppTask.cpp @@ -18,6 +18,7 @@ #include "AppTask.h" #include "AppConfig.h" +#include "FabricTableDelegate.h" #include "LEDUtil.h" #include "LEDWidget.h" #include "PumpManager.h" @@ -189,6 +190,7 @@ CHIP_ERROR AppTask::Init() (void) initParams.InitializeStaticResourcesBeforeServerInit(); initParams.testEventTriggerDelegate = &testEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); + AppFabricTableDelegate::Init(); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); diff --git a/examples/pump-app/nrfconnect/main/include/AppTask.h b/examples/pump-app/nrfconnect/main/include/AppTask.h index fb2fe2c855cb1a..7c6092eda6f43a 100644 --- a/examples/pump-app/nrfconnect/main/include/AppTask.h +++ b/examples/pump-app/nrfconnect/main/include/AppTask.h @@ -39,6 +39,8 @@ struct k_timer; class AppTask { + friend class FabricTableDelegate; + public: static AppTask & Instance(void) { diff --git a/examples/pump-controller-app/nrfconnect/main/AppTask.cpp b/examples/pump-controller-app/nrfconnect/main/AppTask.cpp index 9b00a541cada3b..b3e995e99369a0 100644 --- a/examples/pump-controller-app/nrfconnect/main/AppTask.cpp +++ b/examples/pump-controller-app/nrfconnect/main/AppTask.cpp @@ -18,6 +18,7 @@ #include "AppTask.h" #include "AppConfig.h" +#include "FabricTableDelegate.h" #include "LEDUtil.h" #include "LEDWidget.h" #include "PumpManager.h" @@ -187,6 +188,7 @@ CHIP_ERROR AppTask::Init() (void) initParams.InitializeStaticResourcesBeforeServerInit(); initParams.testEventTriggerDelegate = &testEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); + AppFabricTableDelegate::Init(); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); diff --git a/examples/pump-controller-app/nrfconnect/main/include/AppTask.h b/examples/pump-controller-app/nrfconnect/main/include/AppTask.h index 8ca4a69e91c0f0..7ef978ab594e44 100644 --- a/examples/pump-controller-app/nrfconnect/main/include/AppTask.h +++ b/examples/pump-controller-app/nrfconnect/main/include/AppTask.h @@ -39,6 +39,8 @@ struct k_timer; class AppTask { + friend class FabricTableDelegate; + public: static AppTask & Instance(void) { diff --git a/examples/window-app/nrfconnect/main/AppTask.cpp b/examples/window-app/nrfconnect/main/AppTask.cpp index cda4c0c9e318b8..f607114da6d031 100644 --- a/examples/window-app/nrfconnect/main/AppTask.cpp +++ b/examples/window-app/nrfconnect/main/AppTask.cpp @@ -18,6 +18,7 @@ #include "AppTask.h" #include "AppConfig.h" #include "AppEvent.h" +#include "FabricTableDelegate.h" #include "LEDUtil.h" #include "WindowCovering.h" @@ -191,6 +192,7 @@ CHIP_ERROR AppTask::Init() (void) initParams.InitializeStaticResourcesBeforeServerInit(); initParams.testEventTriggerDelegate = &testEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); + AppFabricTableDelegate::Init(); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); diff --git a/examples/window-app/nrfconnect/main/include/AppTask.h b/examples/window-app/nrfconnect/main/include/AppTask.h index fdd94d0c61e416..998ab34d2177ed 100644 --- a/examples/window-app/nrfconnect/main/include/AppTask.h +++ b/examples/window-app/nrfconnect/main/include/AppTask.h @@ -37,6 +37,8 @@ struct Identify; class AppTask { + friend class FabricTableDelegate; + public: static AppTask & Instance(void) {