Skip to content

Commit

Permalink
call the OffEffect callback before setting the attribut OnOff to fals…
Browse files Browse the repository at this point in the history
…e. Basic application implementation that can deal with executing the off effect

Change action actor to timer. Fix when cancelling offeffect when we on is received during offeffect
  • Loading branch information
jmartinez-silabs committed Jun 10, 2022
1 parent 530e325 commit e3d59fe
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 57 deletions.
5 changes: 5 additions & 0 deletions examples/lighting-app/efr32/include/LightingManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "FreeRTOS.h"
#include "timers.h" // provides FreeRTOS timer support
#include <app/clusters/on-off-server/on-off-server.h>

#include <lib/core/CHIPError.h>

Expand Down Expand Up @@ -58,6 +59,8 @@ class LightingManager
typedef void (*Callback_fn_completed)(Action_t);
void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB);

static void OnTriggerOffWithEffect(OnOffEffect * effect);

private:
friend LightingManager & LightMgr(void);
State_t mState;
Expand All @@ -68,13 +71,15 @@ class LightingManager
bool mAutoTurnOff;
uint32_t mAutoTurnOffDuration;
bool mAutoTurnOffTimerArmed;
bool mOffEffectArmed;

void CancelTimer(void);
void StartTimer(uint32_t aTimeoutMs);

static void TimerEventHandler(TimerHandle_t xTimer);
static void AutoTurnOffTimerEventHandler(AppEvent * aEvent);
static void ActuatorMovementTimerEventHandler(AppEvent * aEvent);
static void OffEffectTimerEventHandler(AppEvent * aEvent);

static LightingManager sLight;
};
Expand Down
46 changes: 0 additions & 46 deletions examples/lighting-app/efr32/src/AppTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,52 +160,6 @@ Identify gIdentify = {
OnTriggerIdentifyEffect,
};

/**********************************************************
* OffWithEffect Callbacks
*********************************************************/

void OnTriggerOffWithEffect(OnOffEffect * effect)
{
chip::app::Clusters::OnOff::OnOffEffectIdentifier effectId = effect->mEffectIdentifier;
uint8_t effectVariant = effect->mEffectVariant;

// Uses print outs until we can support the effects
if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF)
{
if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS)
{
ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS");
}
else if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE)
{
ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE");
}
else if (effectVariant ==
EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_IN_12_SECONDS)
{
ChipLogProgress(Zcl,
"EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_"
"IN_12_SECONDS");
}
}
else if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DYING_LIGHT)
{
if (effectVariant ==
EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND)
{
ChipLogProgress(
Zcl, "EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND");
}
}
}

OnOffEffect gEffect = {
chip::EndpointId{ 1 },
OnTriggerOffWithEffect,
EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF,
static_cast<uint8_t>(EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS),
};

} // namespace

using namespace chip::TLV;
Expand Down
96 changes: 91 additions & 5 deletions examples/lighting-app/efr32/src/LightingManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,28 @@
#include "AppTask.h"
#include <FreeRTOS.h>

#include <app/clusters/on-off-server/on-off-server.h>

using namespace chip;
using namespace ::chip::DeviceLayer;

LightingManager LightingManager::sLight;

TimerHandle_t sLightTimer;

namespace {

/**********************************************************
* OffWithEffect Callbacks
*********************************************************/

OnOffEffect gEffect = {
chip::EndpointId{ 1 },
LightMgr().OnTriggerOffWithEffect,
EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF,
static_cast<uint8_t>(EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS),
};

} // namespace

CHIP_ERROR LightingManager::Init()
{
// Create FreeRTOS sw timer for light timer.
Expand All @@ -58,6 +71,7 @@ CHIP_ERROR LightingManager::Init()
mAutoTurnOffTimerArmed = false;
mAutoTurnOff = false;
mAutoTurnOffDuration = 0;
mOffEffectArmed = false;

return CHIP_NO_ERROR;
}
Expand Down Expand Up @@ -94,13 +108,13 @@ bool LightingManager::InitiateAction(int32_t aActor, Action_t aAction)
State_t new_state;

