Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix overlapping execution for TriggerEffect and Identify commands in Identify Server #21968

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions .github/.wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,9 @@ algs
alloc
Ameba
amebad
AmebaD
andrei-menzopol marked this conversation as resolved.
Show resolved Hide resolved
amebaiot
AmebaZ
amebaz2
AmebaZ2
announcementReason
AnnounceOTAProvider
AnnounceOtaProviderRequest
Expand Down Expand Up @@ -84,8 +82,6 @@ args
argv
armeabi
armino
Armino
andrei-menzopol marked this conversation as resolved.
Show resolved Hide resolved
ARMINO
ARMmbed
armv
ASAN
Expand Down Expand Up @@ -294,8 +290,8 @@ connstring
conntype
const
ContentApp
ContentApp's
ContentAppPlatform
ContentApp's
ContentLaunch
ContentLauncher
continuousHinting
Expand Down Expand Up @@ -1116,8 +1112,8 @@ REPL
repo
req
Requestor
Requestor's
RequestorCanConsent
Requestor's
Requestors
responder
RestrictedEvent
Expand Down Expand Up @@ -1164,8 +1160,8 @@ SDB
SDC
SDHC
SDK
SDK's
sdkconfig
SDK's
SDKs
SDKTARGETSYSROOT
sdl
Expand Down Expand Up @@ -1342,6 +1338,7 @@ trackFree
TransferSession
transitionTime
TransportMgrBase
TriggerEffect
TRNG
TrustedRootCertificates
tsan
Expand Down
19 changes: 19 additions & 0 deletions examples/lighting-app/nxp/k32w/k32w0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

<a name="building"></a>

## Building
Expand Down
139 changes: 129 additions & 10 deletions examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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!");
}
Expand Down Expand Up @@ -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;
Expand Down
11 changes: 11 additions & 0 deletions examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "AppEvent.h"
#include "LightingManager.h"

#include <app/clusters/identify-server/identify-server.h>
#include <platform/CHIPDeviceLayer.h>

#include "FreeRTOS.h"
Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand All @@ -93,6 +102,8 @@ class AppTask
kFunction_SoftwareUpdate = 0,
kFunction_FactoryReset,
kFunctionTurnOnTurnOff,
kFunction_Identify,
kFunction_TriggerEffect,

kFunction_Invalid
} Function;
Expand Down
4 changes: 1 addition & 3 deletions src/app/clusters/identify-server/identify-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
jmartinez-silabs marked this conversation as resolved.
Show resolved Hide resolved
}
/* stop identify process */
if (EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT == identify->mCurrentEffectIdentifier && identifyTime > 0)
Expand Down