[Chef] Implement DoorLock example app (#32532)

* Update Chef Lock to enable user PIN and more

* Remove unused clusters (Groups). Add Power Source

* Refer to the latest lock-app codes

* Update device PowerSource attributes

* Enable PrivacyMode, Remove debug message

* Fix typo

* Restyled by whitespace

* Restyled by clang-format

* Add macro to doorlock to avoid compilation of light

* [Chef] support doorlock in esp32 & nrfconnect

* Update the date from 2023 to 2024

* Use CharSpan instead of "char *". Refine ifdef

* Restyled by clang-format

---------

Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/examples/chef/common/clusters/door-lock/chef-doorlock-stubs.cpp b/examples/chef/common/clusters/door-lock/chef-doorlock-stubs.cpp
new file mode 100644
index 0000000..7d92300
--- /dev/null
+++ b/examples/chef/common/clusters/door-lock/chef-doorlock-stubs.cpp
@@ -0,0 +1,133 @@
+/*
+ *
+ *    Copyright (c) 2020-2024 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.
+ */
+
+#include <app/data-model/Nullable.h>
+#include <app/util/af.h>
+#include <lib/core/DataModelTypes.h>
+
+#ifdef MATTER_DM_PLUGIN_DOOR_LOCK_SERVER
+#include "chef-lock-manager.h"
+#include <app/clusters/door-lock-server/door-lock-server.h>
+
+using namespace chip;
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::DoorLock;
+using chip::app::DataModel::Nullable;
+
+// =============================================================================
+// 'Default' callbacks for cluster commands
+// =============================================================================
+
+// App handles physical aspects of locking but not locking logic. That is it
+// 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 Nullable<chip::FabricIndex> & fabricIdx,
+                                            const Nullable<chip::NodeId> & nodeId, const Optional<ByteSpan> & pinCode,
+                                            OperationErrorEnum & err)
+{
+    return LockManager::Instance().Lock(endpointId, fabricIdx, nodeId, pinCode, err, OperationSourceEnum::kRemote);
+}
+
+bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx,
+                                              const Nullable<chip::NodeId> & nodeId, const Optional<ByteSpan> & pinCode,
+                                              OperationErrorEnum & err)
+{
+    return LockManager::Instance().Unlock(endpointId, fabricIdx, nodeId, pinCode, err, OperationSourceEnum::kRemote);
+}
+
+bool emberAfPluginDoorLockOnDoorUnboltCommand(chip::EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx,
+                                              const Nullable<chip::NodeId> & nodeId, const Optional<ByteSpan> & pinCode,
+                                              OperationErrorEnum & err)
+{
+    return LockManager::Instance().Unbolt(endpointId, fabricIdx, nodeId, pinCode, err, OperationSourceEnum::kRemote);
+}
+
+bool emberAfPluginDoorLockGetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user)
+{
+    return LockManager::Instance().GetUser(endpointId, userIndex, user);
+}
+
+bool emberAfPluginDoorLockSetUser(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)
+{
+
+    return LockManager::Instance().SetUser(endpointId, userIndex, creator, modifier, userName, uniqueId, userStatus, usertype,
+                                           credentialRule, credentials, totalCredentials);
+}
+
+bool emberAfPluginDoorLockGetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, CredentialTypeEnum credentialType,
+                                        EmberAfPluginDoorLockCredentialInfo & credential)
+{
+    return LockManager::Instance().GetCredential(endpointId, credentialIndex, credentialType, credential);
+}
+
+bool emberAfPluginDoorLockSetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, chip::FabricIndex creator,
+                                        chip::FabricIndex modifier, DlCredentialStatus credentialStatus,
+                                        CredentialTypeEnum credentialType, const chip::ByteSpan & credentialData)
+{
+    return LockManager::Instance().SetCredential(endpointId, credentialIndex, creator, modifier, credentialStatus, credentialType,
+                                                 credentialData);
+}
+
+DlStatus emberAfPluginDoorLockGetSchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex,
+                                          EmberAfPluginDoorLockWeekDaySchedule & schedule)
+{
+    return LockManager::Instance().GetSchedule(endpointId, weekdayIndex, userIndex, schedule);
+}
+
+DlStatus emberAfPluginDoorLockGetSchedule(chip::EndpointId endpointId, uint8_t holidayIndex,
+                                          EmberAfPluginDoorLockHolidaySchedule & schedule)
+{
+    return LockManager::Instance().GetSchedule(endpointId, holidayIndex, schedule);
+}
+
+DlStatus emberAfPluginDoorLockSetSchedule(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)
+{
+    return LockManager::Instance().SetSchedule(endpointId, weekdayIndex, userIndex, status, daysMask, startHour, startMinute,
+                                               endHour, endMinute);
+}
+
+DlStatus emberAfPluginDoorLockSetSchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex,
+                                          DlScheduleStatus status, uint32_t localStartTime, uint32_t localEndTime)
+{
+    return LockManager::Instance().SetSchedule(endpointId, yearDayIndex, userIndex, status, localStartTime, localEndTime);
+}
+
+DlStatus emberAfPluginDoorLockGetSchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex,
+                                          EmberAfPluginDoorLockYearDaySchedule & schedule)
+{
+    return LockManager::Instance().GetSchedule(endpointId, yearDayIndex, userIndex, schedule);
+}
+
+DlStatus emberAfPluginDoorLockSetSchedule(chip::EndpointId endpointId, uint8_t holidayIndex, DlScheduleStatus status,
+                                          uint32_t localStartTime, uint32_t localEndTime, OperatingModeEnum operatingMode)
+{
+    return LockManager::Instance().SetSchedule(endpointId, holidayIndex, status, localStartTime, localEndTime, operatingMode);
+}
+
+void emberAfDoorLockClusterInitCallback(EndpointId endpoint)
+{
+    DoorLockServer::Instance().InitServer(endpoint);
+    LockManager::Instance().InitEndpoint(endpoint);
+}
+#endif // MATTER_DM_PLUGIN_DOOR_LOCK_SERVER
diff --git a/examples/chef/common/clusters/door-lock/chef-lock-endpoint.cpp b/examples/chef/common/clusters/door-lock/chef-lock-endpoint.cpp
new file mode 100644
index 0000000..7cff212
--- /dev/null
+++ b/examples/chef/common/clusters/door-lock/chef-lock-endpoint.cpp
@@ -0,0 +1,680 @@
+/*
+ *
+ *    Copyright (c) 2022-2024 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.
+ */
+
+#include <app-common/zap-generated/attributes/Accessors.h>
+#include <app/util/af.h>
+#include <cstring>
+#include <platform/CHIPDeviceLayer.h>
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+
+#ifdef MATTER_DM_PLUGIN_DOOR_LOCK_SERVER
+#include "chef-lock-endpoint.h"
+
+using chip::to_underlying;
+using chip::app::DataModel::MakeNullable;
+
+struct LockActionData
+{
+    chip::EndpointId endpointId;
+    DlLockState lockState;
+    OperationSourceEnum opSource;
+    Nullable<uint16_t> userIndex;
+    uint16_t credentialIndex;
+    Nullable<chip::FabricIndex> fabricIdx;
+    Nullable<chip::NodeId> nodeId;
+    bool moving = false;
+};
+
+static LockActionData gCurrentAction;
+
+bool LockEndpoint::Lock(const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId,
+                        const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource)
+{
+    return setLockState(fabricIdx, nodeId, DlLockState::kLocked, pin, err, opSource);
+}
+
+bool LockEndpoint::Unlock(const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId,
+                          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
+        return setLockState(fabricIdx, nodeId, DlLockState::kUnlatched, pin, err, opSource);
+    }
+
+    return setLockState(fabricIdx, nodeId, DlLockState::kUnlocked, pin, err, opSource);
+}
+
+bool LockEndpoint::Unbolt(const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId,
+                          const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource)
+{
+    return setLockState(fabricIdx, nodeId, DlLockState::kUnlocked, pin, err, opSource);
+}
+
+bool LockEndpoint::GetUser(uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user) const
+{
+    ChipLogProgress(Zcl, "Lock App: LockEndpoint::GetUser [endpoint=%d,userIndex=%hu]", mEndpointId, userIndex);
+
+    auto adjustedUserIndex = static_cast<uint16_t>(userIndex - 1);
+    if (adjustedUserIndex > mLockUsers.size())
+    {
+        ChipLogError(Zcl, "Cannot get user - index out of range [endpoint=%d,index=%hu,adjustedIndex=%d]", mEndpointId, userIndex,
+                     adjustedUserIndex);
+        return false;
+    }
+
+    const auto & userInDb = mLockUsers[adjustedUserIndex];
+    user.userStatus       = userInDb.userStatus;
+    if (UserStatusEnum::kAvailable == user.userStatus)
+    {
+        ChipLogDetail(Zcl, "Found unoccupied user [endpoint=%d,adjustedIndex=%hu]", mEndpointId, adjustedUserIndex);
+        return true;
+    }
+
+    user.userName       = userInDb.userName;
+    user.credentials    = chip::Span<const CredentialStruct>(userInDb.credentials.data(), userInDb.credentials.size());
+    user.userUniqueId   = userInDb.userUniqueId;
+    user.userType       = userInDb.userType;
+    user.credentialRule = userInDb.credentialRule;
+    // So far there's no way to actually create the credential outside the matter, so here we always set the creation/modification
+    // source to Matter
+    user.creationSource     = DlAssetSource::kMatterIM;
+    user.createdBy          = userInDb.createdBy;
+    user.modificationSource = DlAssetSource::kMatterIM;
+    user.lastModifiedBy     = userInDb.lastModifiedBy;
+
+    ChipLogDetail(Zcl,
+                  "Found occupied user "
+                  "[endpoint=%d,adjustedIndex=%hu,name=\"%.*s\",credentialsCount=%u,uniqueId=%x,type=%u,credentialRule=%u,"
+                  "createdBy=%d,lastModifiedBy=%d]",
+                  mEndpointId, adjustedUserIndex, static_cast<int>(user.userName.size()), user.userName.data(),
+                  static_cast<unsigned int>(user.credentials.size()), user.userUniqueId, to_underlying(user.userType),
+                  to_underlying(user.credentialRule), user.createdBy, user.lastModifiedBy);
+
+    return true;
+}
+
+bool LockEndpoint::SetUser(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)
+{
+    ChipLogProgress(Zcl,
+                    "Lock App: LockEndpoint::SetUser "
+                    "[endpoint=%d,userIndex=%u,creator=%d,modifier=%d,userName=\"%.*s\",uniqueId=%" PRIx32
+                    ",userStatus=%u,userType=%u,"
+                    "credentialRule=%u,credentials=%p,totalCredentials=%u]",
+                    mEndpointId, userIndex, creator, modifier, static_cast<int>(userName.size()), userName.data(), uniqueId,
+                    to_underlying(userStatus), to_underlying(usertype), to_underlying(credentialRule), credentials,
+                    static_cast<unsigned int>(totalCredentials));
+
+    auto adjustedUserIndex = static_cast<uint16_t>(userIndex - 1);
+    if (adjustedUserIndex > mLockUsers.size())
+    {
+        ChipLogError(Zcl, "Cannot set user - index out of range [endpoint=%d,index=%d,adjustedUserIndex=%u]", mEndpointId,
+                     userIndex, adjustedUserIndex);
+        return false;
+    }
+
+    auto & userInStorage = mLockUsers[adjustedUserIndex];
+    if (userName.size() > DOOR_LOCK_MAX_USER_NAME_SIZE)
+    {
+        ChipLogError(Zcl, "Cannot set user - user name is too long [endpoint=%d,index=%d,adjustedUserIndex=%u]", mEndpointId,
+                     userIndex, adjustedUserIndex);
+        return false;
+    }
+
+    if (totalCredentials > userInStorage.credentials.capacity())
+    {
+        ChipLogError(Zcl,
+                     "Cannot set user - total number of credentials is too big [endpoint=%d,index=%d,adjustedUserIndex=%u"
+                     ",totalCredentials=%u,maxNumberOfCredentials=%u]",
+                     mEndpointId, userIndex, adjustedUserIndex, static_cast<unsigned int>(totalCredentials),
+                     static_cast<unsigned int>(userInStorage.credentials.capacity()));
+        return false;
+    }
+
+    userInStorage.userName = chip::MutableCharSpan(userInStorage.userNameBuf, DOOR_LOCK_USER_NAME_BUFFER_SIZE);
+    CopyCharSpanToMutableCharSpan(userName, userInStorage.userName);
+    userInStorage.userUniqueId   = uniqueId;
+    userInStorage.userStatus     = userStatus;
+    userInStorage.userType       = usertype;
+    userInStorage.credentialRule = credentialRule;
+    userInStorage.lastModifiedBy = modifier;
+    userInStorage.createdBy      = creator;
+
+    userInStorage.credentials.clear();
+    for (size_t i = 0; i < totalCredentials; ++i)
+    {
+        userInStorage.credentials.push_back(credentials[i]);
+    }
+
+    ChipLogProgress(Zcl, "Successfully set the user [mEndpointId=%d,index=%d,adjustedIndex=%d]", mEndpointId, userIndex,
+                    adjustedUserIndex);
+
+    return true;
+}
+
+DoorStateEnum LockEndpoint::GetDoorState() const
+{
+    return mDoorState;
+}
+
+bool LockEndpoint::SetDoorState(DoorStateEnum newState)
+{
+    if (mDoorState != newState)
+    {
+        ChipLogProgress(Zcl, "Changing the door state to: %d [endpointId=%d,previousState=%d]", to_underlying(newState),
+                        mEndpointId, to_underlying(mDoorState));
+
+        mDoorState = newState;
+        return DoorLockServer::Instance().SetDoorState(mEndpointId, mDoorState);
+    }
+    return true;
+}
+
+bool LockEndpoint::SendLockAlarm(AlarmCodeEnum alarmCode) const
+{
+    ChipLogProgress(Zcl, "Sending the LockAlarm event [endpointId=%d,alarmCode=%u]", mEndpointId, to_underlying(alarmCode));
+    return DoorLockServer::Instance().SendLockAlarmEvent(mEndpointId, alarmCode);
+}
+
+bool LockEndpoint::GetCredential(uint16_t credentialIndex, CredentialTypeEnum credentialType,
+                                 EmberAfPluginDoorLockCredentialInfo & credential) const
+{
+    ChipLogProgress(Zcl, "Lock App: LockEndpoint::GetCredential [endpoint=%d,credentialIndex=%u,credentialType=%u]", mEndpointId,
+                    credentialIndex, to_underlying(credentialType));
+
+    if (to_underlying(credentialType) >= mLockCredentials.size())
+    {
+        ChipLogError(Zcl, "Cannot get the credential - index out of range [endpoint=%d,index=%d]", mEndpointId, credentialIndex);
+        return false;
+    }
+
+    if (credentialIndex >= mLockCredentials.at(to_underlying(credentialType)).size() ||
+        (0 == credentialIndex && CredentialTypeEnum::kProgrammingPIN != credentialType))
+    {
+        ChipLogError(Zcl, "Cannot get the credential - index out of range [endpoint=%d,index=%d]", mEndpointId, credentialIndex);
+        return false;
+    }
+
+    const auto & credentialInStorage = mLockCredentials[to_underlying(credentialType)][credentialIndex];
+
+    credential.status = credentialInStorage.status;
+    if (DlCredentialStatus::kAvailable == credential.status)
+    {
+        ChipLogDetail(Zcl, "Found unoccupied credential [endpoint=%d,index=%u]", mEndpointId, credentialIndex);
+        return true;
+    }
+    credential.credentialType = credentialInStorage.credentialType;
+    credential.credentialData = chip::ByteSpan(credentialInStorage.credentialData, credentialInStorage.credentialDataSize);
+    // So far there's no way to actually create the credential outside the matter, so here we always set the creation/modification
+    // source to Matter
+    credential.creationSource     = DlAssetSource::kMatterIM;
+    credential.createdBy          = credentialInStorage.createdBy;
+    credential.modificationSource = DlAssetSource::kMatterIM;
+    credential.lastModifiedBy     = credentialInStorage.modifiedBy;
+
+    ChipLogDetail(Zcl, "Found occupied credential [endpoint=%d,index=%u,type=%u,dataSize=%u,createdBy=%u,modifiedBy=%u]",
+                  mEndpointId, credentialIndex, to_underlying(credential.credentialType),
+                  static_cast<unsigned int>(credential.credentialData.size()), credential.createdBy, credential.lastModifiedBy);
+
+    return true;
+}
+
+bool LockEndpoint::SetCredential(uint16_t credentialIndex, chip::FabricIndex creator, chip::FabricIndex modifier,
+                                 DlCredentialStatus credentialStatus, CredentialTypeEnum credentialType,
+                                 const chip::ByteSpan & credentialData)
+{
+    ChipLogProgress(
+        Zcl,
+        "Lock App: LockEndpoint::SetCredential "
+        "[endpoint=%d,credentialIndex=%u,credentialStatus=%u,credentialType=%u,credentialDataSize=%u,creator=%u,modifier=%u]",
+        mEndpointId, credentialIndex, to_underlying(credentialStatus), to_underlying(credentialType),
+        static_cast<unsigned int>(credentialData.size()), creator, modifier);
+
+    if (to_underlying(credentialType) >= mLockCredentials.capacity())
+    {
+        ChipLogError(Zcl, "Cannot set the credential - type out of range [endpoint=%d,type=%d]", mEndpointId,
+                     to_underlying(credentialType));
+        return false;
+    }
+
+    if (credentialIndex >= mLockCredentials.at(to_underlying(credentialType)).size() ||
+        (0 == credentialIndex && CredentialTypeEnum::kProgrammingPIN != credentialType))
+    {
+        ChipLogError(Zcl, "Cannot set the credential - index out of range [endpoint=%d,index=%d]", mEndpointId, credentialIndex);
+        return false;
+    }
+
+    // Assign to array by credentialIndex. Note: 0 is reserved for programmingPIN only
+    auto & credentialInStorage = mLockCredentials[to_underlying(credentialType)][credentialIndex];
+    if (credentialData.size() > DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE)
+    {
+        ChipLogError(Zcl,
+                     "Cannot get the credential - data size exceeds limit "
+                     "[endpoint=%d,index=%d,dataSize=%u,maxDataSize=%u]",
+                     mEndpointId, credentialIndex, static_cast<unsigned int>(credentialData.size()),
+                     static_cast<unsigned int>(DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE));
+        return false;
+    }
+    credentialInStorage.status         = credentialStatus;
+    credentialInStorage.credentialType = credentialType;
+    credentialInStorage.createdBy      = creator;
+    credentialInStorage.modifiedBy     = modifier;
+    std::memcpy(credentialInStorage.credentialData, credentialData.data(), credentialData.size());
+    credentialInStorage.credentialDataSize = credentialData.size();
+
+    ChipLogProgress(Zcl, "Successfully set the credential [mEndpointId=%d,index=%d,credentialType=%u,creator=%u,modifier=%u]",
+                    mEndpointId, credentialIndex, to_underlying(credentialType), credentialInStorage.createdBy,
+                    credentialInStorage.modifiedBy);
+
+    return true;
+}
+
+DlStatus LockEndpoint::GetSchedule(uint8_t weekDayIndex, uint16_t userIndex, EmberAfPluginDoorLockWeekDaySchedule & schedule)
+{
+    if (0 == userIndex || userIndex > mWeekDaySchedules.size())
+    {
+        return DlStatus::kFailure;
+    }
+
+    if (0 == weekDayIndex || weekDayIndex > mWeekDaySchedules.at(userIndex - 1).size())
+    {
+        return DlStatus::kFailure;
+    }
+
+    const auto & scheduleInStorage = mWeekDaySchedules.at(userIndex - 1).at(weekDayIndex - 1);
+    if (DlScheduleStatus::kAvailable == scheduleInStorage.status)
+    {
+        return DlStatus::kNotFound;
+    }
+
+    schedule = scheduleInStorage.schedule;
+
+    return DlStatus::kSuccess;
+}
+
+DlStatus LockEndpoint::SetSchedule(uint8_t weekDayIndex, uint16_t userIndex, DlScheduleStatus status, DaysMaskMap daysMask,
+                                   uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute)
+{
+    if (0 == userIndex || userIndex > mWeekDaySchedules.size())
+    {
+        return DlStatus::kFailure;
+    }
+
+    if (0 == weekDayIndex || weekDayIndex > mWeekDaySchedules.at(userIndex - 1).size())
+    {
+        return DlStatus::kFailure;
+    }
+
+    auto & scheduleInStorage = mWeekDaySchedules.at(userIndex - 1).at(weekDayIndex - 1);
+
+    scheduleInStorage.schedule.daysMask    = daysMask;
+    scheduleInStorage.schedule.startHour   = startHour;
+    scheduleInStorage.schedule.startMinute = startMinute;
+    scheduleInStorage.schedule.endHour     = endHour;
+    scheduleInStorage.schedule.endMinute   = endMinute;
+    scheduleInStorage.status               = status;
+
+    return DlStatus::kSuccess;
+}
+
+DlStatus LockEndpoint::GetSchedule(uint8_t yearDayIndex, uint16_t userIndex, EmberAfPluginDoorLockYearDaySchedule & schedule)
+{
+    if (0 == userIndex || userIndex > mYearDaySchedules.size())
+    {
+        return DlStatus::kFailure;
+    }
+
+    if (0 == yearDayIndex || yearDayIndex > mYearDaySchedules.at(userIndex - 1).size())
+    {
+        return DlStatus::kFailure;
+    }
+
+    const auto & scheduleInStorage = mYearDaySchedules.at(userIndex - 1).at(yearDayIndex - 1);
+    if (DlScheduleStatus::kAvailable == scheduleInStorage.status)
+    {
+        return DlStatus::kNotFound;
+    }
+
+    schedule = scheduleInStorage.schedule;
+
+    return DlStatus::kSuccess;
+}
+
+DlStatus LockEndpoint::SetSchedule(uint8_t yearDayIndex, uint16_t userIndex, DlScheduleStatus status, uint32_t localStartTime,
+                                   uint32_t localEndTime)
+{
+    if (0 == userIndex || userIndex > mYearDaySchedules.size())
+    {
+        return DlStatus::kFailure;
+    }
+
+    if (0 == yearDayIndex || yearDayIndex > mYearDaySchedules.at(userIndex - 1).size())
+    {
+        return DlStatus::kFailure;
+    }
+
+    auto & scheduleInStorage                  = mYearDaySchedules.at(userIndex - 1).at(yearDayIndex - 1);
+    scheduleInStorage.schedule.localStartTime = localStartTime;
+    scheduleInStorage.schedule.localEndTime   = localEndTime;
+    scheduleInStorage.status                  = status;
+
+    return DlStatus::kSuccess;
+}
+
+DlStatus LockEndpoint::GetSchedule(uint8_t holidayIndex, EmberAfPluginDoorLockHolidaySchedule & schedule)
+{
+    if (0 == holidayIndex || holidayIndex > mHolidaySchedules.size())
+    {
+        return DlStatus::kFailure;
+    }
+
+    const auto & scheduleInStorage = mHolidaySchedules[holidayIndex - 1];
+    if (DlScheduleStatus::kAvailable == scheduleInStorage.status)
+    {
+        return DlStatus::kNotFound;
+    }
+
+    schedule = scheduleInStorage.schedule;
+    return DlStatus::kSuccess;
+}
+
+DlStatus LockEndpoint::SetSchedule(uint8_t holidayIndex, DlScheduleStatus status, uint32_t localStartTime, uint32_t localEndTime,
+                                   OperatingModeEnum operatingMode)
+{
+    if (0 == holidayIndex || holidayIndex > mHolidaySchedules.size())
+    {
+        return DlStatus::kFailure;
+    }
+
+    auto & scheduleInStorage                  = mHolidaySchedules[holidayIndex - 1];
+    scheduleInStorage.schedule.localStartTime = localStartTime;
+    scheduleInStorage.schedule.localEndTime   = localEndTime;
+    scheduleInStorage.schedule.operatingMode  = operatingMode;
+    scheduleInStorage.status                  = status;
+
+    return DlStatus::kSuccess;
+}
+
+bool LockEndpoint::setLockState(const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId,
+                                DlLockState lockState, const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
+                                OperationSourceEnum opSource)
+{
+    // Assume pin is required until told otherwise
+    bool requirePin = true;
+    chip::app::Clusters::DoorLock::Attributes::RequirePINforRemoteOperation::Get(mEndpointId, &requirePin);
+
+    // If a pin code is not given
+    if (!pin.HasValue())
+    {
+        ChipLogDetail(Zcl, "Door Lock App: PIN code is not specified [endpointId=%d]", mEndpointId);
+
+        // If a pin code is not required
+        if (!requirePin)
+        {
+            ChipLogProgress(Zcl, "Door Lock App: setting door lock state to \"%s\" [endpointId=%d]", lockStateToString(lockState),
+                            mEndpointId);
+
+            if (gCurrentAction.moving == true)
+            {
+                ChipLogProgress(Zcl, "Lock App: not executing lock action as another lock action is already active [endpointId=%d]",
+                                mEndpointId);
+                return false;
+            }
+
+            gCurrentAction.moving     = true;
+            gCurrentAction.endpointId = mEndpointId;
+            gCurrentAction.lockState  = lockState;
+            gCurrentAction.opSource   = opSource;
+            gCurrentAction.userIndex  = NullNullable;
+            gCurrentAction.fabricIdx  = fabricIdx;
+            gCurrentAction.nodeId     = nodeId;
+
+            // Do this async as a real lock would do too but use 0s delay to speed up CI tests
+            chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(0), OnLockActionCompleteCallback, nullptr);
+
+            return true;
+        }
+
+        ChipLogError(Zcl, "Door Lock App: PIN code is not specified, but it is required [endpointId=%d]", mEndpointId);
+
+        err = OperationErrorEnum::kInvalidCredential;
+        return false;
+    }
+
+    // Find the credential so we can make sure it is not absent right away
+    auto & pinCredentials = mLockCredentials[to_underlying(CredentialTypeEnum::kPin)];
+    auto credential       = std::find_if(pinCredentials.begin(), pinCredentials.end(), [&pin](const LockCredentialInfo & c) {
+        return (c.status != DlCredentialStatus::kAvailable) &&
+            chip::ByteSpan{ c.credentialData, c.credentialDataSize }.data_equal(pin.Value());
+    });
+    if (credential == pinCredentials.end())
+    {
+        ChipLogDetail(Zcl,
+                      "Lock App: specified PIN code was not found in the database, ignoring command to set lock state to \"%s\" "
+                      "[endpointId=%d]",
+                      lockStateToString(lockState), mEndpointId);
+
+        err = OperationErrorEnum::kInvalidCredential;
+        return false;
+    }
+
+    // Find a user that correspond to this credential
+    auto credentialIndex = static_cast<unsigned>(credential - pinCredentials.begin());
+    auto user = std::find_if(mLockUsers.begin(), mLockUsers.end(), [credential, credentialIndex](const LockUserInfo & u) {
+        return std::any_of(u.credentials.begin(), u.credentials.end(), [&credential, credentialIndex](const CredentialStruct & c) {
+            return c.credentialIndex == credentialIndex && c.credentialType == credential->credentialType;
+        });
+    });
+    if (user == mLockUsers.end())
+    {
+        ChipLogDetail(Zcl,
+                      "Lock App: specified PIN code was found in the database, but the lock user is not associated with it "
+                      "[endpointId=%d,credentialIndex=%u]",
+                      mEndpointId, credentialIndex);
+    }
+
+    auto userIndex = static_cast<uint8_t>(user - mLockUsers.begin());
+
+    // Check if schedules affect the user
+    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))
+    {
+        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,
+        "Lock App: specified PIN code was found in the database, setting door lock state to \"%s\" [endpointId=%d,userIndex=%u]",
+        lockStateToString(lockState), mEndpointId, userIndex);
+
+    if (gCurrentAction.moving == true)
+    {
+        ChipLogProgress(Zcl,
+                        "Lock App: not executing lock action as another lock action is already active [endpointId=%d,userIndex=%u]",
+                        mEndpointId, userIndex);
+        return false;
+    }
+
+    gCurrentAction.moving          = true;
+    gCurrentAction.endpointId      = mEndpointId;
+    gCurrentAction.lockState       = lockState;
+    gCurrentAction.opSource        = opSource;
+    gCurrentAction.userIndex       = MakeNullable(static_cast<uint16_t>(userIndex + 1));
+    gCurrentAction.credentialIndex = static_cast<uint16_t>(credentialIndex);
+    gCurrentAction.fabricIdx       = fabricIdx;
+    gCurrentAction.nodeId          = nodeId;
+
+    // Do this async as a real lock would do too but use 0s delay to speed up CI tests
+    chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(0), OnLockActionCompleteCallback, nullptr);
+
+    return true;
+}
+
+void LockEndpoint::OnLockActionCompleteCallback(chip::System::Layer *, void * callbackContext)
+{
+    if (gCurrentAction.userIndex.IsNull())
+    {
+        DoorLockServer::Instance().SetLockState(gCurrentAction.endpointId, gCurrentAction.lockState, gCurrentAction.opSource,
+                                                NullNullable, NullNullable, gCurrentAction.fabricIdx, gCurrentAction.nodeId);
+    }
+    else
+    {
+        LockOpCredentials userCredential[] = { { CredentialTypeEnum::kPin, gCurrentAction.credentialIndex } };
+        auto userCredentials               = MakeNullable<List<const LockOpCredentials>>(userCredential);
+
+        DoorLockServer::Instance().SetLockState(gCurrentAction.endpointId, gCurrentAction.lockState, gCurrentAction.opSource,
+                                                gCurrentAction.userIndex, userCredentials, gCurrentAction.fabricIdx,
+                                                gCurrentAction.nodeId);
+    }
+
+    // move back to Unlocked after Unlatch
+    if (gCurrentAction.lockState == DlLockState::kUnlatched)
+    {
+        gCurrentAction.lockState = DlLockState::kUnlocked;
+
+        // Do this async as a real lock would do too but use 0s delay to speed up CI tests
+        chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(0), OnLockActionCompleteCallback, nullptr);
+    }
+    else
+    {
+        gCurrentAction.moving = false;
+    }
+}
+
+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)
+    {
+        // 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;
+    auto chipError = chip::System::SystemClock().GetClock_RealTimeMS(cTMs);
+    if (chipError != CHIP_NO_ERROR)
+    {
+        ChipLogError(Zcl, "Lock App: unable to get current time to check user schedules [endpointId=%d,error=%d (%s)]", mEndpointId,
+                     chipError.AsInteger(), chipError.AsString());
+        return true;
+    }
+    time_t unixEpoch = std::chrono::duration_cast<chip::System::Clock::Seconds32>(cTMs).count();
+
+    tm calendarTime{};
+    localtime_r(&unixEpoch, &calendarTime);
+
+    auto currentTime =
+        calendarTime.tm_hour * chip::kSecondsPerHour + calendarTime.tm_min * chip::kSecondsPerMinute + calendarTime.tm_sec;
+
+    // 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;
+            auto endTime   = s.schedule.endHour * chip::kSecondsPerHour + s.schedule.endMinute * chip::kSecondsPerMinute;
+
+            return s.status == DlScheduleStatus::kOccupied && (to_underlying(s.schedule.daysMask) & (1 << calendarTime.tm_wday)) &&
+                startTime <= currentTime && currentTime <= endTime;
+        });
+}
+
+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 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;
+    auto chipError = chip::System::SystemClock().GetClock_RealTimeMS(cTMs);
+    if (chipError != CHIP_NO_ERROR)
+    {
+        ChipLogError(Zcl, "Lock App: unable to get current time to check user schedules [endpointId=%d,error=%d (%s)]", mEndpointId,
+                     chipError.AsInteger(), chipError.AsString());
+        return true;
+    }
+    auto unixEpoch     = std::chrono::duration_cast<chip::System::Clock::Seconds32>(cTMs).count();
+    uint32_t chipEpoch = 0;
+    if (!chip::UnixEpochToChipEpochTime(unixEpoch, chipEpoch))
+    {
+        ChipLogError(Zcl,
+                     "Lock App: unable to convert Unix Epoch time to Matter Epoch Time to check user schedules "
+                     "[endpointId=%d,userIndex=%d]",
+                     mEndpointId, userIndex);
+        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;
+                        });
+}
+
+const char * LockEndpoint::lockStateToString(DlLockState lockState) const
+{
+    switch (lockState)
+    {
+    case DlLockState::kNotFullyLocked:
+        return "Not Fully Locked";
+    case DlLockState::kLocked:
+        return "Locked";
+    case DlLockState::kUnlocked:
+        return "Unlocked";
+    case DlLockState::kUnlatched:
+        return "Unlatched";
+    case DlLockState::kUnknownEnumValue:
+        break;
+    }
+
+    return "Unknown";
+}
+#endif // MATTER_DM_PLUGIN_DOOR_LOCK_SERVER
diff --git a/examples/chef/common/clusters/door-lock/chef-lock-endpoint.h b/examples/chef/common/clusters/door-lock/chef-lock-endpoint.h
new file mode 100644
index 0000000..285e703
--- /dev/null
+++ b/examples/chef/common/clusters/door-lock/chef-lock-endpoint.h
@@ -0,0 +1,162 @@
+/*
+ *
+ *    Copyright (c) 2022-2024 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 <app/clusters/door-lock-server/door-lock-server.h>
+#include <vector>
+
+struct LockUserInfo
+{
+    char userNameBuf[DOOR_LOCK_USER_NAME_BUFFER_SIZE];
+    chip::MutableCharSpan userName;
+    uint32_t userUniqueId;
+    UserStatusEnum userStatus;
+    UserTypeEnum userType;
+    CredentialRuleEnum credentialRule;
+    std::vector<CredentialStruct> credentials;
+    chip::FabricIndex createdBy;
+    chip::FabricIndex lastModifiedBy;
+};
+
+struct LockCredentialInfo;
+struct WeekDaysScheduleInfo;
+struct YearDayScheduleInfo;
+struct HolidayScheduleInfo;
+
+static constexpr size_t DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE = 20;
+static constexpr size_t DOOR_LOCK_CREDENTIAL_INFO_MAX_TYPES     = 6; // 0: ProgrammingPIN ~ 5: Face
+
+class LockEndpoint
+{
+public:
+    LockEndpoint(chip::EndpointId endpointId, uint16_t numberOfLockUsersSupported, uint16_t numberOfCredentialsSupported,
+                 uint8_t weekDaySchedulesPerUser, uint8_t yearDaySchedulesPerUser, uint8_t numberOfCredentialsPerUser,
+                 uint8_t numberOfHolidaySchedules) :
+        mEndpointId{ endpointId },
+        mLockState{ DlLockState::kLocked }, mDoorState{ DoorStateEnum::kDoorClosed }, mLockUsers(numberOfLockUsersSupported),
+        mLockCredentials(DOOR_LOCK_CREDENTIAL_INFO_MAX_TYPES, std::vector<LockCredentialInfo>(numberOfCredentialsSupported + 1)),
+        mWeekDaySchedules(numberOfLockUsersSupported, std::vector<WeekDaysScheduleInfo>(weekDaySchedulesPerUser)),
+        mYearDaySchedules(numberOfLockUsersSupported, std::vector<YearDayScheduleInfo>(yearDaySchedulesPerUser)),
+        mHolidaySchedules(numberOfHolidaySchedules)
+    {
+        for (auto & lockUser : mLockUsers)
+        {
+            lockUser.credentials.reserve(numberOfCredentialsPerUser);
+        }
+        DoorLockServer::Instance().SetDoorState(endpointId, mDoorState);
+        DoorLockServer::Instance().SetLockState(endpointId, mLockState);
+    }
+
+    inline chip::EndpointId GetEndpointId() const { return mEndpointId; }
+
+    bool Lock(const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId,
+              const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource);
+    bool Unlock(const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId,
+                const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource);
+    bool Unbolt(const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId,
+                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,
+                 uint32_t uniqueId, UserStatusEnum userStatus, UserTypeEnum usertype, CredentialRuleEnum credentialRule,
+                 const CredentialStruct * credentials, size_t totalCredentials);
+
+    bool SetDoorState(DoorStateEnum newState);
+
+    DoorStateEnum GetDoorState() const;
+
+    bool SendLockAlarm(AlarmCodeEnum alarmCode) const;
+
+    bool GetCredential(uint16_t credentialIndex, CredentialTypeEnum credentialType,
+                       EmberAfPluginDoorLockCredentialInfo & credential) const;
+
+    bool SetCredential(uint16_t credentialIndex, chip::FabricIndex creator, chip::FabricIndex modifier,
+                       DlCredentialStatus credentialStatus, CredentialTypeEnum credentialType,
+                       const chip::ByteSpan & credentialData);
+
+    DlStatus GetSchedule(uint8_t weekDayIndex, uint16_t userIndex, EmberAfPluginDoorLockWeekDaySchedule & schedule);
+    DlStatus GetSchedule(uint8_t yearDayIndex, uint16_t userIndex, EmberAfPluginDoorLockYearDaySchedule & schedule);
+    DlStatus GetSchedule(uint8_t holidayIndex, EmberAfPluginDoorLockHolidaySchedule & schedule);
+
+    DlStatus SetSchedule(uint8_t weekDayIndex, uint16_t userIndex, DlScheduleStatus status, DaysMaskMap daysMask, uint8_t startHour,
+                         uint8_t startMinute, uint8_t endHour, uint8_t endMinute);
+    DlStatus SetSchedule(uint8_t yearDayIndex, uint16_t userIndex, DlScheduleStatus status, uint32_t localStartTime,
+                         uint32_t localEndTime);
+    DlStatus SetSchedule(uint8_t holidayIndex, DlScheduleStatus status, uint32_t localStartTime, uint32_t localEndTime,
+                         OperatingModeEnum operatingMode);
+
+private:
+    bool setLockState(const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId, DlLockState lockState,
+                      const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err,
+                      OperationSourceEnum opSource = OperationSourceEnum::kUnspecified);
+    const char * lockStateToString(DlLockState lockState) 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);
+
+    chip::EndpointId mEndpointId;
+    DlLockState mLockState;
+    DoorStateEnum mDoorState;
+
+    // This is very naive implementation of users/credentials/schedules database and by no means the best practice. Proper storage
+    // of those items is out of scope of this example.
+    std::vector<LockUserInfo> mLockUsers;
+    std::vector<std::vector<LockCredentialInfo>> mLockCredentials;
+    std::vector<std::vector<WeekDaysScheduleInfo>> mWeekDaySchedules;
+    std::vector<std::vector<YearDayScheduleInfo>> mYearDaySchedules;
+    std::vector<HolidayScheduleInfo> mHolidaySchedules;
+};
+
+struct LockCredentialInfo
+{
+    DlCredentialStatus status;
+    CredentialTypeEnum credentialType;
+    chip::FabricIndex createdBy;
+    chip::FabricIndex modifiedBy;
+    uint8_t credentialData[DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE];
+    size_t credentialDataSize;
+};
+
+struct WeekDaysScheduleInfo
+{
+    DlScheduleStatus status;
+    EmberAfPluginDoorLockWeekDaySchedule schedule;
+};
+
+struct YearDayScheduleInfo
+{
+    DlScheduleStatus status;
+    EmberAfPluginDoorLockYearDaySchedule schedule;
+};
+
+struct HolidayScheduleInfo
+{
+    DlScheduleStatus status;
+    EmberAfPluginDoorLockHolidaySchedule schedule;
+};
diff --git a/examples/chef/common/clusters/door-lock/chef-lock-manager.cpp b/examples/chef/common/clusters/door-lock/chef-lock-manager.cpp
new file mode 100644
index 0000000..0b81cce
--- /dev/null
+++ b/examples/chef/common/clusters/door-lock/chef-lock-manager.cpp
@@ -0,0 +1,376 @@
+/*
+ *
+ *    Copyright (c) 2020-2024 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.
+ */
+#include <app/util/af.h>
+#include <iostream>
+#include <lib/support/logging/CHIPLogging.h>
+
+#ifdef MATTER_DM_PLUGIN_DOOR_LOCK_SERVER
+#include "chef-lock-manager.h"
+
+using chip::to_underlying;
+
+LockManager LockManager::instance;
+
+LockManager & LockManager::Instance()
+{
+    return instance;
+}
+
+bool LockManager::InitEndpoint(chip::EndpointId endpointId)
+{
+    uint16_t numberOfSupportedUsers = 0;
+    if (!DoorLockServer::Instance().GetNumberOfUserSupported(endpointId, numberOfSupportedUsers))
+    {
+        ChipLogError(Zcl,
+                     "Unable to get number of supported users when initializing lock endpoint, defaulting to 10 [endpointId=%d]",
+                     endpointId);
+        numberOfSupportedUsers = 10;
+    }
+
+    uint16_t numberOfSupportedCredentials = 0;
+    // We're planning to use shared storage for PIN and RFID users so we will have the maximum of both sizes her to simplify logic
+    uint16_t numberOfPINCredentialsSupported  = 0;
+    uint16_t numberOfRFIDCredentialsSupported = 0;
+    if (!DoorLockServer::Instance().GetNumberOfPINCredentialsSupported(endpointId, numberOfPINCredentialsSupported) ||
+        !DoorLockServer::Instance().GetNumberOfRFIDCredentialsSupported(endpointId, numberOfRFIDCredentialsSupported))
+    {
+        ChipLogError(
+            Zcl, "Unable to get number of supported credentials when initializing lock endpoint, defaulting to 10 [endpointId=%d]",
+            endpointId);
+        numberOfSupportedCredentials = 10;
+    }
+    else
+    {
+        numberOfSupportedCredentials = std::max(numberOfPINCredentialsSupported, numberOfRFIDCredentialsSupported);
+    }
+
+    uint8_t numberOfCredentialsSupportedPerUser = 0;
+    if (!DoorLockServer::Instance().GetNumberOfCredentialsSupportedPerUser(endpointId, numberOfCredentialsSupportedPerUser))
+    {
+        ChipLogError(Zcl,
+                     "Unable to get number of credentials supported per user when initializing lock endpoint, defaulting to 5 "
+                     "[endpointId=%d]",
+                     endpointId);
+        numberOfCredentialsSupportedPerUser = 5;
+    }
+
+    uint8_t numberOfWeekDaySchedulesPerUser = 0;
+    if (!DoorLockServer::Instance().GetNumberOfWeekDaySchedulesPerUserSupported(endpointId, numberOfWeekDaySchedulesPerUser))
+    {
+        ChipLogError(Zcl,
+                     "Unable to get number of supported week day schedules per user when initializing lock endpoint, defaulting to "
+                     "10 [endpointId=%d]",
+                     endpointId);
+        numberOfWeekDaySchedulesPerUser = 10;
+    }
+
+    uint8_t numberOfYearDaySchedulesPerUser = 0;
+    if (!DoorLockServer::Instance().GetNumberOfYearDaySchedulesPerUserSupported(endpointId, numberOfYearDaySchedulesPerUser))
+    {
+        ChipLogError(Zcl,
+                     "Unable to get number of supported year day schedules per user when initializing lock endpoint, defaulting to "
+                     "10 [endpointId=%d]",
+                     endpointId);
+        numberOfYearDaySchedulesPerUser = 10;
+    }
+
+    uint8_t numberOfHolidaySchedules = 0;
+    if (!DoorLockServer::Instance().GetNumberOfHolidaySchedulesSupported(endpointId, numberOfHolidaySchedules))
+    {
+        ChipLogError(
+            Zcl,
+            "Unable to get number of supported holiday schedules when initializing lock endpoint, defaulting to 10 [endpointId=%d]",
+            endpointId);
+        numberOfHolidaySchedules = 10;
+    }
+
+    mEndpoints.emplace_back(endpointId, numberOfSupportedUsers, numberOfSupportedCredentials, numberOfWeekDaySchedulesPerUser,
+                            numberOfYearDaySchedulesPerUser, numberOfCredentialsSupportedPerUser, numberOfHolidaySchedules);
+
+    // Refer to 5.2.10.34. SetUser Command, when Creat a new user record
+    //    - UserIndex value SHALL be set to a user record with UserType set to Available
+    //    - UserName MAY be null causing new user record to use empty string for UserName
+    //        otherwise UserName SHALL be set to the value provided in the new user record.
+    //    - UserUniqueID MAY be null causing new user record to use 0xFFFFFFFF for UserUniqueID
+    //        otherwise UserUniqueID SHALL be set to the value provided in the new user record
+    //    - UserStatus MAY be null causing new user record to use OccupiedEnabled for UserStatus
+    //        otherwise UserStatus SHALL be set to the value provided in the new user record
+    //   - UserType MAY be null causing new user record to use UnrestrictedUser for UserType
+    //        otherwise UserType SHALL be set to the value provided in the new user record.
+    uint16_t userIndex(1);
+    chip::FabricIndex creator(1);
+    chip::FabricIndex modifier(1);
+    const chip::CharSpan userName = chip::CharSpan::fromCharString("user1"); // default
+                                                                             // username
+    uint32_t uniqueId         = 0xFFFFFFFF;                                  // null
+    UserStatusEnum userStatus = UserStatusEnum::kOccupiedEnabled;
+    // Set to programming user instead of unrestrict user to perform
+    // priviledged function
+    UserTypeEnum usertype             = UserTypeEnum::kProgrammingUser;
+    CredentialRuleEnum credentialRule = CredentialRuleEnum::kSingle;
+
+    constexpr size_t totalCredentials(2);
+    // According to spec (5.2.6.26.2. CredentialIndex Field), programming PIN credential should be always indexed as 0
+    uint16_t credentialIndex0(0);
+    // 1st non ProgrammingPIN credential should be indexed as 1
+    uint16_t credentialIndex1(1);
+
+    const CredentialStruct credentials[totalCredentials] = {
+        { credentialType : CredentialTypeEnum::kProgrammingPIN, credentialIndex : credentialIndex0 },
+        { credentialType : CredentialTypeEnum::kPin, credentialIndex : credentialIndex1 }
+    };
+
+    if (!SetUser(endpointId, userIndex, creator, modifier, userName, uniqueId, userStatus, usertype, credentialRule,
+                 &credentials[0], totalCredentials))
+    {
+        ChipLogError(Zcl, "Unable to set the User [endpointId=%d]", endpointId);
+        return false;
+    }
+
+    DlCredentialStatus credentialStatus = DlCredentialStatus::kOccupied;
+
+    // Set the default user's ProgrammingPIN credential
+    uint8_t defaultProgrammingPIN[6] = { 0x39, 0x39, 0x39, 0x39, 0x39, 0x39 }; // 000000
+    if (!SetCredential(endpointId, credentialIndex0, creator, modifier, credentialStatus, CredentialTypeEnum::kProgrammingPIN,
+                       chip::ByteSpan(defaultProgrammingPIN)))
+    {
+        ChipLogError(Zcl, "Unable to set the credential - endpoint does not exist or not initialized [endpointId=%d]", endpointId);
+        return false;
+    }
+
+    // Set the default user's non ProgrammingPIN credential
+    uint8_t defaultPin[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 }; // 123456
+    if (!SetCredential(endpointId, credentialIndex1, creator, modifier, credentialStatus, CredentialTypeEnum::kPin,
+                       chip::ByteSpan(defaultPin)))
+    {
+        ChipLogError(Zcl, "Unable to set the credential - endpoint does not exist or not initialized [endpointId=%d]", endpointId);
+        return false;
+    }
+
+    ChipLogProgress(Zcl,
+                    "Initialized new lock door endpoint "
+                    "[id=%d,users=%d,credentials=%d,weekDaySchedulesPerUser=%d,yearDaySchedulesPerUser=%d,"
+                    "numberOfCredentialsSupportedPerUser=%d,holidaySchedules=%d]",
+                    endpointId, numberOfSupportedUsers, numberOfSupportedCredentials, numberOfWeekDaySchedulesPerUser,
+                    numberOfYearDaySchedulesPerUser, numberOfCredentialsSupportedPerUser, numberOfHolidaySchedules);
+
+    return true;
+}
+
+bool LockManager::SetDoorState(chip::EndpointId endpointId, DoorStateEnum doorState)
+{
+    auto lockEndpoint = getEndpoint(endpointId);
+    if (nullptr == lockEndpoint)
+    {
+        ChipLogError(Zcl, "Unable to toggle the door state - endpoint does not exist or not initialized [endpointId=%d]",
+                     endpointId);
+        return false;
+    }
+    return lockEndpoint->SetDoorState(doorState);
+}
+
+bool LockManager::SendLockAlarm(chip::EndpointId endpointId, AlarmCodeEnum alarmCode)
+{
+    auto lockEndpoint = getEndpoint(endpointId);
+    if (nullptr == lockEndpoint)
+    {
+        ChipLogError(Zcl, "Unable to send lock alarm - endpoint does not exist or not initialized [endpointId=%d]", endpointId);
+        return false;
+    }
+    return lockEndpoint->SendLockAlarm(alarmCode);
+}
+
+bool LockManager::Lock(chip::EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx,
+                       const Nullable<chip::NodeId> & nodeId, 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(fabricIdx, nodeId, pin, err, opSource);
+}
+
+bool LockManager::Unlock(chip::EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx,
+                         const Nullable<chip::NodeId> & nodeId, 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(fabricIdx, nodeId, pin, err, opSource);
+}
+
+bool LockManager::Unbolt(chip::EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx,
+                         const Nullable<chip::NodeId> & nodeId, 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(fabricIdx, nodeId, pin, err, opSource);
+}
+
+bool LockManager::GetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user)
+{
+    auto lockEndpoint = getEndpoint(endpointId);
+    if (nullptr == lockEndpoint)
+    {
+        ChipLogError(Zcl, "Unable to get the user - endpoint does not exist or not initialized [endpointId=%d]", endpointId);
+        return false;
+    }
+    return lockEndpoint->GetUser(userIndex, user);
+}
+
+bool LockManager::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)
+{
+    auto lockEndpoint = getEndpoint(endpointId);
+    if (nullptr == lockEndpoint)
+    {
+        ChipLogError(Zcl, "Unable to set the user - endpoint does not exist or not initialized [endpointId=%d]", endpointId);
+        return false;
+    }
+    return lockEndpoint->SetUser(userIndex, creator, modifier, userName, uniqueId, userStatus, usertype, credentialRule,
+                                 credentials, totalCredentials);
+}
+
+bool LockManager::GetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, CredentialTypeEnum credentialType,
+                                EmberAfPluginDoorLockCredentialInfo & credential)
+{
+    auto lockEndpoint = getEndpoint(endpointId);
+    if (nullptr == lockEndpoint)
+    {
+        ChipLogError(Zcl, "Unable to get the credential - endpoint does not exist or not initialized [endpointId=%d]", endpointId);
+        return false;
+    }
+    return lockEndpoint->GetCredential(credentialIndex, credentialType, credential);
+}
+
+bool LockManager::SetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, chip::FabricIndex creator,
+                                chip::FabricIndex modifier, DlCredentialStatus credentialStatus, CredentialTypeEnum credentialType,
+                                const chip::ByteSpan & credentialData)
+{
+    auto lockEndpoint = getEndpoint(endpointId);
+    if (nullptr == lockEndpoint)
+    {
+        ChipLogError(Zcl, "Unable to set the credential - endpoint does not exist or not initialized [endpointId=%d]", endpointId);
+        return false;
+    }
+    return lockEndpoint->SetCredential(credentialIndex, creator, modifier, credentialStatus, credentialType, credentialData);
+}
+
+DlStatus LockManager::GetSchedule(chip::EndpointId endpointId, uint8_t weekDayIndex, uint16_t userIndex,
+                                  EmberAfPluginDoorLockWeekDaySchedule & schedule)
+{
+    auto lockEndpoint = getEndpoint(endpointId);
+    if (nullptr == lockEndpoint)
+    {
+        ChipLogError(Zcl, "Unable to get the week day schedule - endpoint does not exist or not initialized [endpointId=%d]",
+                     endpointId);
+        return DlStatus::kFailure;
+    }
+    return lockEndpoint->GetSchedule(weekDayIndex, userIndex, schedule);
+}
+
+DlStatus LockManager::SetSchedule(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)
+{
+    auto lockEndpoint = getEndpoint(endpointId);
+    if (nullptr == lockEndpoint)
+    {
+        ChipLogError(Zcl, "Unable to set the week day schedule - endpoint does not exist or not initialized [endpointId=%d]",
+                     endpointId);
+        return DlStatus::kFailure;
+    }
+    return lockEndpoint->SetSchedule(weekDayIndex, userIndex, status, daysMask, startHour, startMinute, endHour, endMinute);
+}
+
+DlStatus LockManager::GetSchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex,
+                                  EmberAfPluginDoorLockYearDaySchedule & schedule)
+{
+    auto lockEndpoint = getEndpoint(endpointId);
+    if (nullptr == lockEndpoint)
+    {
+        ChipLogError(Zcl, "Unable to get the year day schedule - endpoint does not exist or not initialized [endpointId=%d]",
+                     endpointId);
+        return DlStatus::kFailure;
+    }
+    return lockEndpoint->GetSchedule(yearDayIndex, userIndex, schedule);
+}
+
+DlStatus LockManager::SetSchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex, DlScheduleStatus status,
+                                  uint32_t localStartTime, uint32_t localEndTime)
+{
+    auto lockEndpoint = getEndpoint(endpointId);
+    if (nullptr == lockEndpoint)
+    {
+        ChipLogError(Zcl, "Unable to set the year day schedule - endpoint does not exist or not initialized [endpointId=%d]",
+                     endpointId);
+        return DlStatus::kFailure;
+    }
+    return lockEndpoint->SetSchedule(yearDayIndex, userIndex, status, localStartTime, localEndTime);
+}
+
+DlStatus LockManager::GetSchedule(chip::EndpointId endpointId, uint8_t holidayIndex,
+                                  EmberAfPluginDoorLockHolidaySchedule & schedule)
+{
+    auto lockEndpoint = getEndpoint(endpointId);
+    if (nullptr == lockEndpoint)
+    {
+        ChipLogError(Zcl, "Unable to get the holiday schedule - endpoint does not exist or not initialized [endpointId=%d]",
+                     endpointId);
+        return DlStatus::kFailure;
+    }
+    return lockEndpoint->GetSchedule(holidayIndex, schedule);
+}
+
+DlStatus LockManager::SetSchedule(chip::EndpointId endpointId, uint8_t holidayIndex, DlScheduleStatus status,
+                                  uint32_t localStartTime, uint32_t localEndTime, OperatingModeEnum operatingMode)
+{
+    auto lockEndpoint = getEndpoint(endpointId);
+    if (nullptr == lockEndpoint)
+    {
+        ChipLogError(Zcl, "Unable to set the holiday schedule - endpoint does not exist or not initialized [endpointId=%d]",
+                     endpointId);
+        return DlStatus::kFailure;
+    }
+    return lockEndpoint->SetSchedule(holidayIndex, status, localStartTime, localEndTime, operatingMode);
+}
+
+LockEndpoint * LockManager::getEndpoint(chip::EndpointId endpointId)
+{
+    for (auto & mEndpoint : mEndpoints)
+    {
+        if (mEndpoint.GetEndpointId() == endpointId)
+        {
+            return &mEndpoint;
+        }
+    }
+    return nullptr;
+}
+#endif // MATTER_DM_PLUGIN_DOOR_LOCK_SERVER
diff --git a/examples/chef/common/clusters/door-lock/chef-lock-manager.h b/examples/chef/common/clusters/door-lock/chef-lock-manager.h
new file mode 100644
index 0000000..709f13c
--- /dev/null
+++ b/examples/chef/common/clusters/door-lock/chef-lock-manager.h
@@ -0,0 +1,78 @@
+/*
+ *
+ *    Copyright (c) 2020-2024 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 "chef-lock-endpoint.h"
+#include <app/clusters/door-lock-server/door-lock-server.h>
+#include <cstdint>
+
+#include <app/util/af.h>
+
+class LockManager
+{
+public:
+    LockManager() = default;
+
+    bool InitEndpoint(chip::EndpointId endpointId);
+
+    bool SetDoorState(chip::EndpointId endpointId, DoorStateEnum doorState);
+
+    bool SendLockAlarm(chip::EndpointId endpointId, AlarmCodeEnum alarmCode);
+
+    bool Lock(chip::EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId,
+              const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource);
+    bool Unlock(chip::EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId,
+                const Optional<chip::ByteSpan> & pin, OperationErrorEnum & err, OperationSourceEnum opSource);
+    bool Unbolt(chip::EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx, const Nullable<chip::NodeId> & nodeId,
+                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,
+                 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 GetSchedule(chip::EndpointId endpointId, uint8_t weekDayIndex, uint16_t userIndex,
+                         EmberAfPluginDoorLockWeekDaySchedule & schedule);
+    DlStatus GetSchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex,
+                         EmberAfPluginDoorLockYearDaySchedule & schedule);
+    DlStatus GetSchedule(chip::EndpointId endpointId, uint8_t holidayIndex, EmberAfPluginDoorLockHolidaySchedule & schedule);
+
+    DlStatus SetSchedule(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 SetSchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex, DlScheduleStatus status,
+                         uint32_t localStartTime, uint32_t localEndTime);
+    DlStatus SetSchedule(chip::EndpointId endpointId, uint8_t holidayIndex, DlScheduleStatus status, uint32_t localStartTime,
+                         uint32_t localEndTime, OperatingModeEnum operatingMode);
+
+    static LockManager & Instance();
+
+private:
+    LockEndpoint * getEndpoint(chip::EndpointId endpointId);
+
+    std::vector<LockEndpoint> mEndpoints;
+
+    static LockManager instance;
+};
diff --git a/examples/chef/common/stubs.cpp b/examples/chef/common/stubs.cpp
index 48c4862..91a7b5a 100644
--- a/examples/chef/common/stubs.cpp
+++ b/examples/chef/common/stubs.cpp
@@ -111,238 +111,6 @@
     return Protocols::InteractionModel::Status::Success;
 }
 
-// Include door lock callbacks only when the server is enabled
-#ifdef MATTER_DM_PLUGIN_DOOR_LOCK_SERVER
-#include <app/clusters/door-lock-server/door-lock-server.h>
-
-class LockManager
-{
-public:
-    static constexpr uint32_t kNumEndpoints              = 1;
-    static constexpr uint32_t kNumUsersPerEndpoint       = 2;
-    static constexpr uint32_t kNumCredentialsPerEndpoint = 20;
-    static constexpr uint32_t kNumCredentialsPerUser     = 10;
-    static constexpr uint32_t kMaxNameLength             = 32;
-    static constexpr uint32_t kMaxDataLength             = 16;
-
-    struct Credential
-    {
-        bool set(DlCredentialStatus status, CredentialTypeEnum type, chip::ByteSpan newData)
-        {
-            if (newData.size() > kMaxDataLength || type != CredentialTypeEnum::kPin)
-                return false;
-            memcpy(data, newData.data(), newData.size());
-            info = EmberAfPluginDoorLockCredentialInfo{
-                status,
-                type,
-                chip::ByteSpan(data, newData.size()),
-            };
-            return true;
-        }
-
-        EmberAfPluginDoorLockCredentialInfo info = { DlCredentialStatus::kAvailable };
-        uint8_t data[kMaxDataLength];
-    };
-
-    struct User
-    {
-        void set(chip::CharSpan newName, uint32_t userId, UserStatusEnum userStatus, UserTypeEnum type,
-                 CredentialRuleEnum credentialRule)
-        {
-            size_t sz = std::min(sizeof(name), newName.size());
-            memcpy(name, newName.data(), sz);
-            info = EmberAfPluginDoorLockUserInfo{
-                chip::CharSpan(name, sz), chip::Span<const CredentialStruct>(), userId, userStatus, type, credentialRule,
-            };
-        }
-        bool addCredential(CredentialTypeEnum type, uint16_t index)
-        {
-            if (info.credentials.size() == kNumCredentialsPerUser)
-                return false;
-            auto & cr          = credentialMap[info.credentials.size()];
-            cr.credentialType  = type;
-            cr.credentialIndex = index;
-            info.credentials   = chip::Span<const CredentialStruct>(credentialMap, info.credentials.size() + 1);
-            return true;
-        }
-
-        EmberAfPluginDoorLockUserInfo info = { .userStatus = UserStatusEnum::kAvailable };
-        char name[kMaxNameLength];
-        CredentialStruct credentialMap[kNumCredentialsPerUser];
-    };
-
-    struct Endpoint
-    {
-        chip::EndpointId id;
-        User users[kNumUsersPerEndpoint];
-        Credential credentials[kNumCredentialsPerEndpoint];
-    };
-
-    static LockManager & Instance()
-    {
-        static LockManager instance;
-        return instance;
-    }
-
-    LockManager() { defaultInitialize(); }
-
-    bool getUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user)
-    {
-        auto ep = findEndpoint(endpointId);
-        if (!ep)
-            return false;
-        if (userIndex >= kNumUsersPerEndpoint)
-            return false;
-        user = ep->users[userIndex].info;
-        return true;
-    }
-
-    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)
-    {
-        auto ep = findEndpoint(endpointId);
-        if (!ep)
-            return false;
-        if (userIndex >= kNumUsersPerEndpoint || totalCredentials > kNumCredentialsPerUser)
-            return false;
-        ep->users[userIndex].set(userName, uniqueId, userStatus, usertype, credentialRule);
-        ep->users[userIndex].info.creationSource     = DlAssetSource::kMatterIM;
-        ep->users[userIndex].info.createdBy          = creator;
-        ep->users[userIndex].info.modificationSource = DlAssetSource::kMatterIM;
-        ep->users[userIndex].info.lastModifiedBy     = modifier;
-        for (size_t i = 0; i < totalCredentials; i++)
-            ep->users[userIndex].addCredential(credentials[i].credentialType, credentials[i].credentialIndex);
-        return true;
-    }
-
-    bool getCredential(chip::EndpointId endpointId, uint16_t credentialIndex, CredentialTypeEnum credentialType,
-                       EmberAfPluginDoorLockCredentialInfo & credential)
-    {
-        auto ep = findEndpoint(endpointId);
-        if (!ep)
-            return false;
-        if (credentialIndex >= kNumCredentialsPerEndpoint)
-            return false;
-        if (credentialType != CredentialTypeEnum::kPin)
-            return false;
-        credential = ep->credentials[credentialIndex].info;
-        return true;
-    }
-
-    bool setCredential(chip::EndpointId endpointId, uint16_t credentialIndex, chip::FabricIndex creator, chip::FabricIndex modifier,
-                       DlCredentialStatus credentialStatus, CredentialTypeEnum credentialType,
-                       const chip::ByteSpan & credentialData)
-    {
-        auto ep = findEndpoint(endpointId);
-        if (!ep)
-            return false;
-        if (credentialIndex >= kNumCredentialsPerEndpoint)
-            return false;
-        if (credentialType != CredentialTypeEnum::kPin)
-            return false;
-        auto & credential = ep->credentials[credentialIndex];
-        if (!credential.set(credentialStatus, credentialType, credentialData))
-            return false;
-        credential.info.creationSource     = DlAssetSource::kMatterIM;
-        credential.info.createdBy          = creator;
-        credential.info.modificationSource = DlAssetSource::kMatterIM;
-        credential.info.lastModifiedBy     = modifier;
-        return true;
-    }
-
-    bool checkPin(chip::EndpointId endpointId, const chip::Optional<chip::ByteSpan> & pinCode,
-                  chip::app::Clusters::DoorLock::OperationErrorEnum & err)
-    {
-        if (!pinCode.HasValue())
-        {
-            err = OperationErrorEnum::kInvalidCredential;
-            return false;
-        }
-        auto ep = findEndpoint(endpointId);
-        if (!ep)
-            return false;
-        for (auto & pin : ep->credentials)
-        {
-            if (pin.info.status == DlCredentialStatus::kOccupied && pin.info.credentialData.data_equal(pinCode.Value()))
-            {
-                return true;
-            }
-        }
-        err = OperationErrorEnum::kInvalidCredential;
-        return false;
-    }
-
-private:
-    Endpoint * findEndpoint(chip::EndpointId endpointId)
-    {
-        for (auto & e : endpoints)
-        {
-            if (e.id == endpointId)
-                return &e;
-        }
-        return nullptr;
-    }
-
-    void defaultInitialize()
-    {
-        endpoints[0].id = 1;
-        uint8_t pin[6]  = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
-        endpoints[0].credentials[0].set(DlCredentialStatus::kOccupied, CredentialTypeEnum::kPin, chip::ByteSpan(pin));
-        endpoints[0].users[0].set("default"_span, 1, UserStatusEnum::kOccupiedEnabled, UserTypeEnum::kUnrestrictedUser,
-                                  CredentialRuleEnum::kSingle);
-        endpoints[0].users[0].addCredential(CredentialTypeEnum::kPin, 1);
-    }
-
-    Endpoint endpoints[kNumEndpoints];
-};
-
-bool emberAfPluginDoorLockOnDoorLockCommand(chip::EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx,
-                                            const Nullable<chip::NodeId> & nodeId, const chip::Optional<chip::ByteSpan> & pinCode,
-                                            chip::app::Clusters::DoorLock::OperationErrorEnum & err)
-{
-    err = OperationErrorEnum::kUnspecified;
-    return DoorLockServer::Instance().SetLockState(endpointId, DlLockState::kLocked);
-}
-
-bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx,
-                                              const Nullable<chip::NodeId> & nodeId, const chip::Optional<chip::ByteSpan> & pinCode,
-                                              chip::app::Clusters::DoorLock::OperationErrorEnum & err)
-{
-    err = OperationErrorEnum::kUnspecified;
-    return DoorLockServer::Instance().SetLockState(endpointId, DlLockState::kUnlocked);
-}
-
-bool emberAfPluginDoorLockGetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user)
-{
-    return LockManager::Instance().getUser(endpointId, userIndex - 1, user);
-}
-
-bool emberAfPluginDoorLockSetUser(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)
-{
-    return LockManager::Instance().setUser(endpointId, userIndex - 1, creator, modifier, userName, uniqueId, userStatus, usertype,
-                                           credentialRule, credentials, totalCredentials);
-}
-
-bool emberAfPluginDoorLockGetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, CredentialTypeEnum credentialType,
-                                        EmberAfPluginDoorLockCredentialInfo & credential)
-{
-    return LockManager::Instance().getCredential(endpointId, credentialIndex - 1, credentialType, credential);
-}
-
-bool emberAfPluginDoorLockSetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, chip::FabricIndex creator,
-                                        chip::FabricIndex modifier, DlCredentialStatus credentialStatus,
-                                        CredentialTypeEnum credentialType, const chip::ByteSpan & credentialData)
-{
-    return LockManager::Instance().setCredential(endpointId, credentialIndex - 1, creator, modifier, credentialStatus,
-                                                 credentialType, credentialData);
-}
-
-#endif /* MATTER_DM_PLUGIN_DOOR_LOCK_SERVER */
-
 void emberAfPluginSmokeCoAlarmSelfTestRequestCommand(EndpointId endpointId) {}
 
 void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
