Skip to content

Commit

Permalink
project-chip#26925 generate lock operation events after lock state ha…
Browse files Browse the repository at this point in the history
…s changed
  • Loading branch information
mmarc committed Jul 17, 2023
1 parent 9ac1480 commit cc6375a
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 78 deletions.
13 changes: 8 additions & 5 deletions examples/lock-app/lock-common/include/LockEndpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@ class LockEndpoint

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

bool Lock(const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource);
bool Unlock(const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource);
bool Unbolt(const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource);
bool Lock(const chip::app::CommandHandler * commandObj, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
OperationSourceEnum opSource);
bool Unlock(const chip::app::CommandHandler * commandObj, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
OperationSourceEnum opSource);
bool Unbolt(const chip::app::CommandHandler * commandObj, 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 @@ -98,8 +101,8 @@ class LockEndpoint
OperatingModeEnum operatingMode);

private:
bool setLockState(DlLockState lockState, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
OperationSourceEnum opSource = OperationSourceEnum::kUnspecified);
bool setLockState(const chip::app::CommandHandler * commandObj, 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
12 changes: 6 additions & 6 deletions examples/lock-app/lock-common/include/LockManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ class LockManager

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

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 Unbolt(chip::EndpointId endpointId, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
OperationSourceEnum opSource);
bool Lock(const chip::app::CommandHandler * commandObj, chip::EndpointId endpointId, const Optional<chip::ByteSpan> & pin,
OperationErrorEnum & err, OperationSourceEnum opSource);
bool Unlock(const chip::app::CommandHandler * commandObj, chip::EndpointId endpointId, const Optional<chip::ByteSpan> & pin,
OperationErrorEnum & err, OperationSourceEnum opSource);
bool Unbolt(const chip::app::CommandHandler * commandObj, 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
28 changes: 16 additions & 12 deletions examples/lock-app/lock-common/src/LockEndpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,28 @@
using chip::to_underlying;
using chip::app::DataModel::MakeNullable;

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

bool LockEndpoint::Unlock(const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource)
bool LockEndpoint::Unlock(const chip::app::CommandHandler * commandObj, const Optional<chip::ByteSpan> & pin,
OperationErrorEnum & err, OperationSourceEnum opSource)
{
if (DoorLockServer::Instance().SupportsUnbolt(mEndpointId))
{
// If Unbolt is supported Unlock is supposed to pull the latch
setLockState(DlLockState::kUnlatched, pin, err, opSource);
setLockState(commandObj, DlLockState::kUnlatched, pin, err, opSource);
}

return setLockState(DlLockState::kUnlocked, pin, err, opSource);
return setLockState(commandObj, DlLockState::kUnlocked, pin, err, opSource);
}

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

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

bool LockEndpoint::setLockState(DlLockState lockState, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
OperationSourceEnum opSource)
bool LockEndpoint::setLockState(const chip::app::CommandHandler * commandObj, DlLockState lockState,
const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource)
{
// Assume pin is required until told otherwise
bool requirePin = true;
Expand All @@ -406,13 +409,14 @@ bool LockEndpoint::setLockState(DlLockState lockState, const Optional<chip::Byte
ChipLogProgress(Zcl, "Door Lock App: setting door lock state to \"%s\" [endpointId=%d]", lockStateToString(lockState),
mEndpointId);

DoorLockServer::Instance().SetLockState(mEndpointId, lockState);
DoorLockServer::Instance().SetLockState(nullptr, mEndpointId, lockState, opSource);

return true;
}

ChipLogError(Zcl, "Door Lock App: PIN code is not specified, but it is required [endpointId=%d]", mEndpointId);

err = OperationErrorEnum::kInvalidCredential;
return false;
}

Expand Down Expand Up @@ -473,8 +477,8 @@ bool LockEndpoint::setLockState(DlLockState lockState, const Optional<chip::Byte
mLockState = lockState;
LockOpCredentials userCredential[] = { { CredentialTypeEnum::kPin, uint16_t(credentialIndex) } };
auto userCredentials = MakeNullable<List<const LockOpCredentials>>(userCredential);
DoorLockServer::Instance().SetLockState(mEndpointId, mLockState, opSource, MakeNullable(static_cast<uint16_t>(userIndex + 1)),
userCredentials);
DoorLockServer::Instance().SetLockState(nullptr, mEndpointId, mLockState, opSource,
MakeNullable(static_cast<uint16_t>(userIndex + 1)), userCredentials);

return true;
}
Expand Down
18 changes: 9 additions & 9 deletions examples/lock-app/lock-common/src/LockManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,40 +134,40 @@ 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,
OperationSourceEnum opSource)
bool LockManager::Lock(const chip::app::CommandHandler * commandObj, 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, opSource);
return lockEndpoint->Lock(commandObj, pin, err, opSource);
}

