Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the logic around schedule application in LockEndpoint. #31946

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions examples/lock-app/lock-common/include/LockEndpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,16 @@ class LockEndpoint
OperationSourceEnum opSource = OperationSourceEnum::kUnspecified);
const char * lockStateToString(DlLockState lockState) const;

bool weekDayScheduleInAction(uint16_t userIndex) const;
bool yearDayScheduleInAction(uint16_t userIndex) const;
// Returns true if week day schedules should apply to the user, there are
// schedules defined for the user, and access is not currently allowed by
// those schedules. The outparam indicates whether there were in fact any
// year day schedules defined for the user.
bool weekDayScheduleForbidsAccess(uint16_t userIndex, bool * haveSchedule) const;
// Returns true if year day schedules should apply to the user, there are
// schedules defined for the user, and access is not currently allowed by
// those schedules. The outparam indicates whether there were in fact any
// year day schedules defined for the user.
bool yearDayScheduleForbidsAccess(uint16_t userIndex, bool * haveSchedule) const;

static void OnLockActionCompleteCallback(chip::System::Layer *, void * callbackContext);

Expand Down
73 changes: 48 additions & 25 deletions examples/lock-app/lock-common/src/LockEndpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,19 +488,20 @@ bool LockEndpoint::setLockState(const Nullable<chip::FabricIndex> & fabricIdx, c
auto userIndex = static_cast<uint8_t>(user - mLockUsers.begin());

// Check if schedules affect the user
if ((user->userType == UserTypeEnum::kScheduleRestrictedUser || user->userType == UserTypeEnum::kWeekDayScheduleUser) &&
!weekDayScheduleInAction(userIndex))
bool haveWeekDaySchedules = false;
bool haveYearDaySchedules = false;
if (weekDayScheduleForbidsAccess(userIndex, &haveWeekDaySchedules) ||
yearDayScheduleForbidsAccess(userIndex, &haveYearDaySchedules) ||
// Also disallow access for a user that's supposed to have _some_
// schedule but doesn't have any
(user->userType == UserTypeEnum::kScheduleRestrictedUser && !haveWeekDaySchedules && !haveYearDaySchedules))
{
if ((user->userType == UserTypeEnum::kScheduleRestrictedUser || user->userType == UserTypeEnum::kYearDayScheduleUser) &&
!yearDayScheduleInAction(userIndex))
{
ChipLogDetail(Zcl,
"Lock App: associated user is not allowed to operate the lock due to schedules"
"[endpointId=%d,userIndex=%u]",
mEndpointId, userIndex);
err = OperationErrorEnum::kRestricted;
return false;
}
ChipLogDetail(Zcl,
"Lock App: associated user is not allowed to operate the lock due to schedules"
"[endpointId=%d,userIndex=%u]",
mEndpointId, userIndex);
err = OperationErrorEnum::kRestricted;
return false;
}
ChipLogProgress(
Zcl,
Expand Down Expand Up @@ -561,12 +562,23 @@ void LockEndpoint::OnLockActionCompleteCallback(chip::System::Layer *, void * ca
}
}

bool LockEndpoint::weekDayScheduleInAction(uint16_t userIndex) const
bool LockEndpoint::weekDayScheduleForbidsAccess(uint16_t userIndex, bool * haveSchedule) const
{
*haveSchedule = std::any_of(mWeekDaySchedules[userIndex].begin(), mWeekDaySchedules[userIndex].end(),
[](const WeekDaysScheduleInfo & s) { return s.status == DlScheduleStatus::kOccupied; });

const auto & user = mLockUsers[userIndex];
if (user.userType != UserTypeEnum::kScheduleRestrictedUser && user.userType != UserTypeEnum::kWeekDayScheduleUser)
{
return true;
// Weekday schedules don't apply to this user.
return false;
}

if (user.userType == UserTypeEnum::kScheduleRestrictedUser && !*haveSchedule)
{
// It's valid to not have any schedules of a given type; on its own this
// does not prevent access.
return false;
}

chip::System::Clock::Milliseconds64 cTMs;
Expand All @@ -575,7 +587,7 @@ bool LockEndpoint::weekDayScheduleInAction(uint16_t userIndex) const
{
ChipLogError(Zcl, "Lock App: unable to get current time to check user schedules [endpointId=%d,error=%d (%s)]", mEndpointId,
chipError.AsInteger(), chipError.AsString());
return false;
return true;
}
time_t unixEpoch = std::chrono::duration_cast<chip::System::Clock::Seconds32>(cTMs).count();

Expand All @@ -585,8 +597,9 @@ bool LockEndpoint::weekDayScheduleInAction(uint16_t userIndex) const
auto currentTime =
calendarTime.tm_hour * chip::kSecondsPerHour + calendarTime.tm_min * chip::kSecondsPerMinute + calendarTime.tm_sec;

// Second, check the week day schedules.
return std::any_of(
// Now check whether any schedule allows the current time. If it does,
// access is not forbidden.
return !std::any_of(
mWeekDaySchedules[userIndex].begin(), mWeekDaySchedules[userIndex].end(),
[currentTime, calendarTime](const WeekDaysScheduleInfo & s) {
auto startTime = s.schedule.startHour * chip::kSecondsPerHour + s.schedule.startMinute * chip::kSecondsPerMinute;
Expand All @@ -596,12 +609,22 @@ bool LockEndpoint::weekDayScheduleInAction(uint16_t userIndex) const
});
}

bool LockEndpoint::yearDayScheduleInAction(uint16_t userIndex) const
bool LockEndpoint::yearDayScheduleForbidsAccess(uint16_t userIndex, bool * haveSchedule) const
{
*haveSchedule = std::any_of(mYearDaySchedules[userIndex].begin(), mYearDaySchedules[userIndex].end(),
[](const YearDayScheduleInfo & sch) { return sch.status == DlScheduleStatus::kOccupied; });

const auto & user = mLockUsers[userIndex];
if (user.userType != UserTypeEnum::kScheduleRestrictedUser && user.userType != UserTypeEnum::kYearDayScheduleUser)
{
return true;
return false;
}

if (user.userType == UserTypeEnum::kScheduleRestrictedUser && !*haveSchedule)
{
// It's valid to not have any schedules of a given type; on its own this
// does not prevent access.
return false;
}

chip::System::Clock::Milliseconds64 cTMs;
Expand All @@ -610,7 +633,7 @@ bool LockEndpoint::yearDayScheduleInAction(uint16_t userIndex) const
{
ChipLogError(Zcl, "Lock App: unable to get current time to check user schedules [endpointId=%d,error=%d (%s)]", mEndpointId,
chipError.AsInteger(), chipError.AsString());
return false;
return true;
}
auto unixEpoch = std::chrono::duration_cast<chip::System::Clock::Seconds32>(cTMs).count();
uint32_t chipEpoch = 0;
Expand All @@ -623,11 +646,11 @@ bool LockEndpoint::yearDayScheduleInAction(uint16_t userIndex) const
return false;
}

return std::any_of(mYearDaySchedules[userIndex].begin(), mYearDaySchedules[userIndex].end(),
[chipEpoch](const YearDayScheduleInfo & sch) {
return sch.status == DlScheduleStatus::kOccupied && sch.schedule.localStartTime <= chipEpoch &&
chipEpoch <= sch.schedule.localEndTime;
});
return !std::any_of(mYearDaySchedules[userIndex].begin(), mYearDaySchedules[userIndex].end(),
[chipEpoch](const YearDayScheduleInfo & sch) {
return sch.status == DlScheduleStatus::kOccupied && sch.schedule.localStartTime <= chipEpoch &&
chipEpoch <= sch.schedule.localEndTime;
});
}

const char * LockEndpoint::lockStateToString(DlLockState lockState) const
Expand Down
Loading