diff --git a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter
index 5819641..bceebc6 100644
--- a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter
+++ b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter
@@ -51,83 +51,6 @@
   command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64;
 }
 
-/** Attributes and commands for group configuration and manipulation. */
-cluster Groups = 4 {
-  revision 4;
-
-  bitmap Feature : bitmap32 {
-    kGroupNames = 0x1;
-  }
-
-  bitmap NameSupportBitmap : bitmap8 {
-    kGroupNames = 0x80;
-  }
-
-  readonly attribute NameSupportBitmap nameSupport = 0;
-  readonly attribute command_id generatedCommandList[] = 65528;
-  readonly attribute command_id acceptedCommandList[] = 65529;
-  readonly attribute event_id eventList[] = 65530;
-  readonly attribute attrib_id attributeList[] = 65531;
-  readonly attribute bitmap32 featureMap = 65532;
-  readonly attribute int16u clusterRevision = 65533;
-
-  request struct AddGroupRequest {
-    group_id groupID = 0;
-    char_string<16> groupName = 1;
-  }
-
-  response struct AddGroupResponse = 0 {
-    enum8 status = 0;
-    group_id groupID = 1;
-  }
-
-  request struct ViewGroupRequest {
-    group_id groupID = 0;
-  }
-
-  response struct ViewGroupResponse = 1 {
-    enum8 status = 0;
-    group_id groupID = 1;
-    char_string<16> groupName = 2;
-  }
-
-  request struct GetGroupMembershipRequest {
-    group_id groupList[] = 0;
-  }
-
-  response struct GetGroupMembershipResponse = 2 {
-    nullable int8u capacity = 0;
-    group_id groupList[] = 1;
-  }
-
-  request struct RemoveGroupRequest {
-    group_id groupID = 0;
-  }
-
-  response struct RemoveGroupResponse = 3 {
-    enum8 status = 0;
-    group_id groupID = 1;
-  }
-
-  request struct AddGroupIfIdentifyingRequest {
-    group_id groupID = 0;
-    char_string<16> groupName = 1;
-  }
-
-  /** Command description for AddGroup */
-  fabric command access(invoke: manage) AddGroup(AddGroupRequest): AddGroupResponse = 0;
-  /** Command description for ViewGroup */
-  fabric command ViewGroup(ViewGroupRequest): ViewGroupResponse = 1;
-  /** Command description for GetGroupMembership */
-  fabric command GetGroupMembership(GetGroupMembershipRequest): GetGroupMembershipResponse = 2;
-  /** Command description for RemoveGroup */
-  fabric command access(invoke: manage) RemoveGroup(RemoveGroupRequest): RemoveGroupResponse = 3;
-  /** Command description for RemoveAllGroups */
-  fabric command access(invoke: manage) RemoveAllGroups(): DefaultSuccess = 4;
-  /** Command description for AddGroupIfIdentifying */
-  fabric command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5;
-}
-
 /** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */
 cluster Descriptor = 29 {
   revision 2;
@@ -161,27 +84,6 @@
   readonly attribute int16u clusterRevision = 65533;
 }
 