bool LockManager::Unlock(chip::EndpointId endpointId, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
OperationSourceEnum opSource)
bool LockManager::Unlock(const chip::app::CommandHandler * commandObj, 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, opSource);
return lockEndpoint->Unlock(commandObj, pin, err, opSource);
}

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

bool LockManager::GetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user)
Expand Down
18 changes: 9 additions & 9 deletions examples/lock-app/lock-common/src/ZCLDoorLockCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,22 @@ using namespace chip::app::Clusters::DoorLock;
// should wait for door to be locked on lock command and return success) but
// door lock server should check pin before even calling the lock-door
// callback.
bool emberAfPluginDoorLockOnDoorLockCommand(chip::EndpointId endpointId, const Optional<ByteSpan> & pinCode,
OperationErrorEnum & err)
bool emberAfPluginDoorLockOnDoorLockCommand(const chip::app::CommandHandler * commandObj, chip::EndpointId endpointId,
const Optional<ByteSpan> & pinCode, OperationErrorEnum & err)
{
return LockManager::Instance().Lock(endpointId, pinCode, err, OperationSourceEnum::kRemote);
return LockManager::Instance().Lock(commandObj, endpointId, pinCode, err, OperationSourceEnum::kRemote);
}

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

bool emberAfPluginDoorLockOnDoorUnboltCommand(chip::EndpointId endpointId, const Optional<ByteSpan> & pinCode,
OperationErrorEnum & err)
bool emberAfPluginDoorLockOnDoorUnboltCommand(const chip::app::CommandHandler * commandObj, chip::EndpointId endpointId,
const Optional<ByteSpan> & pinCode, OperationErrorEnum & err)
{
return LockManager::Instance().Unbolt(endpointId, pinCode, err, OperationSourceEnum::kRemote);
return LockManager::Instance().Unbolt(commandObj, endpointId, pinCode, err, OperationSourceEnum::kRemote);
}

bool emberAfPluginDoorLockGetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,24 @@ using namespace chip::app::Clusters::DoorLock;
// =============================================================================

bool __attribute__((weak))
emberAfPluginDoorLockOnDoorLockCommand(chip::EndpointId endpointId, const Optional<ByteSpan> & pinCode, OperationErrorEnum & err)
emberAfPluginDoorLockOnDoorLockCommand(const chip::app::CommandHandler * commandObj, chip::EndpointId endpointId,
const Optional<ByteSpan> & pinCode, OperationErrorEnum & err)
{
err = OperationErrorEnum::kUnspecified;
return false;
}

bool __attribute__((weak))
emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, const Optional<ByteSpan> & pinCode, OperationErrorEnum & err)
emberAfPluginDoorLockOnDoorUnlockCommand(const chip::app::CommandHandler * commandObj, chip::EndpointId endpointId,
const Optional<ByteSpan> & pinCode, OperationErrorEnum & err)
{
err = OperationErrorEnum::kUnspecified;
return false;
}

