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 OnOff cmd OffWithEffect action order #19483

Merged
merged 1 commit into from
Jun 13, 2022
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
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