Skip to content

Commit

Permalink
Resolve event notifications from lock when setting the lock state.
Browse files Browse the repository at this point in the history
  • Loading branch information
krypton36 committed Feb 17, 2023
1 parent e08d4e5 commit e022273
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 42 deletions.
7 changes: 4 additions & 3 deletions examples/lock-app/linux/include/LockEndpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ class LockEndpoint

inline chip::EndpointId GetEndpointId() const { return mEndpointId; }

bool Lock(const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err);
bool Unlock(const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err);
bool Lock(const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource);
bool Unlock(const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource);

bool GetUser(uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user) const;
bool SetUser(uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier, const chip::CharSpan & userName,
Expand Down Expand Up @@ -97,7 +97,8 @@ class LockEndpoint
OperatingModeEnum operatingMode);

private:
bool setLockState(DlLockState lockState, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err);
bool setLockState(DlLockState lockState, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
OperationSourceEnum opSource = OperationSourceEnum::kUnspecified);
const char * lockStateToString(DlLockState lockState) const;

bool weekDayScheduleInAction(uint16_t userIndex) const;
Expand Down
6 changes: 4 additions & 2 deletions examples/lock-app/linux/include/LockManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ class LockManager

bool SendLockAlarm(chip::EndpointId endpointId, AlarmCodeEnum alarmCode);

bool Lock(chip::EndpointId endpointId, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err);
bool Unlock(chip::EndpointId endpointId, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err);
bool Lock(chip::EndpointId endpointId, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
OperationSourceEnum opSource);
bool Unlock(chip::EndpointId endpointId, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
OperationSourceEnum opSource);

bool GetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user);
bool SetUser(chip::EndpointId endpointId, uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier,
Expand Down
18 changes: 11 additions & 7 deletions examples/lock-app/linux/src/LockEndpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@
#include <cstring>

using chip::to_underlying;
using chip::app::DataModel::MakeNullable;

bool LockEndpoint::Lock(const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err)
bool LockEndpoint::Lock(const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource)
{
return setLockState(DlLockState::kLocked, pin, err);
return setLockState(DlLockState::kLocked, pin, err, opSource);
}

bool LockEndpoint::Unlock(const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err)
bool LockEndpoint::Unlock(const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource)
{
return setLockState(DlLockState::kUnlocked, pin, err);
return setLockState(DlLockState::kUnlocked, pin, err, opSource);
}

bool LockEndpoint::GetUser(uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user) const
Expand Down Expand Up @@ -376,7 +377,8 @@ DlStatus LockEndpoint::SetSchedule(uint8_t holidayIndex, DlScheduleStatus status
return DlStatus::kSuccess;
}

bool LockEndpoint::setLockState(DlLockState lockState, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err)
bool LockEndpoint::setLockState(DlLockState lockState, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
OperationSourceEnum opSource)
{
// Assume pin is required until told otherwise
bool requirePin = true;
Expand Down Expand Up @@ -457,8 +459,10 @@ bool LockEndpoint::setLockState(DlLockState lockState, const Optional<chip::Byte
"Lock App: specified PIN code was found in the database, setting door lock state to \"%s\" [endpointId=%d,userIndex=%u]",
lockStateToString(lockState), mEndpointId, userIndex);

mLockState = lockState;
DoorLockServer::Instance().SetLockState(mEndpointId, mLockState);
mLockState = lockState;
LockOpCredentials userCredential[] = { { CredentialTypeEnum::kPin, uint16_t(credentialIndex) } };
auto userCredentials = MakeNullable<List<const LockOpCredentials>>(userCredential);
DoorLockServer::Instance().SetLockState(mEndpointId, mLockState, opSource, Nullable<uint16_t>(userIndex + 1), userCredentials);

return true;
}
Expand Down
10 changes: 6 additions & 4 deletions examples/lock-app/linux/src/LockManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,26 +134,28 @@ bool LockManager::SendLockAlarm(chip::EndpointId endpointId, AlarmCodeEnum alarm
return lockEndpoint->SendLockAlarm(alarmCode);
}

bool LockManager::Lock(chip::EndpointId endpointId, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err)
bool LockManager::Lock(chip::EndpointId endpointId, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
OperationSourceEnum opSource)
{
auto lockEndpoint = getEndpoint(endpointId);
if (nullptr == lockEndpoint)
{
ChipLogError(Zcl, "Unable to lock the door - endpoint does not exist or not initialized [endpointId=%d]", endpointId);
return false;
}
return lockEndpoint->Lock(pin, err);
return lockEndpoint->Lock(pin, err, opSource);
}

bool LockManager::Unlock(chip::EndpointId endpointId, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err)
bool LockManager::Unlock(chip::EndpointId endpointId, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
OperationSourceEnum opSource)
{
auto lockEndpoint = getEndpoint(endpointId);
if (nullptr == lockEndpoint)
{
ChipLogError(Zcl, "Unable to unlock the door - endpoint does not exist or not initialized [endpointId=%d]", endpointId);
return false;
}
return lockEndpoint->Unlock(pin, err);
return lockEndpoint->Unlock(pin, err, opSource);
}

bool LockManager::GetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user)
Expand Down
4 changes: 2 additions & 2 deletions examples/lock-app/linux/src/ZCLDoorLockCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ using namespace chip::app::Clusters::DoorLock;
bool emberAfPluginDoorLockOnDoorLockCommand(chip::EndpointId endpointId, const Optional<ByteSpan> & pinCode,
OperationErrorEnum & err)
{
return LockManager::Instance().Lock(endpointId, pinCode, err);
return LockManager::Instance().Lock(endpointId, pinCode, err, OperationSourceEnum::kRemote);
}

bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, const Optional<ByteSpan> & pinCode,
OperationErrorEnum & err)
{
return LockManager::Instance().Unlock(endpointId, pinCode, err);
return LockManager::Instance().Unlock(endpointId, pinCode, err, OperationSourceEnum::kRemote);
}

bool emberAfPluginDoorLockGetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user)
Expand Down
30 changes: 8 additions & 22 deletions src/app/clusters/door-lock-server/door-lock-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ bool DoorLockServer::SetLockState(chip::EndpointId endpointId, DlLockState newLo
return SetAttribute(endpointId, Attributes::LockState::Id, Attributes::LockState::Set, newLockState);
}

bool DoorLockServer::SetLockState(chip::EndpointId endpointId, DlLockState newLockState, OperationSourceEnum opSource)
bool DoorLockServer::SetLockState(chip::EndpointId endpointId, DlLockState newLockState, OperationSourceEnum opSource,
const Nullable<uint16_t> & userIndex, const Nullable<List<const LockOpCredentials>> & credentials)
{
bool success = SetLockState(endpointId, newLockState);

Expand All @@ -122,8 +123,8 @@ bool DoorLockServer::SetLockState(chip::EndpointId endpointId, DlLockState newLo
// Send LockOperation event
auto opType = (DlLockState::kLocked == newLockState) ? LockOperationTypeEnum::kLock : LockOperationTypeEnum::kUnlock;

SendLockOperationEvent(endpointId, opType, opSource, OperationErrorEnum::kUnspecified, Nullable<uint16_t>(),
Nullable<chip::FabricIndex>(), Nullable<chip::NodeId>(), nullptr, 0, success);
SendLockOperationEvent(endpointId, opType, opSource, OperationErrorEnum::kUnspecified, userIndex, Nullable<chip::FabricIndex>(),
Nullable<chip::NodeId>(), credentials, success);

// Schedule auto-relocking
if (success && LockOperationTypeEnum::kUnlock == opType)
Expand Down Expand Up @@ -3380,46 +3381,31 @@ bool DoorLockServer::HandleRemoteLockOperation(chip::app::CommandHandler * comma

// Send LockOperation/LockOperationError event. The credential index in
// foundCred will be filled in if we actually have a value to fill in.
Nullable<List<const LockOpCredentials>> credentials{};
LockOpCredentials foundCred[] = { { CredentialTypeEnum::kPin, UINT16_MAX } };
LockOpCredentials * credList = nullptr;
size_t credListSize = 0;

// appclusters.pdf 5.3.5.3, 5.3.5.4:
// The list of credentials used in performing the lock operation. This SHALL be null if no credentials were involved.
if (pinCode.HasValue() && pinCredIdx.HasValue())
{
foundCred[0].credentialIndex = pinCredIdx.Value();
credList = foundCred;
credListSize = 1;
credentials.SetNonNull(foundCred);
}

SendLockOperationEvent(endpoint, opType, OperationSourceEnum::kRemote, reason, pinUserIdx,
Nullable<chip::FabricIndex>(getFabricIndex(commandObj)), Nullable<chip::NodeId>(getNodeId(commandObj)),
credList, credListSize, success);
credentials, success);
return success;
}

void DoorLockServer::SendLockOperationEvent(chip::EndpointId endpointId, LockOperationTypeEnum opType, OperationSourceEnum opSource,
OperationErrorEnum opErr, const Nullable<uint16_t> & userId,
const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId,
LockOpCredentials * credList, size_t credListSize, bool opSuccess)
const Nullable<List<const LockOpCredentials>> & credentials, bool opSuccess)
{
Nullable<List<const Structs::CredentialStruct::Type>> credentials{};

// appclusters.pdf 5.3.5.3, 5.3.5.4:
// The list of credentials used in performing the lock operation. This SHALL be null if no credentials were involved.
if (nullptr == credList || 0 == credListSize)
{
credentials.SetNull();
}
else
{
credentials.SetNonNull(List<const Structs::CredentialStruct::Type>(credList, credListSize));
}

// TODO: if [USR] feature is not supported then credentials should be omitted (Optional.HasValue()==false)?
// Spec just says that it should be NULL if no PIN were provided.

if (opSuccess)
{
Events::LockOperation::Type event{ opType, opSource, userId, fabricIdx, nodeId, MakeOptional(credentials) };
Expand Down
7 changes: 5 additions & 2 deletions src/app/clusters/door-lock-server/door-lock-server.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ using chip::app::Clusters::DoorLock::UserStatusEnum;
using chip::app::Clusters::DoorLock::UserTypeEnum;
using chip::app::DataModel::List;
using chip::app::DataModel::Nullable;
using chip::app::DataModel::NullNullable;

using CredentialStruct = chip::app::Clusters::DoorLock::Structs::CredentialStruct::Type;
using LockOpCredentials = CredentialStruct;
Expand Down Expand Up @@ -95,7 +96,9 @@ class DoorLockServer
*
* @return true on success, false on failure.
*/
bool SetLockState(chip::EndpointId endpointId, DlLockState newLockState, OperationSourceEnum opSource);
bool SetLockState(chip::EndpointId endpointId, DlLockState newLockState, OperationSourceEnum opSource,
const Nullable<uint16_t> & userIndex = NullNullable,
const Nullable<List<const LockOpCredentials>> & credentials = NullNullable);

/**
* Updates the LockState attribute with new value.
Expand Down Expand Up @@ -408,7 +411,7 @@ class DoorLockServer
void SendLockOperationEvent(chip::EndpointId endpointId, LockOperationTypeEnum opType, OperationSourceEnum opSource,
OperationErrorEnum opErr, const Nullable<uint16_t> & userId,
const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId,
LockOpCredentials * credList, size_t credListSize, bool opSuccess = true);
const Nullable<List<const LockOpCredentials>> & credentials = NullNullable, bool opSuccess = true);

/**
* @brief Schedule auto relocking with a given timeout
Expand Down

0 comments on commit e022273

Please sign in to comment.