bool __attribute__((weak))
emberAfPluginDoorLockOnDoorUnboltCommand(chip::EndpointId endpointId, const Optional<ByteSpan> & pinCode, OperationErrorEnum & err)
emberAfPluginDoorLockOnDoorUnboltCommand(const chip::app::CommandHandler * commandObj, chip::EndpointId endpointId,
const Optional<ByteSpan> & pinCode, OperationErrorEnum & err)
{
err = OperationErrorEnum::kUnspecified;
return false;
Expand Down
47 changes: 23 additions & 24 deletions src/app/clusters/door-lock-server/door-lock-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,12 @@ 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,
const Nullable<uint16_t> & userIndex, const Nullable<List<const LockOpCredentials>> & credentials)
bool DoorLockServer::SetLockState(const chip::app::CommandHandler * commandObj, chip::EndpointId endpointId,
DlLockState newLockState, OperationSourceEnum opSource, const Nullable<uint16_t> & userIndex,
const Nullable<List<const LockOpCredentials>> & credentials)
{
bool success = SetLockState(endpointId, newLockState);

// Remote operations are handled separately as they use more data unavailable here
VerifyOrReturnError(OperationSourceEnum::kRemote != opSource, success);

// DlLockState::kNotFullyLocked has no appropriate event to send. Also it is unclear whether
// it should schedule auto-relocking. So skip it here. Check for supported states explicitly
// to handle possible enum extending in future.
Expand All @@ -130,8 +128,17 @@ bool DoorLockServer::SetLockState(chip::EndpointId endpointId, DlLockState newLo
opType = LockOperationTypeEnum::kUnlatch;
}

SendLockOperationEvent(endpointId, opType, opSource, OperationErrorEnum::kUnspecified, userIndex, Nullable<chip::FabricIndex>(),
Nullable<chip::NodeId>(), credentials, success);
if (commandObj == nullptr)
{
SendLockOperationEvent(endpointId, opType, opSource, OperationErrorEnum::kUnspecified, userIndex,
Nullable<chip::FabricIndex>(), Nullable<chip::NodeId>(), credentials, success);
}
else
{
SendLockOperationEvent(endpointId, opType, opSource, OperationErrorEnum::kUnspecified, userIndex,
Nullable<chip::FabricIndex>(getFabricIndex(commandObj)),
Nullable<chip::NodeId>(getNodeId(commandObj)), credentials, success);
}

// Reset wrong entry attempts (in case there were any incorrect credentials presented before) if lock/unlock was a success
// and a valid credential was presented.
Expand Down Expand Up @@ -3428,7 +3435,7 @@ bool DoorLockServer::HandleRemoteLockOperation(chip::app::CommandHandler * comma
}

// credentials check succeeded, try to lock/unlock door
success = opHandler(endpoint, pinCode, reason);
success = opHandler(commandObj, endpoint, pinCode, reason);
// The app should trigger the lock state change as it may take a while before the lock actually locks/unlocks
exit:
if (!success && reason == OperationErrorEnum::kInvalidCredential)
Expand Down Expand Up @@ -3464,23 +3471,15 @@ bool DoorLockServer::HandleRemoteLockOperation(chip::app::CommandHandler * comma
credentials.SetNonNull(foundCred);
}

// Failed Unlatch requests SHALL generate only a LockOperationError event with LockOperationType set to Unlock
if (LockOperationTypeEnum::kUnlatch == opType && !success)
if (!success)
{
opType = LockOperationTypeEnum::kUnlock;
}

SendLockOperationEvent(endpoint, opType, OperationSourceEnum::kRemote, reason, pinUserIdx,
Nullable<chip::FabricIndex>(getFabricIndex(commandObj)), Nullable<chip::NodeId>(getNodeId(commandObj)),
credentials, success);
// Failed Unlatch requests SHALL generate only a LockOperationError event with LockOperationType set to Unlock
if (LockOperationTypeEnum::kUnlatch == opType)
{
opType = LockOperationTypeEnum::kUnlock;
}

// SHALL generate a LockOperation event with LockOperationType set to Unlatch when the unlatched state is reached and a
// LockOperation event with LockOperationType set to Unlock when the lock successfully completes the unlock. But as the current
// implementation here is sending LockOperation events immediately we're sending both events immediately.
// https://github.com/project-chip/connectedhomeip/issues/26925
if (LockOperationTypeEnum::kUnlatch == opType && success)
{
SendLockOperationEvent(endpoint, LockOperationTypeEnum::kUnlock, OperationSourceEnum::kRemote, reason, pinUserIdx,
SendLockOperationEvent(endpoint, opType, OperationSourceEnum::kRemote, reason, pinUserIdx,
Nullable<chip::FabricIndex>(getFabricIndex(commandObj)),
Nullable<chip::NodeId>(getNodeId(commandObj)), credentials, success);
}
Expand Down Expand Up @@ -3937,7 +3936,7 @@ void DoorLockServer::DoorLockOnAutoRelockCallback(System::Layer *, void * callba
{
ChipLogProgress(Zcl, "Door Auto relock timer expired. %s", "Locking...");

DoorLockServer::Instance().SetLockState(endpointId, DlLockState::kLocked, OperationSourceEnum::kAuto);
DoorLockServer::Instance().SetLockState(nullptr, endpointId, DlLockState::kLocked, OperationSourceEnum::kAuto);
emberAfPluginDoorLockOnAutoRelock(endpointId);
}
else
Expand Down
Loading

0 comments on commit cc6375a

Please sign in to comment.