-/** The Binding Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for supporting the binding table. */
-cluster Binding = 30 {
-  revision 1; // NOTE: Default/not specifically set
-
-  fabric_scoped struct TargetStruct {
-    optional node_id node = 1;
-    optional group_id group = 2;
-    optional endpoint_no endpoint = 3;
-    optional cluster_id cluster = 4;
-    fabric_idx fabricIndex = 254;
-  }
-
-  attribute access(write: manage) TargetStruct binding[] = 0;
-  readonly attribute command_id generatedCommandList[] = 65528;
-  readonly attribute command_id acceptedCommandList[] = 65529;
-  readonly attribute event_id eventList[] = 65530;
-  readonly attribute attrib_id attributeList[] = 65531;
-  readonly attribute bitmap32 featureMap = 65532;
-  readonly attribute int16u clusterRevision = 65533;
-}
-
 /** The Access Control Cluster exposes a data model view of a
       Node's Access Control List (ACL), which codifies the rules used to manage
       and enforce Access Control for the Node's endpoints and their associated
@@ -569,6 +471,265 @@
   readonly attribute int16u clusterRevision = 65533;
 }
 
+/** This cluster is used to describe the configuration and capabilities of a physical power source that provides power to the Node. */
+cluster PowerSource = 47 {
+  revision 1; // NOTE: Default/not specifically set
+
+  enum BatApprovedChemistryEnum : enum16 {
+    kUnspecified = 0;
+    kAlkaline = 1;
+    kLithiumCarbonFluoride = 2;
+    kLithiumChromiumOxide = 3;
+    kLithiumCopperOxide = 4;
+    kLithiumIronDisulfide = 5;
+    kLithiumManganeseDioxide = 6;
+    kLithiumThionylChloride = 7;
+    kMagnesium = 8;
+    kMercuryOxide = 9;
+    kNickelOxyhydride = 10;
+    kSilverOxide = 11;
+    kZincAir = 12;
+    kZincCarbon = 13;
+    kZincChloride = 14;
+    kZincManganeseDioxide = 15;
+    kLeadAcid = 16;
+    kLithiumCobaltOxide = 17;
+    kLithiumIon = 18;
+    kLithiumIonPolymer = 19;
+    kLithiumIronPhosphate = 20;
+    kLithiumSulfur = 21;
+    kLithiumTitanate = 22;
+    kNickelCadmium = 23;
+    kNickelHydrogen = 24;
+    kNickelIron = 25;
+    kNickelMetalHydride = 26;
+    kNickelZinc = 27;
+    kSilverZinc = 28;
+    kSodiumIon = 29;
+    kSodiumSulfur = 30;
+    kZincBromide = 31;
+    kZincCerium = 32;
+  }
+
+  enum BatChargeFaultEnum : enum8 {
+    kUnspecified = 0;
+    kAmbientTooHot = 1;
+    kAmbientTooCold = 2;
+    kBatteryTooHot = 3;
+    kBatteryTooCold = 4;
+    kBatteryAbsent = 5;
+    kBatteryOverVoltage = 6;
+    kBatteryUnderVoltage = 7;
+    kChargerOverVoltage = 8;
+    kChargerUnderVoltage = 9;
+    kSafetyTimeout = 10;
+  }
+
+  enum BatChargeLevelEnum : enum8 {
+    kOK = 0;
+    kWarning = 1;
+    kCritical = 2;
+  }
+
+  enum BatChargeStateEnum : enum8 {
+    kUnknown = 0;
+    kIsCharging = 1;
+    kIsAtFullCharge = 2;
+    kIsNotCharging = 3;
+  }
+
+  enum BatCommonDesignationEnum : enum16 {
+    kUnspecified = 0;
+    kAAA = 1;
+    kAA = 2;
+    kC = 3;
+    kD = 4;
+    k4v5 = 5;
+    k6v0 = 6;
+    k9v0 = 7;
+    k12AA = 8;
+    kAAAA = 9;
+    kA = 10;
+    kB = 11;
+    kF = 12;
+    kN = 13;
+    kNo6 = 14;
+    kSubC = 15;
+    kA23 = 16;
+    kA27 = 17;
+    kBA5800 = 18;
+    kDuplex = 19;
+    k4SR44 = 20;
+    k523 = 21;
+    k531 = 22;
+    k15v0 = 23;
+    k22v5 = 24;
+    k30v0 = 25;
+    k45v0 = 26;
+    k67v5 = 27;
+    kJ = 28;
+    kCR123A = 29;
+    kCR2 = 30;
+    k2CR5 = 31;
+    kCRP2 = 32;
+    kCRV3 = 33;
+    kSR41 = 34;
+    kSR43 = 35;
+    kSR44 = 36;
+    kSR45 = 37;
+    kSR48 = 38;
+    kSR54 = 39;
+    kSR55 = 40;
+    kSR57 = 41;
+    kSR58 = 42;
+    kSR59 = 43;
+    kSR60 = 44;
+    kSR63 = 45;
+    kSR64 = 46;
+    kSR65 = 47;
+    kSR66 = 48;
+    kSR67 = 49;
+    kSR68 = 50;
+    kSR69 = 51;
+    kSR516 = 52;
+    kSR731 = 53;
+    kSR712 = 54;
+    kLR932 = 55;
+    kA5 = 56;
+    kA10 = 57;
+    kA13 = 58;
+    kA312 = 59;
+    kA675 = 60;
+    kAC41E = 61;
+    k10180 = 62;
+    k10280 = 63;
+    k10440 = 64;
+    k14250 = 65;
+    k14430 = 66;
+    k14500 = 67;
+    k14650 = 68;
+    k15270 = 69;
+    k16340 = 70;
+    kRCR123A = 71;
+    k17500 = 72;
+    k17670 = 73;
+    k18350 = 74;
+    k18500 = 75;
+    k18650 = 76;
+    k19670 = 77;
+    k25500 = 78;
+    k26650 = 79;
+    k32600 = 80;
+  }
+
+  enum BatFaultEnum : enum8 {
+    kUnspecified = 0;
+    kOverTemp = 1;
+    kUnderTemp = 2;
+  }
+
+  enum BatReplaceabilityEnum : enum8 {
+    kUnspecified = 0;
+    kNotReplaceable = 1;
+    kUserReplaceable = 2;
+    kFactoryReplaceable = 3;
+  }
+
+  enum PowerSourceStatusEnum : enum8 {
+    kUnspecified = 0;
+    kActive = 1;
+    kStandby = 2;
+    kUnavailable = 3;
+  }
+
+  enum WiredCurrentTypeEnum : enum8 {
+    kAC = 0;
+    kDC = 1;
+  }
+
+  enum WiredFaultEnum : enum8 {
+    kUnspecified = 0;
+    kOverVoltage = 1;
+    kUnderVoltage = 2;
+  }
+
+  bitmap Feature : bitmap32 {
+    kWired = 0x1;
+    kBattery = 0x2;
+    kRechargeable = 0x4;
+    kReplaceable = 0x8;
+  }
+
+  struct BatChargeFaultChangeType {
+    BatChargeFaultEnum current[] = 0;
+    BatChargeFaultEnum previous[] = 1;
+  }
+
+  struct BatFaultChangeType {
+    BatFaultEnum current[] = 0;
+    BatFaultEnum previous[] = 1;
+  }
+
+  struct WiredFaultChangeType {
+    WiredFaultEnum current[] = 0;
+    WiredFaultEnum previous[] = 1;
+  }
+
+  info event WiredFaultChange = 0 {
+    WiredFaultEnum current[] = 0;
+    WiredFaultEnum previous[] = 1;
+  }
+
+  info event BatFaultChange = 1 {
+    BatFaultEnum current[] = 0;
+    BatFaultEnum previous[] = 1;
+  }
+
+  info event BatChargeFaultChange = 2 {
+    BatChargeFaultEnum current[] = 0;
+    BatChargeFaultEnum previous[] = 1;
+  }
+
+  readonly attribute PowerSourceStatusEnum status = 0;
+  readonly attribute int8u order = 1;
+  readonly attribute char_string<60> description = 2;
+  readonly attribute optional nullable int32u wiredAssessedInputVoltage = 3;
+  readonly attribute optional nullable int16u wiredAssessedInputFrequency = 4;
+  readonly attribute optional WiredCurrentTypeEnum wiredCurrentType = 5;
+  readonly attribute optional nullable int32u wiredAssessedCurrent = 6;
+  readonly attribute optional int32u wiredNominalVoltage = 7;
+  readonly attribute optional int32u wiredMaximumCurrent = 8;
+  readonly attribute optional boolean wiredPresent = 9;
+  readonly attribute optional WiredFaultEnum activeWiredFaults[] = 10;
+  readonly attribute optional nullable int32u batVoltage = 11;
+  readonly attribute optional nullable int8u batPercentRemaining = 12;
+  readonly attribute optional nullable int32u batTimeRemaining = 13;
+  readonly attribute optional BatChargeLevelEnum batChargeLevel = 14;
+  readonly attribute optional boolean batReplacementNeeded = 15;
+  readonly attribute optional BatReplaceabilityEnum batReplaceability = 16;
+  readonly attribute optional boolean batPresent = 17;
+  readonly attribute optional BatFaultEnum activeBatFaults[] = 18;
+  readonly attribute optional char_string<60> batReplacementDescription = 19;
+  readonly attribute optional BatCommonDesignationEnum batCommonDesignation = 20;
+  readonly attribute optional char_string<20> batANSIDesignation = 21;
+  readonly attribute optional char_string<20> batIECDesignation = 22;
+  readonly attribute optional BatApprovedChemistryEnum batApprovedChemistry = 23;
+  readonly attribute optional int32u batCapacity = 24;
+  readonly attribute optional int8u batQuantity = 25;
+  readonly attribute optional BatChargeStateEnum batChargeState = 26;
+  readonly attribute optional nullable int32u batTimeToFullCharge = 27;
+  readonly attribute optional boolean batFunctionalWhileCharging = 28;
+  readonly attribute optional nullable int32u batChargingCurrent = 29;
+  readonly attribute optional BatChargeFaultEnum activeBatChargeFaults[] = 30;
+  readonly attribute endpoint_no endpointList[] = 31;
+  readonly attribute command_id generatedCommandList[] = 65528;
+  readonly attribute command_id acceptedCommandList[] = 65529;
+  readonly attribute event_id eventList[] = 65530;
+  readonly attribute attrib_id attributeList[] = 65531;
+  readonly attribute bitmap32 featureMap = 65532;
+  readonly attribute int16u clusterRevision = 65533;
+}
+
 /** This cluster is used to manage global aspects of the Commissioning flow. */
 cluster GeneralCommissioning = 48 {
   revision 1; // NOTE: Default/not specifically set
@@ -2178,40 +2339,22 @@
   }
 }
 endpoint 1 {
+  device type ma_powersource = 17, version 1;
   device type ma_doorlock = 10, version 1;
 
-  binding cluster Binding;
 
   server cluster Identify {
     ram      attribute identifyTime default = 0x0;
     ram      attribute identifyType default = 0x0;
     callback attribute generatedCommandList;
     callback attribute acceptedCommandList;
+    callback attribute eventList;
     callback attribute attributeList;
     ram      attribute featureMap default = 0;
     ram      attribute clusterRevision default = 2;
 
     handle command Identify;
-  }
-
-  server cluster Groups {
-    ram      attribute nameSupport default = 0;
-    callback attribute generatedCommandList;
-    callback attribute acceptedCommandList;
-    callback attribute attributeList;
-    ram      attribute featureMap default = 0;
-    ram      attribute clusterRevision default = 3;
-
-    handle command AddGroup;
-    handle command AddGroupResponse;
-    handle command ViewGroup;
-    handle command ViewGroupResponse;
-    handle command GetGroupMembership;
-    handle command GetGroupMembershipResponse;
-    handle command RemoveGroup;
-    handle command RemoveGroupResponse;
-    handle command RemoveAllGroups;
-    handle command AddGroupIfIdentifying;
+    handle command TriggerEffect;
   }
 
   server cluster Descriptor {
@@ -2221,39 +2364,90 @@
     callback attribute partsList;
     callback attribute generatedCommandList;
     callback attribute acceptedCommandList;
+    callback attribute eventList;
     callback attribute attributeList;
     callback attribute featureMap;
     callback attribute clusterRevision;
   }
 
+  server cluster PowerSource {
+    ram      attribute status default = 1;
+    ram      attribute order default = 1;
+    ram      attribute description default = "Battery";
+    ram      attribute batVoltage;
+    ram      attribute batPercentRemaining;
+    ram      attribute batTimeRemaining;
+    ram      attribute batChargeLevel;
+    ram      attribute batReplacementNeeded;
+    ram      attribute batReplaceability;
+    ram      attribute batPresent;
+    ram      attribute batReplacementDescription;
+    ram      attribute batQuantity default = 1;
+    callback attribute endpointList;
+    callback attribute generatedCommandList;
+    callback attribute acceptedCommandList;
+    callback attribute eventList;
+    callback attribute attributeList;
+    ram      attribute featureMap default = 0x0A;
+    ram      attribute clusterRevision default = 2;
+  }
+
   server cluster DoorLock {
     emits event DoorLockAlarm;
+    emits event DoorStateChange;
     emits event LockOperation;
     emits event LockOperationError;
+    emits event LockUserChange;
     ram      attribute lockState default = 1;
     ram      attribute lockType default = 0;
     ram      attribute actuatorEnabled default = 0;
-    ram      attribute numberOfTotalUsersSupported default = 2;
-    ram      attribute numberOfPINUsersSupported default = 2;
-    ram      attribute maxPINCodeLength default = 10;
-    ram      attribute minPINCodeLength default = 5;
+    ram      attribute doorState default = 1;
+    ram      attribute doorOpenEvents;
+    ram      attribute doorClosedEvents;
+    ram      attribute numberOfTotalUsersSupported default = 10;
+    ram      attribute numberOfPINUsersSupported default = 10;
+    ram      attribute numberOfRFIDUsersSupported default = 10;
+    ram      attribute numberOfWeekDaySchedulesSupportedPerUser default = 10;
+    ram      attribute numberOfYearDaySchedulesSupportedPerUser default = 10;
+    ram      attribute numberOfHolidaySchedulesSupported default = 10;
+    ram      attribute maxPINCodeLength default = 8;
+    ram      attribute minPINCodeLength default = 6;
+    ram      attribute maxRFIDCodeLength default = 20;
+    ram      attribute minRFIDCodeLength default = 10;
+    ram      attribute credentialRulesSupport default = 1;
     ram      attribute numberOfCredentialsSupportedPerUser default = 5;
-    ram      attribute autoRelockTime default = 0;
+    ram      attribute language default = "en";
+    ram      attribute autoRelockTime default = 5;
+    ram      attribute soundVolume default = 0;
     ram      attribute operatingMode default = 0;
-    ram      attribute supportedOperatingModes default = 0xFFF6;
+    ram      attribute supportedOperatingModes default = 0xFFFF;
+    ram      attribute enableOneTouchLocking default = 0;
+    ram      attribute enablePrivacyModeButton default = 0;
     ram      attribute wrongCodeEntryLimit default = 3;
     ram      attribute userCodeTemporaryDisableTime default = 10;
-    ram      attribute sendPINOverTheAir default = 0;
-    ram      attribute requirePINforRemoteOperation default = 1;
+    ram      attribute requirePINforRemoteOperation default = 0;
     callback attribute generatedCommandList;
     callback attribute acceptedCommandList;
+    callback attribute eventList;
     callback attribute attributeList;
-    ram      attribute featureMap default = 0x0181;
-    ram      attribute clusterRevision default = 6;
+    ram      attribute featureMap default = 0x1DB3;
+    ram      attribute clusterRevision default = 7;
 
     handle command LockDoor;
     handle command UnlockDoor;
     handle command UnlockWithTimeout;
+    handle command SetWeekDaySchedule;
+    handle command GetWeekDaySchedule;
+    handle command GetWeekDayScheduleResponse;
+    handle command ClearWeekDaySchedule;
+    handle command SetYearDaySchedule;
+    handle command GetYearDaySchedule;
+    handle command GetYearDayScheduleResponse;
+    handle command ClearYearDaySchedule;
+    handle command SetHolidaySchedule;
+    handle command GetHolidaySchedule;
+    handle command GetHolidayScheduleResponse;
+    handle command ClearHolidaySchedule;
     handle command SetUser;
     handle command GetUser;
     handle command GetUserResponse;
@@ -2263,6 +2457,7 @@
     handle command GetCredentialStatus;
     handle command GetCredentialStatusResponse;
     handle command ClearCredential;
+    handle command UnboltDoor;
   }
 }
 
