Skip to content

Commit 4702321

Browse files
jmartinez-silabspull[bot]
authored andcommitted
call the OffEffect callback before setting the attribut OnOff to false. Basic application implementation that can deal with executing the off effect (#19483)
Change action actor to timer. Fix when cancelling offeffect when we on is received during offeffect
1 parent ddec307 commit 4702321

File tree

4 files changed

+98
-57
lines changed

4 files changed

+98
-57
lines changed

examples/lighting-app/efr32/include/LightingManager.h

+5
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "FreeRTOS.h"
2727
#include "timers.h" // provides FreeRTOS timer support
28+
#include <app/clusters/on-off-server/on-off-server.h>
2829

2930
#include <lib/core/CHIPError.h>
3031

@@ -58,6 +59,8 @@ class LightingManager
5859
typedef void (*Callback_fn_completed)(Action_t);
5960
void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB);
6061

62+
static void OnTriggerOffWithEffect(OnOffEffect * effect);
63+
6164
private:
6265
friend LightingManager & LightMgr(void);
6366
State_t mState;
@@ -68,13 +71,15 @@ class LightingManager
6871
bool mAutoTurnOff;
6972
uint32_t mAutoTurnOffDuration;
7073
bool mAutoTurnOffTimerArmed;
74+
bool mOffEffectArmed;
7175

7276
void CancelTimer(void);
7377
void StartTimer(uint32_t aTimeoutMs);
7478

7579
static void TimerEventHandler(TimerHandle_t xTimer);
7680
static void AutoTurnOffTimerEventHandler(AppEvent * aEvent);
7781
static void ActuatorMovementTimerEventHandler(AppEvent * aEvent);
82+
static void OffEffectTimerEventHandler(AppEvent * aEvent);
7883

7984
static LightingManager sLight;
8085
};

examples/lighting-app/efr32/src/AppTask.cpp

-46
Original file line numberDiff line numberDiff line change
@@ -160,52 +160,6 @@ Identify gIdentify = {
160160
OnTriggerIdentifyEffect,
161161
};
162162

163-
/**********************************************************
164-
* OffWithEffect Callbacks
165-
*********************************************************/
166-
167-
void OnTriggerOffWithEffect(OnOffEffect * effect)
168-
{
169-
chip::app::Clusters::OnOff::OnOffEffectIdentifier effectId = effect->mEffectIdentifier;
170-
uint8_t effectVariant = effect->mEffectVariant;
171-
172-
// Uses print outs until we can support the effects
173-
if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF)
174-
{
175-
if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS)
176-
{
177-
ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS");
178-
}
179-
else if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE)
180-
{
181-
ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE");
182-
}
183-
else if (effectVariant ==
184-
EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_IN_12_SECONDS)
185-
{
186-
ChipLogProgress(Zcl,
187-
"EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_"
188-
"IN_12_SECONDS");
189-
}
190-
}
191-
else if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DYING_LIGHT)
192-
{
193-
if (effectVariant ==
194-
EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND)
195-
{
196-
ChipLogProgress(
197-
Zcl, "EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND");
198-
}
199-
}
200-
}
201-
202-
OnOffEffect gEffect = {
203-
chip::EndpointId{ 1 },
204-
OnTriggerOffWithEffect,
205-
EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF,
206-
static_cast<uint8_t>(EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS),
207-
};
208-
209163
} // namespace
210164

211165
using namespace chip::TLV;

examples/lighting-app/efr32/src/LightingManager.cpp

+91-5
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,28 @@
2323
#include "AppTask.h"
2424
#include <FreeRTOS.h>
2525

26-
#include <app/clusters/on-off-server/on-off-server.h>
27-
2826
using namespace chip;
2927
using namespace ::chip::DeviceLayer;
3028

3129
LightingManager LightingManager::sLight;
3230

3331
TimerHandle_t sLightTimer;
3432

33+
namespace {
34+
35+
/**********************************************************
36+
* OffWithEffect Callbacks
37+
*********************************************************/
38+
39+
OnOffEffect gEffect = {
40+
chip::EndpointId{ 1 },
41+
LightMgr().OnTriggerOffWithEffect,
42+
EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF,
43+
static_cast<uint8_t>(EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS),
44+
};
45+
46+
} // namespace
47+
3548
CHIP_ERROR LightingManager::Init()
3649
{
3750
// Create FreeRTOS sw timer for light timer.
@@ -58,6 +71,7 @@ CHIP_ERROR LightingManager::Init()
5871
mAutoTurnOffTimerArmed = false;
5972
mAutoTurnOff = false;
6073
mAutoTurnOffDuration = 0;
74+
mOffEffectArmed = false;
6175

6276
return CHIP_NO_ERROR;
6377
}
@@ -94,13 +108,13 @@ bool LightingManager::InitiateAction(int32_t aActor, Action_t aAction)
94108
State_t new_state;
95109

