Skip to content

Commit 3e35809

Browse files
Improve the logic around schedule application in LockEndpoint.
The old logic had several bugs: * For kYearDayScheduleUser users, there was no schedule enforcement at all, since the outer "if" never tested true. * For kWeekDayScheduleUser users, there was no schedule enforcement at all, since the inner "if" never tested true. * For kScheduleRestrictedUser users, access was allowed if there was any schedule, weekday or yearday, that granted access. But the intent is that access should be disallowed if there are year day schedules and none of them grants access, no matter what's going on with weekday. And vice versa.
1 parent cc56f66 commit 3e35809

File tree

2 files changed

+58
-27
lines changed

2 files changed

+58
-27
lines changed

examples/lock-app/lock-common/include/LockEndpoint.h

+10-2
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,16 @@ class LockEndpoint
106106
OperationSourceEnum opSource = OperationSourceEnum::kUnspecified);
107107
const char * lockStateToString(DlLockState lockState) const;
108108

109-
bool weekDayScheduleInAction(uint16_t userIndex) const;
110-
bool yearDayScheduleInAction(uint16_t userIndex) const;
109+
// Returns true if week day schedules should apply to the user, there are
110+
// schedules defined for the user, and access is not currently allowed by
111+
// those schedules. The outparam indicates whether there were in fact any
112+
// year day schedules defined for the user.
113+
bool weekDayScheduleForbidsAccess(uint16_t userIndex, bool * haveSchedule) const;
114+
// Returns true if year day schedules should apply to the user, there are
115+
// schedules defined for the user, and access is not currently allowed by
116+
// those schedules. The outparam indicates whether there were in fact any
117+
// year day schedules defined for the user.
118+
bool yearDayScheduleForbidsAccess(uint16_t userIndex, bool * haveSchedule) const;
111119

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

examples/lock-app/lock-common/src/LockEndpoint.cpp

+48-25
Original file line numberDiff line numberDiff line change
@@ -488,19 +488,20 @@ bool LockEndpoint::setLockState(const Nullable<chip::FabricIndex> & fabricIdx, c
488488
auto userIndex = static_cast<uint8_t>(user - mLockUsers.begin());
489489

490490
// Check if schedules affect the user
491-
if ((user->userType == UserTypeEnum::kScheduleRestrictedUser || user->userType == UserTypeEnum::kWeekDayScheduleUser) &&
492-
!weekDayScheduleInAction(userIndex))
491+
bool haveWeekDaySchedules = false;
492+
bool haveYearDaySchedules = false;
493+
if (weekDayScheduleForbidsAccess(userIndex, &haveWeekDaySchedules) ||
494+
yearDayScheduleForbidsAccess(userIndex, &haveYearDaySchedules) ||
495+
// Also disallow access for a user that's supposed to have _some_
496+
// schedule but doesn't have any
497+
(user->userType == UserTypeEnum::kScheduleRestrictedUser && !haveWeekDaySchedules && !haveYearDaySchedules))
493498
{
494-
if ((user->userType == UserTypeEnum::kScheduleRestrictedUser || user->userType == UserTypeEnum::kYearDayScheduleUser) &&
495-
!yearDayScheduleInAction(userIndex))
496-
{
497-
ChipLogDetail(Zcl,
498-
"Lock App: associated user is not allowed to operate the lock due to schedules"
499-
"[endpointId=%d,userIndex=%u]",
500-
mEndpointId, userIndex);
501-
err = OperationErrorEnum::kRestricted;
502-
return false;
503-
}
499+
ChipLogDetail(Zcl,
500+
"Lock App: associated user is not allowed to operate the lock due to schedules"
501+
"[endpointId=%d,userIndex=%u]",
502+
mEndpointId, userIndex);
503+
err = OperationErrorEnum::kRestricted;
504+
return false;
504505
}
505506
ChipLogProgress(
506507
Zcl,
@@ -561,12 +562,23 @@ void LockEndpoint::OnLockActionCompleteCallback(chip::System::Layer *, void * ca
561562
}
562563
}
563564

564-
bool LockEndpoint::weekDayScheduleInAction(uint16_t userIndex) const
565+
bool LockEndpoint::weekDayScheduleForbidsAccess(uint16_t userIndex, bool * haveSchedule) const
565566
{
567+
*haveSchedule = std::any_of(mWeekDaySchedules[userIndex].begin(), mWeekDaySchedules[userIndex].end(),
568+
[](const WeekDaysScheduleInfo & s) { return s.status == DlScheduleStatus::kOccupied; });
569+
566570
const auto & user = mLockUsers[userIndex];
567571
if (user.userType != UserTypeEnum::kScheduleRestrictedUser && user.userType != UserTypeEnum::kWeekDayScheduleUser)
568572
{
569-
return true;
573+
// Weekday schedules don't apply to this user.
574+
return false;
575+
}
576+
577+
if (user.userType == UserTypeEnum::kScheduleRestrictedUser && !*haveSchedule)
578+
{
579+
// It's valid to not have any schedules of a given type; on its own this
580+
// does not prevent access.
581+
return false;
570582
}
571583

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

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

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

599-
bool LockEndpoint::yearDayScheduleInAction(uint16_t userIndex) const
612+
bool LockEndpoint::yearDayScheduleForbidsAccess(uint16_t userIndex, bool * haveSchedule) const
600613
{
614+
*haveSchedule = std::any_of(mYearDaySchedules[userIndex].begin(), mYearDaySchedules[userIndex].end(),
615+
[](const YearDayScheduleInfo & sch) { return sch.status == DlScheduleStatus::kOccupied; });
616+
601617
const auto & user = mLockUsers[userIndex];
602618
if (user.userType != UserTypeEnum::kScheduleRestrictedUser && user.userType != UserTypeEnum::kYearDayScheduleUser)
603619
{
604-
return true;
620+
return false;
621+
}
622+
623+
if (user.userType == UserTypeEnum::kScheduleRestrictedUser && !*haveSchedule)
624+
{
625+
// It's valid to not have any schedules of a given type; on its own this
626+
// does not prevent access.
627+
return false;
605628
}
606629

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

626-
return std::any_of(mYearDaySchedules[userIndex].begin(), mYearDaySchedules[userIndex].end(),
627-
[chipEpoch](const YearDayScheduleInfo & sch) {
628-
return sch.status == DlScheduleStatus::kOccupied && sch.schedule.localStartTime <= chipEpoch &&
629-
chipEpoch <= sch.schedule.localEndTime;
630-
});
649+
return !std::any_of(mYearDaySchedules[userIndex].begin(), mYearDaySchedules[userIndex].end(),
650+
[chipEpoch](const YearDayScheduleInfo & sch) {
651+
return sch.status == DlScheduleStatus::kOccupied && sch.schedule.localStartTime <= chipEpoch &&
652+
chipEpoch <= sch.schedule.localEndTime;
653+
});
631654
}
632655

633656
const char * LockEndpoint::lockStateToString(DlLockState lockState) const

0 commit comments

Comments
 (0)