// Initiate Turn On/Off Action only when the previous one is complete.
if (mState == kState_OffCompleted && aAction == ON_ACTION)
if (((mState == kState_OffCompleted) || mOffEffectArmed) && aAction == ON_ACTION)
{
action_initiated = true;

new_state = kState_OnInitiated;
}
else if (mState == kState_OnCompleted && aAction == OFF_ACTION)
else if (mState == kState_OnCompleted && aAction == OFF_ACTION && mOffEffectArmed == false)
{
action_initiated = true;

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

if (mOffEffectArmed && new_state == kState_OnInitiated)
{
CancelTimer();
mOffEffectArmed = false;
}

StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS);

// Since the timer started successfully, update the state and trigger callback
Expand Down Expand Up @@ -174,6 +194,10 @@ void LightingManager::TimerEventHandler(TimerHandle_t xTimer)
{
event.Handler = AutoTurnOffTimerEventHandler;
}
else if (light->mOffEffectArmed)
{
event.Handler = OffEffectTimerEventHandler;
}
else
{
event.Handler = ActuatorMovementTimerEventHandler;
Expand All @@ -184,7 +208,7 @@ void LightingManager::TimerEventHandler(TimerHandle_t xTimer)
void LightingManager::AutoTurnOffTimerEventHandler(AppEvent * aEvent)
{
LightingManager * light = static_cast<LightingManager *>(aEvent->TimerEvent.Context);
int32_t actor = 0;
int32_t actor = AppEvent::kEventType_Timer;

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

void LightingManager::OffEffectTimerEventHandler(AppEvent * aEvent)
{
LightingManager * light = static_cast<LightingManager *>(aEvent->TimerEvent.Context);
int32_t actor = AppEvent::kEventType_Timer;

// Make sure auto turn off timer is still armed.
if (!light->mOffEffectArmed)
{
return;
}

light->mOffEffectArmed = false;

EFR32_LOG("OffEffect completed");

light->InitiateAction(actor, OFF_ACTION);
}

void LightingManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
{
Action_t actionCompleted = INVALID_ACTION;
Expand Down Expand Up @@ -234,3 +276,47 @@ void LightingManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
}
}
}

void LightingManager::OnTriggerOffWithEffect(OnOffEffect * effect)
{
chip::app::Clusters::OnOff::OnOffEffectIdentifier effectId = effect->mEffectIdentifier;
uint8_t effectVariant = effect->mEffectVariant;
uint32_t offEffectDuration = 0;

// Temporary print outs and delay to test OffEffect behaviour
// Until dimming is supported for dev boards.
if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF)
{
if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS)
{
offEffectDuration = 800;
ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS");
}
else if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE)
{
offEffectDuration = 800;
ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE");
}
else if (effectVariant ==
EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_IN_12_SECONDS)
{
offEffectDuration = 12800;
ChipLogProgress(Zcl,
"EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_"
"IN_12_SECONDS");
}
}
else if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DYING_LIGHT)
{
if (effectVariant ==
EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND)
{
offEffectDuration = 1500;
ChipLogProgress(
Zcl, "EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND");
}
}

LightMgr().mOffEffectArmed = true;
LightMgr().StartTimer(offEffectDuration);
}
8 changes: 2 additions & 6 deletions src/app/clusters/on-off-server/on-off-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,14 +383,8 @@ bool OnOffServer::offWithEffectCommand(app::CommandHandler * commandObj, const a
#endif // EMBER_AF_PLUGIN_SCENES

OnOff::Attributes::GlobalSceneControl::Set(endpoint, false);

status = setOnOffValue(endpoint, Commands::Off::Id, false);
Attributes::OnTime::Set(endpoint, 0);
}
else
{
status = setOnOffValue(endpoint, Commands::Off::Id, false);
}

// Only apply effect if OnOff is on
if (isOnBeforeCommand)
Expand All @@ -405,6 +399,8 @@ bool OnOffServer::offWithEffectCommand(app::CommandHandler * commandObj, const a
effect->mOffWithEffectTrigger(effect);
}
}

status = setOnOffValue(endpoint, Commands::Off::Id, false);
}
else
{
Expand Down

0 comments on commit e3d59fe

Please sign in to comment.