96110
// Initiate Turn On/Off Action only when the previous one is complete.
97-
if (mState == kState_OffCompleted && aAction == ON_ACTION)
111+
if (((mState == kState_OffCompleted) || mOffEffectArmed) && aAction == ON_ACTION)
98112
{
99113
action_initiated = true;
100114

101115
new_state = kState_OnInitiated;
102116
}
103-
else if (mState == kState_OnCompleted && aAction == OFF_ACTION)
117+
else if (mState == kState_OnCompleted && aAction == OFF_ACTION && mOffEffectArmed == false)
104118
{
105119
action_initiated = true;
106120

@@ -118,6 +132,12 @@ bool LightingManager::InitiateAction(int32_t aActor, Action_t aAction)
118132
CancelTimer();
119133
}
120134

135+
if (mOffEffectArmed && new_state == kState_OnInitiated)
136+
{
137+
CancelTimer();
138+
mOffEffectArmed = false;
139+
}
140+
121141
StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS);
122142

123143
// Since the timer started successfully, update the state and trigger callback
@@ -174,6 +194,10 @@ void LightingManager::TimerEventHandler(TimerHandle_t xTimer)
174194
{
175195
event.Handler = AutoTurnOffTimerEventHandler;
176196
}
197+
else if (light->mOffEffectArmed)
198+
{
199+
event.Handler = OffEffectTimerEventHandler;
200+
}
177201
else
178202
{
179203
event.Handler = ActuatorMovementTimerEventHandler;
@@ -184,7 +208,7 @@ void LightingManager::TimerEventHandler(TimerHandle_t xTimer)
184208
void LightingManager::AutoTurnOffTimerEventHandler(AppEvent * aEvent)
185209
{
186210
LightingManager * light = static_cast<LightingManager *>(aEvent->TimerEvent.Context);
187-
int32_t actor = 0;
211+
int32_t actor = AppEvent::kEventType_Timer;
188212

189213
// Make sure auto turn off timer is still armed.
190214
if (!light->mAutoTurnOffTimerArmed)
@@ -199,6 +223,24 @@ void LightingManager::AutoTurnOffTimerEventHandler(AppEvent * aEvent)
199223
light->InitiateAction(actor, OFF_ACTION);
200224
}
201225

226+
void LightingManager::OffEffectTimerEventHandler(AppEvent * aEvent)
227+
{
228+
LightingManager * light = static_cast<LightingManager *>(aEvent->TimerEvent.Context);
229+
int32_t actor = AppEvent::kEventType_Timer;
230+
231+
// Make sure auto turn off timer is still armed.
232+
if (!light->mOffEffectArmed)
233+
{
234+
return;
235+
}
236+
237+
light->mOffEffectArmed = false;
238+
239+
EFR32_LOG("OffEffect completed");
240+
241+
light->InitiateAction(actor, OFF_ACTION);
242+
}
243+
202244
void LightingManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
203245
{
204246
Action_t actionCompleted = INVALID_ACTION;
@@ -234,3 +276,47 @@ void LightingManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
234276
}
235277
}
236278
}
279+
280+
void LightingManager::OnTriggerOffWithEffect(OnOffEffect * effect)
281+
{
282+
chip::app::Clusters::OnOff::OnOffEffectIdentifier effectId = effect->mEffectIdentifier;
283+
uint8_t effectVariant = effect->mEffectVariant;
284+
uint32_t offEffectDuration = 0;
285+
286+
// Temporary print outs and delay to test OffEffect behaviour
287+
// Until dimming is supported for dev boards.
288+
if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF)
289+
{
290+
if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS)
291+
{
292+
offEffectDuration = 800;
293+
ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS");
294+
}
295+
else if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE)
296+
{
297+
offEffectDuration = 800;
298+
ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE");
299+
}
300+
else if (effectVariant ==
301+
EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_IN_12_SECONDS)
302+
{
303+
offEffectDuration = 12800;
304+
ChipLogProgress(Zcl,
305+
"EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_"
306+
"IN_12_SECONDS");
307+
}
308+
}
309+
else if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DYING_LIGHT)
310+
{
311+
if (effectVariant ==
312+
EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND)
313+
{
314+
offEffectDuration = 1500;
315+
ChipLogProgress(
316+
Zcl, "EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND");
317+
}
318+
}
319+
320+
LightMgr().mOffEffectArmed = true;
321+
LightMgr().StartTimer(offEffectDuration);
322+
}

src/app/clusters/on-off-server/on-off-server.cpp

+2-6
Original file line numberDiff line numberDiff line change
@@ -383,14 +383,8 @@ bool OnOffServer::offWithEffectCommand(app::CommandHandler * commandObj, const a
383383
#endif // EMBER_AF_PLUGIN_SCENES
384384

385385
OnOff::Attributes::GlobalSceneControl::Set(endpoint, false);
386-
387-
status = setOnOffValue(endpoint, Commands::Off::Id, false);
388386
Attributes::OnTime::Set(endpoint, 0);
389387
}
390-
else
391-
{
392-
status = setOnOffValue(endpoint, Commands::Off::Id, false);
393-
}
394388

395389
// Only apply effect if OnOff is on
396390
if (isOnBeforeCommand)
@@ -405,6 +399,8 @@ bool OnOffServer::offWithEffectCommand(app::CommandHandler * commandObj, const a
405399
effect->mOffWithEffectTrigger(effect);
406400
}
407401
}
402+
403+
status = setOnOffValue(endpoint, Commands::Off::Id, false);
408404
}
409405
else
410406
{

0 commit comments

Comments
 (0)