Skip to content

Commit

Permalink
Update of Lock app to transition locked->unlatched->unlocked when the…
Browse files Browse the repository at this point in the history
… feature is supported
  • Loading branch information
lpbeliveau-silabs committed Feb 15, 2024
1 parent c06f533 commit ed82e78
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 4 deletions.
6 changes: 6 additions & 0 deletions examples/lock-app/silabs/include/LockManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class LockManager
{
LOCK_ACTION = 0,
UNLOCK_ACTION,
UNLATCH_ACTION,

INVALID_ACTION
} Action;
Expand All @@ -130,7 +131,9 @@ class LockManager
kState_LockInitiated = 0,
kState_LockCompleted,
kState_UnlockInitiated,
kState_UnlatchInitiated,
kState_UnlockCompleted,
kState_UnlatchCompleted,
} State;

CHIP_ERROR Init(chip::app::DataModel::Nullable<chip::app::Clusters::DoorLock::DlLockState> state,
Expand Down Expand Up @@ -194,6 +197,8 @@ class LockManager
bool ReadConfigValues();

private:
chip::EndpointId mCurrentEndpointId;

friend LockManager & LockMgr();
State_t mState;

Expand All @@ -206,6 +211,7 @@ class LockManager
static void TimerEventHandler(TimerHandle_t xTimer);
static void AutoLockTimerEventHandler(AppEvent * aEvent);
static void ActuatorMovementTimerEventHandler(AppEvent * aEvent);
static void UpdateClusterStateAfterUnlatch(intptr_t context);

EmberAfPluginDoorLockUserInfo mLockUsers[kMaxUsers];
EmberAfPluginDoorLockCredentialInfo mLockCredentials[kNumCredentialTypes][kMaxCredentials];
Expand Down
9 changes: 9 additions & 0 deletions examples/lock-app/silabs/src/AppTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,10 @@ void AppTask::ActionInitiated(LockManager::Action_t aAction, int32_t aActor)
sAppTask.GetLCD().WriteDemoUI(locked);
#endif // DISPLAY_ENABLED
}
else if (aAction == LockManager::UNLATCH_ACTION)
{
SILABS_LOG("Unlatch Action has been initiated");
}

if (aActor == AppEvent::kEventType_Button)
{
Expand All @@ -325,6 +329,11 @@ void AppTask::ActionCompleted(LockManager::Action_t aAction)
{
SILABS_LOG("Lock Action has been completed")
}
else if (aAction == LockManager::UNLATCH_ACTION)
{
SILABS_LOG("Unlatch Action has been completed")
LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION);
}
else if (aAction == LockManager::UNLOCK_ACTION)
{
SILABS_LOG("Unlock Action has been completed")
Expand Down
55 changes: 52 additions & 3 deletions examples/lock-app/silabs/src/LockManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ using namespace EFR32DoorLock::LockInitParams;
CHIP_ERROR LockManager::Init(chip::app::DataModel::Nullable<chip::app::Clusters::DoorLock::DlLockState> state, LockParam lockParam)
{

LockParams = lockParam;
LockParams = lockParam;
mCurrentEndpointId = kInvalidEndpointId;

if (LockParams.numberOfUsers > kMaxUsers)
{
Expand Down Expand Up @@ -190,12 +191,18 @@ bool LockManager::InitiateAction(int32_t aActor, Action_t aAction)
State_t new_state;

// Initiate Turn Lock/Unlock Action only when the previous one is complete.
if (mState == kState_LockCompleted && aAction == UNLOCK_ACTION)
if ((mState == kState_LockCompleted || mState == kState_UnlatchCompleted) && (aAction == UNLOCK_ACTION))
{
action_initiated = true;

new_state = kState_UnlockInitiated;
}
else if ((mState == kState_LockCompleted || mState == kState_UnlockCompleted) && (aAction == UNLATCH_ACTION))
{
action_initiated = true;

new_state = kState_UnlatchInitiated;
}
else if (mState == kState_UnlockCompleted && aAction == LOCK_ACTION)
{
action_initiated = true;
Expand Down Expand Up @@ -262,6 +269,22 @@ void LockManager::TimerEventHandler(TimerHandle_t xTimer)
AppTask::GetAppTask().PostEvent(&event);
}

void LockManager::UpdateClusterStateAfterUnlatch(intptr_t context)
{
EndpointId endpointId = *reinterpret_cast<EndpointId *>(context);
// write the new lock value
bool succes = false;
if (endpointId != kInvalidEndpointId)
{
succes = DoorLockServer::Instance().SetLockState(endpointId, DlLockState::kUnlocked);
}

if (!succes)
{
SILABS_LOG("Failed to update the lock state after Unlatch");
}
}

void LockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
{
Action_t actionCompleted = INVALID_ACTION;
Expand All @@ -273,6 +296,13 @@ void LockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
lock->mState = kState_LockCompleted;
actionCompleted = LOCK_ACTION;
}
else if (lock->mState == kState_UnlatchInitiated)
{
chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateClusterStateAfterUnlatch,
reinterpret_cast<intptr_t>(&lock->mCurrentEndpointId));
lock->mState = kState_UnlatchCompleted;
actionCompleted = UNLATCH_ACTION;
}
else if (lock->mState == kState_UnlockInitiated)
{
lock->mState = kState_UnlockCompleted;
Expand All @@ -299,7 +329,26 @@ bool LockManager::Unlock(chip::EndpointId endpointId, const Nullable<chip::Fabri
{
if (DoorLockServer::Instance().SupportsUnbolt(endpointId))
{
return setLockState(endpointId, fabricIdx, nodeId, DlLockState::kUnlatched, pin, err);
// TODO: Our current implementation does not support multiple endpoint. This needs to be fixed in the future.
if (endpointId != mCurrentEndpointId)
{
// If we get a request to unlock on a different endpoint while the current endpoint is in the middle of an action,
// we return false for now. This needs to be fixed in the future.
if (mState != kState_UnlockCompleted && mState != kState_LockCompleted)
{
ChipLogError(Zcl, "Cannot unlock while unlatch on another endpoint is in progress on anotther endpoint");
return false;
}
else
{
mCurrentEndpointId = endpointId;
return setLockState(endpointId, fabricIdx, nodeId, DlLockState::kUnlatched, pin, err);
}
}
else
{
return setLockState(endpointId, fabricIdx, nodeId, DlLockState::kUnlatched, pin, err);
}
}
return setLockState(endpointId, fabricIdx, nodeId, DlLockState::kUnlocked, pin, err);
}
Expand Down
9 changes: 8 additions & 1 deletion examples/lock-app/silabs/src/ZclCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,14 @@ bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, const
bool status = LockMgr().Unlock(endpointId, fabricIdx, nodeId, pinCode, err);
if (status == true)
{
LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION);
if (DoorLockServer::Instance().SupportsUnbolt(endpointId))
{
LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLATCH_ACTION);
}
else
{
LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION);
}
}

return status;
Expand Down

0 comments on commit ed82e78

Please sign in to comment.