diff --git a/examples/lighting-app/efr32/src/ZclCallbacks.cpp b/examples/lighting-app/efr32/src/ZclCallbacks.cpp index 7e1810190d5b0d..7233d74481f454 100644 --- a/examples/lighting-app/efr32/src/ZclCallbacks.cpp +++ b/examples/lighting-app/efr32/src/ZclCallbacks.cpp @@ -56,3 +56,16 @@ extern "C" void emberAfPostAttributeChangeCallback(uint8_t endpoint, EmberAfClus LightMgr().InitiateAction(AppEvent::kEventType_Light, LightingManager::OFF_ACTION); } } + +/** @brief On/off Cluster Server Post Init + * + * Following resolution of the On/Off state at startup for this endpoint, + * perform any additional initialization needed; e.g., synchronize hardware + * state. + * + * @param endpoint Endpoint that is being initialized Ver.: always + */ +extern "C" void emberAfPluginOnOffClusterServerPostInitCallback(uint8_t endpoint) +{ + // TODO: implement any additional On/off Cluster Server post init actions +} diff --git a/examples/lighting-app/lighting-common/gen/callback-stub.c b/examples/lighting-app/lighting-common/gen/callback-stub.c index 37bb1d673f615a..50d94e92b6c2e4 100644 --- a/examples/lighting-app/lighting-common/gen/callback-stub.c +++ b/examples/lighting-app/lighting-common/gen/callback-stub.c @@ -43,16 +43,6 @@ //#include "hal/hal.h" //#include EMBER_AF_API_NETWORK_STEERING -/** @brief On/off Cluster Server Post Init - * - * Following resolution of the On/Off state at startup for this endpoint, - * perform any additional initialization needed; e.g., synchronize hardware - * state. - * - * @param endpoint Endpoint that is being initialized Ver.: always - */ -void emberAfPluginOnOffClusterServerPostInitCallback(uint8_t endpoint) {} - /** @brief Add To Current App Tasks * * This function is only useful to sleepy end devices. This function will note diff --git a/examples/lighting-app/linux/main.cpp b/examples/lighting-app/linux/main.cpp index e30fff5241c1b3..e0f67238248de7 100644 --- a/examples/lighting-app/linux/main.cpp +++ b/examples/lighting-app/linux/main.cpp @@ -61,6 +61,19 @@ void emberAfPostAttributeChangeCallback(uint8_t endpoint, EmberAfClusterId clust LightingMgr().InitiateAction(LightingManager::OFF_ACTION); } } + +/** @brief On/off Cluster Server Post Init + * + * Following resolution of the On/Off state at startup for this endpoint, + * perform any additional initialization needed; e.g., synchronize hardware + * state. + * + * @param endpoint Endpoint that is being initialized Ver.: always + */ +void emberAfPluginOnOffClusterServerPostInitCallback(uint8_t endpoint) +{ + // TODO: implement any additional On/off Cluster Server post init actions +} } int main() diff --git a/examples/lighting-app/nrf5/main/ZclCallbacks.cpp b/examples/lighting-app/nrf5/main/ZclCallbacks.cpp index f73cb0e00598fa..9de4df2464b676 100644 --- a/examples/lighting-app/nrf5/main/ZclCallbacks.cpp +++ b/examples/lighting-app/nrf5/main/ZclCallbacks.cpp @@ -53,4 +53,17 @@ void emberAfPostAttributeChangeCallback(uint8_t endpoint, EmberAfClusterId clust LightingMgr().InitiateAction(LightingManager::OFF_ACTION); } } + +/** @brief On/off Cluster Server Post Init + * + * Following resolution of the On/Off state at startup for this endpoint, + * perform any additional initialization needed; e.g., synchronize hardware + * state. + * + * @param endpoint Endpoint that is being initialized Ver.: always + */ +void emberAfPluginOnOffClusterServerPostInitCallback(uint8_t endpoint) +{ + // TODO: implement any additional On/off Cluster Server post init actions +} } diff --git a/examples/lighting-app/nrfconnect/main/AppTask.cpp b/examples/lighting-app/nrfconnect/main/AppTask.cpp index a159bb867d8771..e36e56fc410540 100644 --- a/examples/lighting-app/nrfconnect/main/AppTask.cpp +++ b/examples/lighting-app/nrfconnect/main/AppTask.cpp @@ -27,6 +27,9 @@ #include "Service.h" #include "ThreadUtil.h" +#include "attribute-storage.h" +#include "gen/cluster-id.h" + #include #include @@ -197,17 +200,20 @@ int AppTask::StartApp() void AppTask::LightingActionEventHandler(AppEvent * aEvent) { LightingManager::Action_t action = LightingManager::INVALID_ACTION; + int32_t actor = 0; if (aEvent->Type == AppEvent::kEventType_Lighting) { action = static_cast(aEvent->LightingEvent.Action); + actor = aEvent->LightingEvent.Actor; } else if (aEvent->Type == AppEvent::kEventType_Button) { action = LightingMgr().IsTurnedOn() ? LightingManager::OFF_ACTION : LightingManager::ON_ACTION; + actor = AppEvent::kEventType_Button; } - if (action != LightingManager::INVALID_ACTION && !LightingMgr().InitiateAction(action)) + if (action != LightingManager::INVALID_ACTION && !LightingMgr().InitiateAction(action, actor)) LOG_INF("Action is already in progress or active."); } @@ -350,7 +356,7 @@ void AppTask::StartTimer(uint32_t aTimeoutInMs) mFunctionTimerActive = true; } -void AppTask::ActionInitiated(LightingManager::Action_t aAction) +void AppTask::ActionInitiated(LightingManager::Action_t aAction, int32_t aActor) { if (aAction == LightingManager::ON_ACTION) { @@ -362,7 +368,7 @@ void AppTask::ActionInitiated(LightingManager::Action_t aAction) } } -void AppTask::ActionCompleted(LightingManager::Action_t aAction) +void AppTask::ActionCompleted(LightingManager::Action_t aAction, int32_t aActor) { if (aAction == LightingManager::ON_ACTION) { @@ -372,6 +378,11 @@ void AppTask::ActionCompleted(LightingManager::Action_t aAction) { LOG_INF("Turn Off Action has been completed"); } + + if (aActor == AppEvent::kEventType_Button) + { + sAppTask.UpdateClusterState(); + } } void AppTask::PostLightingActionRequest(LightingManager::Action_t aAction) @@ -402,3 +413,16 @@ void AppTask::DispatchEvent(AppEvent * aEvent) LOG_INF("Event received with no handler. Dropping event."); } } + +void AppTask::UpdateClusterState() +{ + uint8_t newValue = LightingMgr().IsTurnedOn(); + + // write the new on/off value + EmberAfStatus status = emberAfWriteAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, &newValue, + ZCL_BOOLEAN_ATTRIBUTE_TYPE); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + LOG_ERR("Updating on/off %x", status); + } +} diff --git a/examples/lighting-app/nrfconnect/main/LightingManager.cpp b/examples/lighting-app/nrfconnect/main/LightingManager.cpp index 3247ae2311ef31..6ce56ae41a4173 100644 --- a/examples/lighting-app/nrfconnect/main/LightingManager.cpp +++ b/examples/lighting-app/nrfconnect/main/LightingManager.cpp @@ -59,7 +59,7 @@ void LightingManager::SetCallbacks(LightingCallback_fn aActionInitiated_CB, Ligh mActionCompleted_CB = aActionCompleted_CB; } -bool LightingManager::InitiateAction(Action_t aAction) +bool LightingManager::InitiateAction(Action_t aAction, int32_t aActor) { // TODO: this function is called InitiateAction because we want to implement some features such as ramping up here. bool action_initiated = false; @@ -81,14 +81,14 @@ bool LightingManager::InitiateAction(Action_t aAction) { if (mActionInitiated_CB) { - mActionInitiated_CB(aAction); + mActionInitiated_CB(aAction, aActor); } Set(new_state == kState_On); if (mActionCompleted_CB) { - mActionCompleted_CB(aAction); + mActionCompleted_CB(aAction, aActor); } } diff --git a/examples/lighting-app/nrfconnect/main/ZclCallbacks.cpp b/examples/lighting-app/nrfconnect/main/ZclCallbacks.cpp index eee11f92caa89b..fabf17d15da93e 100644 --- a/examples/lighting-app/nrfconnect/main/ZclCallbacks.cpp +++ b/examples/lighting-app/nrfconnect/main/ZclCallbacks.cpp @@ -23,6 +23,7 @@ #include "gen/znet-bookkeeping.h" #include +#include "AppTask.h" #include "LightingManager.h" extern "C" { @@ -41,6 +42,19 @@ void emberAfPostAttributeChangeCallback(uint8_t endpoint, EmberAfClusterId clust return; } - LightingMgr().InitiateAction(*value ? LightingManager::ON_ACTION : LightingManager::OFF_ACTION); + LightingMgr().InitiateAction(*value ? LightingManager::ON_ACTION : LightingManager::OFF_ACTION, AppEvent::kEventType_Lighting); +} + +/** @brief On/off Cluster Server Post Init + * + * Following resolution of the On/Off state at startup for this endpoint, + * perform any additional initialization needed; e.g., synchronize hardware + * state. + * + * @param endpoint Endpoint that is being initialized Ver.: always + */ +void emberAfPluginOnOffClusterServerPostInitCallback(uint8_t endpoint) +{ + GetAppTask().UpdateClusterState(); } } diff --git a/examples/lighting-app/nrfconnect/main/include/AppEvent.h b/examples/lighting-app/nrfconnect/main/include/AppEvent.h index 319a68060fd326..1406d2249fa27b 100644 --- a/examples/lighting-app/nrfconnect/main/include/AppEvent.h +++ b/examples/lighting-app/nrfconnect/main/include/AppEvent.h @@ -49,6 +49,7 @@ struct AppEvent struct { uint8_t Action; + int32_t Actor; } LightingEvent; }; diff --git a/examples/lighting-app/nrfconnect/main/include/AppTask.h b/examples/lighting-app/nrfconnect/main/include/AppTask.h index fb382d756e9ef2..5b960292e75449 100644 --- a/examples/lighting-app/nrfconnect/main/include/AppTask.h +++ b/examples/lighting-app/nrfconnect/main/include/AppTask.h @@ -32,14 +32,15 @@ class AppTask void PostLightingActionRequest(LightingManager::Action_t aAction); void PostEvent(AppEvent * event); + void UpdateClusterState(); private: friend AppTask & GetAppTask(void); int Init(); - static void ActionInitiated(LightingManager::Action_t aAction); - static void ActionCompleted(LightingManager::Action_t aAction); + static void ActionInitiated(LightingManager::Action_t aAction, int32_t aActor); + static void ActionCompleted(LightingManager::Action_t aAction, int32_t aActor); void CancelTimer(void); @@ -66,7 +67,6 @@ class AppTask Function_t mFunction; bool mFunctionTimerActive; - static AppTask sAppTask; }; diff --git a/examples/lighting-app/nrfconnect/main/include/LightingManager.h b/examples/lighting-app/nrfconnect/main/include/LightingManager.h index ed4c098dfc9692..88d4c513dcaa71 100644 --- a/examples/lighting-app/nrfconnect/main/include/LightingManager.h +++ b/examples/lighting-app/nrfconnect/main/include/LightingManager.h @@ -40,11 +40,11 @@ class LightingManager kState_Off, }; - using LightingCallback_fn = void (*)(Action_t); + using LightingCallback_fn = void (*)(Action_t, int32_t); int Init(const char * gpioDeviceName, gpio_pin_t gpioPin); bool IsTurnedOn() const { return mState == kState_On; } - bool InitiateAction(Action_t aAction); + bool InitiateAction(Action_t aAction, int32_t aActor); void SetCallbacks(LightingCallback_fn aActionInitiated_CB, LightingCallback_fn aActionCompleted_CB); private: diff --git a/examples/lock-app/efr32/src/ZclCallbacks.cpp b/examples/lock-app/efr32/src/ZclCallbacks.cpp index 2ac726018a7c6f..f404512f97152f 100644 --- a/examples/lock-app/efr32/src/ZclCallbacks.cpp +++ b/examples/lock-app/efr32/src/ZclCallbacks.cpp @@ -57,3 +57,16 @@ extern "C" void emberAfPostAttributeChangeCallback(uint8_t endpoint, EmberAfClus BoltLockMgr().InitiateAction(AppEvent::kEventType_Lock, BoltLockManager::UNLOCK_ACTION); } } + +/** @brief On/off Cluster Server Post Init + * + * Following resolution of the On/Off state at startup for this endpoint, + * perform any additional initialization needed; e.g., synchronize hardware + * state. + * + * @param endpoint Endpoint that is being initialized Ver.: always + */ +extern "C" void emberAfPluginOnOffClusterServerPostInitCallback(uint8_t endpoint) +{ + // TODO: implement any additional On/off Cluster Server post init actions +} diff --git a/examples/lock-app/k32w/main/ZclCallbacks.cpp b/examples/lock-app/k32w/main/ZclCallbacks.cpp index dbca355b33f8ba..383ac4d197aed8 100644 --- a/examples/lock-app/k32w/main/ZclCallbacks.cpp +++ b/examples/lock-app/k32w/main/ZclCallbacks.cpp @@ -45,4 +45,17 @@ void emberAfPostAttributeChangeCallback(uint8_t endpoint, EmberAfClusterId clust BoltLockMgr().InitiateAction(0, *value ? BoltLockManager::LOCK_ACTION : BoltLockManager::UNLOCK_ACTION); } + +/** @brief On/off Cluster Server Post Init + * + * Following resolution of the On/Off state at startup for this endpoint, + * perform any additional initialization needed; e.g., synchronize hardware + * state. + * + * @param endpoint Endpoint that is being initialized Ver.: always + */ +void emberAfPluginOnOffClusterServerPostInitCallback(uint8_t endpoint) +{ + // TODO: implement any additional On/off Cluster Server post init actions +} } diff --git a/examples/lock-app/lock-common/gen/callback-stub.c b/examples/lock-app/lock-common/gen/callback-stub.c index bd2109eef231b8..fc36207dd8e351 100644 --- a/examples/lock-app/lock-common/gen/callback-stub.c +++ b/examples/lock-app/lock-common/gen/callback-stub.c @@ -44,16 +44,6 @@ //#include "hal/hal.h" //#include EMBER_AF_API_NETWORK_STEERING -/** @brief On/off Cluster Server Post Init - * - * Following resolution of the On/Off state at startup for this endpoint, - * perform any additional initialization needed; e.g., synchronize hardware - * state. - * - * @param endpoint Endpoint that is being initialized Ver.: always - */ -void emberAfPluginOnOffClusterServerPostInitCallback(uint8_t endpoint) {} - /** @brief Add To Current App Tasks * * This function is only useful to sleepy end devices. This function will note diff --git a/examples/lock-app/nrf5/main/ZclCallbacks.cpp b/examples/lock-app/nrf5/main/ZclCallbacks.cpp index a6604daf3e9c0f..b4bceaff343a8b 100644 --- a/examples/lock-app/nrf5/main/ZclCallbacks.cpp +++ b/examples/lock-app/nrf5/main/ZclCallbacks.cpp @@ -55,4 +55,17 @@ void emberAfPostAttributeChangeCallback(uint8_t endpoint, EmberAfClusterId clust BoltLockMgr().InitiateAction(0, BoltLockManager::UNLOCK_ACTION); } } + +/** @brief On/off Cluster Server Post Init + * + * Following resolution of the On/Off state at startup for this endpoint, + * perform any additional initialization needed; e.g., synchronize hardware + * state. + * + * @param endpoint Endpoint that is being initialized Ver.: always + */ +void emberAfPluginOnOffClusterServerPostInitCallback(uint8_t endpoint) +{ + // TODO: implement any additional On/off Cluster Server post init actions +} } diff --git a/examples/lock-app/nrfconnect/main/AppTask.cpp b/examples/lock-app/nrfconnect/main/AppTask.cpp index 4f69b78908268a..c2277675424e06 100644 --- a/examples/lock-app/nrfconnect/main/AppTask.cpp +++ b/examples/lock-app/nrfconnect/main/AppTask.cpp @@ -25,6 +25,9 @@ #include "Service.h" #include "ThreadUtil.h" +#include "attribute-storage.h" +#include "gen/cluster-id.h" + #include #include @@ -200,6 +203,7 @@ void AppTask::LockActionEventHandler(AppEvent * aEvent) else if (aEvent->Type == AppEvent::kEventType_Button) { action = BoltLockMgr().IsUnlocked() ? BoltLockManager::LOCK_ACTION : BoltLockManager::UNLOCK_ACTION; + actor = AppEvent::kEventType_Button; } if (action != BoltLockManager::INVALID_ACTION && !BoltLockMgr().InitiateAction(actor, action)) @@ -370,7 +374,7 @@ void AppTask::ActionInitiated(BoltLockManager::Action_t aAction, int32_t aActor) sLockLED.Blink(50, 50); } -void AppTask::ActionCompleted(BoltLockManager::Action_t aAction) +void AppTask::ActionCompleted(BoltLockManager::Action_t aAction, int32_t aActor) { // if the action has been completed by the lock, update the bolt lock trait. // Turn on the lock LED if in a LOCKED state OR @@ -385,6 +389,11 @@ void AppTask::ActionCompleted(BoltLockManager::Action_t aAction) LOG_INF("Unlock Action has been completed"); sLockLED.Set(false); } + + if (aActor == AppEvent::kEventType_Button) + { + sAppTask.UpdateClusterState(); + } } void AppTask::PostLockActionRequest(int32_t aActor, BoltLockManager::Action_t aAction) @@ -416,3 +425,16 @@ void AppTask::DispatchEvent(AppEvent * aEvent) LOG_INF("Event received with no handler. Dropping event."); } } + +void AppTask::UpdateClusterState() +{ + uint8_t newValue = !BoltLockMgr().IsUnlocked(); + + // write the new on/off value + EmberAfStatus status = emberAfWriteAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, &newValue, + ZCL_BOOLEAN_ATTRIBUTE_TYPE); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + LOG_ERR("Updating on/off %x", status); + } +} diff --git a/examples/lock-app/nrfconnect/main/BoltLockManager.cpp b/examples/lock-app/nrfconnect/main/BoltLockManager.cpp index d994d36e24b371..c72e98ea3e4d34 100644 --- a/examples/lock-app/nrfconnect/main/BoltLockManager.cpp +++ b/examples/lock-app/nrfconnect/main/BoltLockManager.cpp @@ -77,14 +77,14 @@ bool BoltLockManager::InitiateAction(int32_t aActor, Action_t aAction) if (mState == kState_LockingCompleted && aAction == UNLOCK_ACTION) { action_initiated = true; - - new_state = kState_UnlockingInitiated; + mCurrentActor = aActor; + new_state = kState_UnlockingInitiated; } else if (mState == kState_UnlockingCompleted && aAction == LOCK_ACTION) { action_initiated = true; - - new_state = kState_LockingInitiated; + mCurrentActor = aActor; + new_state = kState_LockingInitiated; } if (action_initiated) @@ -173,7 +173,7 @@ void BoltLockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent) { if (lock->mActionCompleted_CB) { - lock->mActionCompleted_CB(actionCompleted); + lock->mActionCompleted_CB(actionCompleted, lock->mCurrentActor); } if (lock->mAutoRelock && actionCompleted == UNLOCK_ACTION) diff --git a/examples/lock-app/nrfconnect/main/ZclCallbacks.cpp b/examples/lock-app/nrfconnect/main/ZclCallbacks.cpp index dbca355b33f8ba..abdbd3ab4106f2 100644 --- a/examples/lock-app/nrfconnect/main/ZclCallbacks.cpp +++ b/examples/lock-app/nrfconnect/main/ZclCallbacks.cpp @@ -18,6 +18,7 @@ #include +#include "AppTask.h" #include "BoltLockManager.h" #include "gen/attribute-id.h" @@ -45,4 +46,17 @@ void emberAfPostAttributeChangeCallback(uint8_t endpoint, EmberAfClusterId clust BoltLockMgr().InitiateAction(0, *value ? BoltLockManager::LOCK_ACTION : BoltLockManager::UNLOCK_ACTION); } + +/** @brief On/off Cluster Server Post Init + * + * Following resolution of the On/Off state at startup for this endpoint, + * perform any additional initialization needed; e.g., synchronize hardware + * state. + * + * @param endpoint Endpoint that is being initialized Ver.: always + */ +void emberAfPluginOnOffClusterServerPostInitCallback(uint8_t endpoint) +{ + GetAppTask().UpdateClusterState(); +} } diff --git a/examples/lock-app/nrfconnect/main/include/AppTask.h b/examples/lock-app/nrfconnect/main/include/AppTask.h index db10126fcb6655..9ef1067ff19de2 100644 --- a/examples/lock-app/nrfconnect/main/include/AppTask.h +++ b/examples/lock-app/nrfconnect/main/include/AppTask.h @@ -31,6 +31,7 @@ class AppTask void PostLockActionRequest(int32_t aActor, BoltLockManager::Action_t aAction); void PostEvent(AppEvent * event); + void UpdateClusterState(); private: friend AppTask & GetAppTask(void); @@ -38,7 +39,7 @@ class AppTask int Init(); static void ActionInitiated(BoltLockManager::Action_t aAction, int32_t aActor); - static void ActionCompleted(BoltLockManager::Action_t aAction); + static void ActionCompleted(BoltLockManager::Action_t aAction, int32_t aActor); void CancelTimer(void); @@ -65,7 +66,6 @@ class AppTask Function_t mFunction; bool mFunctionTimerActive; - static AppTask sAppTask; }; diff --git a/examples/lock-app/nrfconnect/main/include/BoltLockManager.h b/examples/lock-app/nrfconnect/main/include/BoltLockManager.h index 0500bfb60e5e95..982092a959ef80 100644 --- a/examples/lock-app/nrfconnect/main/include/BoltLockManager.h +++ b/examples/lock-app/nrfconnect/main/include/BoltLockManager.h @@ -52,7 +52,7 @@ class BoltLockManager bool InitiateAction(int32_t aActor, Action_t aAction); typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor); - typedef void (*Callback_fn_completed)(Action_t); + typedef void (*Callback_fn_completed)(Action_t, int32_t aActor); void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB); private: @@ -65,6 +65,7 @@ class BoltLockManager bool mAutoRelock; uint32_t mAutoLockDuration; bool mAutoLockTimerArmed; + int32_t mCurrentActor; void CancelTimer(void); void StartTimer(uint32_t aTimeoutMs);