Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 47b31c8

Browse files
committedMar 21, 2025·
samples: matter: lock: Support all fields of LockOperation event
Add support for `UserIndex`, `FabricIndex`, `SourceNode` and `Credentials` fields. Signed-off-by: Adrian Gielniewski <adrian.gielniewski@nordicsemi.no>
1 parent 9f4bc34 commit 47b31c8

File tree

5 files changed

+100
-49
lines changed

5 files changed

+100
-49
lines changed
 

‎samples/matter/lock/src/app_task.cpp

+47-21
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ void AppTask::SwitchTransportTriggerHandler(const SwitchButtonAction &action)
130130
}
131131
#endif
132132

133-
void AppTask::LockStateChanged(BoltLockManager::State state, BoltLockManager::OperationSource source)
133+
void AppTask::LockStateChanged(const BoltLockManager::StateData &stateData)
134134
{
135-
switch (state) {
135+
switch (stateData.state) {
136136
case BoltLockManager::State::kLockingInitiated:
137137
LOG_INF("Lock action initiated");
138138
Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED2).Blink(50, 50);
@@ -164,26 +164,33 @@ void AppTask::LockStateChanged(BoltLockManager::State state, BoltLockManager::Op
164164
}
165165

166166
/* Handle changing attribute state in the application */
167-
Instance().UpdateClusterState(state, source);
167+
Instance().UpdateClusterState(stateData);
168168
}
169169

170-
void AppTask::UpdateClusterState(BoltLockManager::State state, BoltLockManager::OperationSource source)
170+
void AppTask::UpdateClusterState(const BoltLockManager::StateData &stateData)
171171
{
172-
DlLockState newLockState;
172+
BoltLockManager::StateData *stateDataCopy = Platform::New<BoltLockManager::StateData>(stateData);
173173

174-
switch (state) {
175-
case BoltLockManager::State::kLockingCompleted:
176-
newLockState = DlLockState::kLocked;
177-
break;
178-
case BoltLockManager::State::kUnlockingCompleted:
179-
newLockState = DlLockState::kUnlocked;
180-
break;
181-
default:
182-
newLockState = DlLockState::kNotFullyLocked;
183-
break;
174+
if (stateDataCopy == nullptr) {
175+
LOG_ERR("Failed to allocate memory for BoltLockManager::StateData");
176+
return;
184177
}
185178

186-
SystemLayer().ScheduleLambda([newLockState, source] {
179+
SystemLayer().ScheduleLambda([stateData = stateDataCopy]() {
180+
DlLockState newLockState;
181+
182+
switch (stateData->state) {
183+
case BoltLockManager::State::kLockingCompleted:
184+
newLockState = DlLockState::kLocked;
185+
break;
186+
case BoltLockManager::State::kUnlockingCompleted:
187+
newLockState = DlLockState::kUnlocked;
188+
break;
189+
default:
190+
newLockState = DlLockState::kNotFullyLocked;
191+
break;
192+
}
193+
187194
chip::app::DataModel::Nullable<chip::app::Clusters::DoorLock::DlLockState> currentLockState;
188195
chip::app::Clusters::DoorLock::Attributes::LockState::Get(kLockEndpointId, currentLockState);
189196

@@ -193,19 +200,38 @@ void AppTask::UpdateClusterState(BoltLockManager::State state, BoltLockManager::
193200
} else {
194201
LOG_INF("Updating LockState attribute");
195202

196-
if (!DoorLockServer::Instance().SetLockState(kLockEndpointId, newLockState, source)) {
203+
Nullable<uint16_t> userId;
204+
Nullable<List<const LockOpCredentials>> credentials;
205+
List<const LockOpCredentials> credentialList;
206+
207+
if (!stateData->validatePINResult.IsNull()) {
208+
userId = { stateData->validatePINResult.Value().userId };
209+
210+
/* `DoorLockServer::SetLockState` exptects list of `LockOpCredentials`,
211+
however in case of PIN validation it makes no sense to have more than one
212+
credential corresponding to validation result. For simplicity we wrap single
213+
credential in list here. */
214+
credentialList = { &stateData->validatePINResult.Value().credential, 1 };
215+
credentials = { credentialList };
216+
}
217+
218+
if (!DoorLockServer::Instance().SetLockState(kLockEndpointId, newLockState, stateData->source,
219+
userId, credentials, stateData->fabricIdx,
220+
stateData->nodeId)) {
197221
LOG_ERR("Failed to update LockState attribute");
198222
}
199223
}
224+
225+
Platform::Delete(stateData);
200226
});
201227
}
202228

203229
#ifdef CONFIG_CHIP_NUS
204230
void AppTask::NUSLockCallback(void *context)
205231
{
206232
LOG_DBG("Received LOCK command from NUS");
207-
if (BoltLockMgr().mState == BoltLockManager::State::kLockingCompleted ||
208-
BoltLockMgr().mState == BoltLockManager::State::kLockingInitiated) {
233+
if (BoltLockMgr().GetState().state == BoltLockManager::State::kLockingCompleted ||
234+
BoltLockMgr().GetState().state == BoltLockManager::State::kLockingInitiated) {
209235
LOG_INF("Device is already locked");
210236
} else {
211237
Nrf::PostTask([] { LockActionEventHandler(); });
@@ -215,8 +241,8 @@ void AppTask::NUSLockCallback(void *context)
215241
void AppTask::NUSUnlockCallback(void *context)
216242
{
217243
LOG_DBG("Received UNLOCK command from NUS");
218-
if (BoltLockMgr().mState == BoltLockManager::State::kUnlockingCompleted ||
219-
BoltLockMgr().mState == BoltLockManager::State::kUnlockingInitiated) {
244+
if (BoltLockMgr().GetState().state == BoltLockManager::State::kUnlockingCompleted ||
245+
BoltLockMgr().GetState().state == BoltLockManager::State::kUnlockingInitiated) {
220246
LOG_INF("Device is already unlocked");
221247
} else {
222248
Nrf::PostTask([] { LockActionEventHandler(); });

‎samples/matter/lock/src/app_task.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class AppTask {
3131

3232
CHIP_ERROR StartApp();
3333

34-
void UpdateClusterState(BoltLockManager::State state, BoltLockManager::OperationSource source);
34+
void UpdateClusterState(const BoltLockManager::StateData &stateData);
3535
static void IdentifyStartHandler(Identify *);
3636
static void IdentifyStopHandler(Identify *);
3737

@@ -40,7 +40,7 @@ class AppTask {
4040

4141
static void LockActionEventHandler();
4242
static void ButtonEventHandler(Nrf::ButtonState state, Nrf::ButtonMask hasChanged);
43-
static void LockStateChanged(BoltLockManager::State state, BoltLockManager::OperationSource source);
43+
static void LockStateChanged(const BoltLockManager::StateData &stateData);
4444

4545
#ifdef CONFIG_THREAD_WIFI_SWITCHING
4646
static void SwitchTransportEventHandler();

‎samples/matter/lock/src/bolt_lock_manager.cpp

+25-14
Original file line numberDiff line numberDiff line change
@@ -111,21 +111,23 @@ bool BoltLockManager::GetRequirePIN()
111111
return AccessMgr::Instance().GetRequirePIN();
112112
}
113113

114-
void BoltLockManager::Lock(OperationSource source)
114+
void BoltLockManager::Lock(const OperationSource source, const Nullable<chip::FabricIndex> &fabricIdx,
115+
const Nullable<chip::NodeId> &nodeId, const Nullable<ValidatePINResult> &validatePINResult)
115116
{
116-
VerifyOrReturn(mState != State::kLockingCompleted);
117-
SetState(State::kLockingInitiated, source);
117+
VerifyOrReturn(mStateData.state != State::kLockingCompleted);
118+
StateData newStateData{ State::kLockingInitiated, source, fabricIdx, nodeId, validatePINResult };
119+
SetStateData(newStateData);
118120

119-
mActuatorOperationSource = source;
120121
k_timer_start(&mActuatorTimer, K_MSEC(kActuatorMovementTimeMs), K_NO_WAIT);
121122
}
122123

123-
void BoltLockManager::Unlock(OperationSource source)
124+
void BoltLockManager::Unlock(const OperationSource source, const Nullable<chip::FabricIndex> &fabricIdx,
125+
const Nullable<chip::NodeId> &nodeId, const Nullable<ValidatePINResult> &validatePINResult)
124126
{
125-
VerifyOrReturn(mState != State::kUnlockingCompleted);
126-
SetState(State::kUnlockingInitiated, source);
127+
VerifyOrReturn(mStateData.state != State::kUnlockingCompleted);
128+
StateData newStateData{ State::kUnlockingInitiated, source, fabricIdx, nodeId, validatePINResult };
129+
SetStateData(newStateData);
127130

128-
mActuatorOperationSource = source;
129131
k_timer_start(&mActuatorTimer, K_MSEC(kActuatorMovementTimeMs), K_NO_WAIT);
130132
}
131133

@@ -146,24 +148,33 @@ void BoltLockManager::ActuatorAppEventHandler(const BoltLockManagerEvent &event)
146148
{
147149
BoltLockManager *lock = reinterpret_cast<BoltLockManager *>(event.manager);
148150

149-
switch (lock->mState) {
151+
switch (lock->mStateData.state) {
150152
case State::kLockingInitiated:
151-
lock->SetState(State::kLockingCompleted, lock->mActuatorOperationSource);
153+
lock->SetState(State::kLockingCompleted);
152154
break;
153155
case State::kUnlockingInitiated:
154-
lock->SetState(State::kUnlockingCompleted, lock->mActuatorOperationSource);
156+
lock->SetState(State::kUnlockingCompleted);
155157
break;
156158
default:
157159
break;
158160
}
159161
}
160162

161-
void BoltLockManager::SetState(State state, OperationSource source)
163+
void BoltLockManager::SetState(State state)
162164
{
163-
mState = state;
165+
mStateData.state = state;
164166

165167
if (mStateChangeCallback != nullptr) {
166-
mStateChangeCallback(state, source);
168+
mStateChangeCallback(mStateData);
169+
}
170+
}
171+
172+
void BoltLockManager::SetStateData(const StateData &stateData)
173+
{
174+
mStateData = stateData;
175+
176+
if (mStateChangeCallback != nullptr) {
177+
mStateChangeCallback(mStateData);
167178
}
168179
}
169180

‎samples/matter/lock/src/bolt_lock_manager.h

+21-8
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,24 @@ class BoltLockManager {
4040
};
4141

4242
using OperationSource = chip::app::Clusters::DoorLock::OperationSourceEnum;
43-
using StateChangeCallback = void (*)(State, OperationSource);
4443
using ValidatePINResult = AccessMgr::ValidatePINResult;
4544

45+
struct StateData {
46+
State state;
47+
OperationSource source;
48+
Nullable<chip::FabricIndex> fabricIdx;
49+
Nullable<chip::NodeId> nodeId;
50+
Nullable<ValidatePINResult> validatePINResult;
51+
};
52+
53+
using StateChangeCallback = void (*)(const StateData &);
54+
4655
static constexpr uint32_t kActuatorMovementTimeMs = 2000;
4756

4857
void Init(StateChangeCallback callback);
4958

50-
State GetState() const { return mState; }
51-
bool IsLocked() const { return mState == State::kLockingCompleted; }
59+
const StateData &GetState() const { return mStateData; }
60+
bool IsLocked() const { return mStateData.state == State::kLockingCompleted; }
5261

5362
bool GetUser(uint16_t userIndex, EmberAfPluginDoorLockUserInfo &user);
5463
bool SetUser(uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier,
@@ -80,8 +89,12 @@ class BoltLockManager {
8089
bool ValidatePIN(const Optional<chip::ByteSpan> &pinCode, OperationErrorEnum &err,
8190
Nullable<ValidatePINResult> &result);
8291

83-
void Lock(OperationSource source);
84-
void Unlock(OperationSource source);
92+
void Lock(const OperationSource source, const Nullable<chip::FabricIndex> &fabricIdx = NullNullable,
93+
const Nullable<chip::NodeId> &nodeId = NullNullable,
94+
const Nullable<ValidatePINResult> &validatePINResult = NullNullable);
95+
void Unlock(const OperationSource source, const Nullable<chip::FabricIndex> &fabricIdx = NullNullable,
96+
const Nullable<chip::NodeId> &nodeId = NullNullable,
97+
const Nullable<ValidatePINResult> &validatePINResult = NullNullable);
8598

8699
void SetRequirePIN(bool require);
87100
bool GetRequirePIN();
@@ -91,15 +104,15 @@ class BoltLockManager {
91104
private:
92105
friend class AppTask;
93106

94-
void SetState(State state, OperationSource source);
107+
void SetState(State state);
108+
void SetStateData(const StateData &stateData);
95109

96110
static void ActuatorTimerEventHandler(k_timer *timer);
97111
static void ActuatorAppEventHandler(const BoltLockManagerEvent &event);
98112
friend BoltLockManager &BoltLockMgr();
99113

100-
State mState = State::kLockingCompleted;
114+
StateData mStateData = { State::kLockingCompleted, OperationSource::kButton, {}, {}, {} };
101115
StateChangeCallback mStateChangeCallback = nullptr;
102-
OperationSource mActuatorOperationSource = OperationSource::kButton;
103116
k_timer mActuatorTimer = {};
104117

105118
static BoltLockManager sLock;

‎samples/matter/lock/src/zcl_callbacks.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ bool emberAfPluginDoorLockOnDoorLockCommand(EndpointId endpointId, const Nullabl
6868

6969
/* Handle changing attribute state on command reception */
7070
if (success) {
71-
BoltLockMgr().Lock(BoltLockManager::OperationSource::kRemote);
71+
BoltLockMgr().Lock(BoltLockManager::OperationSource::kRemote, fabricIdx, nodeId, validatePINResult);
7272
}
7373

7474
return success;
@@ -83,7 +83,7 @@ bool emberAfPluginDoorLockOnDoorUnlockCommand(EndpointId endpointId, const Nulla
8383

8484
/* Handle changing attribute state on command reception */
8585
if (success) {
86-
BoltLockMgr().Unlock(BoltLockManager::OperationSource::kRemote);
86+
BoltLockMgr().Unlock(BoltLockManager::OperationSource::kRemote, fabricIdx, nodeId, validatePINResult);
8787
}
8888

8989
return success;
@@ -124,8 +124,9 @@ void emberAfDoorLockClusterInitCallback(EndpointId endpoint)
124124
"number of holiday schedules");
125125
#endif /* CONFIG_LOCK_SCHEDULES */
126126

127-
AppTask::Instance().UpdateClusterState(BoltLockMgr().GetState(),
128-
BoltLockManager::OperationSource::kUnspecified);
127+
BoltLockManager::StateData state = BoltLockMgr().GetState();
128+
state.source = BoltLockManager::OperationSource::kUnspecified;
129+
AppTask::Instance().UpdateClusterState(state);
129130
}
130131

131132
#ifdef CONFIG_LOCK_SCHEDULES

0 commit comments

Comments
 (0)
Please sign in to comment.