/* * * Copyright (c) 2023 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include struct WeekDaysScheduleInfo { DlScheduleStatus status = DlScheduleStatus::kAvailable; EmberAfPluginDoorLockWeekDaySchedule schedule; }; struct YearDayScheduleInfo { DlScheduleStatus status = DlScheduleStatus::kAvailable; EmberAfPluginDoorLockYearDaySchedule schedule; }; struct HolidayScheduleInfo { DlScheduleStatus status = DlScheduleStatus::kAvailable; EmberAfPluginDoorLockHolidaySchedule schedule; }; namespace TelinkDoorLock { namespace ResourceRanges { // Used to size arrays static constexpr uint8_t kMaxCredentialSize = 20; static constexpr uint8_t kNumCredentialTypes = 6; } // namespace ResourceRanges namespace LockInitParams { struct LockParam { // Read from zap attributes uint16_t numberOfUsers = 0; uint8_t numberOfCredentialsPerUser = 0; uint8_t numberOfWeekdaySchedulesPerUser = 0; uint8_t numberOfYeardaySchedulesPerUser = 0; uint8_t numberOfHolidaySchedules = 0; }; class ParamBuilder { public: ParamBuilder & SetNumberOfUsers(uint16_t numberOfUsers) { lockParam_.numberOfUsers = numberOfUsers; return *this; } ParamBuilder & SetNumberOfCredentialsPerUser(uint8_t numberOfCredentialsPerUser) { lockParam_.numberOfCredentialsPerUser = numberOfCredentialsPerUser; return *this; } ParamBuilder & SetNumberOfWeekdaySchedulesPerUser(uint8_t numberOfWeekdaySchedulesPerUser) { lockParam_.numberOfWeekdaySchedulesPerUser = numberOfWeekdaySchedulesPerUser; return *this; } ParamBuilder & SetNumberOfYeardaySchedulesPerUser(uint8_t numberOfYeardaySchedulesPerUser) { lockParam_.numberOfYeardaySchedulesPerUser = numberOfYeardaySchedulesPerUser; return *this; } ParamBuilder & SetNumberOfHolidaySchedules(uint8_t numberOfHolidaySchedules) { lockParam_.numberOfHolidaySchedules = numberOfHolidaySchedules; return *this; } LockParam GetLockParam() { return lockParam_; } private: LockParam lockParam_; }; } // namespace LockInitParams } // namespace TelinkDoorLock using namespace ::chip; using namespace TelinkDoorLock::ResourceRanges; class LockManager { public: enum Action_t { LOCK_ACTION = 0, UNLOCK_ACTION, UNBOLT_ACTION, INVALID_ACTION } Action; enum State_t { kState_LockInitiated = 0, kState_LockCompleted, kState_UnlockInitiated, kState_UnlockCompleted, kState_UnlatchInitiated, kState_UnlatchCompleted, kState_NotFulyLocked } State; using StateChangeCallback = void (*)(State_t); using OperationSource = chip::app::Clusters::DoorLock::OperationSourceEnum; CHIP_ERROR Init(chip::app::DataModel::Nullable state, TelinkDoorLock::LockInitParams::LockParam lockParam, StateChangeCallback callback); bool LockAction(int32_t appSource, Action_t aAction, OperationSource source, chip::EndpointId endpointId); bool LockAction(int32_t appSource, Action_t aAction, OperationSource source, chip::EndpointId endpointId, OperationErrorEnum & err, const Nullable & fabricIdx = NullNullable, const Nullable & nodeId = NullNullable, const Optional & pinCode = NullNullable); bool IsLocked() const { return mState == State_t::kState_LockCompleted; } State_t getLockState() { return mState; } bool GetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user); bool SetUser(chip::EndpointId endpointId, uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier, const chip::CharSpan & userName, uint32_t uniqueId, UserStatusEnum userStatus, UserTypeEnum usertype, CredentialRuleEnum credentialRule, const CredentialStruct * credentials, size_t totalCredentials); bool GetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, CredentialTypeEnum credentialType, EmberAfPluginDoorLockCredentialInfo & credential); bool SetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, chip::FabricIndex creator, chip::FabricIndex modifier, DlCredentialStatus credentialStatus, CredentialTypeEnum credentialType, const chip::ByteSpan & credentialData); DlStatus GetWeekdaySchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex, EmberAfPluginDoorLockWeekDaySchedule & schedule); DlStatus SetWeekdaySchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex, DlScheduleStatus status, DaysMaskMap daysMask, uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute); DlStatus GetYeardaySchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex, EmberAfPluginDoorLockYearDaySchedule & schedule); DlStatus SetYeardaySchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex, DlScheduleStatus status, uint32_t localStartTime, uint32_t localEndTime); DlStatus GetHolidaySchedule(chip::EndpointId endpointId, uint8_t holidayIndex, EmberAfPluginDoorLockHolidaySchedule & schedule); DlStatus SetHolidaySchedule(chip::EndpointId endpointId, uint8_t holidayIndex, DlScheduleStatus status, uint32_t localStartTime, uint32_t localEndTime, OperatingModeEnum operatingMode); bool IsValidUserIndex(uint16_t userIndex); bool IsValidCredentialIndex(uint16_t credentialIndex, CredentialTypeEnum type); bool IsValidCredentialType(CredentialTypeEnum type); bool IsValidWeekdayScheduleIndex(uint8_t scheduleIndex); bool IsValidYeardayScheduleIndex(uint8_t scheduleIndex); bool IsValidHolidayScheduleIndex(uint8_t scheduleIndex); const char * lockStateToString(DlLockState lockState) const; private: friend LockManager & LockMgr(); State_t mState = kState_NotFulyLocked; StateChangeCallback mStateChangeCallback = nullptr; OperationSource mActuatorOperationSource = OperationSource::kButton; k_timer mActuatorTimer = {}; bool setLockState(chip::EndpointId endpointId, DlLockState lockState, OperationSource source, OperationErrorEnum & err, const Nullable & fabricIdx, const Nullable & nodeId, const Optional & pin); static void ActuatorTimerEventHandler(k_timer * timer); static void ActuatorAppEventHandler(const AppEvent & event); #if !LOCK_MANAGER_CONFIG_USE_NVM_CREDENTIAL_STORAGE EmberAfPluginDoorLockUserInfo mLockUsers[APP_MAX_USERS]; EmberAfPluginDoorLockCredentialInfo mLockCredentials[kNumCredentialTypes][APP_MAX_CREDENTIAL]; WeekDaysScheduleInfo mWeekdaySchedule[APP_MAX_USERS][APP_MAX_WEEKDAY_SCHEDULE_PER_USER]; YearDayScheduleInfo mYeardaySchedule[APP_MAX_USERS][APP_MAX_YEARDAY_SCHEDULE_PER_USER]; HolidayScheduleInfo mHolidaySchedule[APP_MAX_HOLYDAY_SCHEDULE_PER_USER]; char mUserNames[ArraySize(mLockUsers)][DOOR_LOCK_MAX_USER_NAME_SIZE]; uint8_t mCredentialData[kNumCredentialTypes][APP_MAX_CREDENTIAL][kMaxCredentialSize]; CredentialStruct mCredentials[APP_MAX_USERS][APP_MAX_CREDENTIAL]; #endif static LockManager sLock; TelinkDoorLock::LockInitParams::LockParam LockParams; }; inline LockManager & LockMgr() { return LockManager::sLock; }