diff --git a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.zap b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.zap
index 66f7adb..1e9094f 100644
--- a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.zap
+++ b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.zap
@@ -2480,13 +2480,21 @@
           "profileId": 259,
           "label": "MA-doorlock",
           "name": "MA-doorlock"
+        },
+        {
+          "code": 17,
+          "profileId": 259,
+          "label": "MA-powersource",
+          "name": "MA-powersource"
         }
       ],
       "deviceVersions": [
+        1,
         1
       ],
       "deviceIdentifiers": [
-        10
+        10,
+        17
       ],
       "deviceTypeName": "MA-doorlock",
       "deviceTypeCode": 10,
@@ -2507,6 +2515,14 @@
               "source": "client",
               "isIncoming": 1,
               "isEnabled": 1
+            },
+            {
+              "name": "TriggerEffect",
+              "code": 64,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
             }
           ],
           "attributes": [
@@ -2575,6 +2591,22 @@
               "reportableChange": 0
             },
             {
+              "name": "EventList",
+              "code": 65530,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
               "name": "AttributeList",
               "code": 65531,
               "mfgCode": null,
@@ -2625,194 +2657,6 @@
           ]
         },
         {
-          "name": "Groups",
-          "code": 4,
-          "mfgCode": null,
-          "define": "GROUPS_CLUSTER",
-          "side": "server",
-          "enabled": 1,
-          "commands": [
-            {
-              "name": "AddGroup",
-              "code": 0,
-              "mfgCode": null,
-              "source": "client",
-              "isIncoming": 1,
-              "isEnabled": 1
-            },
-            {
-              "name": "AddGroupResponse",
-              "code": 0,
-              "mfgCode": null,
-              "source": "server",
-              "isIncoming": 0,
-              "isEnabled": 1
-            },
-            {
-              "name": "ViewGroup",
-              "code": 1,
-              "mfgCode": null,
-              "source": "client",
-              "isIncoming": 1,
-              "isEnabled": 1
-            },
-            {
-              "name": "ViewGroupResponse",
-              "code": 1,
-              "mfgCode": null,
-              "source": "server",
-              "isIncoming": 0,
-              "isEnabled": 1
-            },
-            {
-              "name": "GetGroupMembership",
-              "code": 2,
-              "mfgCode": null,
-              "source": "client",
-              "isIncoming": 1,
-              "isEnabled": 1
-            },
-            {
-              "name": "GetGroupMembershipResponse",
-              "code": 2,
-              "mfgCode": null,
-              "source": "server",
-              "isIncoming": 0,
-              "isEnabled": 1
-            },
-            {
-              "name": "RemoveGroup",
-              "code": 3,
-              "mfgCode": null,
-              "source": "client",
-              "isIncoming": 1,
-              "isEnabled": 1
-            },
-            {
-              "name": "RemoveGroupResponse",
-              "code": 3,
-              "mfgCode": null,
-              "source": "server",
-              "isIncoming": 0,
-              "isEnabled": 1
-            },
-            {
-              "name": "RemoveAllGroups",
-              "code": 4,
-              "mfgCode": null,
-              "source": "client",
-              "isIncoming": 1,
-              "isEnabled": 1
-            },
-            {
-              "name": "AddGroupIfIdentifying",
-              "code": 5,
-              "mfgCode": null,
-              "source": "client",
-              "isIncoming": 1,
-              "isEnabled": 1
-            }
-          ],
-          "attributes": [
-            {
-              "name": "NameSupport",
-              "code": 0,
-              "mfgCode": null,
-              "side": "server",
-              "type": "NameSupportBitmap",
-              "included": 1,
-              "storageOption": "RAM",
-              "singleton": 0,
-              "bounded": 0,
-              "defaultValue": "0",
-              "reportable": 1,
-              "minInterval": 1,
-              "maxInterval": 65534,
-              "reportableChange": 0
-            },
-            {
-              "name": "GeneratedCommandList",
-              "code": 65528,
-              "mfgCode": null,
-              "side": "server",
-              "type": "array",
-              "included": 1,
-              "storageOption": "External",
-              "singleton": 0,
-              "bounded": 0,
-              "defaultValue": null,
-              "reportable": 1,
-              "minInterval": 1,
-              "maxInterval": 65534,
-              "reportableChange": 0
-            },
-            {
-              "name": "AcceptedCommandList",
-              "code": 65529,
-              "mfgCode": null,
-              "side": "server",
-              "type": "array",
-              "included": 1,
-              "storageOption": "External",
-              "singleton": 0,
-              "bounded": 0,
-              "defaultValue": null,
-              "reportable": 1,
-              "minInterval": 1,
-              "maxInterval": 65534,
-              "reportableChange": 0
-            },
-            {
-              "name": "AttributeList",
-              "code": 65531,
-              "mfgCode": null,
-              "side": "server",
-              "type": "array",
-              "included": 1,
-              "storageOption": "External",
-              "singleton": 0,
-              "bounded": 0,
-              "defaultValue": null,
-              "reportable": 1,
-              "minInterval": 1,
-              "maxInterval": 65534,
-              "reportableChange": 0
-            },
-            {
-              "name": "FeatureMap",
-              "code": 65532,
-              "mfgCode": null,
-              "side": "server",
-              "type": "bitmap32",
-              "included": 1,
-              "storageOption": "RAM",
-              "singleton": 0,
-              "bounded": 0,
-              "defaultValue": "0",
-              "reportable": 1,
-              "minInterval": 1,
-              "maxInterval": 65534,
-              "reportableChange": 0
-            },
-            {
-              "name": "ClusterRevision",
-              "code": 65533,
-              "mfgCode": null,
-              "side": "server",
-              "type": "int16u",
-              "included": 1,
-              "storageOption": "RAM",
-              "singleton": 0,
-              "bounded": 0,
-              "defaultValue": "3",
-              "reportable": 1,
-              "minInterval": 1,
-              "maxInterval": 65534,
-              "reportableChange": 0
-            }
-          ]
-        },
-        {
           "name": "Descriptor",
           "code": 29,
           "mfgCode": null,
@@ -2917,6 +2761,22 @@
               "reportableChange": 0
             },
             {
+              "name": "EventList",
+              "code": 65530,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
               "name": "AttributeList",
               "code": 65531,
               "mfgCode": null,
@@ -2967,19 +2827,19 @@
           ]
         },
         {
-          "name": "Binding",
-          "code": 30,
+          "name": "Power Source",
+          "code": 47,
           "mfgCode": null,
-          "define": "BINDING_CLUSTER",
-          "side": "client",
+          "define": "POWER_SOURCE_CLUSTER",
+          "side": "server",
           "enabled": 1,
           "attributes": [
             {
-              "name": "ClusterRevision",
-              "code": 65533,
+              "name": "Status",
+              "code": 0,
               "mfgCode": null,
-              "side": "client",
-              "type": "int16u",
+              "side": "server",
+              "type": "PowerSourceStatusEnum",
               "included": 1,
               "storageOption": "RAM",
               "singleton": 0,
@@ -2989,6 +2849,294 @@
               "minInterval": 1,
               "maxInterval": 65534,
               "reportableChange": 0
+            },
+            {
+              "name": "Order",
+              "code": 1,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int8u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "1",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "Description",
+              "code": 2,
+              "mfgCode": null,
+              "side": "server",
+              "type": "char_string",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "Battery",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "BatVoltage",
+              "code": 11,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int32u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "BatPercentRemaining",
+              "code": 12,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int8u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "BatTimeRemaining",
+              "code": 13,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int32u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "BatChargeLevel",
+              "code": 14,
+              "mfgCode": null,
+              "side": "server",
+              "type": "BatChargeLevelEnum",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "BatReplacementNeeded",
+              "code": 15,
+              "mfgCode": null,
+              "side": "server",
+              "type": "boolean",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "BatReplaceability",
+              "code": 16,
+              "mfgCode": null,
+              "side": "server",
+              "type": "BatReplaceabilityEnum",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "BatPresent",
+              "code": 17,
+              "mfgCode": null,
+              "side": "server",
+              "type": "boolean",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "BatReplacementDescription",
+              "code": 19,
+              "mfgCode": null,
+              "side": "server",
+              "type": "char_string",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "BatQuantity",
+              "code": 25,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int8u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "1",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "EndpointList",
+              "code": 31,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "GeneratedCommandList",
+              "code": 65528,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "AcceptedCommandList",
+              "code": 65529,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "EventList",
+              "code": 65530,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "AttributeList",
+              "code": 65531,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "FeatureMap",
+              "code": 65532,
+              "mfgCode": null,
+              "side": "server",
+              "type": "bitmap32",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "0x0A",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "ClusterRevision",
+              "code": 65533,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int16u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "2",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
             }
           ]
         },
