Skip to content

Commit d311644

Browse files
Added unlatch state on unlock supporting Ubolt and tdded ransition locked->unlatched->unlocked (#32023)
1 parent 20a37e0 commit d311644

File tree

7 files changed

+149
-8
lines changed

7 files changed

+149
-8
lines changed

examples/lock-app/silabs/include/AppConfig.h

+4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
// state to another.
3232
#define ACTUATOR_MOVEMENT_PERIOS_MS 10
3333

34+
// Time the device will be left in the unlatched state before sending it back to the unlocked state.
35+
// Left at 100 ms for testing purposes.
36+
#define UNLATCH_TIME_MS 100
37+
3438
#define ON_DEMO_BITMAP \
3539
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
3640
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, \

examples/lock-app/silabs/include/AppTask.h

+7
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,13 @@ class AppTask : public BaseApplication
119119
*/
120120
static void UpdateClusterState(intptr_t context);
121121

122+
/**
123+
* @brief Update Cluster State After Unlatch
124+
*
125+
* @param context current context
126+
*/
127+
static void UpdateClusterStateAfterUnlatch(intptr_t context);
128+
122129
/**
123130
* @brief Handle lock update event
124131
*

examples/lock-app/silabs/include/LockManager.h

+26
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ class LockManager
119119
{
120120
LOCK_ACTION = 0,
121121
UNLOCK_ACTION,
122+
UNLATCH_ACTION,
122123

123124
INVALID_ACTION
124125
} Action;
@@ -128,7 +129,9 @@ class LockManager
128129
kState_LockInitiated = 0,
129130
kState_LockCompleted,
130131
kState_UnlockInitiated,
132+
kState_UnlatchInitiated,
131133
kState_UnlockCompleted,
134+
kState_UnlatchCompleted,
132135
} State;
133136

134137
CHIP_ERROR Init(chip::app::DataModel::Nullable<chip::app::Clusters::DoorLock::DlLockState> state,
@@ -191,7 +194,30 @@ class LockManager
191194

192195
bool ReadConfigValues();
193196

197+
void UnlockAfterUnlatch();
198+
194199
private:
200+
struct UnlatchContext
201+
{
202+
chip::EndpointId mEndpointId;
203+
Nullable<chip::FabricIndex> mFabricIdx;
204+
Nullable<chip::NodeId> mNodeId;
205+
Optional<chip::ByteSpan> mPin;
206+
OperationErrorEnum mErr;
207+
208+
void Update(chip::EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx,
209+
const Nullable<chip::NodeId> & nodeId, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err)
210+
{
211+
mEndpointId = endpointId;
212+
mFabricIdx = fabricIdx;
213+
mNodeId = nodeId;
214+
mPin = pin;
215+
mErr = err;
216+
}
217+
};
218+
UnlatchContext mUnlatchContext;
219+
chip::EndpointId mCurrentEndpointId;
220+
195221
friend LockManager & LockMgr();
196222
State_t mState;
197223

examples/lock-app/silabs/openthread.gni

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ openthread_external_platform =
2828
sl_enable_test_event_trigger = true
2929

3030
# ICD Default configurations
31-
chip_enable_icd_server = true
31+
chip_enable_icd_server = false
3232
chip_subscription_timeout_resumption = false
3333
sl_use_subscription_syncing = true
3434

examples/lock-app/silabs/src/AppTask.cpp

+50
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,45 @@ using namespace EFR32DoorLock::LockInitParams;
7070

7171
namespace {
7272
LEDWidget sLockLED;
73+
TimerHandle_t sUnlatchTimer;
74+
75+
void UpdateClusterStateAfterUnlatch(intptr_t context)
76+
{
77+
LockMgr().UnlockAfterUnlatch();
78+
}
79+
80+
void UnlatchTimerCallback(TimerHandle_t xTimer)
81+
{
82+
chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateClusterStateAfterUnlatch, reinterpret_cast<intptr_t>(nullptr));
83+
}
84+
85+
void CancelUnlatchTimer(void)
86+
{
87+
if (xTimerStop(sUnlatchTimer, pdMS_TO_TICKS(0)) == pdFAIL)
88+
{
89+
SILABS_LOG("sUnlatchTimer stop() failed");
90+
appError(APP_ERROR_STOP_TIMER_FAILED);
91+
}
92+
}
93+
94+
void StartUnlatchTimer(uint32_t timeoutMs)
95+
{
96+
if (xTimerIsTimerActive(sUnlatchTimer))
97+
{
98+
SILABS_LOG("app timer already started!");
99+
CancelUnlatchTimer();
100+
}
101+
102+
// timer is not active, change its period to required value (== restart).
103+
// FreeRTOS- Block for a maximum of 100 ms if the change period command
104+
// cannot immediately be sent to the timer command queue.
105+
if (xTimerStart(sUnlatchTimer, pdMS_TO_TICKS(timeoutMs)) != pdPASS)
106+
{
107+
SILABS_LOG("sUnlatchTimer timer start() failed");
108+
appError(APP_ERROR_START_TIMER_FAILED);
109+
}
110+
}
111+
73112
} // namespace
74113

75114
using namespace chip::TLV;
@@ -180,6 +219,8 @@ CHIP_ERROR AppTask::Init()
180219
sLockLED.Init(LOCK_STATE_LED);
181220
sLockLED.Set(state.Value() == DlLockState::kUnlocked);
182221

222+
sUnlatchTimer = xTimerCreate("UnlatchTimer", pdMS_TO_TICKS(UNLATCH_TIME_MS), pdFALSE, (void *) 0, UnlatchTimerCallback);
223+
183224
// Update the LCD with the Stored value. Show QR Code if not provisioned
184225
#ifdef DISPLAY_ENABLED
185226
GetLCD().WriteDemoUI(state.Value() != DlLockState::kUnlocked);
@@ -309,6 +350,10 @@ void AppTask::ActionInitiated(LockManager::Action_t aAction, int32_t aActor)
309350
sAppTask.GetLCD().WriteDemoUI(locked);
310351
#endif // DISPLAY_ENABLED
311352
}
353+
else if (aAction == LockManager::UNLATCH_ACTION)
354+
{
355+
SILABS_LOG("Unlatch Action has been initiated");
356+
}
312357

313358
if (aActor == AppEvent::kEventType_Button)
314359
{
@@ -325,6 +370,11 @@ void AppTask::ActionCompleted(LockManager::Action_t aAction)
325370
{
326371
SILABS_LOG("Lock Action has been completed")
327372
}
373+
else if (aAction == LockManager::UNLATCH_ACTION)
374+
{
375+
SILABS_LOG("Unlatch Action has been completed")
376+
StartUnlatchTimer(UNLATCH_TIME_MS);
377+
}
328378
else if (aAction == LockManager::UNLOCK_ACTION)
329379
{
330380
SILABS_LOG("Unlock Action has been completed")

examples/lock-app/silabs/src/LockManager.cpp

+53-6
Original file line numberDiff line numberDiff line change
@@ -186,22 +186,24 @@ bool LockManager::InitiateAction(int32_t aActor, Action_t aAction)
186186
State_t new_state;
187187

188188
// Initiate Turn Lock/Unlock Action only when the previous one is complete.
189-
if (mState == kState_LockCompleted && aAction == UNLOCK_ACTION)
189+
if ((mState == kState_LockCompleted || mState == kState_UnlatchCompleted) && (aAction == UNLOCK_ACTION))
190190
{
191191
action_initiated = true;
192-
193-
new_state = kState_UnlockInitiated;
192+
new_state = kState_UnlockInitiated;
193+
}
194+
else if ((mState == kState_LockCompleted || mState == kState_UnlockCompleted) && (aAction == UNLATCH_ACTION))
195+
{
196+
action_initiated = true;
197+
new_state = kState_UnlatchInitiated;
194198
}
195199
else if (mState == kState_UnlockCompleted && aAction == LOCK_ACTION)
196200
{
197201
action_initiated = true;
198-
199-
new_state = kState_LockInitiated;
202+
new_state = kState_LockInitiated;
200203
}
201204

202205
if (action_initiated)
203206
{
204-
205207
StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS);
206208

207209
// Since the timer started successfully, update the state and trigger callback
@@ -249,6 +251,23 @@ void LockManager::TimerEventHandler(void * timerCbArg)
249251
event.Handler = ActuatorMovementTimerEventHandler;
250252
AppTask::GetAppTask().PostEvent(&event);
251253
}
254+
void LockManager::UnlockAfterUnlatch()
255+
{
256+
// write the new lock value
257+
bool succes = false;
258+
if (mUnlatchContext.mEndpointId != kInvalidEndpointId)
259+
{
260+
succes = setLockState(mUnlatchContext.mEndpointId, mUnlatchContext.mFabricIdx, mUnlatchContext.mNodeId,
261+
DlLockState::kUnlocked, mUnlatchContext.mPin, mUnlatchContext.mErr);
262+
}
263+
264+
if (!succes)
265+
{
266+
SILABS_LOG("Failed to update the lock state after Unlatch");
267+
}
268+
269+
InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION);
270+
}
252271

253272
void LockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
254273
{
@@ -261,6 +280,11 @@ void LockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
261280
lock->mState = kState_LockCompleted;
262281
actionCompleted = LOCK_ACTION;
263282
}
283+
else if (lock->mState == kState_UnlatchInitiated)
284+
{
285+
lock->mState = kState_UnlatchCompleted;
286+
actionCompleted = UNLATCH_ACTION;
287+
}
264288
else if (lock->mState == kState_UnlockInitiated)
265289
{
266290
lock->mState = kState_UnlockCompleted;
@@ -285,6 +309,29 @@ bool LockManager::Lock(chip::EndpointId endpointId, const Nullable<chip::FabricI
285309
bool LockManager::Unlock(chip::EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx,
286310
const Nullable<chip::NodeId> & nodeId, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err)
287311
{
312+
if (DoorLockServer::Instance().SupportsUnbolt(endpointId))
313+
{
314+
// TODO: Our current implementation does not support multiple endpoint. This needs to be fixed in the future.
315+
if (endpointId != mUnlatchContext.mEndpointId)
316+
{
317+
// If we get a request to unlock on a different endpoint while the current endpoint is in the middle of an action,
318+
// we return false for now. This needs to be fixed in the future.
319+
if (mState != kState_UnlockCompleted && mState != kState_LockCompleted)
320+
{
321+
ChipLogError(Zcl, "Cannot unlock while unlatch on another endpoint is in progress on anotther endpoint");
322+
return false;
323+
}
324+
else
325+
{
326+
mUnlatchContext.Update(endpointId, fabricIdx, nodeId, pin, err);
327+
return setLockState(endpointId, fabricIdx, nodeId, DlLockState::kUnlatched, pin, err);
328+
}
329+
}
330+
else
331+
{
332+
return setLockState(endpointId, fabricIdx, nodeId, DlLockState::kUnlatched, pin, err);
333+
}
334+
}
288335
return setLockState(endpointId, fabricIdx, nodeId, DlLockState::kUnlocked, pin, err);
289336
}
290337

examples/lock-app/silabs/src/ZclCallbacks.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,14 @@ bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, const
8989
bool status = LockMgr().Unlock(endpointId, fabricIdx, nodeId, pinCode, err);
9090
if (status == true)
9191
{
92-
LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION);
92+
if (DoorLockServer::Instance().SupportsUnbolt(endpointId))
93+
{
94+
LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLATCH_ACTION);
95+
}
96+
else
97+
{
98+
LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION);
99+
}
93100
}
94101

95102
return status;

0 commit comments

Comments
 (0)