Skip to content

Commit

Permalink
Fix overlapping execution for TriggerEffect and Identify commands in …
Browse files Browse the repository at this point in the history
…Identify Server (project-chip#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 <[email protected]>

* Restyled by clang-format

* Restyled by prettier-markdown

Signed-off-by: Andrei Menzopol <[email protected]>
Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
2 people authored and isiu-apple committed Sep 16, 2022
1 parent c11ed05 commit e730606
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 20 deletions.
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
amebaiot
AmebaZ
amebaz2
AmebaZ2
announcementReason
AnnounceOTAProvider
AnnounceOtaProviderRequest
Expand Down Expand Up @@ -84,8 +82,6 @@ args
argv
armeabi
armino
Armino
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_ &mdash; flash with a 1 second period for 2 seconds
- _Breathe_ &mdash; flash with a 1 second period for 15 seconds
- _Okay_ &mdash; flash with a 1 second period for 4 seconds
- _Channel change_ &mdash; same as Blink
- _Finish effect_ &mdash; complete current effect sequence and terminate
- _Stop effect_ &mdash; 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);
}
/* stop identify process */
if (EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT == identify->mCurrentEffectIdentifier && identifyTime > 0)
Expand Down

0 comments on commit e730606

Please sign in to comment.