@@ -3025,6 +3173,102 @@
               "isEnabled": 1
             },
             {
+              "name": "SetWeekDaySchedule",
+              "code": 11,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
+              "name": "GetWeekDaySchedule",
+              "code": 12,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
+              "name": "GetWeekDayScheduleResponse",
+              "code": 12,
+              "mfgCode": null,
+              "source": "server",
+              "isIncoming": 0,
+              "isEnabled": 1
+            },
+            {
+              "name": "ClearWeekDaySchedule",
+              "code": 13,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
+              "name": "SetYearDaySchedule",
+              "code": 14,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
+              "name": "GetYearDaySchedule",
+              "code": 15,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
+              "name": "GetYearDayScheduleResponse",
+              "code": 15,
+              "mfgCode": null,
+              "source": "server",
+              "isIncoming": 0,
+              "isEnabled": 1
+            },
+            {
+              "name": "ClearYearDaySchedule",
+              "code": 16,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
+              "name": "SetHolidaySchedule",
+              "code": 17,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
+              "name": "GetHolidaySchedule",
+              "code": 18,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
+              "name": "GetHolidayScheduleResponse",
+              "code": 18,
+              "mfgCode": null,
+              "source": "server",
+              "isIncoming": 0,
+              "isEnabled": 1
+            },
+            {
+              "name": "ClearHolidaySchedule",
+              "code": 19,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
               "name": "SetUser",
               "code": 26,
               "mfgCode": null,
@@ -3095,6 +3339,14 @@
               "source": "client",
               "isIncoming": 1,
               "isEnabled": 1
+            },
+            {
+              "name": "UnboltDoor",
+              "code": 39,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
             }
           ],
           "attributes": [
@@ -3147,6 +3399,54 @@
               "reportableChange": 0
             },
             {
+              "name": "DoorState",
+              "code": 3,
+              "mfgCode": null,
+              "side": "server",
+              "type": "DoorStateEnum",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "1",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "DoorOpenEvents",
+              "code": 4,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int32u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "DoorClosedEvents",
+              "code": 5,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int32u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
               "name": "NumberOfTotalUsersSupported",
               "code": 17,
               "mfgCode": null,
@@ -3156,7 +3456,7 @@
               "storageOption": "RAM",
               "singleton": 0,
               "bounded": 0,
-              "defaultValue": "2",
+              "defaultValue": "10",
               "reportable": 1,
               "minInterval": 1,
               "maxInterval": 65534,
@@ -3172,7 +3472,71 @@
               "storageOption": "RAM",
               "singleton": 0,
               "bounded": 0,
-              "defaultValue": "2",
+              "defaultValue": "10",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "NumberOfRFIDUsersSupported",
+              "code": 19,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int16u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "10",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "NumberOfWeekDaySchedulesSupportedPerUser",
+              "code": 20,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int8u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "10",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "NumberOfYearDaySchedulesSupportedPerUser",
+              "code": 21,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int8u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "10",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "NumberOfHolidaySchedulesSupported",
+              "code": 22,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int8u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "10",
               "reportable": 1,
               "minInterval": 1,
               "maxInterval": 65534,
@@ -3188,7 +3552,7 @@
               "storageOption": "RAM",
               "singleton": 0,
               "bounded": 0,
-              "defaultValue": "10",
+              "defaultValue": "8",
               "reportable": 1,
               "minInterval": 1,
               "maxInterval": 65534,
@@ -3204,7 +3568,55 @@
               "storageOption": "RAM",
               "singleton": 0,
               "bounded": 0,
-              "defaultValue": "5",
+              "defaultValue": "6",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "MaxRFIDCodeLength",
+              "code": 25,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int8u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "20",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "MinRFIDCodeLength",
+              "code": 26,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int8u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "10",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "CredentialRulesSupport",
+              "code": 27,
+              "mfgCode": null,
+              "side": "server",
+              "type": "DlCredentialRuleMask",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "1",
               "reportable": 1,
               "minInterval": 1,
               "maxInterval": 65534,
@@ -3227,6 +3639,22 @@
               "reportableChange": 0
             },
             {
+              "name": "Language",
+              "code": 33,
+              "mfgCode": null,
+              "side": "server",
+              "type": "char_string",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "en",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
               "name": "AutoRelockTime",
               "code": 35,
               "mfgCode": null,
@@ -3236,6 +3664,22 @@
               "storageOption": "RAM",
               "singleton": 0,
               "bounded": 0,
+              "defaultValue": "5",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "SoundVolume",
+              "code": 36,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int8u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
               "defaultValue": "0",
               "reportable": 1,
               "minInterval": 1,
@@ -3268,7 +3712,39 @@
               "storageOption": "RAM",
               "singleton": 0,
               "bounded": 0,
-              "defaultValue": "0xFFF6",
+              "defaultValue": "0xFFFF",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "EnableOneTouchLocking",
+              "code": 41,
+              "mfgCode": null,
+              "side": "server",
+              "type": "boolean",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "0",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "EnablePrivacyModeButton",
+              "code": 43,
+              "mfgCode": null,
+              "side": "server",
+              "type": "boolean",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "0",
               "reportable": 1,
               "minInterval": 1,
               "maxInterval": 65534,
@@ -3307,22 +3783,6 @@
               "reportableChange": 0
             },
             {
-              "name": "SendPINOverTheAir",
-              "code": 50,
-              "mfgCode": null,
-              "side": "server",
-              "type": "boolean",
-              "included": 1,
-              "storageOption": "RAM",
-              "singleton": 0,
-              "bounded": 0,
-              "defaultValue": "0",
-              "reportable": 1,
-              "minInterval": 1,
-              "maxInterval": 65534,
-              "reportableChange": 0
-            },
-            {
               "name": "RequirePINforRemoteOperation",
               "code": 51,
               "mfgCode": null,
@@ -3332,7 +3792,7 @@
               "storageOption": "RAM",
               "singleton": 0,
               "bounded": 0,
-              "defaultValue": "1",
+              "defaultValue": "0",
               "reportable": 1,
               "minInterval": 1,
               "maxInterval": 65534,
@@ -3371,6 +3831,22 @@
               "reportableChange": 0
             },
             {
+              "name": "EventList",
+              "code": 65530,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
               "name": "AttributeList",
               "code": 65531,
               "mfgCode": null,
@@ -3396,7 +3872,7 @@
               "storageOption": "RAM",
               "singleton": 0,
               "bounded": 0,
-              "defaultValue": "0x0181",
+              "defaultValue": "0x1DB3",
               "reportable": 1,
               "minInterval": 1,
               "maxInterval": 65534,
@@ -3412,7 +3888,7 @@
               "storageOption": "RAM",
               "singleton": 0,
               "bounded": 0,
-              "defaultValue": "6",
+              "defaultValue": "7",
               "reportable": 1,
               "minInterval": 1,
               "maxInterval": 65534,
@@ -3428,6 +3904,13 @@
               "included": 1
             },
             {
+              "name": "DoorStateChange",
+              "code": 1,
+              "mfgCode": null,
+              "side": "server",
+              "included": 1
+            },
+            {
               "name": "LockOperation",
               "code": 2,
               "mfgCode": null,
@@ -3440,6 +3923,13 @@
               "mfgCode": null,
               "side": "server",
               "included": 1
+            },
+            {
+              "name": "LockUserChange",
+              "code": 4,
+              "mfgCode": null,
+              "side": "server",
+              "included": 1
             }
           ]
         }
