diff --git a/examples/lock-app/silabs/include/LockManager.h b/examples/lock-app/silabs/include/LockManager.h index 671aedb81c4e56..1334a84fd29d7c 100644 --- a/examples/lock-app/silabs/include/LockManager.h +++ b/examples/lock-app/silabs/include/LockManager.h @@ -27,7 +27,9 @@ #include #include -struct WeekDaysScheduleInfo +#include + +struct WeekDayScheduleInfo { DlScheduleStatus status; EmberAfPluginDoorLockWeekDaySchedule schedule; @@ -112,6 +114,30 @@ class ParamBuilder using namespace ::chip; using namespace EFR32DoorLock::ResourceRanges; +struct LockUserInfo +{ + char userName[DOOR_LOCK_USER_NAME_BUFFER_SIZE]; + size_t userNameSize; + uint32_t userUniqueId; + UserStatusEnum userStatus; + UserTypeEnum userType; + CredentialRuleEnum credentialRule; + chip::EndpointId endpointId; + chip::FabricIndex createdBy; + chip::FabricIndex lastModifiedBy; + uint16_t currentCredentialCount; +}; + +struct LockCredentialInfo +{ + DlCredentialStatus status; + CredentialTypeEnum credentialType; + chip::FabricIndex createdBy; + chip::FabricIndex lastModifiedBy; + uint8_t credentialData[kMaxCredentialSize]; + size_t credentialDataSize; +}; + class LockManager { public: @@ -192,8 +218,6 @@ class LockManager OperationErrorEnum & err); const char * lockStateToString(DlLockState lockState) const; - bool ReadConfigValues(); - void UnlockAfterUnlatch(); private: @@ -244,17 +268,24 @@ class LockManager static void ActuatorMovementTimerEventHandler(AppEvent * aEvent); osTimerId_t mLockTimer; - EmberAfPluginDoorLockUserInfo mLockUsers[kMaxUsers]; - EmberAfPluginDoorLockCredentialInfo mLockCredentials[kNumCredentialTypes][kMaxCredentials]; - WeekDaysScheduleInfo mWeekdaySchedule[kMaxUsers][kMaxWeekdaySchedulesPerUser]; - YearDayScheduleInfo mYeardaySchedule[kMaxUsers][kMaxYeardaySchedulesPerUser]; - HolidayScheduleInfo mHolidaySchedule[kMaxHolidaySchedules]; - - char mUserNames[MATTER_ARRAY_SIZE(mLockUsers)][DOOR_LOCK_MAX_USER_NAME_SIZE]; - uint8_t mCredentialData[kNumCredentialTypes][kMaxCredentials][kMaxCredentialSize]; - CredentialStruct mCredentials[kMaxUsers][kMaxCredentials]; EFR32DoorLock::LockInitParams::LockParam LockParams; + + static StorageKeyName LockUserEndpoint(uint16_t userIndex, chip::EndpointId endpoint) { return StorageKeyName::Formatted("g/lu/%x/e/%x", userIndex, endpoint); } + static StorageKeyName LockCredentialEndpoint(uint16_t credentialIndex, chip::EndpointId endpoint) { return StorageKeyName::Formatted("g/lc/%x/e/%x", credentialIndex, endpoint); } + static StorageKeyName LockUserCredentialMap(uint16_t userIndex) { return StorageKeyName::Formatted("g/lu/%x/lc", userIndex); } // Stores all the credential indices that belong to a user + static StorageKeyName LockUserWeekDayScheduleEndpoint(uint16_t userIndex, uint16_t scheduleIndex, chip::EndpointId endpoint) { return StorageKeyName::Formatted("g/lu/%x/lw/%x/e/%x", userIndex, scheduleIndex, endpoint); } + static StorageKeyName LockUserYearDayScheduleEndpoint(uint16_t userIndex, uint16_t scheduleIndex, chip::EndpointId endpoint) { return StorageKeyName::Formatted("g/lu/%x/ly/%x/e/%x", userIndex, scheduleIndex, endpoint); } + static StorageKeyName LockHolidayScheduleEndpoint(uint16_t scheduleIndex, chip::EndpointId endpoint) { return StorageKeyName::Formatted("g/lh/%x/e/%x", scheduleIndex, endpoint); } + + LockUserInfo userInStorage; + LockCredentialInfo credentialInStorage; + WeekDayScheduleInfo weekDayScheduleInStorage; + YearDayScheduleInfo yearDayScheduleInStorage; + HolidayScheduleInfo holidayScheduleInStorage; + CredentialStruct mCredential; + CredentialStruct mCredentials[kMaxCredentialsPerUser]; + }; LockManager & LockMgr(); diff --git a/examples/lock-app/silabs/src/AppTask.cpp b/examples/lock-app/silabs/src/AppTask.cpp index 3dd0a0ba7c9c69..78cac4b8eef312 100644 --- a/examples/lock-app/silabs/src/AppTask.cpp +++ b/examples/lock-app/silabs/src/AppTask.cpp @@ -37,9 +37,9 @@ #include #include +#include #include #include -#include #include @@ -266,8 +266,6 @@ void AppTask::AppTaskMain(void * pvParameter) SILABS_LOG("App Task started"); - // Users and credentials should be checked once from nvm flash on boot - LockMgr().ReadConfigValues(); while (true) { @@ -412,3 +410,4 @@ void AppTask::UpdateClusterState(intptr_t context) SILABS_LOG("ERR: updating lock state %x", to_underlying(status)); } } + \ No newline at end of file diff --git a/examples/lock-app/silabs/src/LockManager.cpp b/examples/lock-app/silabs/src/LockManager.cpp index 66050da62a1bec..f2643ac13b5270 100644 --- a/examples/lock-app/silabs/src/LockManager.cpp +++ b/examples/lock-app/silabs/src/LockManager.cpp @@ -21,10 +21,12 @@ #include "AppConfig.h" #include "AppTask.h" +#include #include #include #include +using chip::app::DataModel::MakeNullable; using namespace ::chip::DeviceLayer::Internal; using namespace EFR32DoorLock::LockInitParams; @@ -136,41 +138,6 @@ bool LockManager::IsValidHolidayScheduleIndex(uint8_t scheduleIndex) return (scheduleIndex < kMaxHolidaySchedules); } -bool LockManager::ReadConfigValues() -{ - size_t outLen; - SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_LockUser, reinterpret_cast(&mLockUsers), - sizeof(EmberAfPluginDoorLockUserInfo) * MATTER_ARRAY_SIZE(mLockUsers), outLen); - - SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_Credential, reinterpret_cast(&mLockCredentials), - sizeof(EmberAfPluginDoorLockCredentialInfo) * kMaxCredentials * kNumCredentialTypes, outLen); - - SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_LockUserName, reinterpret_cast(mUserNames), - sizeof(mUserNames), outLen); - - SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_CredentialData, reinterpret_cast(mCredentialData), - sizeof(mCredentialData), outLen); - - SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_UserCredentials, reinterpret_cast(mCredentials), - sizeof(CredentialStruct) * LockParams.numberOfUsers * LockParams.numberOfCredentialsPerUser, - outLen); - - SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_WeekDaySchedules, reinterpret_cast(mWeekdaySchedule), - sizeof(EmberAfPluginDoorLockWeekDaySchedule) * LockParams.numberOfWeekdaySchedulesPerUser * - LockParams.numberOfUsers, - outLen); - - SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_YearDaySchedules, reinterpret_cast(mYeardaySchedule), - sizeof(EmberAfPluginDoorLockYearDaySchedule) * LockParams.numberOfYeardaySchedulesPerUser * - LockParams.numberOfUsers, - outLen); - - SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_HolidaySchedules, reinterpret_cast(&(mHolidaySchedule)), - sizeof(EmberAfPluginDoorLockHolidaySchedule) * LockParams.numberOfHolidaySchedules, outLen); - - return true; -} - void LockManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB) { mActionInitiated_CB = aActionInitiated_CB; @@ -353,6 +320,8 @@ bool LockManager::Unbolt(chip::EndpointId endpointId, const Nullable 0, false); // indices are one-indexed userIndex--; @@ -361,26 +330,70 @@ bool LockManager::GetUser(chip::EndpointId endpointId, uint16_t userIndex, Ember ChipLogProgress(Zcl, "Door Lock App: LockManager::GetUser [endpoint=%d,userIndex=%hu]", endpointId, userIndex); - const auto & userInDb = mLockUsers[userIndex]; + chip::StorageKeyName userKey = LockUserEndpoint(userIndex, endpointId); + + uint16_t size = static_cast(sizeof(LockUserInfo)); - user.userStatus = userInDb.userStatus; - if (UserStatusEnum::kAvailable == user.userStatus) + error = chip::Server::GetInstance().GetPersistentStorage().SyncGetKeyValue(userKey.KeyName(), &userInStorage, size); + // If no data is found at user key + if(error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) { - ChipLogDetail(Zcl, "Found unoccupied user [endpoint=%d]", endpointId); + user.userStatus = UserStatusEnum::kAvailable; + + ChipLogError(Zcl, "No user data found"); return true; } + // Else if KVS read was successful + else if(error == CHIP_NO_ERROR) + { + user.userStatus = userInStorage.userStatus; - user.userName = chip::CharSpan(userInDb.userName.data(), userInDb.userName.size()); - user.credentials = chip::Span(mCredentials[userIndex], userInDb.credentials.size()); - user.userUniqueId = userInDb.userUniqueId; - user.userType = userInDb.userType; - user.credentialRule = userInDb.credentialRule; + if(userInStorage.userStatus == UserStatusEnum::kAvailable) + { + ChipLogDetail(Zcl, "Found unoccupied user [endpoint=%d]", endpointId); + return true; + } + + } + else + { + ChipLogError(Zcl, "Error reading from KVS key"); + return false; + } + + user.userName = chip::CharSpan(userInStorage.userName, userInStorage.userNameSize); + user.userUniqueId = userInStorage.userUniqueId; + user.userType = userInStorage.userType; + user.credentialRule = userInStorage.credentialRule; // So far there's no way to actually create the credential outside Matter, so here we always set the creation/modification // source to Matter user.creationSource = DlAssetSource::kMatterIM; - user.createdBy = userInDb.createdBy; + user.createdBy = userInStorage.createdBy; user.modificationSource = DlAssetSource::kMatterIM; - user.lastModifiedBy = userInDb.lastModifiedBy; + user.lastModifiedBy = userInStorage.lastModifiedBy; + + // Get credential struct from nvm3 + chip::StorageKeyName credentialKey = LockUserCredentialMap(userIndex); + + uint16_t credentialSize = static_cast(sizeof(CredentialStruct)*userInStorage.currentCredentialCount); + + error = chip::Server::GetInstance().GetPersistentStorage().SyncGetKeyValue(credentialKey.KeyName(), &mCredential, credentialSize); + + // If no data is found at credential key + if(error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + // No credentials found for this user + } + // Else if KVS read was successful + else if(error == CHIP_NO_ERROR) + { + user.credentials = chip::Span {&mCredential, userInStorage.currentCredentialCount}; + } + else + { + ChipLogError(Zcl, "Error reading KVS key"); + return false; + } ChipLogDetail(Zcl, "Found occupied user " @@ -397,6 +410,9 @@ bool LockManager::SetUser(chip::EndpointId endpointId, uint16_t userIndex, chip: const chip::CharSpan & userName, uint32_t uniqueId, UserStatusEnum userStatus, UserTypeEnum usertype, CredentialRuleEnum credentialRule, const CredentialStruct * credentials, size_t totalCredentials) { + + CHIP_ERROR error; + ChipLogProgress(Zcl, "Door Lock App: LockManager::SetUser " "[endpoint=%d,userIndex=%d,creator=%d,modifier=%d,userName=%s,uniqueId=%ld " @@ -409,8 +425,8 @@ bool LockManager::SetUser(chip::EndpointId endpointId, uint16_t userIndex, chip: userIndex--; VerifyOrReturnValue(IsValidUserIndex(userIndex), false); - - auto & userInStorage = mLockUsers[userIndex]; + + VerifyOrReturnValue(kInvalidEndpointId != endpointId, false); if (userName.size() > DOOR_LOCK_MAX_USER_NAME_SIZE) { @@ -425,8 +441,8 @@ bool LockManager::SetUser(chip::EndpointId endpointId, uint16_t userIndex, chip: return false; } - chip::Platform::CopyString(mUserNames[userIndex], userName); - userInStorage.userName = chip::CharSpan(mUserNames[userIndex], userName.size()); + chip::Platform::CopyString(userInStorage.userName, userName.data()); + userInStorage.userNameSize = userName.size(); userInStorage.userUniqueId = uniqueId; userInStorage.userStatus = userStatus; userInStorage.userType = usertype; @@ -434,22 +450,29 @@ bool LockManager::SetUser(chip::EndpointId endpointId, uint16_t userIndex, chip: userInStorage.lastModifiedBy = modifier; userInStorage.createdBy = creator; - for (size_t i = 0; i < totalCredentials; ++i) - { - mCredentials[userIndex][i] = credentials[i]; - } + userInStorage.currentCredentialCount = totalCredentials; - userInStorage.credentials = chip::Span(mCredentials[userIndex], totalCredentials); + // Save credential struct in nvm3 + chip::StorageKeyName credentialKey = LockUserCredentialMap(userIndex); - // Save user information in NVM flash - SilabsConfig::WriteConfigValueBin(SilabsConfig::kConfigKey_LockUser, reinterpret_cast(&mLockUsers), - sizeof(EmberAfPluginDoorLockUserInfo) * LockParams.numberOfUsers); + error = chip::Server::GetInstance().GetPersistentStorage().SyncSetKeyValue(credentialKey.KeyName(), credentials, static_cast(sizeof(CredentialStruct)*totalCredentials)); + + if((error != CHIP_NO_ERROR)) + { + ChipLogError(Zcl, "Error reading from KVS key"); + return false; + } + + // Save user in nvm3 + chip::StorageKeyName userKey = LockUserEndpoint(userIndex, endpointId); - SilabsConfig::WriteConfigValueBin(SilabsConfig::kConfigKey_UserCredentials, reinterpret_cast(mCredentials), - sizeof(CredentialStruct) * LockParams.numberOfUsers * LockParams.numberOfCredentialsPerUser); + error = chip::Server::GetInstance().GetPersistentStorage().SyncSetKeyValue(userKey.KeyName(), &userInStorage, static_cast(sizeof(LockUserInfo))); - SilabsConfig::WriteConfigValueBin(SilabsConfig::kConfigKey_LockUserName, reinterpret_cast(mUserNames), - sizeof(mUserNames)); + if((error != CHIP_NO_ERROR)) + { + ChipLogError(Zcl, "Error reading from KVS key"); + return false; + } ChipLogProgress(Zcl, "Successfully set the user [mEndpointId=%d,index=%d]", endpointId, userIndex); @@ -459,6 +482,7 @@ bool LockManager::SetUser(chip::EndpointId endpointId, uint16_t userIndex, chip: bool LockManager::GetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, CredentialTypeEnum credentialType, EmberAfPluginDoorLockCredentialInfo & credential) { + CHIP_ERROR error; VerifyOrReturnValue(IsValidCredentialType(credentialType), false); @@ -475,10 +499,32 @@ bool LockManager::GetCredential(chip::EndpointId endpointId, uint16_t credential ChipLogProgress(Zcl, "Lock App: LockManager::GetCredential [credentialType=%u], credentialIndex=%d", to_underlying(credentialType), credentialIndex); - const auto & credentialInStorage = mLockCredentials[to_underlying(credentialType)][credentialIndex]; + uint16_t size = static_cast(sizeof(LockCredentialInfo)); - credential.status = credentialInStorage.status; - ChipLogDetail(Zcl, "CredentialStatus: %d, CredentialIndex: %d ", (int) credential.status, credentialIndex); + chip::StorageKeyName key = LockCredentialEndpoint(credentialIndex, endpointId); + + error = chip::Server::GetInstance().GetPersistentStorage().SyncGetKeyValue(key.KeyName(), &credentialInStorage, size); + + // If no data is found at credential key + if(error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + // No credentials found + credential.status = DlCredentialStatus::kAvailable; + + return true; + } + // Else if KVS read was successful + else if(error == CHIP_NO_ERROR) + { + credential.status = credentialInStorage.status; + ChipLogDetail(Zcl, "CredentialStatus: %d, CredentialIndex: %d ", (int) credential.status, credentialIndex); + + } + else + { + ChipLogError(Zcl, "Error reading KVS key"); + return false; + } if (DlCredentialStatus::kAvailable == credential.status) { @@ -486,7 +532,7 @@ bool LockManager::GetCredential(chip::EndpointId endpointId, uint16_t credential return true; } credential.credentialType = credentialInStorage.credentialType; - credential.credentialData = credentialInStorage.credentialData; + credential.credentialData = chip::ByteSpan{ credentialInStorage.credentialData, credentialInStorage.credentialDataSize }; credential.createdBy = credentialInStorage.createdBy; credential.lastModifiedBy = credentialInStorage.lastModifiedBy; // So far there's no way to actually create the credential outside Matter, so here we always set the creation/modification @@ -504,6 +550,7 @@ bool LockManager::SetCredential(chip::EndpointId endpointId, uint16_t credential chip::FabricIndex modifier, DlCredentialStatus credentialStatus, CredentialTypeEnum credentialType, const chip::ByteSpan & credentialData) { + CHIP_ERROR error; VerifyOrReturnValue(IsValidCredentialType(credentialType), false); @@ -522,23 +569,29 @@ bool LockManager::SetCredential(chip::EndpointId endpointId, uint16_t credential "[credentialStatus=%u,credentialType=%u,credentialDataSize=%u,creator=%d,modifier=%d]", to_underlying(credentialStatus), to_underlying(credentialType), credentialData.size(), creator, modifier); - auto & credentialInStorage = mLockCredentials[to_underlying(credentialType)][credentialIndex]; - credentialInStorage.status = credentialStatus; credentialInStorage.credentialType = credentialType; credentialInStorage.createdBy = creator; credentialInStorage.lastModifiedBy = modifier; + credentialInStorage.credentialDataSize = credentialData.size(); - memcpy(mCredentialData[to_underlying(credentialType)][credentialIndex], credentialData.data(), credentialData.size()); - credentialInStorage.credentialData = - chip::ByteSpan{ mCredentialData[to_underlying(credentialType)][credentialIndex], credentialData.size() }; + memcpy(credentialInStorage.credentialData, credentialData.data(), credentialInStorage.credentialDataSize); - // Save credential information in NVM flash - SilabsConfig::WriteConfigValueBin(SilabsConfig::kConfigKey_Credential, reinterpret_cast(&mLockCredentials), - sizeof(EmberAfPluginDoorLockCredentialInfo) * kMaxCredentials * kNumCredentialTypes); + chip::StorageKeyName key = LockCredentialEndpoint(credentialIndex, endpointId); - SilabsConfig::WriteConfigValueBin(SilabsConfig::kConfigKey_CredentialData, reinterpret_cast(&mCredentialData), - sizeof(mCredentialData)); + if((error != CHIP_NO_ERROR)) + { + ChipLogError(Zcl, "Error reading from KVS key"); + return false; + } + + chip::Server::GetInstance().GetPersistentStorage().SyncSetKeyValue(key.KeyName(), &credentialInStorage, static_cast(sizeof(LockCredentialInfo))); + + if((error != CHIP_NO_ERROR)) + { + ChipLogError(Zcl, "Error reading from KVS key"); + return false; + } ChipLogProgress(Zcl, "Successfully set the credential [credentialType=%u]", to_underlying(credentialType)); @@ -548,6 +601,7 @@ bool LockManager::SetCredential(chip::EndpointId endpointId, uint16_t credential DlStatus LockManager::GetWeekdaySchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex, EmberAfPluginDoorLockWeekDaySchedule & schedule) { + CHIP_ERROR error; VerifyOrReturnValue(weekdayIndex > 0, DlStatus::kFailure); // indices are one-indexed VerifyOrReturnValue(userIndex > 0, DlStatus::kFailure); // indices are one-indexed @@ -558,13 +612,36 @@ DlStatus LockManager::GetWeekdaySchedule(chip::EndpointId endpointId, uint8_t we VerifyOrReturnValue(IsValidWeekdayScheduleIndex(weekdayIndex), DlStatus::kFailure); VerifyOrReturnValue(IsValidUserIndex(userIndex), DlStatus::kFailure); - const auto & scheduleInStorage = mWeekdaySchedule[userIndex][weekdayIndex]; - if (DlScheduleStatus::kAvailable == scheduleInStorage.status) + // Get schedule data from nvm3 + chip::StorageKeyName scheduleDataKey = LockUserWeekDayScheduleEndpoint(userIndex, weekdayIndex, endpointId); + + uint16_t scheduleSize = static_cast(sizeof(WeekDayScheduleInfo)); + + error = chip::Server::GetInstance().GetPersistentStorage().SyncGetKeyValue(scheduleDataKey.KeyName(), &weekDayScheduleInStorage, scheduleSize); + + // If no data is found at scheduleUserMapKey key + if(error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) { + ChipLogError(Zcl, "No schedule data found for user"); return DlStatus::kNotFound; } + // Else if KVS read was successful + else if(error == CHIP_NO_ERROR) + { + + if (weekDayScheduleInStorage.status == DlScheduleStatus::kAvailable) + { + return DlStatus::kNotFound; + } + + } + else + { + ChipLogError(Zcl, "Error reading from KVS key"); + return DlStatus::kFailure; + } - schedule = scheduleInStorage.schedule; + schedule = weekDayScheduleInStorage.schedule; return DlStatus::kSuccess; } @@ -573,6 +650,7 @@ DlStatus LockManager::SetWeekdaySchedule(chip::EndpointId endpointId, uint8_t we DlScheduleStatus status, DaysMaskMap daysMask, uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute) { + CHIP_ERROR error; VerifyOrReturnValue(weekdayIndex > 0, DlStatus::kFailure); // indices are one-indexed VerifyOrReturnValue(userIndex > 0, DlStatus::kFailure); // indices are one-indexed @@ -583,19 +661,23 @@ DlStatus LockManager::SetWeekdaySchedule(chip::EndpointId endpointId, uint8_t we VerifyOrReturnValue(IsValidWeekdayScheduleIndex(weekdayIndex), DlStatus::kFailure); VerifyOrReturnValue(IsValidUserIndex(userIndex), DlStatus::kFailure); - auto & scheduleInStorage = mWeekdaySchedule[userIndex][weekdayIndex]; + weekDayScheduleInStorage.schedule.daysMask = daysMask; + weekDayScheduleInStorage.schedule.startHour = startHour; + weekDayScheduleInStorage.schedule.startMinute = startMinute; + weekDayScheduleInStorage.schedule.endHour = endHour; + weekDayScheduleInStorage.schedule.endMinute = endMinute; + weekDayScheduleInStorage.status = status; + + // Save schedule data in nvm3 + chip::StorageKeyName scheduleDataKey = LockUserWeekDayScheduleEndpoint(userIndex, weekdayIndex, endpointId); - scheduleInStorage.schedule.daysMask = daysMask; - scheduleInStorage.schedule.startHour = startHour; - scheduleInStorage.schedule.startMinute = startMinute; - scheduleInStorage.schedule.endHour = endHour; - scheduleInStorage.schedule.endMinute = endMinute; - scheduleInStorage.status = status; + error = chip::Server::GetInstance().GetPersistentStorage().SyncSetKeyValue(scheduleDataKey.KeyName(), &weekDayScheduleInStorage, static_cast(sizeof(WeekDayScheduleInfo))); - // Save schedule information in NVM flash - SilabsConfig::WriteConfigValueBin( - SilabsConfig::kConfigKey_WeekDaySchedules, reinterpret_cast(mWeekdaySchedule), - sizeof(EmberAfPluginDoorLockWeekDaySchedule) * LockParams.numberOfWeekdaySchedulesPerUser * LockParams.numberOfUsers); + if((error != CHIP_NO_ERROR)) + { + ChipLogError(Zcl, "Error reading from KVS key"); + return DlStatus::kFailure; + } return DlStatus::kSuccess; } @@ -603,6 +685,8 @@ DlStatus LockManager::SetWeekdaySchedule(chip::EndpointId endpointId, uint8_t we DlStatus LockManager::GetYeardaySchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex, EmberAfPluginDoorLockYearDaySchedule & schedule) { + CHIP_ERROR error; + VerifyOrReturnValue(yearDayIndex > 0, DlStatus::kFailure); // indices are one-indexed VerifyOrReturnValue(userIndex > 0, DlStatus::kFailure); // indices are one-indexed @@ -612,13 +696,36 @@ DlStatus LockManager::GetYeardaySchedule(chip::EndpointId endpointId, uint8_t ye VerifyOrReturnValue(IsValidYeardayScheduleIndex(yearDayIndex), DlStatus::kFailure); VerifyOrReturnValue(IsValidUserIndex(userIndex), DlStatus::kFailure); - const auto & scheduleInStorage = mYeardaySchedule[userIndex][yearDayIndex]; - if (DlScheduleStatus::kAvailable == scheduleInStorage.status) + // Get schedule data from nvm3 + chip::StorageKeyName scheduleDataKey = LockUserYearDayScheduleEndpoint(userIndex, yearDayIndex, endpointId); + + uint16_t scheduleSize = static_cast(sizeof(YearDayScheduleInfo)); + + error = chip::Server::GetInstance().GetPersistentStorage().SyncGetKeyValue(scheduleDataKey.KeyName(), &yearDayScheduleInStorage, scheduleSize); + + // If no data is found at scheduleUserMapKey key + if(error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) { + ChipLogError(Zcl, "No schedule data found for user"); return DlStatus::kNotFound; } + // Else if KVS read was successful + else if(error == CHIP_NO_ERROR) + { - schedule = scheduleInStorage.schedule; + if (yearDayScheduleInStorage.status == DlScheduleStatus::kAvailable) + { + return DlStatus::kNotFound; + } + + } + else + { + ChipLogError(Zcl, "Error reading from KVS key"); + return DlStatus::kFailure; + } + + schedule = yearDayScheduleInStorage.schedule; return DlStatus::kSuccess; } @@ -626,6 +733,8 @@ DlStatus LockManager::GetYeardaySchedule(chip::EndpointId endpointId, uint8_t ye DlStatus LockManager::SetYeardaySchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex, DlScheduleStatus status, uint32_t localStartTime, uint32_t localEndTime) { + CHIP_ERROR error; + VerifyOrReturnValue(yearDayIndex > 0, DlStatus::kFailure); // indices are one-indexed VerifyOrReturnValue(userIndex > 0, DlStatus::kFailure); // indices are one-indexed @@ -635,16 +744,20 @@ DlStatus LockManager::SetYeardaySchedule(chip::EndpointId endpointId, uint8_t ye VerifyOrReturnValue(IsValidYeardayScheduleIndex(yearDayIndex), DlStatus::kFailure); VerifyOrReturnValue(IsValidUserIndex(userIndex), DlStatus::kFailure); - auto & scheduleInStorage = mYeardaySchedule[userIndex][yearDayIndex]; + yearDayScheduleInStorage.schedule.localStartTime = localStartTime; + yearDayScheduleInStorage.schedule.localEndTime = localEndTime; + yearDayScheduleInStorage.status = status; - scheduleInStorage.schedule.localStartTime = localStartTime; - scheduleInStorage.schedule.localEndTime = localEndTime; - scheduleInStorage.status = status; + // Save schedule data in nvm3 + chip::StorageKeyName scheduleDataKey = LockUserYearDayScheduleEndpoint(userIndex, yearDayIndex, endpointId); - // Save schedule information in NVM flash - SilabsConfig::WriteConfigValueBin( - SilabsConfig::kConfigKey_YearDaySchedules, reinterpret_cast(mYeardaySchedule), - sizeof(EmberAfPluginDoorLockYearDaySchedule) * LockParams.numberOfYeardaySchedulesPerUser * LockParams.numberOfUsers); + error = chip::Server::GetInstance().GetPersistentStorage().SyncSetKeyValue(scheduleDataKey.KeyName(), &yearDayScheduleInStorage, static_cast(sizeof(YearDayScheduleInfo))); + + if((error != CHIP_NO_ERROR)) + { + ChipLogError(Zcl, "Error reading from KVS key"); + return DlStatus::kFailure; + } return DlStatus::kSuccess; } @@ -652,19 +765,44 @@ DlStatus LockManager::SetYeardaySchedule(chip::EndpointId endpointId, uint8_t ye DlStatus LockManager::GetHolidaySchedule(chip::EndpointId endpointId, uint8_t holidayIndex, EmberAfPluginDoorLockHolidaySchedule & schedule) { + CHIP_ERROR error; + VerifyOrReturnValue(holidayIndex > 0, DlStatus::kFailure); // indices are one-indexed holidayIndex--; VerifyOrReturnValue(IsValidHolidayScheduleIndex(holidayIndex), DlStatus::kFailure); - const auto & scheduleInStorage = mHolidaySchedule[holidayIndex]; - if (DlScheduleStatus::kAvailable == scheduleInStorage.status) + // Get schedule data from nvm3 + chip::StorageKeyName scheduleDataKey = LockHolidayScheduleEndpoint(holidayIndex, endpointId); + + uint16_t scheduleSize = static_cast(sizeof(HolidayScheduleInfo)); + + error = chip::Server::GetInstance().GetPersistentStorage().SyncGetKeyValue(scheduleDataKey.KeyName(), &holidayScheduleInStorage, scheduleSize); + + // If no data is found at scheduleUserMapKey key + if(error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) { + ChipLogError(Zcl, "No schedule data found for user"); return DlStatus::kNotFound; } + // Else if KVS read was successful + else if(error == CHIP_NO_ERROR) + { - schedule = scheduleInStorage.schedule; + if (holidayScheduleInStorage.status == DlScheduleStatus::kAvailable) + { + return DlStatus::kNotFound; + } + + } + else + { + ChipLogError(Zcl, "Error reading from KVS key"); + return DlStatus::kFailure; + } + + schedule = holidayScheduleInStorage.schedule; return DlStatus::kSuccess; } @@ -672,23 +810,29 @@ DlStatus LockManager::GetHolidaySchedule(chip::EndpointId endpointId, uint8_t ho DlStatus LockManager::SetHolidaySchedule(chip::EndpointId endpointId, uint8_t holidayIndex, DlScheduleStatus status, uint32_t localStartTime, uint32_t localEndTime, OperatingModeEnum operatingMode) { + CHIP_ERROR error; + VerifyOrReturnValue(holidayIndex > 0, DlStatus::kFailure); // indices are one-indexed holidayIndex--; VerifyOrReturnValue(IsValidHolidayScheduleIndex(holidayIndex), DlStatus::kFailure); - auto & scheduleInStorage = mHolidaySchedule[holidayIndex]; + holidayScheduleInStorage.schedule.localStartTime = localStartTime; + holidayScheduleInStorage.schedule.localEndTime = localEndTime; + holidayScheduleInStorage.schedule.operatingMode = operatingMode; + holidayScheduleInStorage.status = status; - scheduleInStorage.schedule.localStartTime = localStartTime; - scheduleInStorage.schedule.localEndTime = localEndTime; - scheduleInStorage.schedule.operatingMode = operatingMode; - scheduleInStorage.status = status; + // Save schedule data in nvm3 + chip::StorageKeyName scheduleDataKey = LockHolidayScheduleEndpoint(holidayIndex, endpointId); - // Save schedule information in NVM flash - SilabsConfig::WriteConfigValueBin(SilabsConfig::kConfigKey_HolidaySchedules, - reinterpret_cast(&(mHolidaySchedule)), - sizeof(EmberAfPluginDoorLockHolidaySchedule) * LockParams.numberOfHolidaySchedules); + error = chip::Server::GetInstance().GetPersistentStorage().SyncSetKeyValue(scheduleDataKey.KeyName(), &holidayScheduleInStorage, static_cast(sizeof(HolidayScheduleInfo))); + + if((error != CHIP_NO_ERROR)) + { + ChipLogError(Zcl, "Error reading from KVS key"); + return DlStatus::kFailure; + } return DlStatus::kSuccess; } @@ -717,6 +861,8 @@ bool LockManager::setLockState(chip::EndpointId endpointId, const Nullable(sizeof(LockUserInfo)); + + error = chip::Server::GetInstance().GetPersistentStorage().SyncGetKeyValue(userKey.KeyName(), &userInStorage, size); + + // No user exists at this index + if(error != CHIP_NO_ERROR) + { continue; } - if (currentCredential.credentialData.data_equal(pin.Value())) - { - ChipLogDetail(Zcl, - "Lock App: specified PIN code was found in the database, setting lock state to \"%s\" [endpointId=%d]", - lockStateToString(lockState), endpointId); + chip::StorageKeyName credentialKey = LockUserCredentialMap(userIndex); - DoorLockServer::Instance().SetLockState(endpointId, lockState, OperationSourceEnum::kRemote, NullNullable, NullNullable, - fabricIdx, nodeId); + uint16_t credentialSize = static_cast(sizeof(CredentialStruct)*userInStorage.currentCredentialCount); - return true; + // Get array of credential indices and types associated to user + error = chip::Server::GetInstance().GetPersistentStorage().SyncGetKeyValue(credentialKey.KeyName(), &mCredentials, credentialSize); + + // No credential data associated with user + if(error != CHIP_NO_ERROR) + { + continue; + } + + for(int j = 0; j < userInStorage.currentCredentialCount; j++) + { + // If the current credential is a pin type, then check it against pin input. Otherwise ignore + if(mCredentials[j].credentialType == CredentialTypeEnum::kPin) + { + // Read the individual credential at credentialIndex j + uint16_t size = static_cast(sizeof(LockCredentialInfo)); + + chip::StorageKeyName key = LockCredentialEndpoint(mCredentials[j].credentialIndex, endpointId); + + error = chip::Server::GetInstance().GetPersistentStorage().SyncGetKeyValue(key.KeyName(), &credentialInStorage, size); + + if(error != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Error reading credential"); + return false; + } + + // See if it matches the provided PIN + if (credentialInStorage.status == DlCredentialStatus::kAvailable) + { + continue; + } + + chip::ByteSpan currentCredential = chip::ByteSpan{ credentialInStorage.credentialData, credentialInStorage.credentialDataSize }; + + if (currentCredential.data_equal(pin.Value())) + { + ChipLogDetail(Zcl, + "Lock App: specified PIN code was found in the database, setting lock state to \"%s\" [endpointId=%d]", + lockStateToString(lockState), endpointId); + + LockOpCredentials userCredential[] = { { CredentialTypeEnum::kPin, mCredentials[j].credentialIndex } }; + auto userCredentials = MakeNullable>(userCredential); + + DoorLockServer::Instance().SetLockState(endpointId, lockState, OperationSourceEnum::kRemote, userIndex, userCredentials, + fabricIdx, nodeId); + + return true; + } + + } } }