From 183916598317f1ae7c4f59a18d618564a34e2812 Mon Sep 17 00:00:00 2001 From: Andrii Bilynskyi Date: Mon, 7 Aug 2023 18:45:11 +0300 Subject: [PATCH] [Telink] Factory reset using power on sequence (#28519) --- config/telink/chip-module/Kconfig | 8 +++ .../lighting-app/telink/include/AppTask.h | 9 +++ examples/lighting-app/telink/src/AppTask.cpp | 51 +++++++++++++++ .../telink/common/include/AppTaskCommon.h | 3 + .../telink/common/src/AppTaskCommon.cpp | 8 +++ .../platform/telink/common/src/mainCommon.cpp | 63 ++++++++++++++++++- 6 files changed, 141 insertions(+), 1 deletion(-) diff --git a/config/telink/chip-module/Kconfig b/config/telink/chip-module/Kconfig index 97f42e01932c5d..fcd205102f22aa 100644 --- a/config/telink/chip-module/Kconfig +++ b/config/telink/chip-module/Kconfig @@ -207,3 +207,11 @@ config CHIP_MAX_PREFERRED_SUBSCRIPTION_REPORT_INTERVAL the initiator device to detect the publisher absence reasonably fast due to not sending the reports too rarely. The current algorithm is to select bigger value from the one requested by the initiator and the one preferred by the publisher. + +config CHIP_ENABLE_POWER_ON_FACTORY_RESET + bool "Enable power on factory reset sequence" + default n + help + Enable power on factory reset sequence. If device power triggered off during + first 5 seconds after power on and this sequence repeated 5 times - factory + reset will be involved. diff --git a/examples/lighting-app/telink/include/AppTask.h b/examples/lighting-app/telink/include/AppTask.h index f1085763e74086..a9d9ab3712ef94 100644 --- a/examples/lighting-app/telink/include/AppTask.h +++ b/examples/lighting-app/telink/include/AppTask.h @@ -23,6 +23,9 @@ class AppTask : public AppTaskCommon { public: +#ifdef CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET + void PowerOnFactoryReset(void); +#endif /* CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET */ void SetInitiateAction(PWMDevice::Action_t aAction, int32_t aActor, uint8_t * value); void UpdateClusterState(void); PWMDevice & GetPWMDevice(void) { return mPwmRgbBlueLed; } @@ -37,7 +40,13 @@ class AppTask : public AppTaskCommon static void ActionCompleted(PWMDevice::Action_t aAction, int32_t aActor); static void LightingActionEventHandler(AppEvent * aEvent); +#ifdef CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET + static void PowerOnFactoryResetEventHandler(AppEvent * aEvent); + static void PowerOnFactoryResetTimerEvent(struct k_timer * dummy); + static unsigned int sPowerOnFactoryResetTimerCnt; + static k_timer sPowerOnFactoryResetTimer; +#endif /* CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET */ PWMDevice mPwmRgbBlueLed; #if USE_RGB_PWM PWMDevice mPwmRgbGreenLed; diff --git a/examples/lighting-app/telink/src/AppTask.cpp b/examples/lighting-app/telink/src/AppTask.cpp index f875086b9d59c7..1d1f3b748a97fb 100644 --- a/examples/lighting-app/telink/src/AppTask.cpp +++ b/examples/lighting-app/telink/src/AppTask.cpp @@ -17,6 +17,7 @@ */ #include "AppTask.h" +#include #include "ColorFormat.h" #include "PWMDevice.h" @@ -41,6 +42,17 @@ CtColor_t sCT; AppTask AppTask::sAppTask; +#ifdef CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET +void AppTask::PowerOnFactoryReset(void) +{ + LOG_INF("Lighting App Power On Factory Reset"); + AppEvent event; + event.Type = AppEvent::kEventType_Lighting; + event.Handler = PowerOnFactoryResetEventHandler; + GetAppTask().PostEvent(&event); +} +#endif /* CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET */ + CHIP_ERROR AppTask::Init(void) { // Init lighting manager @@ -284,3 +296,42 @@ void AppTask::SetInitiateAction(PWMDevice::Action_t aAction, int32_t aActor, uin } #endif } + +#ifdef CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET +static constexpr uint32_t kPowerOnFactoryResetIndicationMax = 4; +static constexpr uint32_t kPowerOnFactoryResetIndicationTimeMs = 1000; + +unsigned int AppTask::sPowerOnFactoryResetTimerCnt; +k_timer AppTask::sPowerOnFactoryResetTimer; + +void AppTask::PowerOnFactoryResetEventHandler(AppEvent * aEvent) +{ + LOG_INF("Lighting App Power On Factory Reset Handler"); + sPowerOnFactoryResetTimerCnt = 1; + sAppTask.mPwmRgbBlueLed.Set(sPowerOnFactoryResetTimerCnt % 2); +#if USE_RGB_PWM + sAppTask.mPwmRgbRedLed.Set(sPowerOnFactoryResetTimerCnt % 2); + sAppTask.mPwmRgbGreenLed.Set(sPowerOnFactoryResetTimerCnt % 2); +#endif + k_timer_init(&sPowerOnFactoryResetTimer, PowerOnFactoryResetTimerEvent, nullptr); + k_timer_start(&sPowerOnFactoryResetTimer, K_MSEC(kPowerOnFactoryResetIndicationTimeMs), + K_MSEC(kPowerOnFactoryResetIndicationTimeMs)); +} + +void AppTask::PowerOnFactoryResetTimerEvent(struct k_timer * timer) +{ + sPowerOnFactoryResetTimerCnt++; + LOG_INF("Lighting App Power On Factory Reset Handler %u", sPowerOnFactoryResetTimerCnt); + sAppTask.mPwmRgbBlueLed.Set(sPowerOnFactoryResetTimerCnt % 2); +#if USE_RGB_PWM + sAppTask.mPwmRgbRedLed.Set(sPowerOnFactoryResetTimerCnt % 2); + sAppTask.mPwmRgbGreenLed.Set(sPowerOnFactoryResetTimerCnt % 2); +#endif + if (sPowerOnFactoryResetTimerCnt > kPowerOnFactoryResetIndicationMax) + { + k_timer_stop(timer); + LOG_INF("schedule factory reset"); + chip::Server::GetInstance().ScheduleFactoryReset(); + } +} +#endif /* CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET */ diff --git a/examples/platform/telink/common/include/AppTaskCommon.h b/examples/platform/telink/common/include/AppTaskCommon.h index fe1c400b22c448..74f1f879056ba5 100644 --- a/examples/platform/telink/common/include/AppTaskCommon.h +++ b/examples/platform/telink/common/include/AppTaskCommon.h @@ -63,6 +63,9 @@ constexpr uint8_t kButtonReleaseEvent = 0; class AppTaskCommon { public: +#ifdef CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET + void PowerOnFactoryReset(void); +#endif /* CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET */ CHIP_ERROR StartApp(); void PostEvent(AppEvent * event); diff --git a/examples/platform/telink/common/src/AppTaskCommon.cpp b/examples/platform/telink/common/src/AppTaskCommon.cpp index a13e84ca527cad..41d3a0c3e3fec5 100644 --- a/examples/platform/telink/common/src/AppTaskCommon.cpp +++ b/examples/platform/telink/common/src/AppTaskCommon.cpp @@ -222,6 +222,14 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_telink, SHELL_CMD(reboot, NULL, "Reboot board SHELL_CMD_REGISTER(telink, &sub_telink, "Telink commands", NULL); #endif // CONFIG_CHIP_LIB_SHELL +#ifdef CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET +void AppTaskCommon::PowerOnFactoryReset(void) +{ + LOG_INF("schedule factory reset"); + chip::Server::GetInstance().ScheduleFactoryReset(); +} +#endif /* CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET */ + CHIP_ERROR AppTaskCommon::StartApp(void) { CHIP_ERROR err = GetAppTask().Init(); diff --git a/examples/platform/telink/common/src/mainCommon.cpp b/examples/platform/telink/common/src/mainCommon.cpp index 12abb1de76ec74..63c41b3a211982 100644 --- a/examples/platform/telink/common/src/mainCommon.cpp +++ b/examples/platform/telink/common/src/mainCommon.cpp @@ -33,6 +33,65 @@ using namespace ::chip; using namespace ::chip::Inet; using namespace ::chip::DeviceLayer; +#ifdef CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET +static constexpr uint32_t kFactoryResetOnBootMaxCnt = 5; +static constexpr const char * kFactoryResetOnBootStoreKey = "TelinkFactoryResetOnBootCnt"; +static constexpr uint32_t kFactoryResetUsualBootTimeoutMs = 5000; + +static k_timer FactoryResetUsualBootTimer; + +static void FactoryResetUsualBoot(struct k_timer * dummy) +{ + (void) dummy; + (void) chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFactoryResetOnBootStoreKey); + LOG_INF("Schedule factory counter deleted"); +} + +static void FactoryResetOnBoot(void) +{ + uint32_t FactoryResetOnBootCnt; + CHIP_ERROR FactoryResetOnBootErr = chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get( + kFactoryResetOnBootStoreKey, &FactoryResetOnBootCnt, sizeof(FactoryResetOnBootCnt)); + + if (FactoryResetOnBootErr == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + FactoryResetOnBootCnt = 1; + if (chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFactoryResetOnBootStoreKey, &FactoryResetOnBootCnt, + sizeof(FactoryResetOnBootCnt)) != CHIP_NO_ERROR) + { + LOG_ERR("FactoryResetOnBootCnt write fail"); + } + else + { + LOG_INF("Schedule factory counter %u", FactoryResetOnBootCnt); + } + } + else if (FactoryResetOnBootErr == CHIP_NO_ERROR) + { + FactoryResetOnBootCnt++; + if (chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFactoryResetOnBootStoreKey, &FactoryResetOnBootCnt, + sizeof(FactoryResetOnBootCnt)) != CHIP_NO_ERROR) + { + LOG_ERR("FactoryResetOnBootCnt write fail"); + } + else + { + LOG_INF("Schedule factory counter %u", FactoryResetOnBootCnt); + if (FactoryResetOnBootCnt >= kFactoryResetOnBootMaxCnt) + { + GetAppTask().PowerOnFactoryReset(); + } + } + } + else + { + LOG_ERR("FactoryResetOnBootCnt read fail"); + } + k_timer_init(&FactoryResetUsualBootTimer, FactoryResetUsualBoot, nullptr); + k_timer_start(&FactoryResetUsualBootTimer, K_MSEC(kFactoryResetUsualBootTimeoutMs), K_NO_WAIT); +} +#endif /* CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET */ + int main(void) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -61,7 +120,9 @@ int main(void) LOG_ERR("StartEventLoopTask fail"); goto exit; } - +#ifdef CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET + FactoryResetOnBoot(); +#endif /* CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET */ err = ThreadStackMgr().InitThreadStack(); if (err != CHIP_NO_ERROR) {