diff --git a/examples/lighting-app/efr32/include/LightingManager.h b/examples/lighting-app/efr32/include/LightingManager.h index 3aa9871e919074..6d286faa30ef96 100644 --- a/examples/lighting-app/efr32/include/LightingManager.h +++ b/examples/lighting-app/efr32/include/LightingManager.h @@ -25,6 +25,7 @@ #include "FreeRTOS.h" #include "timers.h" // provides FreeRTOS timer support +#include #include @@ -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; @@ -68,6 +71,7 @@ class LightingManager bool mAutoTurnOff; uint32_t mAutoTurnOffDuration; bool mAutoTurnOffTimerArmed; + bool mOffEffectArmed; void CancelTimer(void); void StartTimer(uint32_t aTimeoutMs); @@ -75,6 +79,7 @@ class LightingManager static void TimerEventHandler(TimerHandle_t xTimer); static void AutoTurnOffTimerEventHandler(AppEvent * aEvent); static void ActuatorMovementTimerEventHandler(AppEvent * aEvent); + static void OffEffectTimerEventHandler(AppEvent * aEvent); static LightingManager sLight; }; diff --git a/examples/lighting-app/efr32/src/AppTask.cpp b/examples/lighting-app/efr32/src/AppTask.cpp index cf95bdf2c036cd..7e1e8d9a811e82 100644 --- a/examples/lighting-app/efr32/src/AppTask.cpp +++ b/examples/lighting-app/efr32/src/AppTask.cpp @@ -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(EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS), -}; - } // namespace using namespace chip::TLV; diff --git a/examples/lighting-app/efr32/src/LightingManager.cpp b/examples/lighting-app/efr32/src/LightingManager.cpp index 3857a0d50e7fe5..47791911ea7308 100644 --- a/examples/lighting-app/efr32/src/LightingManager.cpp +++ b/examples/lighting-app/efr32/src/LightingManager.cpp @@ -23,8 +23,6 @@ #include "AppTask.h" #include -#include - using namespace chip; using namespace ::chip::DeviceLayer; @@ -32,6 +30,21 @@ 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(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. @@ -58,6 +71,7 @@ CHIP_ERROR LightingManager::Init() mAutoTurnOffTimerArmed = false; mAutoTurnOff = false; mAutoTurnOffDuration = 0; + mOffEffectArmed = false; return CHIP_NO_ERROR; } @@ -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; @@ -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 @@ -174,6 +194,10 @@ void LightingManager::TimerEventHandler(TimerHandle_t xTimer) { event.Handler = AutoTurnOffTimerEventHandler; } + else if (light->mOffEffectArmed) + { + event.Handler = OffEffectTimerEventHandler; + } else { event.Handler = ActuatorMovementTimerEventHandler; @@ -184,7 +208,7 @@ void LightingManager::TimerEventHandler(TimerHandle_t xTimer) void LightingManager::AutoTurnOffTimerEventHandler(AppEvent * aEvent) { LightingManager * light = static_cast(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) @@ -199,6 +223,24 @@ void LightingManager::AutoTurnOffTimerEventHandler(AppEvent * aEvent) light->InitiateAction(actor, OFF_ACTION); } +void LightingManager::OffEffectTimerEventHandler(AppEvent * aEvent) +{ + LightingManager * light = static_cast(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; @@ -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); +} diff --git a/src/app/clusters/on-off-server/on-off-server.cpp b/src/app/clusters/on-off-server/on-off-server.cpp index 305da0bafff1e3..12299050929586 100644 --- a/src/app/clusters/on-off-server/on-off-server.cpp +++ b/src/app/clusters/on-off-server/on-off-server.cpp @@ -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) @@ -405,6 +399,8 @@ bool OnOffServer::offWithEffectCommand(app::CommandHandler * commandObj, const a effect->mOffWithEffectTrigger(effect); } } + + status = setOnOffValue(endpoint, Commands::Off::Id, false); } else {