@@ -3458,10 +3948,10 @@
     {
       "endpointTypeName": "Anonymous Endpoint Type",
       "endpointTypeIndex": 1,
-      "profileId": 260,
+      "profileId": 259,
       "endpointId": 1,
       "networkId": 0,
       "parentEndpointIdentifier": null
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/examples/chef/esp32/main/CMakeLists.txt b/examples/chef/esp32/main/CMakeLists.txt
index 8278cf9..75cf0b8 100644
--- a/examples/chef/esp32/main/CMakeLists.txt
+++ b/examples/chef/esp32/main/CMakeLists.txt
@@ -63,14 +63,15 @@
                       ${SRC_DIRS_LIST}
                       "${CMAKE_CURRENT_LIST_DIR}"
                       "${CMAKE_SOURCE_DIR}/../common"
-                      "${CMAKE_SOURCE_DIR}/../common/clusters/media-input/"
+                      "${CMAKE_SOURCE_DIR}/../common/clusters/audio-output/"
+                      "${CMAKE_SOURCE_DIR}/../common/clusters/channel/"
+                      "${CMAKE_SOURCE_DIR}/../common/clusters/door-lock/"
+                      "${CMAKE_SOURCE_DIR}/../common/clusters/keypad-input/"
                       "${CMAKE_SOURCE_DIR}/../common/clusters/low-power/"
+                      "${CMAKE_SOURCE_DIR}/../common/clusters/media-input/"
                       "${CMAKE_SOURCE_DIR}/../common/clusters/media-playback/"
                       "${CMAKE_SOURCE_DIR}/../common/clusters/target-navigator/"
                       "${CMAKE_SOURCE_DIR}/../common/clusters/wake-on-lan/"
-                      "${CMAKE_SOURCE_DIR}/../common/clusters/channel/"
-                      "${CMAKE_SOURCE_DIR}/../common/clusters/keypad-input/"
-                      "${CMAKE_SOURCE_DIR}/../common/clusters/audio-output/"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util"
diff --git a/examples/chef/linux/BUILD.gn b/examples/chef/linux/BUILD.gn
index 0a4e238..3cf4bdc 100644
--- a/examples/chef/linux/BUILD.gn
+++ b/examples/chef/linux/BUILD.gn
@@ -49,6 +49,9 @@
     "${project_dir}/common/chef-rvc-operational-state-delegate.cpp",
     "${project_dir}/common/clusters/audio-output/AudioOutputManager.cpp",
     "${project_dir}/common/clusters/channel/ChannelManager.cpp",
+    "${project_dir}/common/clusters/door-lock/chef-doorlock-stubs.cpp",
+    "${project_dir}/common/clusters/door-lock/chef-lock-endpoint.cpp",
+    "${project_dir}/common/clusters/door-lock/chef-lock-manager.cpp",
     "${project_dir}/common/clusters/keypad-input/KeypadInputManager.cpp",
     "${project_dir}/common/clusters/low-power/LowPowerManager.cpp",
     "${project_dir}/common/clusters/media-input/MediaInputManager.cpp",
diff --git a/examples/chef/nrfconnect/CMakeLists.txt b/examples/chef/nrfconnect/CMakeLists.txt
index 25d6632..29b2181 100644
--- a/examples/chef/nrfconnect/CMakeLists.txt
+++ b/examples/chef/nrfconnect/CMakeLists.txt
@@ -88,14 +88,17 @@
     ${CHEF}/common/chef-resource-monitoring-delegates.cpp
     ${CHEF}/common/chef-rvc-mode-delegate.cpp
     ${CHEF}/common/chef-rvc-operational-state-delegate.cpp
-    ${CHEF}/common/clusters/media-input/MediaInputManager.cpp
+    ${CHEF}/common/clusters/audio-output/AudioOutputManager.cpp
+    ${CHEF}/common/clusters/channel/ChannelManager.cpp
+    ${CHEF}/common/clusters/door-lock/chef-doorlock-stubs.cpp
+    ${CHEF}/common/clusters/door-lock/chef-lock-endpoint.cpp
+    ${CHEF}/common/clusters/door-lock/chef-lock-manager.cpp
+    ${CHEF}/common/clusters/keypad-input/KeypadInputManager.cpp
     ${CHEF}/common/clusters/low-power/LowPowerManager.cpp
+    ${CHEF}/common/clusters/media-input/MediaInputManager.cpp
     ${CHEF}/common/clusters/media-playback/MediaPlaybackManager.cpp
     ${CHEF}/common/clusters/target-navigator/TargetNavigatorManager.cpp
     ${CHEF}/common/clusters/wake-on-lan/WakeOnLanManager.cpp
-    ${CHEF}/common/clusters/channel/ChannelManager.cpp
-    ${CHEF}/common/clusters/keypad-input/KeypadInputManager.cpp
-    ${CHEF}/common/clusters/audio-output/AudioOutputManager.cpp
     ${CHEF}/common/stubs.cpp
     ${CHEF}/nrfconnect/main.cpp
 )