From e730606136824ccedafac26dad11874efbee3cce Mon Sep 17 00:00:00 2001 From: andrei-menzopol <96489227+andrei-menzopol@users.noreply.github.com> Date: Mon, 29 Aug 2022 16:02:43 +0300 Subject: [PATCH] Fix overlapping execution for TriggerEffect and Identify commands in Identify Server (#21968) * Fix overlapping behaviour for TriggerEffect and Identify commands * [K32W0] Add TriggerEffect support, update readme * Fix behaviour when TriggerEffect called during Identify and vice versa * Update wordlist Signed-off-by: Andrei Menzopol * Restyled by clang-format * Restyled by prettier-markdown Signed-off-by: Andrei Menzopol Co-authored-by: Restyled.io --- .github/.wordlist.txt | 11 +- .../lighting-app/nxp/k32w/k32w0/README.md | 19 +++ .../nxp/k32w/k32w0/main/AppTask.cpp | 139 ++++++++++++++++-- .../nxp/k32w/k32w0/main/include/AppTask.h | 11 ++ .../identify-server/identify-server.cpp | 4 +- 5 files changed, 164 insertions(+), 20 deletions(-) diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 4e3560d7fba70e..6ed9654a620149 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -48,11 +48,9 @@ algs alloc Ameba amebad -AmebaD amebaiot AmebaZ amebaz2 -AmebaZ2 announcementReason AnnounceOTAProvider AnnounceOtaProviderRequest @@ -84,8 +82,6 @@ args argv armeabi armino -Armino -ARMINO ARMmbed armv ASAN @@ -294,8 +290,8 @@ connstring conntype const ContentApp -ContentApp's ContentAppPlatform +ContentApp's ContentLaunch ContentLauncher continuousHinting @@ -1116,8 +1112,8 @@ REPL repo req Requestor -Requestor's RequestorCanConsent +Requestor's Requestors responder RestrictedEvent @@ -1164,8 +1160,8 @@ SDB SDC SDHC SDK -SDK's sdkconfig +SDK's SDKs SDKTARGETSYSROOT sdl @@ -1342,6 +1338,7 @@ trackFree TransferSession transitionTime TransportMgrBase +TriggerEffect TRNG TrustedRootCertificates tsan diff --git a/examples/lighting-app/nxp/k32w/k32w0/README.md b/examples/lighting-app/nxp/k32w/k32w0/README.md index 6b638d0660447a..8ea1d9848debcd 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/README.md +++ b/examples/lighting-app/nxp/k32w/k32w0/README.md @@ -167,6 +167,25 @@ DS3, which can be found on the DK6 board. Also, by long pressing the **USERINTERFACE** button, the factory reset action will be initiated. +### Identify cluster LED state + +The Identify cluster server supports two identification commands: **Identify** +and **TriggerEffect**. These commands allow a user to identify a particular +device. For these commands, the **LED D3** is used. + +The **Identify command** will use the **LED D3** to flash with a period of 0.5 +seconds. + +The **TriggerEffect command** will use the **LED D3** with the following +effects: + +- _Blink_ — flash with a 1 second period for 2 seconds +- _Breathe_ — flash with a 1 second period for 15 seconds +- _Okay_ — flash with a 1 second period for 4 seconds +- _Channel change_ — same as Blink +- _Finish effect_ — complete current effect sequence and terminate +- _Stop effect_ — terminate as soon as possible + ## Building diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp index d5f30e05b79224..8d3f2f0bd0afac 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -82,10 +82,16 @@ extern "C" void K32WUartProcess(void); using namespace ::chip::Credentials; using namespace ::chip::DeviceLayer; using namespace chip; -; AppTask AppTask::sAppTask; +static Identify gIdentify = { chip::EndpointId{ 1 }, AppTask::OnIdentifyStart, AppTask::OnIdentifyStop, + EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED, AppTask::OnTriggerEffect, + // Use invalid value for identifiers to enable TriggerEffect command + // to stop Identify command for each effect + (EmberAfIdentifyEffectIdentifier)(EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT - 0x10), + EMBER_ZCL_IDENTIFY_EFFECT_VARIANT_DEFAULT }; + /* OTA related variables */ #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR static DefaultOTARequestor gRequestorCore; @@ -415,15 +421,7 @@ void AppTask::ResetActionEventHandler(AppEvent * aEvent) sAppTask.CancelTimer(); sAppTask.mFunction = kFunction_NoneSelected; - /* restore initial state for the LED indicating Lighting state */ - if (LightingMgr().IsTurnedOff()) - { - sLightLED.Set(false); - } - else - { - sLightLED.Set(true); - } + RestoreLightingState(); K32W_LOG("Factory Reset was cancelled!"); } @@ -682,6 +680,127 @@ void AppTask::ActionCompleted(LightingManager::Action_t aAction) sAppTask.mFunction = kFunction_NoneSelected; } +void AppTask::RestoreLightingState(void) +{ + /* restore initial state for the LED indicating Lighting state */ + if (LightingMgr().IsTurnedOff()) + { + sLightLED.Set(false); + } + else + { + sLightLED.Set(true); + } +} + +void AppTask::OnIdentifyStart(Identify * identify) +{ + if ((kFunction_NoneSelected != sAppTask.mFunction) && (kFunction_TriggerEffect != sAppTask.mFunction)) + { + K32W_LOG("Another function is scheduled. Could not initiate Identify process!"); + return; + } + + if (kFunction_TriggerEffect == sAppTask.mFunction) + { + chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerEffectComplete, identify); + OnTriggerEffectComplete(&chip::DeviceLayer::SystemLayer(), identify); + } + + ChipLogProgress(Zcl, "Identify process has started. Status LED should blink with a period of 0.5 seconds."); + sAppTask.mFunction = kFunction_Identify; + sLightLED.Set(false); + sLightLED.Blink(250); +} + +void AppTask::OnIdentifyStop(Identify * identify) +{ + if (kFunction_Identify == sAppTask.mFunction) + { + ChipLogProgress(Zcl, "Identify process has stopped."); + sAppTask.mFunction = kFunction_NoneSelected; + + RestoreLightingState(); + } +} + +void AppTask::OnTriggerEffectComplete(chip::System::Layer * systemLayer, void * appState) +{ + // Let Identify command take over if called during TriggerEffect already running + if (kFunction_TriggerEffect == sAppTask.mFunction) + { + ChipLogProgress(Zcl, "TriggerEffect has stopped."); + sAppTask.mFunction = kFunction_NoneSelected; + + // TriggerEffect finished - reset identifiers + // Use invalid value for identifiers to enable TriggerEffect command + // to stop Identify command for each effect + gIdentify.mCurrentEffectIdentifier = + (EmberAfIdentifyEffectIdentifier)(EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT - 0x10); + gIdentify.mTargetEffectIdentifier = + (EmberAfIdentifyEffectIdentifier)(EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT - 0x10); + gIdentify.mEffectVariant = EMBER_ZCL_IDENTIFY_EFFECT_VARIANT_DEFAULT; + + RestoreLightingState(); + } +} + +void AppTask::OnTriggerEffect(Identify * identify) +{ + // Allow overlapping TriggerEffect calls + if ((kFunction_NoneSelected != sAppTask.mFunction) && (kFunction_TriggerEffect != sAppTask.mFunction)) + { + K32W_LOG("Another function is scheduled. Could not initiate Identify process!"); + return; + } + + sAppTask.mFunction = kFunction_TriggerEffect; + uint16_t timerDelay = 0; + + ChipLogProgress(Zcl, "TriggerEffect has started."); + + switch (identify->mCurrentEffectIdentifier) + { + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK: + timerDelay = 2; + break; + + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE: + timerDelay = 15; + break; + + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY: + timerDelay = 4; + break; + + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE: + ChipLogProgress(Zcl, "Channel Change effect not supported, using effect %d", EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK); + timerDelay = 2; + break; + + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT: + chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerEffectComplete, identify); + timerDelay = 1; + break; + + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT: + chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerEffectComplete, identify); + OnTriggerEffectComplete(&chip::DeviceLayer::SystemLayer(), identify); + break; + + default: + ChipLogProgress(Zcl, "Invalid effect identifier."); + } + + if (timerDelay) + { + sLightLED.Set(false); + sLightLED.Blink(500); + + chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(timerDelay), OnTriggerEffectComplete, identify); + } +} + void AppTask::PostTurnOnActionRequest(int32_t aActor, LightingManager::Action_t aAction) { AppEvent event; diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h index d0ef272e00350c..fc8c164871d15e 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h +++ b/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h @@ -24,6 +24,7 @@ #include "AppEvent.h" #include "LightingManager.h" +#include #include #include "FreeRTOS.h" @@ -49,6 +50,12 @@ class AppTask void UpdateClusterState(void); void UpdateDeviceState(void); + // Identify cluster callbacks. + static void OnIdentifyStart(Identify * identify); + static void OnIdentifyStop(Identify * identify); + static void OnTriggerEffect(Identify * identify); + static void OnTriggerEffectComplete(chip::System::Layer * systemLayer, void * appState); + private: friend AppTask & GetAppTask(void); @@ -77,6 +84,8 @@ class AppTask static void ThreadProvisioningHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); void StartTimer(uint32_t aTimeoutInMs); + static void RestoreLightingState(void); + #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR static void InitOTA(intptr_t arg); static void StartOTAQuery(intptr_t arg); @@ -93,6 +102,8 @@ class AppTask kFunction_SoftwareUpdate = 0, kFunction_FactoryReset, kFunctionTurnOnTurnOff, + kFunction_Identify, + kFunction_TriggerEffect, kFunction_Invalid } Function; diff --git a/src/app/clusters/identify-server/identify-server.cpp b/src/app/clusters/identify-server/identify-server.cpp index a9294aea5bbab5..23a3cae299ca23 100644 --- a/src/app/clusters/identify-server/identify-server.cpp +++ b/src/app/clusters/identify-server/identify-server.cpp @@ -179,9 +179,7 @@ void MatterIdentifyClusterServerAttributeChangedCallback(const app::ConcreteAttr /* finish identify process */ if (EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT == identify->mCurrentEffectIdentifier && identifyTime > 0) { - (void) chip::DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(1), onIdentifyClusterTick, - identify); - return; + Clusters::Identify::Attributes::IdentifyTime::Set(endpoint, 1); } /* stop identify process */ if (EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT == identify->mCurrentEffectIdentifier && identifyTime > 0)