From e49d9cabed3898d14bc8dba5095c1f6ade03f8f8 Mon Sep 17 00:00:00 2001 From: Evgeniy Morozov Date: Thu, 27 Jan 2022 18:27:55 +0300 Subject: [PATCH] Implement users and credentials in the Door Lock Cluster (#13789) * Make nextUserIndex nullable in Door Lock as it is required by spec. * Initial implementation of Get/Set/Clear User command. * Refactor User-related commands in Door Lock Cluster * Minor tweaks in commands logging, add todos for events. * Properly handle nullable command arguments in chip-tool * Make more door lock command arguments nullable * Add placeholder implementation for the set credential command * Add missing argument to SetCredential command in Door Lock CLuster * Add basic SetCredential handler for Door Lock cluster. * Add YAML tests for Door Lock cluster (users/credentials) * Adjust underlying data structures for sample Door Lock credentials manager. * Move command handler to the door lock server class * A touch of clean-up in the Door Lock Server. * Add features bitmap to the Door Lock Cluster. * Implement GetCredentialStatus command in Door Lock Cluster. * Fix the door lock cluster feature checks. * Small refactoring of GetCredentialStatus. * Enable RFID attributes in the all-clusters app for now. * Refactor SetCredential command. * Replace unnecessary parameters in the user management of the door lock. * Reorder door lock server functions. Fix compiler errors * Check credential data range * Add documentation for application callbacks related to user management in Door Lock cluster. * Use Span for username and credentials. * Implement ability to modify credentials. * Change ZAP files for door lock app to include all necessary features * Don't use 'using namespace' in header files * Move users/credential database implementation to the door-lock-app. * Remove debug prints in the door lock cluster. * Add more verbose logging to the door lock app. * Make door-lock XML compliant to spec * Add clear credential command * Update door lock test suite to excercise ClearCredential command * Add Lock User Change event to Door Lock Cluster * Use credentials instead of hard-coded PIN when operating the lock * Support programming PIN * Refactor SetCredential command handler * Temporary make credential parameter in clearCredential command nullable to avoid generator errors * Bring back definition to make ESP32 builds work again * Fix format strings and leave out clearCredential logic that is not longer supported * Use appropriate format strings for logging in door lock cluster. * Add implicit casts when adding uint16_t variables to make compiler happy * Temporally ignore Door Lock tests when starting all test. - This is done to avoid fixing github actions for now. - I would like to address the github stuff as a separate fix. * Fix logging types in the door lock app * Fix styling issues * Clear the associated credentials when clearing the user * Make argument in ClearCredential command nullable again because recent changes improved the ZAP generator * Update auto-generated files --- .../all-clusters-app.matter | 24 +- .../all-clusters-common/all-clusters-app.zap | 285 + examples/chip-tool/templates/commands.zapt | 9 +- examples/chip-tool/templates/tests.js | 6 + .../door-lock-common/door-lock-app.matter | 24 +- .../door-lock-common/door-lock-app.zap | 439 +- .../door-lock-app/linux/include/LockManager.h | 47 +- examples/door-lock-app/linux/main.cpp | 27 + .../door-lock-app/linux/src/LockManager.cpp | 219 +- .../tv-casting-common/tv-casting-app.matter | 20 +- scripts/tests/chiptest/__init__.py | 2 + scripts/tests/chiptest/test_definition.py | 5 + .../door-lock-server/door-lock-server.cpp | 2099 +++++- .../door-lock-server/door-lock-server.h | 277 +- src/app/tests/suites/DL_LockUnlock.yaml | 113 + .../tests/suites/DL_UsersAndCredentials.yaml | 2112 ++++++ .../zcl/data-model/chip/door-lock-cluster.xml | 65 +- .../data_model/controller-clusters.matter | 23 +- .../data_model/controller-clusters.zap | 45 + .../java/zap-generated/CHIPCallbackTypes.h | 6 + .../java/zap-generated/CHIPClusters-JNI.cpp | 211 +- .../zap-generated/CHIPInvokeCallbacks.cpp | 15 +- .../chip/devicecontroller/ChipClusters.java | 90 +- .../devicecontroller/ClusterInfoMapping.java | 10 +- .../devicecontroller/ClusterReadMapping.java | 38 + .../python/chip/clusters/CHIPClusters.py | 19 + .../python/chip/clusters/Objects.py | 50 +- .../CHIPAttributeTLVValueDecoder.mm | 33 + .../CHIP/zap-generated/CHIPCallbackBridge.mm | 58 +- .../CHIPCallbackBridge_internal.h | 61 - .../CHIP/zap-generated/CHIPClustersObjc.h | 25 + .../CHIP/zap-generated/CHIPClustersObjc.mm | 141 +- .../zap-generated/CHIPCommandPayloadsObjc.h | 23 +- .../zap-generated/CHIPCommandPayloadsObjc.mm | 24 +- .../CHIP/zap-generated/CHIPTestClustersObjc.h | 4 + .../zap-generated/CHIPTestClustersObjc.mm | 55 + .../Framework/CHIPTests/CHIPClustersTests.m | 75 + .../zap-generated/endpoint_config.h | 436 +- .../zap-generated/cluster-objects.cpp | 4 + .../zap-generated/cluster-objects.h | 76 +- .../app-common/zap-generated/enums.h | 20 + .../zap-generated/cluster/Commands.h | 25 +- .../cluster/logging/DataModelLogger.cpp | 15 + .../chip-tool/zap-generated/test/Commands.h | 5778 +++++++++++++++++ .../zap-generated/CHIPClusters.cpp | 4 +- .../zap-generated/CHIPClusters.h | 2 +- .../zap-generated/endpoint_config.h | 28 +- 47 files changed, 12419 insertions(+), 748 deletions(-) create mode 100644 src/app/tests/suites/DL_LockUnlock.yaml create mode 100644 src/app/tests/suites/DL_UsersAndCredentials.yaml diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index f347f1ec34846b..56ef62d03f69eb 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -756,11 +756,6 @@ server cluster DoorLock = 257 { kModify = 2; } - enum DlDoorLockStatus : ENUM8 { - kDuplicate = 2; - kOccupied = 3; - } - enum DlDoorState : ENUM8 { kDoorOpen = 0; kDoorClosed = 1; @@ -968,11 +963,14 @@ server cluster DoorLock = 257 { attribute int16u openPeriod = 6; readonly attribute int16u numberOfTotalUsersSupported = 17; readonly attribute int16u numberOfPINUsersSupported = 18; + readonly attribute int16u numberOfRFIDUsersSupported = 19; readonly attribute int16u numberOfWeekDaySchedulesSupportedPerUser = 20; readonly attribute int16u numberOfYearDaySchedulesSupportedPerUser = 21; readonly attribute int16u numberOfHolidaySchedulesSupported = 22; readonly attribute int8u maxPINCodeLength = 23; readonly attribute int8u minPINCodeLength = 24; + readonly attribute int8u maxRFIDCodeLength = 25; + readonly attribute int8u minRFIDCodeLength = 26; readonly attribute bitmap8 credentialRulesSupport = 27; attribute char_string<3> language = 33; attribute int32u autoRelockTime = 35; @@ -986,10 +984,11 @@ server cluster DoorLock = 257 { attribute int8u wrongCodeEntryLimit = 48; attribute int8u userCodeTemporaryDisableTime = 49; attribute boolean requirePINforRemoteOperation = 51; + readonly global attribute bitmap32 featureMap = 65532; readonly global attribute int16u clusterRevision = 65533; request struct ClearCredentialRequest { - DlCredential credential = 0; + nullable DlCredential credential = 0; } request struct ClearUserRequest { @@ -1012,8 +1011,9 @@ server cluster DoorLock = 257 { DlDataOperationType operationType = 0; DlCredential credential = 1; LONG_OCTET_STRING credentialData = 2; - INT16U userIndex = 3; - DlUserStatus userStatus = 4; + nullable INT16U userIndex = 3; + nullable DlUserStatus userStatus = 4; + nullable DlUserType userType = 5; } request struct SetUserRequest { @@ -1021,9 +1021,9 @@ server cluster DoorLock = 257 { INT16U userIndex = 1; nullable CHAR_STRING userName = 2; nullable INT32U userUniqueId = 3; - DlUserStatus userStatus = 4; - DlUserType userType = 5; - DlCredentialRule credentialRule = 6; + nullable DlUserStatus userStatus = 4; + nullable DlUserType userType = 5; + nullable DlCredentialRule credentialRule = 6; } request struct UnlockDoorRequest { @@ -1046,7 +1046,7 @@ server cluster DoorLock = 257 { nullable DlCredential credentials[] = 6; nullable fabric_idx creatorFabricIndex = 7; nullable fabric_idx lastModifiedFabricIndex = 8; - INT16U nextUserIndex = 9; + nullable INT16U nextUserIndex = 9; } response struct SetCredentialResponse { diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index 671d9b8b5baff6..6e0df1b1600117 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -10738,6 +10738,21 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "NumberOfRFIDUsersSupported", + "code": 19, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "10", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "NumberOfWeekDaySchedulesSupportedPerUser", "code": 20, @@ -10813,6 +10828,36 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "MaxRFIDCodeLength", + "code": 25, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "20", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinRFIDCodeLength", + "code": 26, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "10", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "CredentialRulesSupport", "code": 27, @@ -10828,6 +10873,21 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "EnableLogging", + "code": 32, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "Language", "code": 33, @@ -10843,6 +10903,21 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "LEDSettings", + "code": 34, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "AutoRelockTime", "code": 35, @@ -10918,6 +10993,21 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "EnableLocalProgramming", + "code": 40, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "EnableOneTouchLocking", "code": 41, @@ -10963,6 +11053,21 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "LocalProgrammingFeatures", + "code": 44, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "WrongCodeEntryLimit", "code": 48, @@ -10993,6 +11098,21 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "SendPINOverTheAir", + "code": 50, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "RequirePINforRemoteOperation", "code": 51, @@ -11008,6 +11128,171 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "ExpiringUserTimeout", + "code": 53, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AlarmMask", + "code": 64, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "KeypadOperationEventMask", + "code": 65, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RemoteOperationEventMask", + "code": 66, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ManualOperationEventMask", + "code": 67, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RFIDOperationEventMask", + "code": 68, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "KeypadProgrammingEventMask", + "code": 69, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RemoteProgrammingEventMask", + "code": 70, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RFIDProgrammingEventMask", + "code": 71, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x103", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "ClusterRevision", "code": 65533, diff --git a/examples/chip-tool/templates/commands.zapt b/examples/chip-tool/templates/commands.zapt index fda28dec81be13..7f0e521f77e6ee 100644 --- a/examples/chip-tool/templates/commands.zapt +++ b/examples/chip-tool/templates/commands.zapt @@ -34,9 +34,12 @@ public: AddArgument("{{asUpperCamelCase label}}", &{{>field}}); {{else}} AddArgument("{{asUpperCamelCase label}}", {{asTypeMinValue type}}, {{asTypeMaxValue type}}, - {{~#if ./isEnum}}reinterpret_castfield}})> *>(&{{>field}}) - {{else ./isBitmap}}reinterpret_cast *>(&{{>field}}) - {{else}}&{{>field}} + {{~#if isNullable}}&{{>field}} + {{else}} + {{~#if ./isEnum}}reinterpret_castfield}})> *>(&{{>field}}) + {{else ./isBitmap}}reinterpret_cast *>(&{{>field}}) + {{else}}&{{>field}} + {{/if~}} {{/if~}} ); {{/if}} diff --git a/examples/chip-tool/templates/tests.js b/examples/chip-tool/templates/tests.js index a85b63d25dc961..f013f26e1bc234 100644 --- a/examples/chip-tool/templates/tests.js +++ b/examples/chip-tool/templates/tests.js @@ -249,6 +249,11 @@ function getTests() 'TestSubscribe_OnOff', ]; + const DoorLock = [ + 'DL_UsersAndCredentials', + 'DL_LockUnlock', + ]; + const tests = [ BinaryInput, // BooleanState, // @@ -279,6 +284,7 @@ function getTests() Others, // SoftwareDiagnostics, // Subscriptions, // + DoorLock, // ]; return tests.flat(1); } diff --git a/examples/door-lock-app/door-lock-common/door-lock-app.matter b/examples/door-lock-app/door-lock-common/door-lock-app.matter index 07cf64dea9adea..664e28863bd57c 100644 --- a/examples/door-lock-app/door-lock-common/door-lock-app.matter +++ b/examples/door-lock-app/door-lock-common/door-lock-app.matter @@ -155,11 +155,6 @@ server cluster DoorLock = 257 { kModify = 2; } - enum DlDoorLockStatus : ENUM8 { - kDuplicate = 2; - kOccupied = 3; - } - enum DlDoorState : ENUM8 { kDoorOpen = 0; kDoorClosed = 1; @@ -364,8 +359,11 @@ server cluster DoorLock = 257 { readonly attribute nullable DlDoorState doorState = 3; readonly attribute int16u numberOfTotalUsersSupported = 17; readonly attribute int16u numberOfPINUsersSupported = 18; + readonly attribute int16u numberOfRFIDUsersSupported = 19; readonly attribute int8u maxPINCodeLength = 23; readonly attribute int8u minPINCodeLength = 24; + readonly attribute int8u maxRFIDCodeLength = 25; + readonly attribute int8u minRFIDCodeLength = 26; readonly attribute bitmap8 credentialRulesSupport = 27; attribute char_string<3> language = 33; attribute int32u autoRelockTime = 35; @@ -376,10 +374,11 @@ server cluster DoorLock = 257 { attribute boolean enablePrivacyModeButton = 43; attribute int8u wrongCodeEntryLimit = 48; attribute int8u userCodeTemporaryDisableTime = 49; + readonly global attribute bitmap32 featureMap = 65532; readonly global attribute int16u clusterRevision = 65533; request struct ClearCredentialRequest { - DlCredential credential = 0; + nullable DlCredential credential = 0; } request struct ClearUserRequest { @@ -402,8 +401,9 @@ server cluster DoorLock = 257 { DlDataOperationType operationType = 0; DlCredential credential = 1; LONG_OCTET_STRING credentialData = 2; - INT16U userIndex = 3; - DlUserStatus userStatus = 4; + nullable INT16U userIndex = 3; + nullable DlUserStatus userStatus = 4; + nullable DlUserType userType = 5; } request struct SetUserRequest { @@ -411,9 +411,9 @@ server cluster DoorLock = 257 { INT16U userIndex = 1; nullable CHAR_STRING userName = 2; nullable INT32U userUniqueId = 3; - DlUserStatus userStatus = 4; - DlUserType userType = 5; - DlCredentialRule credentialRule = 6; + nullable DlUserStatus userStatus = 4; + nullable DlUserType userType = 5; + nullable DlCredentialRule credentialRule = 6; } request struct UnlockDoorRequest { @@ -436,7 +436,7 @@ server cluster DoorLock = 257 { nullable DlCredential credentials[] = 6; nullable fabric_idx creatorFabricIndex = 7; nullable fabric_idx lastModifiedFabricIndex = 8; - INT16U nextUserIndex = 9; + nullable INT16U nextUserIndex = 9; } response struct SetCredentialResponse { diff --git a/examples/door-lock-app/door-lock-common/door-lock-app.zap b/examples/door-lock-app/door-lock-common/door-lock-app.zap index 278988a502dfdb..607fc84155d072 100644 --- a/examples/door-lock-app/door-lock-common/door-lock-app.zap +++ b/examples/door-lock-app/door-lock-common/door-lock-app.zap @@ -6237,6 +6237,66 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "DoorOpenEvents", + "code": 4, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "DoorClosedEvents", + "code": 5, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OpenPeriod", + "code": 6, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfLogRecordsSupported", + "code": 16, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "NumberOfTotalUsersSupported", "code": 17, @@ -6267,6 +6327,66 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "NumberOfRFIDUsersSupported", + "code": 19, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "10", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfWeekDaySchedulesSupportedPerUser", + "code": 20, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfYearDaySchedulesSupportedPerUser", + "code": 21, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfHolidaySchedulesSupported", + "code": 22, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "MaxPINCodeLength", "code": 23, @@ -6276,8 +6396,8 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "6", - "reportable": 1, + "defaultValue": "8", + "reportable": 0, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -6297,6 +6417,36 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "MaxRFIDCodeLength", + "code": 25, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "20", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinRFIDCodeLength", + "code": 26, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "10", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "CredentialRulesSupport", "code": 27, @@ -6312,6 +6462,21 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "EnableLogging", + "code": 32, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "Language", "code": 33, @@ -6327,6 +6492,21 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "LEDSettings", + "code": 34, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "AutoRelockTime", "code": 35, @@ -6387,6 +6567,36 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "DefaultConfigurationRegister", + "code": 39, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EnableLocalProgramming", + "code": 40, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "EnableOneTouchLocking", "code": 41, @@ -6402,6 +6612,21 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "EnableInsideStatusLED", + "code": 42, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "EnablePrivacyModeButton", "code": 43, @@ -6417,6 +6642,21 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "LocalProgrammingFeatures", + "code": 44, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "WrongCodeEntryLimit", "code": 48, @@ -6447,6 +6687,201 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "SendPINOverTheAir", + "code": 50, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RequirePINforRemoteOperation", + "code": 51, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ExpiringUserTimeout", + "code": 53, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AlarmMask", + "code": 64, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "KeypadOperationEventMask", + "code": 65, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RemoteOperationEventMask", + "code": 66, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ManualOperationEventMask", + "code": 67, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RFIDOperationEventMask", + "code": 68, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "KeypadProgrammingEventMask", + "code": 69, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RemoteProgrammingEventMask", + "code": 70, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RFIDProgrammingEventMask", + "code": 71, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x103", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "ClusterRevision", "code": 65533, diff --git a/examples/door-lock-app/linux/include/LockManager.h b/examples/door-lock-app/linux/include/LockManager.h index e2e1bdcec3afe9..80119fd6991c4c 100644 --- a/examples/door-lock-app/linux/include/LockManager.h +++ b/examples/door-lock-app/linux/include/LockManager.h @@ -18,6 +18,7 @@ #pragma once +#include #include #include @@ -25,17 +26,59 @@ #include +struct LockUserInfo +{ + char userName[DOOR_LOCK_USER_NAME_BUFFER_SIZE]; + DlCredential credentials[DOOR_LOCK_MAX_CREDENTIALS_PER_USER]; + size_t totalCredentials; + uint32_t userUniqueId; + DlUserStatus userStatus; + DlUserType userType; + DlCredentialRule credentialRule; + chip::FabricIndex createdBy; + chip::FabricIndex lastModifiedBy; +}; + +static constexpr size_t DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE = 20; + +struct LockCredentialInfo +{ + DlCredentialStatus status; + DlCredentialType credentialType; + uint8_t credentialData[DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE]; + size_t credentialDataSize; +}; + class LockManager { public: - LockManager() : mLocked(false) {} + LockManager() : mLocked(DlLockState::kLocked) {} bool Lock(chip::Optional pin); bool Unlock(chip::Optional pin); + 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, DlUserStatus userStatus, DlUserType usertype, + DlCredentialRule credentialRule, const DlCredential * credentials, size_t totalCredentials); + + bool GetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType, + EmberAfPluginDoorLockCredentialInfo & credential); + + bool SetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialStatus credentialStatus, + DlCredentialType credentialType, const chip::ByteSpan & credentialData); + static LockManager & Instance(); private: - bool mLocked; + bool setLockState(DlLockState lockState, chip::Optional & pin); + const char * lockStateToString(DlLockState lockState); + + DlLockState mLocked; + + // TODO: Support multiple endpoints in the app. + std::array mLockUsers; + // Also include programming User PIN as a zero index + std::array mLockCredentials; static LockManager instance; }; diff --git a/examples/door-lock-app/linux/main.cpp b/examples/door-lock-app/linux/main.cpp index 9193e9afd87378..779a55058370fa 100644 --- a/examples/door-lock-app/linux/main.cpp +++ b/examples/door-lock-app/linux/main.cpp @@ -41,6 +41,33 @@ bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, chip: return LockManager::Instance().Unlock(pinCode); } +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, + DlUserStatus userStatus, DlUserType usertype, DlCredentialRule credentialRule, + const DlCredential * 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, DlCredentialType credentialType, + EmberAfPluginDoorLockCredentialInfo & credential) +{ + return LockManager::Instance().GetCredential(endpointId, credentialIndex, credentialType, credential); +} + +bool emberAfPluginDoorLockSetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialStatus credentialStatus, + DlCredentialType credentialType, const chip::ByteSpan & credentialData) +{ + return LockManager::Instance().SetCredential(endpointId, credentialIndex, credentialStatus, credentialType, credentialData); +} + void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t mask, uint8_t type, uint16_t size, uint8_t * value) { diff --git a/examples/door-lock-app/linux/src/LockManager.cpp b/examples/door-lock-app/linux/src/LockManager.cpp index 9ab302c27e5d85..71c821de4b7533 100644 --- a/examples/door-lock-app/linux/src/LockManager.cpp +++ b/examples/door-lock-app/linux/src/LockManager.cpp @@ -22,6 +22,8 @@ #include #include +using chip::to_underlying; + LockManager LockManager::instance; LockManager & LockManager::Instance() @@ -31,12 +33,223 @@ LockManager & LockManager::Instance() bool LockManager::Lock(chip::Optional pin) { - mLocked = true; - return true; + return setLockState(DlLockState::kLocked, pin); } bool LockManager::Unlock(chip::Optional pin) { - mLocked = false; + return setLockState(DlLockState::kUnlocked, pin); +} + +bool LockManager::GetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user) +{ + ChipLogProgress(Zcl, "Door Lock App: LockManager::GetUser [endpoint=%d,userIndex=%hu]", endpointId, userIndex); + + uint16_t adjustedUserIndex = static_cast(userIndex - 1); + if (adjustedUserIndex > mLockUsers.size()) + { + ChipLogError(Zcl, "Cannot get user - index out of range [endpoint=%d,index=%hu,adjustedIndex=%d]", endpointId, userIndex, + adjustedUserIndex); + return false; + } + + const auto & userInDb = mLockUsers[adjustedUserIndex]; + user.userStatus = userInDb.userStatus; + if (DlUserStatus::kAvailable == user.userStatus) + { + ChipLogDetail(Zcl, "Found unoccupied user [endpoint=%d,adjustedIndex=%hu]", endpointId, adjustedUserIndex); + return true; + } + + user.userName = chip::CharSpan(userInDb.userName, strlen(userInDb.userName)); + user.credentials = chip::Span(userInDb.credentials, userInDb.totalCredentials); + user.userUniqueId = userInDb.userUniqueId; + user.userType = userInDb.userType; + user.credentialRule = userInDb.credentialRule; + user.createdBy = userInDb.createdBy; + user.lastModifiedBy = userInDb.lastModifiedBy; + + ChipLogDetail( + Zcl, + "Found occupied user " + "[endpoint=%d,adjustedIndex=%hu,name=\"%*.s\",credentialsCount=%zu,uniqueId=%x,type=%" PRIu8 ",credentialRule=%" PRIu8 "," + "createdBy=%d,lastModifiedBy=%d]", + endpointId, adjustedUserIndex, static_cast(user.userName.size()), user.userName.data(), user.credentials.size(), + user.userUniqueId, to_underlying(user.userType), to_underlying(user.credentialRule), user.createdBy, user.lastModifiedBy); + + return true; +} + +bool LockManager::SetUser(chip::EndpointId endpointId, uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier, + const chip::CharSpan & userName, uint32_t uniqueId, DlUserStatus userStatus, DlUserType usertype, + DlCredentialRule credentialRule, const DlCredential * credentials, size_t totalCredentials) +{ + ChipLogProgress(Zcl, + "Door Lock App: LockManager::SetUser " + "[endpoint=%d,userIndex=%" PRIu16 ",creator=%d,modifier=%d,userName=\"%*.s\",uniqueId=%" PRIx32 + ",userStatus=%" PRIu8 ",userType=%" PRIu8 "," + "credentialRule=%" PRIu8 ",credentials=%p,totalCredentials=%zu]", + endpointId, userIndex, creator, modifier, static_cast(userName.size()), userName.data(), uniqueId, + to_underlying(userStatus), to_underlying(usertype), to_underlying(credentialRule), credentials, + totalCredentials); + + uint16_t adjustedUserIndex = static_cast(userIndex - 1); + if (adjustedUserIndex > mLockUsers.size()) + { + ChipLogError(Zcl, "Cannot set user - index out of range [endpoint=%d,index=%d,adjustedUserIndex=%" PRIu16 "]", endpointId, + 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=%" PRIu16 "]", + endpointId, userIndex, adjustedUserIndex); + return false; + } + + strncpy(userInStorage.userName, userName.data(), userName.size()); + userInStorage.userName[userName.size()] = 0; + userInStorage.userUniqueId = uniqueId; + userInStorage.userStatus = userStatus; + userInStorage.userType = usertype; + userInStorage.credentialRule = credentialRule; + userInStorage.lastModifiedBy = modifier; + userInStorage.createdBy = creator; + + userInStorage.totalCredentials = totalCredentials; + for (size_t i = 0; i < totalCredentials; ++i) + { + userInStorage.credentials[i] = credentials[i]; + } + + ChipLogProgress(Zcl, "Successfully set the user [endpointId=%d,index=%d,adjustedIndex=%d]", endpointId, userIndex, + adjustedUserIndex); + return true; } + +bool LockManager::GetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType, + EmberAfPluginDoorLockCredentialInfo & credential) +{ + ChipLogProgress(Zcl, + "Door Lock App: LockManager::GetCredential [endpoint=%d,credentialIndex=%" PRIu16 ",credentialType=%" PRIu8 "]", + endpointId, credentialIndex, to_underlying(credentialType)); + + if (credentialIndex >= mLockCredentials.size() || (0 == credentialIndex && DlCredentialType::kProgrammingPIN != credentialType)) + { + ChipLogError(Zcl, "Cannot get the credential - index out of range [endpoint=%d,index=%d]", endpointId, credentialIndex); + return false; + } + + const auto & credentialInStorage = mLockCredentials[credentialIndex]; + + credential.status = credentialInStorage.status; + if (DlCredentialStatus::kAvailable == credential.status) + { + ChipLogDetail(Zcl, "Found unoccupied credential [endpoint=%d,index=%" PRIu16 "]", endpointId, credentialIndex); + return true; + } + credential.credentialType = credentialInStorage.credentialType; + credential.credentialData = chip::ByteSpan(credentialInStorage.credentialData, credentialInStorage.credentialDataSize); + + ChipLogDetail(Zcl, "Found occupied credential [endpoint=%d,index=%" PRIu16 ",type=%" PRIu8 ",dataSize=%zu]", endpointId, + credentialIndex, to_underlying(credential.credentialType), credential.credentialData.size()); + + return true; +} + +bool LockManager::SetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialStatus credentialStatus, + DlCredentialType credentialType, const chip::ByteSpan & credentialData) +{ + ChipLogProgress( + Zcl, + "Door Lock App: LockManager::SetCredential " + "[endpoint=%d,credentialIndex=%" PRIu16 ",credentialStatus=%" PRIu8 ",credentialType=%" PRIu8 ",credentialDataSize=%zu]", + endpointId, credentialIndex, to_underlying(credentialStatus), to_underlying(credentialType), credentialData.size()); + + if (credentialIndex >= mLockCredentials.size() || (0 == credentialIndex && DlCredentialType::kProgrammingPIN != credentialType)) + { + ChipLogError(Zcl, "Cannot set the credential - index out of range [endpoint=%d,index=%d]", endpointId, credentialIndex); + return false; + } + + auto & credentialInStorage = mLockCredentials[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=%zu,maxDataSize=%zu]", + endpointId, credentialIndex, credentialData.size(), DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE); + return false; + } + credentialInStorage.status = credentialStatus; + credentialInStorage.credentialType = credentialType; + std::memcpy(credentialInStorage.credentialData, credentialData.data(), credentialData.size()); + credentialInStorage.credentialDataSize = credentialData.size(); + + ChipLogProgress(Zcl, "Successfully set the credential [endpointId=%d,index=%d,credentialType=%" PRIu8 "]", endpointId, + credentialIndex, to_underlying(credentialType)); + + return true; +} + +bool LockManager::setLockState(DlLockState lockState, chip::Optional & pin) +{ + if (mLocked == lockState) + { + ChipLogDetail(Zcl, "Door Lock App: door is already locked, ignoring command to set lock state to \"%s\"", + lockStateToString(lockState)); + return true; + } + + if (!pin.HasValue()) + { + ChipLogDetail(Zcl, "Door Lock App: PIN code is not specified, setting door lock state to \"%s\"", + lockStateToString(lockState)); + mLocked = lockState; + return true; + } + + // Check the PIN code + for (const auto & pinCredential : mLockCredentials) + { + if (pinCredential.credentialType != DlCredentialType::kPin || pinCredential.status == DlCredentialStatus::kAvailable) + { + continue; + } + + chip::ByteSpan credentialData(pinCredential.credentialData, pinCredential.credentialDataSize); + if (credentialData.data_equal(pin.Value())) + { + ChipLogDetail(Zcl, "Door Lock App: specified PIN code was found in the database, setting door lock state to \"%s\"", + lockStateToString(lockState)); + + mLocked = lockState; + return true; + } + } + + ChipLogDetail(Zcl, + "Door Lock App: specified PIN code was not found in the database, ignoring command to set lock state to \"%s\"", + lockStateToString(lockState)); + + return false; +} + +const char * LockManager::lockStateToString(DlLockState lockState) +{ + switch (lockState) + { + case DlLockState::kNotFullyLocked: + return "Not Fully Locked"; + case DlLockState::kLocked: + return "Locked"; + case DlLockState::kUnlocked: + return "Unlocked"; + } + + return "Unknown"; +} diff --git a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter index 8648b12c5b48e8..0166afd617111e 100644 --- a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter +++ b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter @@ -674,11 +674,6 @@ server cluster DoorLock = 257 { kModify = 2; } - enum DlDoorLockStatus : ENUM8 { - kDuplicate = 2; - kOccupied = 3; - } - enum DlDoorState : ENUM8 { kDoorOpen = 0; kDoorClosed = 1; @@ -907,7 +902,7 @@ server cluster DoorLock = 257 { readonly global attribute int16u clusterRevision = 65533; request struct ClearCredentialRequest { - DlCredential credential = 0; + nullable DlCredential credential = 0; } request struct ClearUserRequest { @@ -930,8 +925,9 @@ server cluster DoorLock = 257 { DlDataOperationType operationType = 0; DlCredential credential = 1; LONG_OCTET_STRING credentialData = 2; - INT16U userIndex = 3; - DlUserStatus userStatus = 4; + nullable INT16U userIndex = 3; + nullable DlUserStatus userStatus = 4; + nullable DlUserType userType = 5; } request struct SetUserRequest { @@ -939,9 +935,9 @@ server cluster DoorLock = 257 { INT16U userIndex = 1; nullable CHAR_STRING userName = 2; nullable INT32U userUniqueId = 3; - DlUserStatus userStatus = 4; - DlUserType userType = 5; - DlCredentialRule credentialRule = 6; + nullable DlUserStatus userStatus = 4; + nullable DlUserType userType = 5; + nullable DlCredentialRule credentialRule = 6; } request struct UnlockDoorRequest { @@ -964,7 +960,7 @@ server cluster DoorLock = 257 { nullable DlCredential credentials[] = 6; nullable fabric_idx creatorFabricIndex = 7; nullable fabric_idx lastModifiedFabricIndex = 8; - INT16U nextUserIndex = 9; + nullable INT16U nextUserIndex = 9; } response struct SetCredentialResponse { diff --git a/scripts/tests/chiptest/__init__.py b/scripts/tests/chiptest/__init__.py index b21fc02f310859..4a10af957a1bdf 100644 --- a/scripts/tests/chiptest/__init__.py +++ b/scripts/tests/chiptest/__init__.py @@ -38,6 +38,8 @@ def AllTests(chip_tool: str): if name.startswith('TV_'): target = TestTarget.TV + elif name.startswith('DL_'): + target = TestTarget.DOOR_LOCK else: target = TestTarget.ALL_CLUSTERS diff --git a/scripts/tests/chiptest/test_definition.py b/scripts/tests/chiptest/test_definition.py index bcd353c2915908..a5ae512d659a1c 100644 --- a/scripts/tests/chiptest/test_definition.py +++ b/scripts/tests/chiptest/test_definition.py @@ -32,6 +32,7 @@ class TestTarget(Enum): ALL_CLUSTERS = auto() TV = auto() + DOOR_LOCK = auto() @dataclass @@ -96,6 +97,10 @@ def Run(self, runner, paths: ApplicationPaths): app_cmd = paths.all_clusters_app elif self.target == TestTarget.TV: app_cmd = paths.tv_app + elif self.target == TestTarget.DOOR_LOCK: + logging.info( + "Ignore test - test is made for door lock which is not supported yet") + return else: raise Exception( "Unknown test target - don't know which application to run") diff --git a/src/app/clusters/door-lock-server/door-lock-server.cpp b/src/app/clusters/door-lock-server/door-lock-server.cpp index c843c2f5afe9e3..af8f98f157b36a 100644 --- a/src/app/clusters/door-lock-server/door-lock-server.cpp +++ b/src/app/clusters/door-lock-server/door-lock-server.cpp @@ -22,23 +22,20 @@ ******************************************************************************/ #include "door-lock-server.h" -#include -#include #include #include #include -#include -#include #include -#include #include #include #include #include +#include #include using namespace chip; +using namespace chip::app::DataModel; using namespace chip::app::Clusters::DoorLock; EmberEventControl emberAfPluginDoorLockServerLockoutEventControl; @@ -46,12 +43,8 @@ EmberEventControl emberAfPluginDoorLockServerRelockEventControl; DoorLockServer DoorLockServer::instance; -// TODO: Remove hardcoded pin when SetCredential command is implemented. -static const uint8_t HARD_CODED_PIN_CODE[] = { 1, 2, 3, 4 }; -chip::ByteSpan mPin(HARD_CODED_PIN_CODE); - /********************************************************** - * DoorLockServer Implementation + * DoorLockServer public methods *********************************************************/ DoorLockServer & DoorLockServer::Instance() @@ -59,226 +52,1986 @@ DoorLockServer & DoorLockServer::Instance() return instance; } -/** - * @brief Initializes given endpoint for a server. - * - * @param endpointId - */ -void DoorLockServer::InitServer(chip::EndpointId endpointId) +/** + * @brief Initializes given endpoint for a server. + * + * @param endpointId + */ +void DoorLockServer::InitServer(chip::EndpointId endpointId) +{ + emberAfDoorLockClusterPrintln("Door Lock cluster initialized at endpoint #%" PRIu16, endpointId); + + SetLockState(endpointId, DlLockState::kLocked); + SetActuatorEnabled(endpointId, true); +} + +bool DoorLockServer::SetLockState(chip::EndpointId endpointId, DlLockState newLockState) +{ + auto lockState = chip::to_underlying(newLockState); + + emberAfDoorLockClusterPrintln("Setting LockState to '%" PRIu8 "'", lockState); + EmberAfStatus status = Attributes::LockState::Set(endpointId, newLockState); + + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "Unable to set LockState attribute: status=0x%" PRIx8, status); + } + + return (EMBER_ZCL_STATUS_SUCCESS == status); +} + +bool DoorLockServer::SetActuatorEnabled(chip::EndpointId endpointId, bool newActuatorState) +{ + auto actuatorState = static_cast(newActuatorState); + + emberAfDoorLockClusterPrintln("Setting ActuatorEnabled to '%" PRIu8 "'", actuatorState); + EmberAfStatus status = Attributes::ActuatorEnabled::Set(endpointId, newActuatorState); + + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "Unable to set ActuatorEnabled attribute: status=0x%" PRIx8, status); + } + + return (EMBER_ZCL_STATUS_SUCCESS == status); +} + +bool DoorLockServer::SetDoorState(chip::EndpointId endpointId, DlDoorState newDoorState) +{ + auto doorState = chip::to_underlying(newDoorState); + + emberAfDoorLockClusterPrintln("Setting DoorState to '%" PRIu8 "'", doorState); + EmberAfStatus status = Attributes::DoorState::Set(endpointId, newDoorState); + + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "Unable to set DoorState attribute: status=0x%" PRIx8, status); + } + + return (EMBER_ZCL_STATUS_SUCCESS == status); +} + +bool DoorLockServer::SetLanguage(chip::EndpointId endpointId, chip::CharSpan newLanguage) +{ + emberAfDoorLockClusterPrintln("Setting Language to '%.*s'", static_cast(newLanguage.size()), newLanguage.data()); + EmberAfStatus status = Attributes::Language::Set(endpointId, newLanguage); + + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "Unable to set Language attribute: status=0x%" PRIx8, status); + } + + return (EMBER_ZCL_STATUS_SUCCESS == status); +} + +bool DoorLockServer::SetAutoRelockTime(chip::EndpointId endpointId, uint32_t newAutoRelockTimeSec) +{ + emberAfDoorLockClusterPrintln("Setting AutoRelockTime to '%" PRIu32 "'", newAutoRelockTimeSec); + EmberAfStatus status = Attributes::AutoRelockTime::Set(endpointId, newAutoRelockTimeSec); + + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "Unable to set AutoRelockTime attribute to %" PRIu32 ": status=0x%" PRIx8, newAutoRelockTimeSec, status); + } + + return (EMBER_ZCL_STATUS_SUCCESS == status); +} + +bool DoorLockServer::SetSoundVolume(chip::EndpointId endpointId, uint8_t newSoundVolume) +{ + emberAfDoorLockClusterPrintln("Setting SoundVolume to '%" PRIu8 "'", newSoundVolume); + EmberAfStatus status = Attributes::SoundVolume::Set(endpointId, newSoundVolume); + + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "Unable to set SoundVolume attribute: status=0x%" PRIx8, status); + } + + return (EMBER_ZCL_STATUS_SUCCESS == status); +} + +bool DoorLockServer::SetOneTouchLocking(chip::EndpointId endpointId, bool isEnabled) +{ + auto enable = static_cast(isEnabled); + + emberAfDoorLockClusterPrintln("Setting EnableOneTouchLocking to '%" PRIu8 "'", enable); + EmberAfStatus status = Attributes::EnableOneTouchLocking::Set(endpointId, isEnabled); + + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "Unable to set EnableOneTouchLocking attribute: status=0x%" PRIx8, status); + } + + return (EMBER_ZCL_STATUS_SUCCESS == status); +} + +bool DoorLockServer::SetPrivacyModeButton(chip::EndpointId endpointId, bool isEnabled) +{ + auto enable = static_cast(isEnabled); + + emberAfDoorLockClusterPrintln("Setting EnablePrivacyModeButton to '%" PRIu8 "'", enable); + EmberAfStatus status = Attributes::EnablePrivacyModeButton::Set(endpointId, isEnabled); + + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "Unable to set EnablePrivacyModeButton attribute: status=0x%" PRIx8, status); + } + + return (EMBER_ZCL_STATUS_SUCCESS == status); +} + +void DoorLockServer::SetUserCommandHandler(chip::app::CommandHandler * commandObj, + const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::SetUser::DecodableType & commandData) +{ + auto & userIndex = commandData.userIndex; + emberAfDoorLockClusterPrintln("[SetUser] Incoming command [endpointId=%d,userIndex=%d]", commandPath.mEndpointId, userIndex); + + if (!SupportsUSR(commandPath.mEndpointId)) + { + emberAfDoorLockClusterPrintln("[SetUser] User management is not supported [endpointId=%d]", commandPath.mEndpointId); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_UNSUPPORTED_COMMAND); + return; + } + + auto fabricIdx = getFabricIndex(commandObj); + if (chip::kUndefinedFabricIndex == fabricIdx) + { + ChipLogError(Zcl, "[SetUser] Unable to get the fabric IDX [endpointId=%d,userIndex=%d]", commandPath.mEndpointId, + userIndex); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return; + } + + auto sourceNodeId = getNodeId(commandObj); + if (chip::kUndefinedNodeId == sourceNodeId) + { + ChipLogError(Zcl, "[SetUser] Unable to get the source node index [endpointId=%d,userIndex=%d]", commandPath.mEndpointId, + userIndex); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return; + } + + auto & operationType = commandData.operationType; + auto & userName = commandData.userName; + auto & userUniqueId = commandData.userUniqueId; + auto & userStatus = commandData.userStatus; + auto & userType = commandData.userType; + auto & credentialRule = commandData.credentialRule; + + if (!userIndexValid(commandPath.mEndpointId, userIndex)) + { + emberAfDoorLockClusterPrintln("[SetUser] User index out of bounds [userIndex=%d]", userIndex); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_COMMAND); + return; + } + + // appclusters, 5.2.4.34: UserName has maximum DOOR_LOCK_MAX_USER_NAME_SIZE (10) characters excluding NUL terminator in it. + if (!userName.IsNull() && userName.Value().size() > DOOR_LOCK_MAX_USER_NAME_SIZE) + { + emberAfDoorLockClusterPrintln( + "[SetUser] Unable to set user: userName too long [endpointId=%d,userIndex=%d,userNameSize=%zu]", + commandPath.mEndpointId, userIndex, userName.Value().size()); + + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_COMMAND); + return; + } + + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + switch (operationType) + { + case DlDataOperationType::kAdd: + status = createUser(commandPath.mEndpointId, fabricIdx, sourceNodeId, userIndex, userName, userUniqueId, userStatus, + userType, credentialRule); + break; + case DlDataOperationType::kModify: + status = modifyUser(commandPath.mEndpointId, fabricIdx, sourceNodeId, userIndex, userName, userUniqueId, userStatus, + userType, credentialRule); + break; + case DlDataOperationType::kClear: + // appclusters, 5.2.4.34: SetUser command allow only kAdd/kModify, we should respond with INVALID_COMMAND if we got kClear + status = EMBER_ZCL_STATUS_INVALID_COMMAND; + break; + } + + emberAfSendImmediateDefaultResponse(status); +} + +void DoorLockServer::GetUserCommandHandler(chip::app::CommandHandler * commandObj, + const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::GetUser::DecodableType & commandData) +{ + auto & userIndex = commandData.userIndex; + + emberAfDoorLockClusterPrintln("[GetUser] Incoming command [endpointId=%d,userIndex=%d]", commandPath.mEndpointId, userIndex); + + if (!SupportsUSR(commandPath.mEndpointId)) + { + emberAfDoorLockClusterPrintln("[GetUser] User management is not supported [endpointId=%d]", commandPath.mEndpointId); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_UNSUPPORTED_COMMAND); + return; + } + + uint16_t maxNumberOfUsers = 0; + if (!userIndexValid(commandPath.mEndpointId, userIndex, maxNumberOfUsers)) + { + emberAfDoorLockClusterPrintln("[GetUser] User index out of bounds [userIndex=%d,numberOfTotalUsersSupported=%d]", userIndex, + maxNumberOfUsers); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_COMMAND); + return; + } + + CHIP_ERROR err = CHIP_NO_ERROR; + EmberAfPluginDoorLockUserInfo user; + VerifyOrExit(emberAfPluginDoorLockGetUser(commandPath.mEndpointId, userIndex, user), err = CHIP_ERROR_INTERNAL); + { + chip::app::ConcreteCommandPath path = { emberAfCurrentEndpoint(), ::Id, Commands::GetUserResponse::Id }; + chip::TLV::TLVWriter * writer; + SuccessOrExit(err = commandObj->PrepareCommand(path)); + VerifyOrExit((writer = commandObj->GetCommandDataIBTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit( + err = writer->Put(chip::TLV::ContextTag(to_underlying(Commands::GetUserResponse::Fields::kUserIndex)), userIndex)); + + using ResponseFields = Commands::GetUserResponse::Fields; + + // appclusters, 5.2.4.36: we should not add user-specific field if the user status is set to Available + if (DlUserStatus::kAvailable != user.userStatus) + { + emberAfDoorLockClusterPrintln("Found user in storage: " + "[userIndex=%d,userName=\"%s\",userStatus=%" PRIu8 ",userType=%" PRIu8 + ",credentialRule=%" PRIu8 ",createdBy=%" PRIu8 ",modifiedBy=%" PRIu8 "]", + userIndex, user.userName.data(), to_underlying(user.userStatus), + to_underlying(user.userType), to_underlying(user.credentialRule), user.createdBy, + user.lastModifiedBy); + + SuccessOrExit(err = writer->PutString(TLV::ContextTag(to_underlying(ResponseFields::kUserName)), user.userName)); + if (0xFFFFFFFFU != user.userUniqueId) + { + SuccessOrExit(err = writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kUserUniqueId)), user.userUniqueId)); + } + SuccessOrExit(err = writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kUserStatus)), user.userStatus)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kUserType)), user.userType)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kCredentialRule)), user.credentialRule)); + if (user.credentials.size() > 0) + { + TLV::TLVType credentialsContainer; + SuccessOrExit(err = writer->StartContainer(TLV::ContextTag(to_underlying(ResponseFields::kCredentials)), + TLV::kTLVType_Array, credentialsContainer)); + for (size_t i = 0; i < user.credentials.size(); ++i) + { + Structs::DlCredential::Type credential; + credential.credentialIndex = user.credentials.data()[i].CredentialIndex; + credential.credentialType = static_cast(user.credentials.data()[i].CredentialType); + SuccessOrExit(err = credential.Encode(*writer, TLV::AnonymousTag())); + } + SuccessOrExit(err = writer->EndContainer(credentialsContainer)); + } + SuccessOrExit(err = writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kCreatorFabricIndex)), user.createdBy)); + SuccessOrExit( + err = writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kLastModifiedFabricIndex)), user.lastModifiedBy)); + } + else + { + emberAfDoorLockClusterPrintln("[GetUser] User not found [userIndex=%d]", userIndex); + } + + // appclusters, 5.2.4.36.1: We need to add next available user after userIndex if any. + uint16_t nextAvailableUserIndex = 0; + if (findUnoccupiedUserSlot(commandPath.mEndpointId, static_cast(userIndex + 1), nextAvailableUserIndex)) + { + SuccessOrExit(err = + writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kNextUserIndex)), nextAvailableUserIndex)); + } + SuccessOrExit(err = commandObj->FinishCommand()); + } + +exit: + if (CHIP_NO_ERROR != err) + { + ChipLogError(Zcl, "[GetUser] Command processing failed [endpointId=%d,userIndex=%d,err=\"%s\"]", commandPath.mEndpointId, + userIndex, err.AsString()); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + } +} + +void DoorLockServer::ClearUserCommandHandler(chip::app::CommandHandler * commandObj, + const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::ClearUser::DecodableType & commandData) +{ + auto & userIndex = commandData.userIndex; + emberAfDoorLockClusterPrintln("[ClearUser] Incoming command [endpointId=%d,userIndex=%d]", commandPath.mEndpointId, userIndex); + + if (!SupportsUSR(commandPath.mEndpointId)) + { + emberAfDoorLockClusterPrintln("[ClearUser] User management is not supported [endpointId=%d]", commandPath.mEndpointId); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_UNSUPPORTED_COMMAND); + return; + } + + auto fabricIdx = getFabricIndex(commandObj); + if (chip::kUndefinedFabricIndex == fabricIdx) + { + ChipLogError(Zcl, "[ClearUser] Unable to get the fabric IDX [endpointId=%d,userIndex=%d]", commandPath.mEndpointId, + userIndex); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return; + } + + auto sourceNodeId = getNodeId(commandObj); + if (chip::kUndefinedNodeId == sourceNodeId) + { + ChipLogError(Zcl, "[ClearUser] Unable to get the source node index [endpointId=%d,userIndex=%d]", commandPath.mEndpointId, + userIndex); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return; + } + + uint16_t maxNumberOfUsers = 0; + if (!userIndexValid(commandPath.mEndpointId, userIndex, maxNumberOfUsers) && userIndex != 0xFFFE) + { + emberAfDoorLockClusterPrintln("[ClearUser] User index out of bounds [userIndex=%d,numberOfTotalUsersSupported=%d]", + userIndex, maxNumberOfUsers); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_COMMAND); + return; + } + + if (0xFFFE != userIndex) + { + auto status = clearUser(commandPath.mEndpointId, fabricIdx, sourceNodeId, userIndex, true); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "[ClearUser] App reported failure when resetting the user [userIndex=%d,status=0x%x]", userIndex, + status); + } + emberAfSendImmediateDefaultResponse(status); + return; + } + + emberAfDoorLockClusterPrintln("[ClearUser] Removing all users from storage"); + for (uint16_t i = 1; i <= maxNumberOfUsers; ++i) + { + auto status = clearUser(commandPath.mEndpointId, fabricIdx, sourceNodeId, i, false); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "[ClearUser] App reported failure when resetting the user [userIndex=%d,status=0x%x]", i, status); + + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return; + } + } + emberAfDoorLockClusterPrintln("[ClearUser] Removed all users from storage [users=%d]", maxNumberOfUsers); + + sendRemoteLockUserChange(commandPath.mEndpointId, DlLockDataType::kUserIndex, DlDataOperationType::kClear, sourceNodeId, + fabricIdx, 0xFFFE, 0xFFFE); + + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); +} + +void DoorLockServer::SetCredentialCommandHandler( + chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::SetCredential::DecodableType & commandData) +{ + emberAfDoorLockClusterPrintln("[SetCredential] Incoming command [endpointId=%d]", commandPath.mEndpointId); + + auto fabricIdx = getFabricIndex(commandObj); + if (kUndefinedFabricIndex == fabricIdx) + { + ChipLogError(Zcl, "[SetCredential] Unable to get the fabric IDX [endpointId=%d]", commandPath.mEndpointId); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return; + } + + auto sourceNodeId = getNodeId(commandObj); + if (chip::kUndefinedNodeId == sourceNodeId) + { + ChipLogError(Zcl, "[SetCredential] Unable to get the source node index [endpointId=%d]", commandPath.mEndpointId); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return; + } + + auto & operationType = commandData.operationType; + auto & credentialType = commandData.credential.credentialType; + auto & credentialIndex = commandData.credential.credentialIndex; + auto & credentialData = commandData.credentialData; + auto & userIndex = commandData.userIndex; + auto & userStatus = commandData.userStatus; + auto & userType = commandData.userType; + + if (!credentialTypeSupported(commandPath.mEndpointId, credentialType)) + { + emberAfDoorLockClusterPrintln("[SetCredential] Credential type is not supported [endpointId=%d,credentialType=%" PRIu8 "]", + commandPath.mEndpointId, to_underlying(credentialType)); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_UNSUPPORTED_COMMAND); + return; + } + + // appclusters, 5.2.4.41: response should contain next available credential slot + uint16_t nextAvailableCredentialSlot = 0; + findUnoccupiedCredentialSlot(commandPath.mEndpointId, credentialType, static_cast(credentialIndex + 1), + nextAvailableCredentialSlot); + + uint16_t maxNumberOfCredentials = 0; + if (!credentialIndexValid(commandPath.mEndpointId, credentialType, credentialIndex, maxNumberOfCredentials)) + { + emberAfDoorLockClusterPrintln("[SetCredential] Credential index is out of range [endpointId=%d,credentialType=%" PRIu8 + ",credentialIndex=%d]", + commandPath.mEndpointId, to_underlying(credentialType), credentialIndex); + sendSetCredentialResponse(commandObj, DlStatus::kInvalidField, 0, nextAvailableCredentialSlot); + return; + } + + // appclusters, 5.2.4.40.3: If the credential data length is out of bounds we should return INVALID_COMMAND + size_t minSize, maxSize; + if (!getCredentialRange(commandPath.mEndpointId, credentialType, minSize, maxSize)) + { + emberAfDoorLockClusterPrintln( + "[SetCredential] Unable to get min/max range for credential: internal error [endpointId=%d,credentialIndex=%d]", + commandPath.mEndpointId, credentialIndex); + sendSetCredentialResponse(commandObj, DlStatus::kFailure, 0, nextAvailableCredentialSlot); + return; + } + if (credentialData.size() < minSize || credentialData.size() > maxSize) + { + emberAfDoorLockClusterPrintln("[SetCredential] Credential data size is out of range " + "[endpointId=%d,credentialType=%" PRIu8 ",minLength=%zu,maxLength=%zu,length=%zu]", + commandPath.mEndpointId, to_underlying(credentialType), minSize, maxSize, + credentialData.size()); + sendSetCredentialResponse(commandObj, DlStatus::kInvalidField, 0, nextAvailableCredentialSlot); + return; + } + + // appclusters, 5.2.4.41.1: we should return DUPLICATE in the response if we're trying to create duplicated credential entry + for (uint16_t i = 1; DlCredentialType::kProgrammingPIN != credentialType && (i <= maxNumberOfCredentials); ++i) + { + EmberAfPluginDoorLockCredentialInfo currentCredential; + if (!emberAfPluginDoorLockGetCredential(commandPath.mEndpointId, i, credentialType, currentCredential)) + { + emberAfDoorLockClusterPrintln("[SetCredential] Unable to get the credential to exclude duplicated entry " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d]", + commandPath.mEndpointId, to_underlying(credentialType), i); + sendSetCredentialResponse(commandObj, DlStatus::kFailure, 0, nextAvailableCredentialSlot); + return; + } + if (DlCredentialStatus::kAvailable != currentCredential.status && currentCredential.credentialType == credentialType && + currentCredential.credentialData.data_equal(credentialData)) + { + emberAfDoorLockClusterPrintln( + "[SetCredential] Credential with the same data and type already exist " + "[endpointId=%d,credentialType=%" PRIu8 ",dataLength=%zu,existingCredentialIndex=%d,credentialIndex=%d]", + commandPath.mEndpointId, to_underlying(credentialType), credentialData.size(), i, credentialIndex); + sendSetCredentialResponse(commandObj, DlStatus::kDuplicate, 0, nextAvailableCredentialSlot); + return; + } + } + + EmberAfPluginDoorLockCredentialInfo existingCredential; + if (!emberAfPluginDoorLockGetCredential(commandPath.mEndpointId, credentialIndex, credentialType, existingCredential)) + { + emberAfDoorLockClusterPrintln( + "[SetCredential] Unable to check if credential exists: app error [endpointId=%d,credentialIndex=%d]", + commandPath.mEndpointId, credentialIndex); + + sendSetCredentialResponse(commandObj, DlStatus::kFailure, 0, nextAvailableCredentialSlot); + return; + } + + switch (operationType) + { + case DlDataOperationType::kAdd: { + uint16_t createdUserIndex = 0; + + DlStatus status = createCredential(commandPath.mEndpointId, fabricIdx, sourceNodeId, credentialIndex, credentialType, + existingCredential, credentialData, userIndex, userStatus, userType, createdUserIndex); + sendSetCredentialResponse(commandObj, status, createdUserIndex, nextAvailableCredentialSlot); + return; + } + case DlDataOperationType::kModify: { + // appclusters, 5.2.4.41.1: should send the INVALID_COMMAND in the response when the credential is in use + if (DlCredentialStatus::kAvailable == existingCredential.status) + { + emberAfDoorLockClusterPrintln("[SetCredential] Unable to modify the credential: credential slot is not occupied " + "[endpointId=%d,credentialIndex=%d]", + commandPath.mEndpointId, credentialIndex); + + sendSetCredentialResponse(commandObj, DlStatus::kInvalidField, 0, nextAvailableCredentialSlot); + return; + } + + // if userIndex is NULL then we're changing the programming user PIN + if (userIndex.IsNull()) + { + auto status = modifyProgrammingPIN(commandPath.mEndpointId, fabricIdx, sourceNodeId, credentialIndex, credentialType, + existingCredential, credentialData); + sendSetCredentialResponse(commandObj, status, 0, nextAvailableCredentialSlot); + return; + } + + auto status = modifyCredential(commandPath.mEndpointId, fabricIdx, sourceNodeId, credentialIndex, credentialType, + existingCredential, credentialData, userIndex.Value(), userStatus, userType); + sendSetCredentialResponse(commandObj, status, 0, nextAvailableCredentialSlot); + return; + } + case DlDataOperationType::kClear: + // appclusters, 5.2.4.40: set credential command supports only Add and Modify operational type. + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_COMMAND); + return; + } + + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); +} + +void DoorLockServer::GetCredentialStatusCommandHandler( + chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::DecodableType & commandData) +{ + emberAfDoorLockClusterPrintln("[GetCredentialStatus] Incoming command [endpointId=%d]", commandPath.mEndpointId); + + const auto & credentialType = commandData.credential.credentialType; + const auto & credentialIndex = commandData.credential.credentialIndex; + + if (!credentialTypeSupported(commandPath.mEndpointId, credentialType)) + { + emberAfDoorLockClusterPrintln("[GetCredentialStatus] Credential type is not supported [endpointId=%d,credentialType=%" PRIu8 + "]", + commandPath.mEndpointId, to_underlying(credentialType)); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_UNSUPPORTED_COMMAND); + return; + } + + uint16_t maxNumberOfCredentials = 0; + if (!credentialIndexValid(commandPath.mEndpointId, credentialType, credentialIndex, maxNumberOfCredentials)) + { + emberAfDoorLockClusterPrintln("[GetCredentialStatus] Credential index is out of range " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,maxNumberOfCredentials=%d]", + commandPath.mEndpointId, to_underlying(credentialType), credentialIndex, + maxNumberOfCredentials); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_COMMAND); + return; + } + + EmberAfPluginDoorLockCredentialInfo credentialInfo; + if (!emberAfPluginDoorLockGetCredential(commandPath.mEndpointId, credentialIndex, credentialType, credentialInfo)) + { + emberAfDoorLockClusterPrintln("[GetCredentialStatus] Unable to get the credential: app error " + "[endpointId=%d,credentialIndex=%d,credentialType=%" PRIu8 "]", + commandPath.mEndpointId, credentialIndex, to_underlying(credentialType)); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return; + } + + auto credentialExists = DlCredentialStatus::kAvailable != credentialInfo.status; + uint16_t userIndexWithCredential = 0; + if (credentialExists) + { + if (!findUserIndexByCredential(commandPath.mEndpointId, credentialType, credentialIndex, userIndexWithCredential)) + { + // That means that there's some kind of error in our database -- there is an unassociated credential. I'm not sure how + // to handle that properly other than panic in the log. + ChipLogError(Zcl, + "[GetCredentialStatus] Database possibly corrupted - credential exists without user assigned " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d]", + commandPath.mEndpointId, to_underlying(credentialType), credentialIndex); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return; + } + } + + uint16_t nextCredentialIndex = 0; + + CHIP_ERROR err = CHIP_NO_ERROR; + using ResponseFields = Commands::GetCredentialStatusResponse::Fields; + app::ConcreteCommandPath path = { emberAfCurrentEndpoint(), ::Id, Commands::GetCredentialStatusResponse::Id }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(path)); + VerifyOrExit((writer = commandObj->GetCommandDataIBTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kCredentialExists)), credentialExists)); + if (0 != userIndexWithCredential) + { + SuccessOrExit(err = writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kUserIndex)), userIndexWithCredential)); + } + if (findUnoccupiedCredentialSlot(commandPath.mEndpointId, credentialType, static_cast(credentialIndex + 1), + nextCredentialIndex)) + { + SuccessOrExit(err = writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kNextCredentialIndex)), nextCredentialIndex)); + } + SuccessOrExit(err = commandObj->FinishCommand()); + + emberAfDoorLockClusterPrintln( + "[GetCredentialStatus] Prepared credential status " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,userIndex=%d,nextCredentialIndex=%d]", + commandPath.mEndpointId, to_underlying(credentialType), credentialIndex, userIndexWithCredential, nextCredentialIndex); + +exit: + if (CHIP_NO_ERROR != err) + { + ChipLogError(Zcl, + "[GetCredentialStatus] Error occurred when preparing response: %s " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,userIndex=%d,nextCredentialIndex=%d]", + err.AsString(), commandPath.mEndpointId, to_underlying(credentialType), credentialIndex, + userIndexWithCredential, nextCredentialIndex); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + } +} + +void DoorLockServer::ClearCredentialCommandHandler( + chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::ClearCredential::DecodableType & commandData) +{ + emberAfDoorLockClusterPrintln("[ClearCredential] Incoming command [endpointId=%d]", commandPath.mEndpointId); + + auto modifier = getFabricIndex(commandObj); + if (kUndefinedFabricIndex == modifier) + { + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return; + } + + auto sourceNodeId = getNodeId(commandObj); + if (chip::kUndefinedNodeId == sourceNodeId) + { + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return; + } + + const auto & credential = commandData.credential; + if (credential.IsNull()) + { + emberAfDoorLockClusterPrintln("[ClearCredential] Clearing all credentials [endpointId=%d]", commandPath.mEndpointId); + emberAfSendImmediateDefaultResponse(clearCredentials(commandPath.mEndpointId, modifier, sourceNodeId)); + return; + } + + // Remove all the credentials of the particular type. + auto credentialType = credential.Value().credentialType; + auto credentialIndex = credential.Value().credentialIndex; + if (0xFFFE == credentialIndex) + { + emberAfSendImmediateDefaultResponse(clearCredentials(commandPath.mEndpointId, modifier, sourceNodeId, credentialType)); + return; + } + + emberAfSendImmediateDefaultResponse( + clearCredential(commandPath.mEndpointId, modifier, sourceNodeId, credentialType, credentialIndex, false)); +} + +void DoorLockServer::LockUnlockDoorCommandHandler(chip::app::CommandHandler * commandObj, + const chip::app::ConcreteCommandPath & commandPath, + DlLockOperationType operationType, const chip::Optional & pinCode) +{ + chip::EndpointId endpoint = commandPath.mEndpointId; + + VerifyOrDie(DlLockOperationType::kLock == operationType || DlLockOperationType::kUnlock == operationType); + + EmberAfDoorLockLockUnlockCommand appCommandHandler = emberAfPluginDoorLockOnDoorLockCommand; + const char * commandNameStr = "LockDoor"; + auto newLockState = DlLockState::kLocked; + if (DlLockOperationType::kUnlock == operationType) + { + newLockState = DlLockState::kUnlocked; + commandNameStr = "UnlockDoor"; + appCommandHandler = emberAfPluginDoorLockOnDoorUnlockCommand; + } + VerifyOrDie(nullptr != commandNameStr); + VerifyOrDie(nullptr != appCommandHandler); + + emberAfDoorLockClusterPrintln("[%s] Received Lock Door command [endpointId=%d]", commandNameStr, endpoint); + + bool require_pin = false; + auto status = Attributes::RequirePINforRemoteOperation::Get(endpoint, &require_pin); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + emberAfDoorLockClusterPrintln( + "[%s] Unable to get value of RequirePINforRemoteOperation attribute, defaulting to 'true' [endpointId=%d,status=%d]", + commandNameStr, endpoint, status); + + require_pin = true; + } + + if (pinCode.HasValue() && !(SupportsPIN(endpoint) && SupportsUSR(endpoint))) + { + emberAfDoorLockClusterPrintln( + "[%s] PIN is supplied but USR and PIN features are disabled - ignoring command [endpointId=%d]", commandNameStr, + endpoint); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_COMMAND); + } + + if (require_pin && !pinCode.HasValue()) + { + emberAfDoorLockClusterPrintln("[%s] PIN is required but not provided - ignoring command [endpointId=%d]", commandNameStr, + endpoint); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_COMMAND); + + return; + } + + // Look up the user index and credential index -- it should be used in the Lock Operation event. However, I don't think we + // should prevent door lock/unlocking if we couldn't find credential associated with user - I think if the app thinks that PIN + // is correct the door should be unlocked. + uint16_t associatedUserIndex = 0; + uint16_t usedCredentialIndex = 0; + if (pinCode.HasValue()) + { + if (!findUserIndexByCredential(endpoint, DlCredentialType::kPin, pinCode.Value(), associatedUserIndex, usedCredentialIndex)) + { + emberAfDoorLockClusterPrintln("[%s] Provided credential is not associated with any user [endpointId=%d]", + commandNameStr, endpoint); + } + } + + // The app is responsible to search through the list of PIN codes internally + if (!appCommandHandler(endpoint, pinCode)) + { + ChipLogError(Zcl, "[%s] Unable to change the door state - internal error [endpointId=%d]", commandNameStr, endpoint); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + + return; + } + + // TODO: Send lock operation change event + SetLockState(endpoint, newLockState); + + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); +} + +bool DoorLockServer::HasFeature(chip::EndpointId endpointId, DoorLockFeature feature) +{ + uint32_t featureMap = 0; + if (EMBER_ZCL_STATUS_SUCCESS != Attributes::FeatureMap::Get(endpointId, &featureMap)) + { + return false; + } + return (featureMap & to_underlying(feature)) != 0; +} + +/********************************************************** + * DoorLockServer private methods + *********************************************************/ + +chip::FabricIndex DoorLockServer::getFabricIndex(const chip::app::CommandHandler * commandObj) +{ + if (nullptr == commandObj || nullptr == commandObj->GetExchangeContext()) + { + ChipLogError(Zcl, "Cannot access ExchangeContext of Command Object for Fabric Index"); + return kUndefinedFabricIndex; + } + + return commandObj->GetAccessingFabricIndex(); +} + +chip::NodeId DoorLockServer::getNodeId(const chip::app::CommandHandler * commandObj) +{ + if (nullptr == commandObj || nullptr == commandObj->GetExchangeContext()) + { + ChipLogError(Zcl, "Cannot access ExchangeContext of Command Object for Node ID"); + return kUndefinedNodeId; + } + + auto secureSession = commandObj->GetExchangeContext()->GetSessionHandle()->AsSecureSession(); + if (nullptr == secureSession) + { + ChipLogError(Zcl, "Cannot access Secure session handle of Command Object for Node ID"); + } + return secureSession->GetPeerNodeId(); +} + +bool DoorLockServer::userIndexValid(chip::EndpointId endpointId, uint16_t userIndex) +{ + uint16_t maxNumberOfUsers; + return userIndexValid(endpointId, userIndex, maxNumberOfUsers); +} + +bool DoorLockServer::userIndexValid(chip::EndpointId endpointId, uint16_t userIndex, uint16_t & maxNumberOfUser) +{ + EmberAfStatus status = Attributes::NumberOfTotalUsersSupported::Get(endpointId, &maxNumberOfUser); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "Unable to read attribute 'NumberOfTotalUsersSupported' [status:%d]", status); + return false; + } + + // appclusters, 5.2.4.34-37: user index changes from 1 to maxNumberOfUsers + if (0 == userIndex || userIndex > maxNumberOfUser) + { + return false; + } + return true; +} + +bool DoorLockServer::credentialIndexValid(chip::EndpointId endpointId, DlCredentialType type, uint16_t credentialIndex) +{ + uint16_t maxCredentials = 0; + return credentialIndexValid(endpointId, type, credentialIndex, maxCredentials); +} + +bool DoorLockServer::credentialIndexValid(chip::EndpointId endpointId, DlCredentialType type, uint16_t credentialIndex, + uint16_t & maxNumberOfCredentials) +{ + if (!getMaxNumberOfCredentials(endpointId, type, maxNumberOfCredentials)) + { + return false; + } + + // appclusters, 5.2.6.3.1: 0 is allowed index for Programming PIN credential only + if (DlCredentialType::kProgrammingPIN == type) + { + return (0 == credentialIndex); + } + + if (0 == credentialIndex || credentialIndex > maxNumberOfCredentials) + { + return false; + } + + return true; +} + +bool DoorLockServer::getCredentialRange(chip::EndpointId endpointId, DlCredentialType type, size_t & minSize, size_t & maxSize) +{ + EmberAfStatus statusMin = EMBER_ZCL_STATUS_SUCCESS, statusMax = EMBER_ZCL_STATUS_SUCCESS; + uint8_t minLen, maxLen; + switch (type) + { + case DlCredentialType::kProgrammingPIN: + case DlCredentialType::kPin: + statusMin = Attributes::MinPINCodeLength::Get(endpointId, &minLen); + statusMax = Attributes::MaxPINCodeLength::Get(endpointId, &maxLen); + break; + case DlCredentialType::kRfid: + statusMin = Attributes::MinRFIDCodeLength::Get(endpointId, &minLen); + statusMax = Attributes::MaxRFIDCodeLength::Get(endpointId, &maxLen); + break; + default: + return false; + } + + if (EMBER_ZCL_STATUS_SUCCESS != statusMin || EMBER_ZCL_STATUS_SUCCESS != statusMax) + { + ChipLogError(Zcl, + "Unable to read attributes to get min/max length for credentials [endpointId=%d,credentialType=%" PRIu8 "]", + endpointId, to_underlying(type)); + return false; + } + + minSize = minLen; + maxSize = maxLen; + + return true; +} + +bool DoorLockServer::getMaxNumberOfCredentials(chip::EndpointId endpointId, DlCredentialType credentialType, + uint16_t & maxNumberOfCredentials) +{ + maxNumberOfCredentials = 0; + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + switch (credentialType) + { + case DlCredentialType::kProgrammingPIN: + maxNumberOfCredentials = 1; + return true; + case DlCredentialType::kPin: + status = Attributes::NumberOfPINUsersSupported::Get(endpointId, &maxNumberOfCredentials); + break; + case DlCredentialType::kRfid: + status = Attributes::NumberOfRFIDUsersSupported::Get(endpointId, &maxNumberOfCredentials); + break; + default: + return false; + } + + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, + "Unable to read an attribute to get the max number of credentials [endpointId=%d,credentialType=%" PRIu8 + ",status=%d]", + endpointId, to_underlying(credentialType), status); + return false; + } + + return true; +} + +bool DoorLockServer::findUnoccupiedUserSlot(chip::EndpointId endpointId, uint16_t & userIndex) +{ + return findUnoccupiedUserSlot(endpointId, 1, userIndex); +} + +bool DoorLockServer::findUnoccupiedUserSlot(chip::EndpointId endpointId, uint16_t startIndex, uint16_t & userIndex) +{ + uint16_t maxNumberOfUsers; + EmberAfStatus status = Attributes::NumberOfTotalUsersSupported::Get(endpointId, &maxNumberOfUsers); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "Unable to read attribute 'NumberOfTotalUsersSupported' [status:%d]", status); + return false; + } + + userIndex = 0; + for (uint16_t i = startIndex; i <= maxNumberOfUsers; ++i) + { + EmberAfPluginDoorLockUserInfo user; + if (!emberAfPluginDoorLockGetUser(endpointId, i, user)) + { + ChipLogError(Zcl, "Unable to get user to check if slot is occupied: app error [status:%d,userIndex=%d]", status, i); + return false; + } + + if (DlUserStatus::kAvailable == user.userStatus) + { + userIndex = i; + return true; + } + } + return false; +} + +bool DoorLockServer::findUnoccupiedCredentialSlot(chip::EndpointId endpointId, DlCredentialType credentialType, uint16_t startIndex, + uint16_t & credentialIndex) +{ + uint16_t maxNumberOfCredentials = 0; + if (!getMaxNumberOfCredentials(endpointId, credentialType, maxNumberOfCredentials)) + { + return false; + } + + // Programming PIN index starts with 0, and it is assumed that it is unique. Therefor different bounds checking for that + // credential type + if (DlCredentialType::kProgrammingPIN == credentialType) + { + maxNumberOfCredentials--; + } + + for (uint16_t i = startIndex; i <= maxNumberOfCredentials; ++i) + { + EmberAfPluginDoorLockCredentialInfo info; + if (!emberAfPluginDoorLockGetCredential(endpointId, i, credentialType, info)) + { + ChipLogError(Zcl, "Unable to get credential: app error [endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d]", + endpointId, to_underlying(credentialType), i); + return false; + } + + if (DlCredentialStatus::kAvailable == info.status) + { + credentialIndex = i; + return true; + } + } + + return false; +} + +bool DoorLockServer::findUserIndexByCredential(chip::EndpointId endpointId, DlCredentialType credentialType, + uint16_t credentialIndex, uint16_t & userIndex) +{ + uint16_t maxNumberOfUsers = 0; + EmberAfStatus status = Attributes::NumberOfTotalUsersSupported::Get(endpointId, &maxNumberOfUsers); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "Unable to read attribute 'NumberOfTotalUsersSupported' [status=%d]", status); + return false; + } + + for (uint16_t i = 1; i <= maxNumberOfUsers; ++i) + { + EmberAfPluginDoorLockUserInfo user; + if (!emberAfPluginDoorLockGetUser(endpointId, i, user)) + { + ChipLogError(Zcl, "[GetCredentialStatus] Unable to get user: app error [status=%d,userIndex=%d]", status, i); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return false; + } + + // Go through occupied users only + if (DlUserStatus::kAvailable == user.userStatus) + { + continue; + } + + for (uint16_t j = 0; j < user.credentials.size(); ++j) + { + if (user.credentials.data()[j].CredentialIndex == credentialIndex && + user.credentials.data()[j].CredentialType == to_underlying(credentialType)) + { + userIndex = i; + return true; + } + } + } + + return false; +} + +bool DoorLockServer::findUserIndexByCredential(chip::EndpointId endpointId, DlCredentialType credentialType, + chip::ByteSpan credentialData, uint16_t & userIndex, uint16_t & credentialIndex) +{ + uint16_t maxNumberOfUsers = 0; + EmberAfStatus status = Attributes::NumberOfTotalUsersSupported::Get(endpointId, &maxNumberOfUsers); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "[findUserIndexByCredential] Unable to read attribute 'NumberOfTotalUsersSupported' [status=%d]", status); + return false; + } + + for (uint16_t i = 1; i <= maxNumberOfUsers; ++i) + { + EmberAfPluginDoorLockUserInfo user; + if (!emberAfPluginDoorLockGetUser(endpointId, i, user)) + { + ChipLogError(Zcl, "[findUserIndexByCredential] Unable to get user: app error [status=%d,userIndex=%d]", status, i); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return false; + } + + // Go through occupied users only + if (DlUserStatus::kAvailable == user.userStatus) + { + continue; + } + + for (const auto & credential : user.credentials) + { + if (credential.CredentialType != to_underlying(credentialType)) + { + continue; + } + + EmberAfPluginDoorLockCredentialInfo credentialInfo; + if (!emberAfPluginDoorLockGetCredential(endpointId, credential.CredentialIndex, credentialType, credentialInfo)) + { + ChipLogError(Zcl, + "[findUserIndexByCredential] Unable to get credential: app error " + "[userIndex=%d,credentialIndex=%d,credentialType=%" PRIu8 "]", + i, credential.CredentialIndex, to_underlying(credentialType)); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return false; + } + + if (credentialInfo.status != DlCredentialStatus::kOccupied) + { + ChipLogError(Zcl, + "[findUserIndexByCredential] Users/Credentials database error: credential index attached to user is " + "not occupied " + "[userIndex=%d,credentialIndex=%d,credentialType=%" PRIu8 "]", + i, credential.CredentialIndex, to_underlying(credentialType)); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return false; + } + + if (credentialInfo.credentialData.data_equal(credentialData)) + { + userIndex = i; + credentialIndex = i; + return true; + } + } + } + + return false; +} + +EmberAfStatus DoorLockServer::createUser(chip::EndpointId endpointId, chip::FabricIndex creatorFabricIdx, chip::NodeId sourceNodeId, + uint16_t userIndex, const Nullable & userName, + const Nullable & userUniqueId, const Nullable & userStatus, + const Nullable & userType, const Nullable & credentialRule, + const Nullable & credential) +{ + EmberAfPluginDoorLockUserInfo user; + if (!emberAfPluginDoorLockGetUser(endpointId, userIndex, user)) + { + ChipLogError(Zcl, "[createUser] Unable to get the user from app [endpointId=%d,userIndex=%d]", endpointId, userIndex); + return EMBER_ZCL_STATUS_FAILURE; + } + + // appclusters, 5.2.4.34: to modify user its status should be set to Available. If it is we should return OCCUPIED. + if (DlUserStatus::kAvailable != user.userStatus) + { + emberAfDoorLockClusterPrintln("[createUser] Unable to overwrite existing user [endpointId=%d,userIndex=%d]", endpointId, + userIndex); + // TODO: Add cluster-specific failure of DlStatus::kOccupied + return EMBER_ZCL_STATUS_FAILURE; + } + + const auto & newUserName = !userName.IsNull() ? userName.Value() : chip::CharSpan(""); + auto newUserUniqueId = userUniqueId.IsNull() ? 0xFFFFFFFF : userUniqueId.Value(); + auto newUserStatus = userStatus.IsNull() ? DlUserStatus::kOccupiedEnabled : userStatus.Value(); + auto newUserType = userType.IsNull() ? DlUserType::kUnrestrictedUser : userType.Value(); + auto newCredentialRule = credentialRule.IsNull() ? DlCredentialRule::kSingle : credentialRule.Value(); + const DlCredential * newCredentials = nullptr; + size_t newTotalCredentials = 0; + if (!credential.IsNull()) + { + newCredentials = &credential.Value(); + newTotalCredentials = 1; + } + + if (!emberAfPluginDoorLockSetUser(endpointId, userIndex, creatorFabricIdx, creatorFabricIdx, newUserName, newUserUniqueId, + newUserStatus, newUserType, newCredentialRule, newCredentials, newTotalCredentials)) + { + emberAfDoorLockClusterPrintln( + "[createUser] Unable to create user: app error " + "[endpointId=%d,creatorFabricId=%d,userIndex=%d,userName=\"%s\",userUniqueId=0x%" PRIx32 ",userStatus=" + "%" PRIu8 ",userType=%" PRIu8 ",credentialRule=%" PRIu8 ",totalCredentials=%zu]", + endpointId, creatorFabricIdx, userIndex, newUserName.data(), newUserUniqueId, to_underlying(newUserStatus), + to_underlying(newUserType), to_underlying(newCredentialRule), newTotalCredentials); + return EMBER_ZCL_STATUS_FAILURE; + } + + emberAfDoorLockClusterPrintln( + "[createUser] User created " + "[endpointId=%d,creatorFabricId=%d,userIndex=%d,userName=\"%s\",userUniqueId=0x%" PRIx32 ",userStatus=%" + "" PRIu8 ",userType=%" PRIu8 ",credentialRule=%" PRIu8 ",totalCredentials=%zu]", + endpointId, creatorFabricIdx, userIndex, newUserName.data(), newUserUniqueId, to_underlying(newUserStatus), + to_underlying(newUserType), to_underlying(newCredentialRule), newTotalCredentials); + + sendRemoteLockUserChange(endpointId, DlLockDataType::kUserIndex, DlDataOperationType::kAdd, sourceNodeId, creatorFabricIdx, + userIndex, userIndex); + + return EMBER_ZCL_STATUS_SUCCESS; +} + +EmberAfStatus DoorLockServer::modifyUser(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIndex, + chip::NodeId sourceNodeId, uint16_t userIndex, const Nullable & userName, + const Nullable & userUniqueId, const Nullable & userStatus, + const Nullable & userType, const Nullable & credentialRule) +{ + // We should get the user by that index first + EmberAfPluginDoorLockUserInfo user; + if (!emberAfPluginDoorLockGetUser(endpointId, userIndex, user)) + { + ChipLogError(Zcl, "[modifyUser] Unable to get the user from app [endpointId=%d,userIndex=%d]", endpointId, userIndex); + return EMBER_ZCL_STATUS_FAILURE; + } + + // appclusters, 5.2.4.34: to modify user its status should NOT be set to Available. If it is we should return INVALID_COMMAND. + if (DlUserStatus::kAvailable == user.userStatus) + { + emberAfDoorLockClusterPrintln("[modifyUser] Unable to modify non-existing user [endpointId=%d,userIndex=%d]", endpointId, + userIndex); + return EMBER_ZCL_STATUS_INVALID_COMMAND; + } + + // appclusters, 5.2.4.34: UserName SHALL be null if modifying a user record that was not created by the accessing fabric + if (user.createdBy != modifierFabricIndex && !userName.IsNull()) + { + emberAfDoorLockClusterPrintln("[modifyUser] Unable to modify name of user created by different fabric " + "[endpointId=%d,userIndex=%d,creatorIdx=%d,modifierIdx=%d]", + endpointId, userIndex, user.createdBy, modifierFabricIndex); + return EMBER_ZCL_STATUS_INVALID_COMMAND; + } + + // appclusters, 5.2.4.34: UserUniqueID SHALL be null if modifying the user record that was not created by the accessing fabric. + if (user.createdBy != modifierFabricIndex && !userUniqueId.IsNull()) + { + emberAfDoorLockClusterPrintln("[modifyUser] Unable to modify UUID of user created by different fabric " + "[endpointId=%d,userIndex=%d,creatorIdx=%d,modifierIdx=%d]", + endpointId, userIndex, user.createdBy, modifierFabricIndex); + return EMBER_ZCL_STATUS_INVALID_COMMAND; + } + + const auto & newUserName = !userName.IsNull() ? userName.Value() : user.userName; + auto newUserUniqueId = userUniqueId.IsNull() ? user.userUniqueId : userUniqueId.Value(); + auto newUserStatus = userStatus.IsNull() ? user.userStatus : userStatus.Value(); + auto newUserType = userType.IsNull() ? user.userType : userType.Value(); + auto newCredentialRule = credentialRule.IsNull() ? user.credentialRule : credentialRule.Value(); + + if (!emberAfPluginDoorLockSetUser(endpointId, userIndex, user.createdBy, modifierFabricIndex, newUserName, newUserUniqueId, + newUserStatus, newUserType, newCredentialRule, user.credentials.data(), + user.credentials.size())) + { + ChipLogError(Zcl, + "[modifyUser] Unable to modify the user: app error " + "[endpointId=%d,modifierFabric=%d,userIndex=%d,userName=\"%s\",userUniqueId=0x%" PRIx32 ",userStatus=%" PRIu8 + ",userType=%" PRIu8 ",credentialRule=%" PRIu8 "]", + endpointId, modifierFabricIndex, userIndex, newUserName.data(), newUserUniqueId, to_underlying(newUserStatus), + to_underlying(newUserType), to_underlying(newCredentialRule)); + return EMBER_ZCL_STATUS_FAILURE; + } + + emberAfDoorLockClusterPrintln("[modifyUser] User modified " + "[endpointId=%d,modifierFabric=%d,userIndex=%d,userName=\"%s\",userUniqueId=0x%" PRIx32 + ",userStatus=%" PRIu8 "," + "userType=%" PRIu8 ",credentialRule=%" PRIu8 "]", + endpointId, modifierFabricIndex, userIndex, newUserName.data(), newUserUniqueId, + to_underlying(newUserStatus), to_underlying(newUserType), to_underlying(newCredentialRule)); + + sendRemoteLockUserChange(endpointId, DlLockDataType::kUserIndex, DlDataOperationType::kModify, sourceNodeId, + modifierFabricIndex, userIndex, userIndex); + + return EMBER_ZCL_STATUS_SUCCESS; +} + +EmberAfStatus DoorLockServer::clearUser(chip::EndpointId endpointId, chip::FabricIndex modifierFabricId, chip::NodeId sourceNodeId, + uint16_t userIndex, bool sendUserChangeEvent) +{ + EmberAfPluginDoorLockUserInfo user; + if (!emberAfPluginDoorLockGetUser(endpointId, userIndex, user)) + { + return EMBER_ZCL_STATUS_FAILURE; + } + + return clearUser(endpointId, modifierFabricId, sourceNodeId, userIndex, user, sendUserChangeEvent); +} + +EmberAfStatus DoorLockServer::clearUser(chip::EndpointId endpointId, chip::FabricIndex modifierFabricId, chip::NodeId sourceNodeId, + uint16_t userIndex, const EmberAfPluginDoorLockUserInfo & user, bool sendUserChangeEvent) +{ + // appclusters, 5.2.4.37: all the credentials associated with user should be cleared when clearing the user + for (const auto & credential : user.credentials) + { + emberAfDoorLockClusterPrintln( + "[ClearUser] Clearing associated credential [endpointId=%d,userIndex=%d,credentialType=%" PRIu8 ",credentialIndex=%d]", + endpointId, userIndex, credential.CredentialType, credential.CredentialIndex); + + if (!emberAfPluginDoorLockSetCredential(endpointId, credential.CredentialIndex, DlCredentialStatus::kAvailable, + static_cast(credential.CredentialType), chip::ByteSpan())) + { + ChipLogError(Zcl, + "[ClearUser] Unable to remove credentials associated with user - internal error " + "[endpointId=%d,userIndex=%d,credentialIndex=%d,credentialType=%" PRIu8 "]", + endpointId, userIndex, credential.CredentialIndex, credential.CredentialType); + return EMBER_ZCL_STATUS_FAILURE; + } + } + + // TODO: Remove all the user schedules + + // Remove the user entry + if (!emberAfPluginDoorLockSetUser(endpointId, userIndex, kUndefinedFabricIndex, kUndefinedFabricIndex, chip::CharSpan(""), 0, + DlUserStatus::kAvailable, DlUserType::kUnrestrictedUser, DlCredentialRule::kSingle, nullptr, + 0)) + { + return EMBER_ZCL_STATUS_FAILURE; + } + + if (sendUserChangeEvent) + { + sendRemoteLockUserChange(endpointId, DlLockDataType::kUserIndex, DlDataOperationType::kClear, sourceNodeId, + modifierFabricId, userIndex, userIndex); + } + return EMBER_ZCL_STATUS_SUCCESS; +} + +DlStatus DoorLockServer::createNewCredentialAndUser(chip::EndpointId endpointId, chip::FabricIndex creatorFabricIdx, + chip::NodeId sourceNodeId, const Nullable & userStatus, + const Nullable & userType, const DlCredential & credential, + const chip::ByteSpan & credentialData, uint16_t & createdUserIndex) +{ + uint16_t availableUserIndex = 0; + if (!findUnoccupiedUserSlot(endpointId, availableUserIndex)) + { + emberAfDoorLockClusterPrintln("[SetCredential] Unable to create new user for credential: no available user slots " + "[endpointId=%d,credentialIndex=%d]", + endpointId, credential.CredentialIndex); + return DlStatus::kOccupied; + } + + auto status = + createUser(endpointId, creatorFabricIdx, sourceNodeId, availableUserIndex, Nullable(), Nullable(), + userStatus, userType, Nullable(), Nullable(credential)); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + emberAfDoorLockClusterPrintln("[SetCredential] Unable to create new user for credential: internal error " + "[endpointId=%d,credentialIndex=%d,userIndex=%d,status=%d]", + endpointId, credential.CredentialIndex, availableUserIndex, status); + return DlStatus::kFailure; + } + + if (!emberAfPluginDoorLockSetCredential(endpointId, credential.CredentialIndex, DlCredentialStatus::kOccupied, + static_cast(credential.CredentialType), credentialData)) + { + emberAfDoorLockClusterPrintln("[SetCredential] Unable to set the credential: app error " + "[endpointId=%d,credentialIndex=%d,credentialType=%" PRIu8 ",dataLength=%zu]", + endpointId, credential.CredentialIndex, credential.CredentialType, credentialData.size()); + return DlStatus::kFailure; + } + + emberAfDoorLockClusterPrintln("[SetCredential] Credential and user were created " + "[endpointId=%d,credentialIndex=%d,credentialType=%" PRIu8 ",dataLength=%zu,userIndex=%d]", + endpointId, credential.CredentialIndex, credential.CredentialType, credentialData.size(), + availableUserIndex); + createdUserIndex = availableUserIndex; + + return DlStatus::kSuccess; +} + +DlStatus DoorLockServer::createNewCredentialAndAddItToUser(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIdx, + uint16_t userIndex, const DlCredential & credential, + const chip::ByteSpan & credentialData) +{ + if (!userIndexValid(endpointId, userIndex)) + { + emberAfDoorLockClusterPrintln("[SetCredential] Unable to add new credential to user: user out of bounds " + "[endpointId=%d,credentialIndex=%d,userIndex=%d]", + endpointId, credential.CredentialIndex, userIndex); + return DlStatus::kInvalidField; + } + + EmberAfPluginDoorLockUserInfo user; + if (!emberAfPluginDoorLockGetUser(endpointId, userIndex, user)) + { + emberAfDoorLockClusterPrintln( + "[SetCredential] Unable to check if credential exists: app error [endpointId=%d,credentialIndex=%d,userIndex=%d]", + endpointId, credential.CredentialIndex, userIndex); + + return DlStatus::kFailure; + } + + // Not in the spec, but common sense: I don't think we need to modify the credential if user slot is not occupied + if (user.userStatus == DlUserStatus::kAvailable) + { + emberAfDoorLockClusterPrintln("[SetCredential] Unable to add credential to user: user clot is empty " + "[endpointId=%d,credentialIndex=%d,userIndex=%d]", + endpointId, credential.CredentialIndex, userIndex); + return DlStatus::kInvalidField; + } + + // Add new credential to the user + auto status = addCredentialToUser(endpointId, modifierFabricIdx, userIndex, credential); + if (DlStatus::kSuccess != status) + { + emberAfDoorLockClusterPrintln("[SetCredential] Unable to add credential to a user: internal error " + "[endpointId=%d,credentialIndex=%d,userIndex=%d,status=%" PRIu8 "]", + endpointId, credential.CredentialIndex, userIndex, to_underlying(status)); + return status; + } + + if (!emberAfPluginDoorLockSetCredential(endpointId, credential.CredentialIndex, DlCredentialStatus::kOccupied, + static_cast(credential.CredentialType), credentialData)) + { + emberAfDoorLockClusterPrintln("[SetCredential] Unable to set the credential: app error " + "[endpointId=%d,credentialIndex=%d,credentialType=%" PRIu8 ",dataLength=%zu]", + endpointId, credential.CredentialIndex, credential.CredentialType, credentialData.size()); + return DlStatus::kFailure; + } + + return DlStatus::kSuccess; +} + +DlStatus DoorLockServer::addCredentialToUser(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIdx, uint16_t userIndex, + const DlCredential & credential) { - emberAfDoorLockClusterPrintln("Door Lock cluster initialized at endpoint #%" PRIu16, endpointId); + // We should get the user by that index first + EmberAfPluginDoorLockUserInfo user; + if (!emberAfPluginDoorLockGetUser(endpointId, userIndex, user)) + { + emberAfDoorLockClusterPrintln("[AddCredentialToUser] Unable to get the user from app [endpointId=%d,userIndex=%d]", + endpointId, userIndex); + return DlStatus::kFailure; + } - SetLockState(endpointId, DlLockState::kLocked); - SetActuatorEnabled(endpointId, true); -} + // TODO: Do we need to check the modifier fabric here? Discuss with Spec team and add it if necessary. -bool DoorLockServer::SetLockState(chip::EndpointId endpointId, DlLockState newLockState) -{ - auto lockState = chip::to_underlying(newLockState); + for (size_t i = 0; i < user.credentials.size(); ++i) + { + // appclusters, 5.2.4.40: If user already contains the credential of the same type we should return INVALID_COMMAND + if (user.credentials.data()[i].CredentialType == credential.CredentialType) + { + emberAfDoorLockClusterPrintln( + "[AddCredentialToUser] Unable to add credential to user: credential with this type already exists " + "[endpointId=%d,userIndex=%d,credentialType=%d]", + endpointId, userIndex, credential.CredentialType); + return DlStatus::kOccupied; + } - emberAfDoorLockClusterPrintln("Setting LockState to '%" PRIu8 "'", lockState); - EmberAfStatus status = Attributes::LockState::Set(endpointId, newLockState); + // appclusters, 5.2.4.40: user should not be already associated with given credentialIndex + if (user.credentials.data()[i].CredentialIndex == credential.CredentialIndex) + { + emberAfDoorLockClusterPrintln( + "[AddCredentialToUser] Unable to add credential to user: credential with this index is already associated " + "with user [endpointId=%d,userIndex=%d,credentialType=%d,credentialIndex=%d]", + endpointId, userIndex, credential.CredentialType, credential.CredentialIndex); + return DlStatus::kInvalidField; + } + } - if (EMBER_ZCL_STATUS_SUCCESS != status) + // appclusters: spec defines up to 5 credentials per user + if (user.credentials.size() + 1 > DOOR_LOCK_MAX_CREDENTIALS_PER_USER) { - ChipLogError(Zcl, "Unable to set LockState attribute: status=0x%" PRIx8, status); + emberAfDoorLockClusterPrintln("[AddCredentialToUser] Unable to add credentials to user: too many credentials " + "[endpointId=%d,userIndex=%d,userTotalCredentials=%zu]", + endpointId, userIndex, user.credentials.size()); + return DlStatus::kInvalidField; } - return (EMBER_ZCL_STATUS_SUCCESS == status); + DlCredential newCredentials[DOOR_LOCK_MAX_CREDENTIALS_PER_USER]; + memcpy(newCredentials, user.credentials.data(), sizeof(DlCredential) * user.credentials.size()); + newCredentials[user.credentials.size()] = credential; + + if (!emberAfPluginDoorLockSetUser(endpointId, userIndex, user.createdBy, modifierFabricIdx, user.userName, user.userUniqueId, + user.userStatus, user.userType, user.credentialRule, newCredentials, + user.credentials.size() + 1)) + { + emberAfDoorLockClusterPrintln( + "[AddCredentialToUser] Unable to add credential to user: credential with this index is already associated " + "with user [endpointId=%d,userIndex=%d,credentialType=%d,credentialIndex=%d,userTotalCredentials=%zu]", + endpointId, userIndex, credential.CredentialType, credential.CredentialIndex, user.credentials.size()); + return DlStatus::kFailure; + } + + emberAfDoorLockClusterPrintln("[AddCredentialToUser] Credential added to user " + "[endpointId=%d,userIndex=%d,credentialType=%d,credentialIndex=%d,userTotalCredentials=%zu]", + endpointId, userIndex, credential.CredentialType, credential.CredentialIndex, + user.credentials.size() + 1); + + return DlStatus::kSuccess; } -bool DoorLockServer::SetActuatorEnabled(chip::EndpointId endpointId, bool newActuatorState) +DlStatus DoorLockServer::modifyCredentialForUser(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIdx, + uint16_t userIndex, const DlCredential & credential) { - auto actuatorState = static_cast(newActuatorState); + // We should get the user by that index first + EmberAfPluginDoorLockUserInfo user; + if (!emberAfPluginDoorLockGetUser(endpointId, userIndex, user)) + { + emberAfDoorLockClusterPrintln("[ModifyUserCredential] Unable to get the user from app [endpointId=%d,userIndex=%d]", + endpointId, userIndex); + return DlStatus::kFailure; + } - emberAfDoorLockClusterPrintln("Setting ActuatorEnabled to '%" PRIu8 "'", actuatorState); - EmberAfStatus status = Attributes::ActuatorEnabled::Set(endpointId, newActuatorState); + // TODO: Do we need to check the modifier fabric here? Discuss with Spec team and add it if necessary. - if (EMBER_ZCL_STATUS_SUCCESS != status) + for (size_t i = 0; i < user.credentials.size(); ++i) { - ChipLogError(Zcl, "Unable to set ActuatorEnabled attribute: status=0x%" PRIx8, status); + // appclusters, 5.2.4.40: user should already be associated with given credentialIndex + if (user.credentials.data()[i].CredentialIndex == credential.CredentialIndex) + { + DlCredential newCredentials[DOOR_LOCK_MAX_CREDENTIALS_PER_USER]; + memcpy(newCredentials, user.credentials.data(), sizeof(DlCredential) * user.credentials.size()); + newCredentials[i] = credential; + + emberAfDoorLockClusterPrintln( + "[ModifyUserCredential] Unable to add credential to user: credential with this index is already associated " + "[endpointId=%d,userIndex=%d,credentialType=%d,credentialIndex=%d]", + endpointId, userIndex, credential.CredentialType, credential.CredentialIndex); + + if (!emberAfPluginDoorLockSetUser(endpointId, userIndex, user.createdBy, modifierFabricIdx, user.userName, + user.userUniqueId, user.userStatus, user.userType, user.credentialRule, + newCredentials, user.credentials.size())) + { + emberAfDoorLockClusterPrintln( + "[ModifyUserCredential] Unable to modify user credential: credential with this index is already associated " + "with user [endpointId=%d,userIndex=%d,credentialType=%d,credentialIndex=%d,userTotalCredentials=%zu]", + endpointId, userIndex, credential.CredentialType, credential.CredentialIndex, user.credentials.size()); + return DlStatus::kFailure; + } + + emberAfDoorLockClusterPrintln( + "[ModifyUserCredential] User credential modified " + "[endpointId=%d,userIndex=%d,credentialType=%d,credentialIndex=%d,userTotalCredentials=%zu]", + endpointId, userIndex, credential.CredentialType, credential.CredentialIndex, user.credentials.size()); + + return DlStatus::kSuccess; + } } - return (EMBER_ZCL_STATUS_SUCCESS == status); + // appclusters, 5.2.4.40: if user is not associated with credential index we should return INVALID_COMMAND + emberAfDoorLockClusterPrintln( + "[ModifyUserCredential] Unable to modify user credential: user is not associated with credential index " + "[endpointId=%d,userIndex=%d,credentialIndex=%d]", + endpointId, userIndex, credential.CredentialIndex); + + return DlStatus::kInvalidField; } -bool DoorLockServer::SetDoorState(chip::EndpointId endpointId, DlDoorState newDoorState) +DlStatus DoorLockServer::createCredential(chip::EndpointId endpointId, chip::FabricIndex creatorFabricIdx, + chip::NodeId sourceNodeId, uint16_t credentialIndex, DlCredentialType credentialType, + const EmberAfPluginDoorLockCredentialInfo & existingCredential, + const chip::ByteSpan & credentialData, Nullable userIndex, + Nullable userStatus, Nullable userType, + uint16_t & createdUserIndex) { - auto doorState = chip::to_underlying(newDoorState); + // appclusters, 5.2.4.41.1: should send the OCCUPIED in the response when the credential is in use + if (DlCredentialStatus::kAvailable != existingCredential.status) + { + emberAfDoorLockClusterPrintln( + "[SetCredential] Unable to set the credential: credential slot is occupied [endpointId=%d,credentialIndex=%d]", + endpointId, credentialIndex); - emberAfDoorLockClusterPrintln("Setting DoorState to '%" PRIu8 "'", doorState); - EmberAfStatus status = Attributes::DoorState::Set(endpointId, newDoorState); + return DlStatus::kOccupied; + } - if (EMBER_ZCL_STATUS_SUCCESS != status) + if (!userType.IsNull() && DlUserType::kProgrammingUser == userType.Value()) { - ChipLogError(Zcl, "Unable to set DoorState attribute: status=0x%" PRIx8, status); + emberAfDoorLockClusterPrintln("[SetCredential] Unable to set the credential: user type is invalid " + "[endpointId=%d,credentialIndex=%d,userType=%" PRIu8 "]", + endpointId, credentialIndex, to_underlying(userType.Value())); + + return DlStatus::kInvalidField; } - return (EMBER_ZCL_STATUS_SUCCESS == status); -} + DlCredential credential{ to_underlying(credentialType), credentialIndex }; + // appclusters, 5.2.4.40: if userIndex is not provided we should create new user + DlStatus status = DlStatus::kSuccess; + if (userIndex.IsNull()) + { + emberAfDoorLockClusterPrintln("[SetCredential] UserIndex is not set, creating new user [endpointId=%d,credentialIndex=%d]", + endpointId, credentialIndex); -bool DoorLockServer::SetLanguage(chip::EndpointId endpointId, chip::CharSpan newLanguage) -{ - emberAfDoorLockClusterPrintln("Setting Language to '%.*s'", static_cast(newLanguage.size()), newLanguage.data()); - EmberAfStatus status = Attributes::Language::Set(endpointId, newLanguage); + status = createNewCredentialAndUser(endpointId, creatorFabricIdx, sourceNodeId, userStatus, userType, credential, + credentialData, createdUserIndex); + } + else + { + // appclusters, 5.2.4.40: if user index is NULL, we should try to modify the existing user + status = createNewCredentialAndAddItToUser(endpointId, creatorFabricIdx, userIndex.Value(), credential, credentialData); + } - if (EMBER_ZCL_STATUS_SUCCESS != status) + if (DlStatus::kSuccess == status) { - ChipLogError(Zcl, "Unable to set Language attribute: status=0x%" PRIx8, status); + sendRemoteLockUserChange(endpointId, credentialTypeToLockDataType(credentialType), DlDataOperationType::kAdd, sourceNodeId, + creatorFabricIdx, createdUserIndex == 0 ? userIndex.Value() : createdUserIndex, credentialIndex); } - return (EMBER_ZCL_STATUS_SUCCESS == status); + return status; } -bool DoorLockServer::SetAutoRelockTime(chip::EndpointId endpointId, uint32_t newAutoRelockTimeSec) +DlStatus DoorLockServer::modifyProgrammingPIN(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIndex, + chip::NodeId sourceNodeId, uint16_t credentialIndex, DlCredentialType credentialType, + const EmberAfPluginDoorLockCredentialInfo & existingCredential, + const chip::ByteSpan & credentialData) { - emberAfDoorLockClusterPrintln("Setting AutoRelockTime to '%" PRIu32 "'", newAutoRelockTimeSec); - EmberAfStatus status = Attributes::AutoRelockTime::Set(endpointId, newAutoRelockTimeSec); + if (DlCredentialType::kProgrammingPIN != credentialType || 0 != credentialIndex) + { + emberAfDoorLockClusterPrintln( + "[SetCredential] Unable to modify programming PIN: invalid argument [endpointId=%d,credentialIndex=%d]", endpointId, + credentialIndex); - if (EMBER_ZCL_STATUS_SUCCESS != status) + return DlStatus::kInvalidField; + } + + emberAfDoorLockClusterPrintln("[SetCredential] Modifying the programming PIN [endpointId=%d,credentialIndex=%d]", endpointId, + credentialIndex); + + uint16_t relatedUserIndex = 0; + if (!findUserIndexByCredential(endpointId, DlCredentialType::kProgrammingPIN, 0, relatedUserIndex)) { - ChipLogError(Zcl, "Unable to set AutoRelockTime attribute to %" PRIu32 ": status=0x%" PRIx8, newAutoRelockTimeSec, status); + ChipLogError(Zcl, "[SetCredential] Unable to modify PIN - related user not found (internal error) [endpointId=%d]", + endpointId); + return DlStatus::kFailure; } - return (EMBER_ZCL_STATUS_SUCCESS == status); + if (!emberAfPluginDoorLockSetCredential(endpointId, credentialIndex, existingCredential.status, + existingCredential.credentialType, credentialData)) + { + emberAfDoorLockClusterPrintln("[SetCredential] Unable to modify the credential: app error " + "[endpointId=%d,credentialIndex=%d,credentialType=%" PRIu8 ",credentialDataSize=%zu]", + endpointId, credentialIndex, to_underlying(credentialType), credentialData.size()); + return DlStatus::kFailure; + } + else + { + emberAfDoorLockClusterPrintln("[SetCredential] Successfully modified the credential " + "[endpointId=%d,credentialIndex=%d,credentialType=%" PRIu8 ",credentialDataSize=%zu]", + endpointId, credentialIndex, to_underlying(credentialType), credentialData.size()); + + sendRemoteLockUserChange(endpointId, credentialTypeToLockDataType(credentialType), DlDataOperationType::kModify, + sourceNodeId, modifierFabricIndex, relatedUserIndex, credentialIndex); + } + + return DlStatus::kSuccess; } -bool DoorLockServer::SetSoundVolume(chip::EndpointId endpointId, uint8_t newSoundVolume) +DlStatus DoorLockServer::modifyCredential(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIndex, + chip::NodeId sourceNodeId, uint16_t credentialIndex, DlCredentialType credentialType, + const EmberAfPluginDoorLockCredentialInfo & existingCredential, + const chip::ByteSpan & credentialData, uint16_t userIndex, + Nullable userStatus, Nullable userType) { - emberAfDoorLockClusterPrintln("Setting SoundVolume to '%" PRIu8 "'", newSoundVolume); - EmberAfStatus status = Attributes::SoundVolume::Set(endpointId, newSoundVolume); - if (EMBER_ZCL_STATUS_SUCCESS != status) + // appclusters, 5.2.4.40: when modifying a credential, userStatus and userType shall both be NULL. + if (!userStatus.IsNull() || (!userType.IsNull() && DlUserType::kProgrammingUser != userType.Value())) { - ChipLogError(Zcl, "Unable to set SoundVolume attribute: status=0x%" PRIx8, status); + emberAfDoorLockClusterPrintln("[SetCredential] Unable to modify the credential: invalid arguments " + "[endpointId=%d,credentialIndex=%d,credentialType=%" PRIu8 "]", + endpointId, credentialIndex, to_underlying(credentialType)); + return DlStatus::kInvalidField; } - return (EMBER_ZCL_STATUS_SUCCESS == status); + DlCredential credential{ to_underlying(credentialType), credentialIndex }; + auto status = modifyCredentialForUser(endpointId, modifierFabricIndex, userIndex, credential); + + if (DlStatus::kSuccess == status) + { + if (!emberAfPluginDoorLockSetCredential(endpointId, credentialIndex, existingCredential.status, + existingCredential.credentialType, credentialData)) + { + emberAfDoorLockClusterPrintln("[SetCredential] Unable to modify the credential: app error " + "[endpointId=%d,credentialIndex=%d,credentialType=%" PRIu8 ",credentialDataSize=%zu]", + endpointId, credentialIndex, to_underlying(credentialType), credentialData.size()); + + return DlStatus::kFailure; + } + + emberAfDoorLockClusterPrintln("[SetCredential] Successfully modified the credential " + "[endpointId=%d,credentialIndex=%d,credentialType=%" PRIu8 ",credentialDataSize=%zu]", + endpointId, credentialIndex, to_underlying(credentialType), credentialData.size()); + + sendRemoteLockUserChange(endpointId, credentialTypeToLockDataType(credentialType), DlDataOperationType::kModify, + sourceNodeId, modifierFabricIndex, userIndex, credentialIndex); + } + return status; } -bool DoorLockServer::SetOneTouchLocking(chip::EndpointId endpointId, bool isEnabled) +CHIP_ERROR DoorLockServer::sendSetCredentialResponse(chip::app::CommandHandler * commandObj, DlStatus status, uint16_t userIndex, + uint16_t nextCredentialIndex) { - auto enable = static_cast(isEnabled); + CHIP_ERROR err = CHIP_NO_ERROR; - emberAfDoorLockClusterPrintln("Setting EnableOneTouchLocking to '%" PRIu8 "'", enable); - EmberAfStatus status = Attributes::EnableOneTouchLocking::Set(endpointId, isEnabled); + using ResponseFields = Commands::SetCredentialResponse::Fields; - if (EMBER_ZCL_STATUS_SUCCESS != status) + app::ConcreteCommandPath path = { emberAfCurrentEndpoint(), ::Id, Commands::SetCredentialResponse::Id }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(path)); + VerifyOrExit((writer = commandObj->GetCommandDataIBTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kStatus)), status)); + + if (0 != userIndex) { - ChipLogError(Zcl, "Unable to set EnableOneTouchLocking attribute: status=0x%" PRIx8, status); + SuccessOrExit(err = writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kUserIndex)), userIndex)); } - return (EMBER_ZCL_STATUS_SUCCESS == status); + if (0 != nextCredentialIndex) + { + SuccessOrExit(err = writer->Put(TLV::ContextTag(to_underlying(ResponseFields::kNextCredentialIndex)), nextCredentialIndex)); + } + SuccessOrExit(err = commandObj->FinishCommand()); + +exit: + return err; } -bool DoorLockServer::SetPrivacyModeButton(chip::EndpointId endpointId, bool isEnabled) +bool DoorLockServer::credentialTypeSupported(chip::EndpointId endpointId, DlCredentialType type) { - auto enable = static_cast(isEnabled); - - emberAfDoorLockClusterPrintln("Setting EnablePrivacyModeButton to '%" PRIu8 "'", enable); - EmberAfStatus status = Attributes::EnablePrivacyModeButton::Set(endpointId, isEnabled); + switch (type) + { + case DlCredentialType::kProgrammingPIN: + case DlCredentialType::kPin: + return SupportsPIN(endpointId); + case DlCredentialType::kRfid: + return SupportsPFID(endpointId); + default: + return false; + } + return false; +} - if (EMBER_ZCL_STATUS_SUCCESS != status) +EmberAfStatus DoorLockServer::clearCredential(chip::EndpointId endpointId, chip::FabricIndex modifier, chip::NodeId sourceNodeId, + DlCredentialType credentialType, uint16_t credentialIndex, bool sendUserChangeEvent) +{ + if (DlCredentialType::kProgrammingPIN == credentialType) { - ChipLogError(Zcl, "Unable to set EnablePrivacyModeButton attribute: status=0x%" PRIx8, status); + emberAfDoorLockClusterPrintln("[clearCredential] Cannot clear programming PIN credentials " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d]", + endpointId, to_underlying(credentialType), credentialIndex, modifier); + return EMBER_ZCL_STATUS_INVALID_COMMAND; } - return (EMBER_ZCL_STATUS_SUCCESS == status); -} + if (!credentialIndexValid(endpointId, credentialType, credentialIndex)) + { + emberAfDoorLockClusterPrintln("[clearCredential] Cannot clear credential - index out of bounds " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d]", + endpointId, to_underlying(credentialType), credentialIndex, modifier); + return EMBER_ZCL_STATUS_INVALID_COMMAND; + } -// ============================================================================= -// Cluster commands callbacks -// ============================================================================= + // 1. Fetch the credential from storage, so we know what we're deleting + EmberAfPluginDoorLockCredentialInfo credential; + if (!emberAfPluginDoorLockGetCredential(endpointId, credentialIndex, credentialType, credential)) + { + ChipLogError(Zcl, + "[clearCredential] Unable to clear credential - couldn't read credential from database " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d]", + endpointId, to_underlying(credentialType), credentialIndex, modifier); + return EMBER_ZCL_STATUS_FAILURE; + } -bool emberAfDoorLockClusterLockDoorCallback(chip::app::CommandHandler * commandObj, - const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::DoorLock::Commands::LockDoor::DecodableType & commandData) -{ - emberAfDoorLockClusterPrintln("Received Lock Door command"); - bool success = false; + if (DlCredentialStatus::kAvailable == credential.status) + { + emberAfDoorLockClusterPrintln("[clearCredential] Ignored attempt to clear unoccupied credential slot " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d]", + endpointId, to_underlying(credentialType), credentialIndex, modifier); + return EMBER_ZCL_STATUS_SUCCESS; + } - chip::EndpointId endpoint = commandPath.mEndpointId; + if (credentialType != credential.credentialType) + { + emberAfDoorLockClusterPrintln( + "[clearCredential] Ignored attempt to clear credential of different type " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d,actualCredentialType=%" PRIu8 "]", + endpointId, to_underlying(credentialType), credentialIndex, modifier, to_underlying(credential.credentialType)); + return EMBER_ZCL_STATUS_SUCCESS; + } - bool require_pin = false; - Attributes::RequirePINforRemoteOperation::Get(endpoint, &require_pin); + // 2. Get the associated user and if it is the only attached credential -- delete the user. This operation will + // also remove the associated credential. + uint16_t relatedUserIndex = 0; + if (!findUserIndexByCredential(endpointId, credentialType, credentialIndex, relatedUserIndex)) + { + ChipLogError(Zcl, + "[clearCredential] Unable to clear related credential user - couldn't find index of related user " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d]", + endpointId, to_underlying(credentialType), credentialIndex, modifier); + return EMBER_ZCL_STATUS_FAILURE; + } + EmberAfPluginDoorLockUserInfo relatedUser; + if (!emberAfPluginDoorLockGetUser(endpointId, relatedUserIndex, relatedUser)) + { + ChipLogError(Zcl, + "[clearCredential] Unable to clear credential for related user - couldn't get user from database " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d,userIndex=%d]", + endpointId, to_underlying(credentialType), credentialIndex, modifier, relatedUserIndex); - if (commandData.pinCode.HasValue()) + return EMBER_ZCL_STATUS_FAILURE; + } + if (1 == relatedUser.credentials.size()) { - // TODO: Search through list of stored PINs and check each. - if (mPin.data_equal(commandData.pinCode.Value())) + emberAfDoorLockClusterPrintln("[clearCredential] Clearing related user - no credentials left " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d,userIndex=%d]", + endpointId, to_underlying(credentialType), credentialIndex, modifier, relatedUserIndex); + auto clearStatus = clearUser(endpointId, modifier, sourceNodeId, relatedUserIndex, relatedUser, true); + if (EMBER_ZCL_STATUS_SUCCESS != clearStatus) { - success = emberAfPluginDoorLockOnDoorLockCommand(endpoint, commandData.pinCode); - } - else - { - success = false; // Just to be explicit. success == false at this point anyway + ChipLogError(Zcl, + "[clearCredential] Unable to clear related credential user - internal error " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d,userIndex=%d,status=%d]", + endpointId, to_underlying(credentialType), credentialIndex, modifier, relatedUserIndex, clearStatus); + + return EMBER_ZCL_STATUS_FAILURE; } + emberAfDoorLockClusterPrintln("[clearCredential] Successfully clear credential and related user " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d,userIndex=%d]", + endpointId, to_underlying(credentialType), credentialIndex, modifier, relatedUserIndex); + return EMBER_ZCL_STATUS_SUCCESS; } - else + + // 3. If the user wasn't deleted, delete the credential and adjust the list of credentials for related user in the storage + if (!emberAfPluginDoorLockSetCredential(endpointId, credentialIndex, DlCredentialStatus::kAvailable, credentialType, + chip::ByteSpan())) { - if (!require_pin) - { - success = emberAfPluginDoorLockOnDoorLockCommand(endpoint, commandData.pinCode); - } - else + ChipLogError(Zcl, + "[clearCredential] Unable to clear credential - couldn't write new credential to database " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d]", + endpointId, to_underlying(credentialType), credentialIndex, modifier); + return EMBER_ZCL_STATUS_FAILURE; + } + + // Should never happen, only possible if the implementation of application is incorrect + if (relatedUser.credentials.size() > DOOR_LOCK_MAX_CREDENTIALS_PER_USER) + { + ChipLogError(Zcl, + "[clearCredential] Unable to clear credential for related user - user has too many credentials associated" + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d,userIndex=%d,credentialsCount=%zu]", + endpointId, to_underlying(credentialType), credentialIndex, modifier, relatedUserIndex, + relatedUser.credentials.size()); + + return EMBER_ZCL_STATUS_FAILURE; + } + + DlCredential newCredentials[DOOR_LOCK_MAX_CREDENTIALS_PER_USER]; + size_t newCredentialsCount = 0; + for (const auto & c : relatedUser.credentials) + { + if (static_cast(c.CredentialType) == credentialType && c.CredentialIndex == credentialIndex) { - success = false; + continue; } + newCredentials[newCredentialsCount++] = c; } - if (success) + if (!emberAfPluginDoorLockSetUser(endpointId, relatedUserIndex, relatedUser.createdBy, modifier, relatedUser.userName, + relatedUser.userUniqueId, relatedUser.userStatus, relatedUser.userType, + relatedUser.credentialRule, newCredentials, newCredentialsCount)) { - success = DoorLockServer::Instance().SetLockState(endpoint, DlLockState::kLocked) == EMBER_ZCL_STATUS_SUCCESS; + ChipLogError(Zcl, + "[clearCredential] Unable to clear credential for related user - unable to update database " + "[endpointId=%d,credentialType=%" PRIu8 + ",credentialIndex=%d,modifier=%d,userIndex=%d,newCredentialsCount=%zu]", + endpointId, to_underlying(credentialType), credentialIndex, modifier, relatedUserIndex, newCredentialsCount); + return EMBER_ZCL_STATUS_FAILURE; } - emberAfSendImmediateDefaultResponse(success ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE); + emberAfDoorLockClusterPrintln( + "[clearCredential] Successfully clear credential and related user " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,modifier=%d,userIndex=%d,newCredentialsCount=%zu]", + endpointId, to_underlying(credentialType), credentialIndex, modifier, relatedUserIndex, newCredentialsCount); - return true; + if (sendUserChangeEvent) + { + sendRemoteLockUserChange(endpointId, credentialTypeToLockDataType(credentialType), DlDataOperationType::kClear, + sourceNodeId, modifier, relatedUserIndex, credentialIndex); + } + + return EMBER_ZCL_STATUS_SUCCESS; } -bool emberAfDoorLockClusterUnlockDoorCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::DoorLock::Commands::UnlockDoor::DecodableType & commandData) +EmberAfStatus DoorLockServer::clearCredentials(chip::EndpointId endpointId, chip::FabricIndex modifier, chip::NodeId sourceNodeId) { - emberAfDoorLockClusterPrintln("Received Unlock Door command"); - bool success = false; + if (SupportsPIN(endpointId)) + { + auto status = clearCredentials(endpointId, modifier, sourceNodeId, DlCredentialType::kPin); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "[clearCredentials] Unable to clear all PIN credentials [endpointId=%d,status=%d]", endpointId, + status); + return status; + } - chip::EndpointId endpoint = commandPath.mEndpointId; + emberAfDoorLockClusterPrintln("[clearCredentials] All PIN credentials were cleared [endpointId=%d]", endpointId); + } - bool require_pin = false; - Attributes::RequirePINforRemoteOperation::Get(endpoint, &require_pin); + if (SupportsPFID(endpointId)) + { + auto status = clearCredentials(endpointId, modifier, sourceNodeId, DlCredentialType::kRfid); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogError(Zcl, "[clearCredentials] Unable to clear all RFID credentials [endpointId=%d,status=%d]", endpointId, + status); + return status; + } + emberAfDoorLockClusterPrintln("[clearCredentials] All RFID credentials were cleared [endpointId=%d]", endpointId); + } - if (commandData.pinCode.HasValue()) + if (SupportsFingers(endpointId)) { - // TODO: Search through list of stored PINs and check each. - if (mPin.data_equal(commandData.pinCode.Value())) + auto status = clearCredentials(endpointId, modifier, sourceNodeId, DlCredentialType::kFingerprint); + if (EMBER_ZCL_STATUS_SUCCESS != status) { - success = emberAfPluginDoorLockOnDoorUnlockCommand(endpoint, commandData.pinCode); + ChipLogError(Zcl, "[clearCredentials] Unable to clear all Fingerprint credentials [endpointId=%d,status=%d]", + endpointId, status); + return status; } - else + + status = clearCredentials(endpointId, modifier, sourceNodeId, DlCredentialType::kFingerVein); + if (EMBER_ZCL_STATUS_SUCCESS != status) { - success = false; // Just to be explicit. success == false at this point anyway + ChipLogError(Zcl, "[clearCredentials] Unable to clear all Finger Vein credentials [endpointId=%d,status=%d]", + endpointId, status); + return status; } + + emberAfDoorLockClusterPrintln("[clearCredentials] All Finger credentials were cleared [endpointId=%d]", endpointId); } - else + + if (SupportsFace(endpointId)) { - if (!require_pin) + auto status = clearCredentials(endpointId, modifier, sourceNodeId, DlCredentialType::kFace); + if (EMBER_ZCL_STATUS_SUCCESS != status) { - success = emberAfPluginDoorLockOnDoorUnlockCommand(endpoint, commandData.pinCode); + ChipLogError(Zcl, "[clearCredentials] Unable to clear all face credentials [endpointId=%d,status=%d]", endpointId, + status); + return status; } - else + emberAfDoorLockClusterPrintln("[clearCredentials] All face credentials were cleared [endpointId=%d]", endpointId); + } + + return EMBER_ZCL_STATUS_SUCCESS; +} + +EmberAfStatus DoorLockServer::clearCredentials(chip::EndpointId endpointId, chip::FabricIndex modifier, chip::NodeId sourceNodeId, + DlCredentialType credentialType) +{ + uint16_t maxNumberOfCredentials = 0; + if (!getMaxNumberOfCredentials(endpointId, credentialType, maxNumberOfCredentials)) + { + ChipLogError(Zcl, + "[clearCredentials] Unable to get max number of credentials to clear - can't get max number of credentials " + "[endpointId=%d,credentialType=%" PRIu8 "]", + endpointId, to_underlying(credentialType)); + return EMBER_ZCL_STATUS_FAILURE; + } + + for (uint16_t i = 1; i < maxNumberOfCredentials; ++i) + { + auto status = clearCredential(endpointId, modifier, sourceNodeId, credentialType, i, false); + if (EMBER_ZCL_STATUS_SUCCESS != status) { - success = false; + ChipLogError(Zcl, + "[clearCredentials] Unable to clear the credential - internal error " + "[endpointId=%d,credentialType=%" PRIu8 ",credentialIndex=%d,status=%d]", + endpointId, to_underlying(credentialType), i, status); + return status; } } - if (success) + sendRemoteLockUserChange(endpointId, credentialTypeToLockDataType(credentialType), DlDataOperationType::kClear, sourceNodeId, + modifier, 0xFFFE, 0xFFFE); + + return EMBER_ZCL_STATUS_SUCCESS; +} + +bool DoorLockServer::sendRemoteLockUserChange(chip::EndpointId endpointId, DlLockDataType dataType, DlDataOperationType operation, + chip::NodeId nodeId, chip::FabricIndex fabricIndex, uint16_t userIndex, + uint16_t dataIndex) +{ + Events::LockUserChange::Type event; + event.lockDataType = dataType; + event.dataOperationType = operation; + event.operationSource = DlOperationSource::kRemote; + if (0 != userIndex) + { + event.userIndex = Nullable(userIndex); + } + event.fabricIndex = Nullable(fabricIndex); + event.sourceNode = Nullable(nodeId); + if (0 != dataIndex) + { + event.dataIndex = Nullable(dataIndex); + } + + EventNumber eventNumber; + CHIP_ERROR error = app::LogEvent(event, endpointId, eventNumber); + if (CHIP_NO_ERROR != error) + { + ChipLogError(Zcl, "[RemoteLockUserChange] Unable to send lock user change event: %s [endpointId=%d]", error.AsString(), + endpointId); + return false; + } + emberAfDoorLockClusterPrintln("[RemoteLockUserChange] Sent lock user change event " + "[endpointId=%d,eventNumber=%" PRIu64 ",dataType=%" PRIu8 ",operation=%" PRIu8 ",nodeId=%" PRIu64 + ",fabricIndex=%d]", + endpointId, eventNumber, to_underlying(dataType), to_underlying(operation), nodeId, fabricIndex); + return true; +} + +DlLockDataType DoorLockServer::credentialTypeToLockDataType(DlCredentialType credentialType) +{ + switch (credentialType) { - success = DoorLockServer::Instance().SetLockState(endpoint, DlLockState::kUnlocked) == EMBER_ZCL_STATUS_SUCCESS; + case DlCredentialType::kProgrammingPIN: + return DlLockDataType::kProgrammingCode; + case DlCredentialType::kPin: + return DlLockDataType::kPin; + case DlCredentialType::kRfid: + return DlLockDataType::kRfid; + case DlCredentialType::kFingerprint: + return DlLockDataType::kFingerprint; + case DlCredentialType::kFingerVein: + return DlLockDataType::kFingerprint; + case DlCredentialType::kFace: + // So far there's no distinct data type for face credentials + return DlLockDataType::kUnspecified; } - emberAfSendImmediateDefaultResponse(success ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE); + return DlLockDataType::kUnspecified; +} +// ============================================================================= +// Cluster commands callbacks +// ============================================================================= + +bool emberAfDoorLockClusterLockDoorCallback(chip::app::CommandHandler * commandObj, + const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::LockDoor::DecodableType & commandData) +{ + DoorLockServer::Instance().LockUnlockDoorCommandHandler(commandObj, commandPath, DlLockOperationType::kLock, + commandData.pinCode); + return true; +} +bool emberAfDoorLockClusterUnlockDoorCallback( + chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::UnlockDoor::DecodableType & commandData) +{ + DoorLockServer::Instance().LockUnlockDoorCommandHandler(commandObj, commandPath, DlLockOperationType::kUnlock, + commandData.pinCode); return true; } @@ -297,18 +2050,7 @@ bool emberAfDoorLockClusterSetUserCallback(chip::app::CommandHandler * commandOb const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::DoorLock::Commands::SetUser::DecodableType & commandData) { - emberAfDoorLockClusterPrintln("Received Set User command (not implemented)"); - // SetUser command fields are: - // DlDataOperationType operationType; - // uint16_t userIndex; - // DataModel::Nullable userName; - // DataModel::Nullable userUniqueId; - // DlUserStatus userStatus; - // DlUserType userType; - // DlCredentialRule credentialRule; - - // TODO: Implement setting the user - emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); + DoorLockServer::Instance().SetUserCommandHandler(commandObj, commandPath, commandData); return true; } @@ -316,12 +2058,7 @@ bool emberAfDoorLockClusterGetUserCallback(chip::app::CommandHandler * commandOb const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::DoorLock::Commands::GetUser::DecodableType & commandData) { - emberAfDoorLockClusterPrintln("Received Get User command (not implemented)"); - // GetUser command fields are: - // uint16_t userIndex; - - // TODO: Implement getting the user - emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); + DoorLockServer::Instance().GetUserCommandHandler(commandObj, commandPath, commandData); return true; } @@ -329,12 +2066,7 @@ bool emberAfDoorLockClusterClearUserCallback(chip::app::CommandHandler * command const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::DoorLock::Commands::ClearUser::DecodableType & commandData) { - emberAfDoorLockClusterPrintln("Received Clear User command (not implemented)"); - // ClearUser command fields are: - // uint16_t userIndex; - - // TODO: Implement clearing the user - emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); + DoorLockServer::Instance().ClearUserCommandHandler(commandObj, commandPath, commandData); return true; } @@ -342,16 +2074,7 @@ bool emberAfDoorLockClusterSetCredentialCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::DoorLock::Commands::SetCredential::DecodableType & commandData) { - emberAfDoorLockClusterPrintln("Received Set Credential command (not implemented)"); - // SetCredential command fields are: - // DlDataOperationType operationType; - // Structs::DlCredential::Type credential; - // chip::ByteSpan credentialData; - // uint16_t userIndex; - // DlUserStatus userStatus; - - // TODO: Implement clearing the user - emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); + DoorLockServer::Instance().SetCredentialCommandHandler(commandObj, commandPath, commandData); return true; } @@ -359,12 +2082,7 @@ bool emberAfDoorLockClusterGetCredentialStatusCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::DecodableType & commandData) { - emberAfDoorLockClusterPrintln("Received Get Credential Status command (not implemented)"); - // GetCredentialStatus command fields are: - // Structs::DlCredential::Type credential; - - // TODO: Implement clearing the user - emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); + DoorLockServer::Instance().GetCredentialStatusCommandHandler(commandObj, commandPath, commandData); return true; } @@ -372,12 +2090,7 @@ bool emberAfDoorLockClusterClearCredentialCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::DoorLock::Commands::ClearCredential::DecodableType & commandData) { - emberAfDoorLockClusterPrintln("Received Clear Credential command (not implemented)"); - // ClearCredential command fields are: - // Structs::DlCredential::Type credential; - - // TODO: Implement clearing the user - emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); + DoorLockServer::Instance().ClearCredentialCommandHandler(commandObj, commandPath, commandData); return true; } @@ -673,3 +2386,35 @@ emberAfPluginDoorLockOnUnhandledAttributeChange(chip::EndpointId EndpointId, Emb { return chip::Protocols::InteractionModel::Status::Success; } + +// ============================================================================= +// Users and credentials access callbacks +// ============================================================================= + +bool __attribute__((weak)) +emberAfPluginDoorLockGetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user) +{ + return false; +} + +bool __attribute__((weak)) +emberAfPluginDoorLockSetUser(chip::EndpointId endpointId, uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier, + const chip::CharSpan & userName, uint32_t uniqueId, DlUserStatus userStatus, DlUserType usertype, + DlCredentialRule credentialRule, const DlCredential * credentials, size_t totalCredentials) +{ + return false; +} + +bool __attribute__((weak)) +emberAfPluginDoorLockGetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType, + EmberAfPluginDoorLockCredentialInfo & credential) +{ + return false; +} + +bool __attribute__((weak)) +emberAfPluginDoorLockSetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialStatus credentialStatus, + DlCredentialType credentialType, const chip::ByteSpan & credentialData) +{ + return false; +} diff --git a/src/app/clusters/door-lock-server/door-lock-server.h b/src/app/clusters/door-lock-server/door-lock-server.h index 585961f9f12746..269c2c8ec22ec5 100644 --- a/src/app/clusters/door-lock-server/door-lock-server.h +++ b/src/app/clusters/door-lock-server/door-lock-server.h @@ -26,23 +26,50 @@ #include #include +#include #include +using chip::Optional; +using chip::app::Clusters::DoorLock::DlCredentialRule; +using chip::app::Clusters::DoorLock::DlCredentialType; +using chip::app::Clusters::DoorLock::DlDataOperationType; +using chip::app::Clusters::DoorLock::DlDoorState; +using chip::app::Clusters::DoorLock::DlLockDataType; +using chip::app::Clusters::DoorLock::DlLockOperationType; +using chip::app::Clusters::DoorLock::DlLockState; +using chip::app::Clusters::DoorLock::DlOperationSource; +using chip::app::Clusters::DoorLock::DlStatus; +using chip::app::Clusters::DoorLock::DlUserStatus; +using chip::app::Clusters::DoorLock::DlUserType; +using chip::app::Clusters::DoorLock::DoorLockFeature; +using chip::app::DataModel::Nullable; + #ifndef DOOR_LOCK_SERVER_ENDPOINT #define DOOR_LOCK_SERVER_ENDPOINT 1 #endif +static constexpr size_t DOOR_LOCK_MAX_USER_NAME_SIZE = 10; /**< Maximum size of the user name (in characters). */ +static constexpr size_t DOOR_LOCK_USER_NAME_BUFFER_SIZE = + DOOR_LOCK_MAX_USER_NAME_SIZE + 1; /**< Maximum size of the user name string (in bytes). */ + +static constexpr size_t DOOR_LOCK_MAX_CREDENTIALS_PER_USER = 5; /**< Maximum number of supported credentials by a single user. */ + +struct EmberAfPluginDoorLockCredentialInfo; +struct EmberAfPluginDoorLockUserInfo; + +/** + * @brief Door Lock Server Plugin class. + */ class DoorLockServer { public: static DoorLockServer & Instance(); - static DoorLockServer instance; void InitServer(chip::EndpointId endpointId); - bool SetLockState(chip::EndpointId endpointId, chip::app::Clusters::DoorLock::DlLockState newLockState); + bool SetLockState(chip::EndpointId endpointId, DlLockState newLockState); bool SetActuatorEnabled(chip::EndpointId endpointId, bool newActuatorState); - bool SetDoorState(chip::EndpointId endpointId, chip::app::Clusters::DoorLock::DlDoorState newDoorState); + bool SetDoorState(chip::EndpointId endpointId, DlDoorState newDoorState); bool SetLanguage(chip::EndpointId endpointId, chip::CharSpan newLanguage); bool SetAutoRelockTime(chip::EndpointId endpointId, uint32_t newAutoRelockTimeSec); @@ -50,8 +77,168 @@ class DoorLockServer bool SetOneTouchLocking(chip::EndpointId endpointId, bool isEnabled); bool SetPrivacyModeButton(chip::EndpointId endpointId, bool isEnabled); + + void SetUserCommandHandler(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::SetUser::DecodableType & commandData); + + void GetUserCommandHandler(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::GetUser::DecodableType & commandData); + + void ClearUserCommandHandler(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::ClearUser::DecodableType & commandData); + + void SetCredentialCommandHandler(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::SetCredential::DecodableType & commandData); + + void GetCredentialStatusCommandHandler( + chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::DecodableType & commandData); + + void ClearCredentialCommandHandler(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::DoorLock::Commands::ClearCredential::DecodableType & commandData); + + void LockUnlockDoorCommandHandler(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + DlLockOperationType operationType, const chip::Optional & pinCode); + + bool HasFeature(chip::EndpointId endpointId, DoorLockFeature feature); + + inline bool SupportsPIN(chip::EndpointId endpointId) { return HasFeature(endpointId, DoorLockFeature::kPINCredentials); } + + inline bool SupportsPFID(chip::EndpointId endpointId) { return HasFeature(endpointId, DoorLockFeature::kRFIDCredentials); } + + inline bool SupportsFingers(chip::EndpointId endpointId) { return HasFeature(endpointId, DoorLockFeature::kFingerCredentials); } + + inline bool SupportsFace(chip::EndpointId endpointId) { return HasFeature(endpointId, DoorLockFeature::kFaceCredentials); } + + inline bool SupportsUSR(chip::EndpointId endpointId) + { + // appclusters, 5.2.2: USR feature has conformance [PIN | RID | FGP | FACE] + // TODO: Add missing functions to check if RID, FGP or FACE are supported + return HasFeature(endpointId, DoorLockFeature::kUsersManagement) && SupportsPIN(endpointId); + } + +private: + chip::FabricIndex getFabricIndex(const chip::app::CommandHandler * commandObj); + chip::NodeId getNodeId(const chip::app::CommandHandler * commandObj); + + bool userIndexValid(chip::EndpointId endpointId, uint16_t userIndex); + bool userIndexValid(chip::EndpointId endpointId, uint16_t userIndex, uint16_t & maxNumberOfUser); + + bool credentialIndexValid(chip::EndpointId endpointId, DlCredentialType type, uint16_t credentialIndex); + bool credentialIndexValid(chip::EndpointId endpointId, DlCredentialType type, uint16_t credentialIndex, + uint16_t & maxNumberOfCredentials); + bool getCredentialRange(chip::EndpointId endpointId, DlCredentialType type, size_t & minSize, size_t & maxSize); + bool getMaxNumberOfCredentials(chip::EndpointId endpointId, DlCredentialType credentialType, uint16_t & maxNumberOfCredentials); + + bool findUnoccupiedUserSlot(chip::EndpointId endpointId, uint16_t & userIndex); + bool findUnoccupiedUserSlot(chip::EndpointId endpointId, uint16_t startIndex, uint16_t & userIndex); + + bool findUnoccupiedCredentialSlot(chip::EndpointId endpointId, DlCredentialType credentialType, uint16_t startIndex, + uint16_t & credentialIndex); + + bool findUserIndexByCredential(chip::EndpointId endpointId, DlCredentialType credentialType, uint16_t credentialIndex, + uint16_t & userIndex); + + bool findUserIndexByCredential(chip::EndpointId endpointId, DlCredentialType credentialType, chip::ByteSpan credentialData, + uint16_t & userIndex, uint16_t & credentialIndex); + + EmberAfStatus createUser(chip::EndpointId endpointId, chip::FabricIndex creatorFabricIdx, chip::NodeId sourceNodeId, + uint16_t userIndex, const Nullable & userName, const Nullable & userUniqueId, + const Nullable & userStatus, const Nullable & userType, + const Nullable & credentialRule, + const Nullable & credential = Nullable()); + EmberAfStatus modifyUser(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIndex, chip::NodeId sourceNodeId, + uint16_t userIndex, const Nullable & userName, const Nullable & userUniqueId, + const Nullable & userStatus, const Nullable & userType, + const Nullable & credentialRule); + EmberAfStatus clearUser(chip::EndpointId endpointId, chip::FabricIndex modifierFabricId, chip::NodeId sourceNodeId, + uint16_t userIndex, bool sendUserChangeEvent); + EmberAfStatus clearUser(chip::EndpointId endpointId, chip::FabricIndex modifierFabricId, chip::NodeId sourceNodeId, + uint16_t userIndex, const EmberAfPluginDoorLockUserInfo & user, bool sendUserChangeEvent); + + DlStatus createNewCredentialAndUser(chip::EndpointId endpointId, chip::FabricIndex creatorFabricIdx, chip::NodeId sourceNodeId, + const Nullable & userStatus, const Nullable & userType, + const DlCredential & credential, const chip::ByteSpan & credentialData, + uint16_t & createdUserIndex); + DlStatus createNewCredentialAndAddItToUser(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIdx, uint16_t userIndex, + const DlCredential & credential, const chip::ByteSpan & credentialData); + + DlStatus addCredentialToUser(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIdx, uint16_t userIndex, + const DlCredential & credential); + DlStatus modifyCredentialForUser(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIdx, uint16_t userIndex, + const DlCredential & credential); + + DlStatus createCredential(chip::EndpointId endpointId, chip::FabricIndex creatorFabricIdx, chip::NodeId sourceNodeId, + uint16_t credentialIndex, DlCredentialType credentialType, + const EmberAfPluginDoorLockCredentialInfo & existingCredential, const chip::ByteSpan & credentialData, + Nullable userIndex, Nullable userStatus, Nullable userType, + uint16_t & createdUserIndex); + DlStatus modifyProgrammingPIN(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIndex, chip::NodeId sourceNodeId, + uint16_t credentialIndex, DlCredentialType credentialType, + const EmberAfPluginDoorLockCredentialInfo & existingCredential, + const chip::ByteSpan & credentialData); + DlStatus modifyCredential(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIndex, chip::NodeId sourceNodeId, + uint16_t credentialIndex, DlCredentialType credentialType, + const EmberAfPluginDoorLockCredentialInfo & existingCredential, const chip::ByteSpan & credentialData, + uint16_t userIndex, Nullable userStatus, Nullable userType); + + EmberAfStatus clearCredential(chip::EndpointId endpointId, chip::FabricIndex modifier, chip::NodeId sourceNodeId, + DlCredentialType credentialType, uint16_t credentialIndex, bool sendUserChangeEvent); + EmberAfStatus clearCredentials(chip::EndpointId endpointId, chip::FabricIndex modifier, chip::NodeId sourceNodeId); + EmberAfStatus clearCredentials(chip::EndpointId endpointId, chip::FabricIndex modifier, chip::NodeId sourceNodeId, + DlCredentialType credentialType); + + CHIP_ERROR sendSetCredentialResponse(chip::app::CommandHandler * commandObj, DlStatus status, uint16_t userIndex, + uint16_t nextCredentialIndex); + + // TODO: Maybe use CHIP_APPLICATION_ERROR instead of boolean in class methods? + bool credentialTypeSupported(chip::EndpointId endpointId, DlCredentialType type); + + bool sendRemoteLockUserChange(chip::EndpointId endpointId, DlLockDataType dataType, DlDataOperationType operation, + chip::NodeId nodeId, chip::FabricIndex fabricIndex, uint16_t userIndex = 0, + uint16_t dataIndex = 0); + + DlLockDataType credentialTypeToLockDataType(DlCredentialType credentialType); + + static DoorLockServer instance; }; +/** + * @brief Status of the credential slot in the credentials database. + */ +enum class DlCredentialStatus : uint8_t +{ + kAvailable = 0x00, /**< Indicates if credential slot is available. */ + kOccupied = 0x01, /**< Indicates if credential slot is already occupied. */ +}; + +/** + * @brief Structure that holds the credential information. + */ +struct EmberAfPluginDoorLockCredentialInfo +{ + DlCredentialStatus status; /**< Indicates if credential slot is occupied or not. */ + DlCredentialType credentialType; /**< Specifies the type of the credential (PIN, RFID, etc.). */ + chip::ByteSpan credentialData; /**< Credential data bytes. */ +}; + +/** + * @brief Structure that holds user information. + */ +struct EmberAfPluginDoorLockUserInfo +{ + chip::CharSpan userName; /**< Name of the user. */ + chip::Span credentials; /**< Credentials that are associated with user (without data).*/ + uint32_t userUniqueId; /**< Unique user identifier. */ + DlUserStatus userStatus; /**< Status of the user slot (available/occupied). */ + DlUserType userType; /**< Type of the user. */ + DlCredentialRule credentialRule; /**< Number of supported credentials. */ + chip::FabricIndex createdBy; /**< ID of the fabric that created the user. */ + chip::FabricIndex lastModifiedBy; /**< ID of the fabric that modified the user. */ +}; + +typedef bool (*EmberAfDoorLockLockUnlockCommand)(chip::EndpointId endpointId, chip::Optional pinCode); + bool emberAfPluginDoorLockOnDoorLockCommand(chip::EndpointId endpointId, chip::Optional pinCode); bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, chip::Optional pinCode); bool emberAfPluginDoorLockOnDoorUnlockWithTimeoutCommand(chip::EndpointId endpointId, chip::Optional pinCode, @@ -162,3 +349,87 @@ chip::Protocols::InteractionModel::Status emberAfPluginDoorLockOnUserCodeTempora chip::Protocols::InteractionModel::Status emberAfPluginDoorLockOnUnhandledAttributeChange(chip::EndpointId EndpointId, EmberAfAttributeType attrType, uint16_t attrSize, uint8_t * attrValue); + +/** + * @brief This callback is called when Door Lock cluster needs to access the users database. + * + * @param endpointId ID of the endpoint which contains the lock. + * @param userIndex Index of the user to access. It is guaranteed to be within limits declared in the spec (from 1 up to the value + * of NumberOfUsersSupported attribute). + * @param[out] user Reference to the user information variable which will hold user info upon successful function call. + * + * @retval true, if \p userIndex was found in the database and \p user parameter was written with valid data. + * @retval false, if error occurred. + */ +bool emberAfPluginDoorLockGetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user); + +/** + * @brief This callback is called when Door Lock cluster needs to create, modify or clear the user in users database. + * + * @note This function is used for creating, modifying and clearing users. It is not guaranteed that the parameters always differ + * from current user state. For example, when modifying a single field (say, uniqueId) the user information that is passed + * to a function will be the same as the user record except this field. + * + * @param endpointId ID of the endpoint which contains the lock. + * @param userIndex Index of the user to create/modify. It is guaranteed to be within limits declared in the spec (from 1 up to the + * value of NumberOfUsersSupported attribute). + * @param creator Fabric ID that created the user. Could be kUndefinedFabricIndex (0). + * @param modifier Fabric ID that was last to modify the user. Could be kUndefinedFabricIndex (0). + * @param[in] userName Pointer to the user name. Could be an empty string, data is guaranteed not to be a nullptr. + * @param uniqueId New Unique ID of the user. + * @param userStatus New status of the user. + * @param usertype New type of the user. + * @param credentialRule New credential rule (how many credentials are allowed for user). + * @param[in] credentials Array of credentials. Size of this array is determined by totalCredentials variable. Could be nullptr + * which means that the credentials should be deleted. + * @param totalCredentials Size of \p credentials array. Could be 0. + * + * @retval true, if user pointed by \p userIndex was successfully changed in the database. + * @retval false, if error occurred while changing the user. + */ +bool emberAfPluginDoorLockSetUser(chip::EndpointId endpointId, uint16_t userIndex, chip::FabricIndex creator, + chip::FabricIndex modifier, const chip::CharSpan & userName, uint32_t uniqueId, + DlUserStatus userStatus, DlUserType usertype, DlCredentialRule credentialRule, + const DlCredential * credentials, size_t totalCredentials); + +/** + * @brief This callback is called when Door Lock cluster needs to access the credential in credentials database. + * + * @note The door lock cluster does not assume in any way underlying implementation of the database. Different credential types + * may be stored in the single data structure with shared index or separately. Door lock cluster guarantees that the + * credentialIndex will always be within the range for a particular credential type. + * + * @param endpointId ID of the endpoint which contains the lock. + * @param credentialIndex Index of the credential to access. It is guaranteed to be within limits declared in the spec for + * particular credential type. Starts from 1 for all credential types except Programming PIN -- in that case + * it could only be equal to 0. + * @param credentialType Type of the accessing credential. + * @param[out] credential Reference to the credential information which will be filled upon successful function call. + * + * @retval true, if the credential pointed by \p credentialIndex was found and \p credential parameter was written with valid data. + * @retval false, if error occurred. + */ +bool emberAfPluginDoorLockGetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType, + EmberAfPluginDoorLockCredentialInfo & credential); + +/** + * @brief This callback is called when Door Lock cluster needs to create, modify or clear the credential in credentials database. + * + * @note It is guaranteed that the call to this function will not cause any duplicated entries in the database (e.g. entries that + * share the same \p credentialType and \p credentialData). + * + * @param endpointId ID of the endpoint which contains the lock. + * @param credentialIndex Index of the credential to access. It is guaranteed to be within limits declared in the spec for + * particular credential type. Starts from 1 for all credential types except Programming PIN -- in that case + * it could only be equal to 0. + * @param credentialStatus New status of the credential slot (occupied/available). DlCredentialStatus::kAvailable means that the + * credential must be deleted. + * @param credentialType Type of the credential (PIN, RFID, etc.). + * @param[in] credentialData Data attached to a credential. Can contain nullptr as data which indicates that the data for credential + * should be removed. + * + * @retval true, if credential pointed by \p credentialIndex of type \p credentialType was successfully changed in the database. + * @retval false, if error occurred. + */ +bool emberAfPluginDoorLockSetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialStatus credentialStatus, + DlCredentialType credentialType, const chip::ByteSpan & credentialData); diff --git a/src/app/tests/suites/DL_LockUnlock.yaml b/src/app/tests/suites/DL_LockUnlock.yaml new file mode 100644 index 00000000000000..bf983fdce1e401 --- /dev/null +++ b/src/app/tests/suites/DL_LockUnlock.yaml @@ -0,0 +1,113 @@ +# Copyright (c) 2021 Project CHIP Authors +# +# 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. + +name: Door Lock Cluster Lock/Unlock tests + +config: + cluster: "Door Lock" + endpoint: 1 + +tests: + - label: "Wait for the commissioned device to be retrieved" + cluster: "DelayCommands" + command: "WaitForCommissionee" + + - label: "Create new PIN credential and lock/unlock user" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 1 } + - name: "credentialData" + value: "123456" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x00 + - name: "userIndex" + value: 1 + - name: "nextCredentialIndex" + value: 2 + + - label: "Try to unlock the door with invalid PIN" + command: "UnlockDoor" + arguments: + values: + - name: "pinCode" + value: "000000" + response: + error: FAILURE + + - label: "Verify that lock state attribute value is set to Locked" + command: "readAttribute" + attribute: "LockState" + response: + value: 1 + + - label: "Try to unlock the door with valid PIN" + command: "UnlockDoor" + arguments: + values: + - name: "pinCode" + value: "123456" + + - label: "Verify that lock state attribute value is set to Unlocked" + command: "readAttribute" + attribute: "LockState" + response: + value: 2 + + - label: "Try to lock the door with invalid PIN" + command: "LockDoor" + arguments: + values: + - name: "pinCode" + value: "000000" + response: + error: FAILURE + + - label: "Verify that lock state attribute value is set to Unlocked" + command: "readAttribute" + attribute: "LockState" + response: + value: 2 + + - label: "Try to unlock the door with valid PIN" + command: "LockDoor" + arguments: + values: + - name: "pinCode" + value: "123456" + + - label: "Verify that lock state attribute value is set to Locked" + command: "readAttribute" + attribute: "LockState" + response: + value: 1 + + # Clean-up + - label: "Clean the created credential" + command: "ClearCredential" + arguments: + values: + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 1 } diff --git a/src/app/tests/suites/DL_UsersAndCredentials.yaml b/src/app/tests/suites/DL_UsersAndCredentials.yaml new file mode 100644 index 00000000000000..081e404d5ebf07 --- /dev/null +++ b/src/app/tests/suites/DL_UsersAndCredentials.yaml @@ -0,0 +1,2112 @@ +# Copyright (c) 2021 Project CHIP Authors +# +# 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. + +name: Door Lock Cluster Users and Credentials tests + +config: + cluster: "Door Lock" + endpoint: 1 + +tests: + - label: "Wait for the commissioned device to be retrieved" + cluster: "DelayCommands" + command: "WaitForCommissionee" + + - label: "Read available user slot and verify response fields" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: null + - name: "lastModifiedFabricIndex" + value: null + - name: "nextUserIndex" + value: 2 + + - label: "Get number of supported users and verify default value" + command: "readAttribute" + attribute: "NumberOfTotalUsersSupported" + response: + saveAs: NumberOfTotalUsersSupported + value: 10 + + - label: "Read fails for user with index 0" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 0 + response: + error: INVALID_COMMAND + + - label: + "Read fails for user with index greater than Number Of Users Supported" + command: "GetUser" + arguments: + values: + - name: "userIndex" + # This ugly hack is required to silence compiler warnings about type promotions + value: static_cast(NumberOfTotalUsersSupported + 1) + response: + error: INVALID_COMMAND + + - label: "Create new user with default parameters" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 0 + - name: "userIndex" + value: 1 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + + - label: "Read the user back and verify its fields" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: "" + - name: "userUniqueId" + value: null + - name: "userStatus" + value: 1 + - name: "userType" + value: 0 + - name: "credentialRule" + value: 0 + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 2 + + - label: "Set user at the occupied index fails with appropriate response" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 0 + - name: "userIndex" + value: 1 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + response: + # So far there's no way to verify cluster-specific error codes so we're just checking generic failure here + error: 0x01 + + - label: "Modify userName for existing user" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 2 + - name: "userIndex" + value: 1 + - name: "userName" + value: "new_user" + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + + - label: "Read the modified user back and verify its fields" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: "new_user" + - name: "userUniqueId" + value: null + - name: "userStatus" + value: 1 + - name: "userType" + value: 0 + - name: "credentialRule" + value: 0 + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 2 + + - label: "Modify userUniqueId for existing user" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 2 + - name: "userIndex" + value: 1 + - name: "userName" + value: null + - name: "userUniqueId" + value: 0x1234ABCD + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + + - label: "Read the modified user back and verify its fields" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: "new_user" + - name: "userUniqueId" + value: 0x1234ABCD + - name: "userStatus" + value: 1 + - name: "userType" + value: 0 + - name: "credentialRule" + value: 0 + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 2 + + - label: "Modify userStatus for existing user" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 2 + - name: "userIndex" + value: 1 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: 0x03 # Occupied, Disabled + - name: "userType" + value: null + - name: "credentialRule" + value: null + + - label: "Read the modified user back and verify its fields" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: "new_user" + - name: "userUniqueId" + value: 0x1234ABCD + - name: "userStatus" + value: 3 + - name: "userType" + value: 0 + - name: "credentialRule" + value: 0 + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 2 + + - label: "Modify userType for existing user" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 2 + - name: "userIndex" + value: 1 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: 0x06 # Disposable user + - name: "credentialRule" + value: null + + - label: "Read the modified user back and verify its fields" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: "new_user" + - name: "userUniqueId" + value: 0x1234ABCD + - name: "userStatus" + value: 3 + - name: "userType" + value: 6 + - name: "credentialRule" + value: 0 + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 2 + + - label: "Modify credentialRule for existing user" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 2 + - name: "userIndex" + value: 1 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: 2 + + - label: "Read the modified user back and verify its fields" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: "new_user" + - name: "userUniqueId" + value: 0x1234ABCD + - name: "userStatus" + value: 3 + - name: "userType" + value: 6 + - name: "credentialRule" + value: 2 + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 2 + + - label: "Modify all fields for existing user" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 2 + - name: "userIndex" + value: 1 + - name: "userName" + value: "test_user" + - name: "userUniqueId" + value: 0x1BCDA0A0 + - name: "userStatus" + value: 1 + - name: "userType" + value: 0 + - name: "credentialRule" + value: 1 + + - label: "Read the modified user back and verify its fields" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: "test_user" + - name: "userUniqueId" + value: 0x1BCDA0A0 + - name: "userStatus" + value: 1 + - name: "userType" + value: 0 + - name: "credentialRule" + value: 1 + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 2 + + - label: "Add another user with non-default fields" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 0 + - name: "userIndex" + value: 2 + - name: "userName" + value: "test_user2" + - name: "userUniqueId" + value: 0xC0FFEE + - name: "userStatus" + value: 1 + - name: "userType" + value: 1 + - name: "credentialRule" + value: 2 + + - label: "Read the new user back and verify its fields" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 2 + response: + values: + - name: "userIndex" + value: 2 + - name: "userName" + value: "test_user2" + - name: "userUniqueId" + value: 0xC0FFEE + - name: "userStatus" + value: 1 + - name: "userType" + value: 1 + - name: "credentialRule" + value: 2 + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 3 + + - label: "Create user in the last slot" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 0 + - name: "userIndex" + value: NumberOfTotalUsersSupported + - name: "userName" + value: "last_user" + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + + - label: "Read the last user back and verify its fields" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: NumberOfTotalUsersSupported + response: + values: + - name: "userIndex" + value: NumberOfTotalUsersSupported + - name: "userName" + value: "last_user" + - name: "userUniqueId" + value: null + - name: "userStatus" + value: 1 + - name: "userType" + value: 0 + - name: "credentialRule" + value: 0 + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: null + + - label: "User creation in the 0 slot fails" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 0 + - name: "userIndex" + value: 0 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + response: + error: INVALID_COMMAND + + - label: "User creation in the out-of-bounds slot fails" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 0 + - name: "userIndex" + # This ugly hack is required to silence compiler warnings about type promotions + value: static_cast(NumberOfTotalUsersSupported + 1) + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + response: + error: INVALID_COMMAND + + - label: "Clear first user" + command: "ClearUser" + arguments: + values: + - name: "userIndex" + value: 1 + + - label: "Read cleared user and verify it is available" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: null + - name: "lastModifiedFabricIndex" + value: null + - name: "nextUserIndex" + value: 3 # Slot 2 is still occupied + + - label: "Create new user in the cleared slot" + command: "SetUser" + arguments: + values: + - name: "operationType" + value: 0 + - name: "userIndex" + value: 1 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + + - label: + "Read the user in the previously cleared slot and verify its fields" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: "" + - name: "userUniqueId" + value: null + - name: "userStatus" + value: 1 + - name: "userType" + value: 0 + - name: "credentialRule" + value: 0 + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 3 # Slot 2 is still occupied + + - label: "Clear user with index 0 fails" + command: "ClearUser" + arguments: + values: + - name: "userIndex" + value: 0 + response: + error: INVALID_COMMAND + + - label: "Clear user with out-of-bounds index fails" + command: "ClearUser" + arguments: + values: + - name: "userIndex" + # This ugly hack is required to silence compiler warnings about type promotions + value: static_cast(NumberOfTotalUsersSupported + 1) + response: + error: INVALID_COMMAND + + - label: "Clear all users" + command: "ClearUser" + arguments: + values: + - name: "userIndex" + value: 0xFFFE + + - label: "Read first cleared user and verify it is available" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 2 + response: + values: + - name: "userIndex" + value: 2 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: null + - name: "lastModifiedFabricIndex" + value: null + - name: "nextUserIndex" + value: 3 + + - label: "Read last cleared user and verify it is available" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: NumberOfTotalUsersSupported + response: + values: + - name: "userIndex" + value: NumberOfTotalUsersSupported + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: null + - name: "lastModifiedFabricIndex" + value: null + - name: "nextUserIndex" + value: null + + # + # Credentials tests + # + + - label: "Get number of supported PIN credentials and verify default value" + command: "readAttribute" + attribute: "NumberOfPINUsersSupported" + response: + saveAs: NumberOfPINUsersSupported + value: 10 + + - label: "Check that PIN credential does not exist" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 1 } + response: + values: + - name: "credentialExists" + value: false + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 2 + + - label: "Reading PIN credential with index 0 fails" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 0 } + response: + error: INVALID_COMMAND + + - label: "Reading PIN credential with out-of-bounds index fails" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { + CredentialType: 1, + # This ugly hack is required to silence compiler warnings about type promotions + CredentialIndex: + static_cast(NumberOfPINUsersSupported + 1), + } + response: + error: INVALID_COMMAND + + - label: "Create new PIN credential and user" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 1 } + - name: "credentialData" + value: "000000" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x00 + - name: "userIndex" + value: 1 + - name: "nextCredentialIndex" + value: 2 + + - label: "Verify created user" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: "" + - name: "userUniqueId" + value: null + - name: "userStatus" + value: 1 + - name: "userType" + value: 0 + - name: "credentialRule" + value: 0 + - name: "credentials" + value: [{ CredentialType: 1, CredentialIndex: 1 }] + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 2 + + - label: "Verify created PIN credential" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 1 } + response: + values: + - name: "credentialExists" + value: true + - name: "userIndex" + value: 1 + - name: "nextCredentialIndex" + value: 2 + + - label: "Create new PIN credential and user with index 0 fails" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 0 } + - name: "credentialData" + value: "123456" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x85 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 2 + + - label: "Create new PIN credential and user with out-of-bounds index fails" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { + CredentialType: 1, + # This ugly hack is required to silence compiler warnings about type promotions + CredentialIndex: + static_cast(NumberOfPINUsersSupported + 1), + } + - name: "credentialData" + value: "123456" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x85 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: null + + - label: "Get number of supported RFID credentials and verify default value" + command: "readAttribute" + attribute: "NumberOfRFIDUsersSupported" + response: + saveAs: NumberOfRFIDUsersSupported + value: 10 + + - label: "Reading RFID credential with index 0 fails" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 0 } + response: + error: INVALID_COMMAND + + - label: "Reading RFID credential with out-of-bounds index fails" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { + CredentialType: 2, + # This ugly hack is required to silence compiler warnings about type promotions + CredentialIndex: + static_cast(NumberOfRFIDUsersSupported + + 1), + } + response: + error: INVALID_COMMAND + + - label: "Check that RFID credential does not exist" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 2 } + response: + values: + - name: "credentialExists" + value: false + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 3 + + - label: "Create new RFID credential and add it to existing user" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 2 } + - name: "credentialData" + value: "rfid_data_123456" + - name: "userIndex" + value: 1 + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x00 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 3 + + - label: "Verify modified user" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: "" + - name: "userUniqueId" + value: null + - name: "userStatus" + value: 1 + - name: "userType" + value: 0 + - name: "credentialRule" + value: 0 + - name: "credentials" + value: + [ + { CredentialType: 1, CredentialIndex: 1 }, + { CredentialType: 2, CredentialIndex: 2 }, + ] + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 2 + + - label: "Verify created credential" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 2 } + response: + values: + - name: "credentialExists" + value: true + - name: "userIndex" + value: 1 + - name: "nextCredentialIndex" + value: 3 + + - label: "Create new RFID credential and user with index 0 fails" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 0 } + - name: "credentialData" + value: "new_rfid_data_field" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x85 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 3 + + - label: + "Create new RFID credential and user with out-of-bounds index fails" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { + CredentialType: 2, + # This ugly hack is required to silence compiler warnings about type promotions + CredentialIndex: + static_cast(NumberOfRFIDUsersSupported + + 1), + } + - name: "credentialData" + value: "new_rfid_data_field" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x85 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: null + + - label: "Create new PIN credential and try to add it to existing user" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 3 } + - name: "credentialData" + value: "123465" + - name: "userIndex" + value: 1 + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x03 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 4 + + - label: "Create new credential and try to add it to 0 user" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 3 } + - name: "credentialData" + value: "123465" + - name: "userIndex" + value: 0 + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x85 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 4 + + - label: "Create new credential and try to add it to out-of-bounds user" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 3 } + - name: "credentialData" + value: "123465" + - name: "userIndex" + # This ugly hack is required to silence compiler warnings about type promotions + value: static_cast(NumberOfTotalUsersSupported + 1) + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x85 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 4 + + - label: "Create new PIN with too short data" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 3 } + - name: "credentialData" + value: "12345" + - name: "userIndex" + value: 0 + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x85 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 4 + + - label: "Create new PIN with too long data" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 3 } + - name: "credentialData" + value: "123456789" + - name: "userIndex" + value: 0 + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x85 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 4 + + - label: "Create new RFID with too short data" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 3 } + - name: "credentialData" + value: "rfid_data" + - name: "userIndex" + value: 0 + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x85 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 4 + + - label: "Create new PIN with Programming user type fails" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 3 } + - name: "credentialData" + value: "123456" + - name: "userIndex" + value: 0 + - name: "userStatus" + value: null + - name: "userType" + value: 3 + response: + values: + - name: "status" + value: 0x85 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 4 + + - label: "Create new RFID with too short data" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 3 } + - name: "credentialData" + value: "very_long_rfid_data_to_test_boundaries" + - name: "userIndex" + value: 0 + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x85 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 4 + + - label: "Create new PIN credential with data the would cause duplicate" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 4 } + - name: "credentialData" + value: "000000" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x02 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 5 + + - label: "Create new RFID credential with data the would cause duplicate" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 4 } + - name: "credentialData" + value: "rfid_data_123456" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x02 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 5 + + - label: "Modify credentialData of existing PIN credential" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 2 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 1 } + - name: "credentialData" + value: "123456" + - name: "userIndex" + value: 1 + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x00 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 3 + + - label: + "Verify that credential was changed by creating new credential with + old data" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 3 } + - name: "credentialData" + value: "000000" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x00 + - name: "userIndex" + value: 2 + - name: "nextCredentialIndex" + value: 4 + + - label: + "Verify that credential was changed by creating new credential with + new data" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 4 } + - name: "credentialData" + value: "123456" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x02 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 5 + + # At that state we have the following users: + # Index = 1, Credentials = {(1, PIN), (2, RFID)} + # Index = 2, Credentials = {(3, PIN)} + + - label: "Clear first PIN credential" + command: "ClearCredential" + arguments: + values: + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 1 } + + - label: "Read back the credential and make sure it is deleted" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 1 } + response: + values: + - name: "credentialExists" + value: false + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 4 + + - label: "Read the user back and make sure PIN credential is deleted" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: "" + - name: "userUniqueId" + value: null + - name: "userStatus" + value: 1 + - name: "userType" + value: 0 + - name: "credentialRule" + value: 0 + - name: "credentials" + value: [{ CredentialType: 2, CredentialIndex: 2 }] + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 3 + + - label: "Clear the second PIN credential" + command: "ClearCredential" + arguments: + values: + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 3 } + + - label: "Read back the credential and make sure it is deleted" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 3 } + response: + values: + - name: "credentialExists" + value: false + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 4 + + - label: "Read the user back and make sure related user is deleted" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 2 + response: + values: + - name: "userIndex" + value: 2 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: null + - name: "lastModifiedFabricIndex" + value: null + - name: "nextUserIndex" + value: 3 + + - label: "Create new RFID credential with user" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 1 } + - name: "credentialData" + value: "rfid_data_12345" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x00 + - name: "userIndex" + value: 2 + - name: "nextCredentialIndex" + value: 3 + + - label: "Clear all the RFID credentials" + command: "ClearCredential" + arguments: + values: + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 0xFFFE } + + - label: "Read back the fist RFID credential and make sure it is deleted" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 1 } + response: + values: + - name: "credentialExists" + value: false + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 2 + + - label: "Read back the second RFID credential and make sure it is deleted" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 2 } + response: + values: + - name: "credentialExists" + value: false + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 3 + + - label: + "Read the user related with first RFID back and make sure it is + deleted" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: null + - name: "lastModifiedFabricIndex" + value: null + - name: "nextUserIndex" + value: 2 + + - label: + "Read the user related with second RFID back and make sure it is + deleted" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 2 + response: + values: + - name: "userIndex" + value: 2 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: null + - name: "lastModifiedFabricIndex" + value: null + - name: "nextUserIndex" + value: 3 + + - label: "Create new PIN credential with user" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 1 } + - name: "credentialData" + value: "123456" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x00 + - name: "userIndex" + value: 1 + - name: "nextCredentialIndex" + value: 2 + + - label: "Create new RFID credential with user" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 2 } + - name: "credentialData" + value: "rfid_data_1234" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x00 + - name: "userIndex" + value: 2 + - name: "nextCredentialIndex" + value: 3 + + - label: "Create another RFID credential with user" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 6 } + - name: "credentialData" + value: "rfid_data_9876" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x00 + - name: "userIndex" + value: 3 + - name: "nextCredentialIndex" + value: 7 + + # This test is disabled for now because ZAP generators are not generating working code when + # command has nullable as a parameter. + - label: "Clear all the credentials" + command: "ClearCredential" + arguments: + values: + - name: "credential" + value: null + + - label: "Read back the first PIN credential and make sure it is deleted" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 1 } + response: + values: + - name: "credentialExists" + value: false + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 2 + + - label: "Read back the first RFID credential and make sure it is deleted" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 2 } + response: + values: + - name: "credentialExists" + value: false + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 3 + + - label: "Read back the second PIN credential and make sure it is deleted" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 6 } + response: + values: + - name: "credentialExists" + value: false + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: 7 + + - label: + "Read the user related with first PIN back and make sure it is deleted" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: null + - name: "lastModifiedFabricIndex" + value: null + - name: "nextUserIndex" + value: 2 + + - label: + "Read the user related with first RFID back and make sure it is + deleted" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 2 + response: + values: + - name: "userIndex" + value: 2 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: null + - name: "lastModifiedFabricIndex" + value: null + - name: "nextUserIndex" + value: 3 + + - label: + "Read the user related with second PIN back and make sure it is + deleted" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 3 + response: + values: + - name: "userIndex" + value: 3 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: null + - name: "lastModifiedFabricIndex" + value: null + - name: "nextUserIndex" + value: 4 + + - label: "Create new Programming PIN credential with invalid index" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 0, CredentialIndex: 1 } + - name: "credentialData" + value: "123456" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x85 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: null + + - label: "Create new Programming PIN credential with valid index" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 0 + - name: "credential" + value: { CredentialType: 0, CredentialIndex: 0 } + - name: "credentialData" + value: "123456" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x00 + - name: "userIndex" + value: 1 + - name: "nextCredentialIndex" + value: null + + - label: "Verify created user" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: "" + - name: "userUniqueId" + value: null + - name: "userStatus" + value: 1 + - name: "userType" + value: 0 + - name: "credentialRule" + value: 0 + - name: "credentials" + value: [{ CredentialType: 0, CredentialIndex: 0 }] + - name: "creatorFabricIndex" + value: 1 + - name: "lastModifiedFabricIndex" + value: 1 + - name: "nextUserIndex" + value: 2 + + - label: "Verify created programming PIN credential" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 0, CredentialIndex: 0 } + response: + values: + - name: "credentialExists" + value: true + - name: "userIndex" + value: 1 + - name: "nextCredentialIndex" + value: null + + - label: "Modify the Programming PIN credential" + command: "SetCredential" + arguments: + values: + - name: "operationType" + value: 2 + - name: "credential" + value: { CredentialType: 0, CredentialIndex: 0 } + - name: "credentialData" + value: "654321" + - name: "userIndex" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + response: + values: + - name: "status" + value: 0x00 + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: null + + - label: "Clearing Programming PIN fails" + command: "ClearCredential" + arguments: + values: + - name: "credential" + value: { CredentialType: 0, CredentialIndex: 0 } + response: + error: INVALID_COMMAND + + - label: "Clearing Programming PIN with invalid index fails" + command: "ClearCredential" + arguments: + values: + - name: "credential" + value: { CredentialType: 0, CredentialIndex: 1 } + response: + error: INVALID_COMMAND + + - label: "Clearing PIN credential with zero index fails" + command: "ClearCredential" + arguments: + values: + - name: "credential" + value: { CredentialType: 1, CredentialIndex: 0 } + response: + error: INVALID_COMMAND + + - label: "Clearing PIN credential with out-of-bound index fails" + command: "ClearCredential" + arguments: + values: + - name: "credential" + value: { + CredentialType: 1, + # This ugly hack is required to silence compiler warnings about type promotions + CredentialIndex: + static_cast(NumberOfPINUsersSupported + 1), + } + response: + error: INVALID_COMMAND + + - label: "Clearing RFID credential with zero index fails" + command: "ClearCredential" + arguments: + values: + - name: "credential" + value: { CredentialType: 2, CredentialIndex: 0 } + response: + error: INVALID_COMMAND + + - label: "Clearing RFID credential with out-of-bound index fails" + command: "ClearCredential" + arguments: + values: + - name: "credential" + value: { + CredentialType: 2, + # This ugly hack is required to silence compiler warnings about type promotions + CredentialIndex: + static_cast(NumberOfRFIDUsersSupported + + 1), + } + response: + error: INVALID_COMMAND + + # Cleanup so the test could be run again. Also checks that clearUser removes associated credentials + - label: "Clear the Programming PIN user" + command: "ClearUser" + arguments: + values: + - name: "userIndex" + value: 1 + + - label: "Make sure Programming PIN user is deleted" + command: "GetUser" + arguments: + values: + - name: "userIndex" + value: 1 + response: + values: + - name: "userIndex" + value: 1 + - name: "userName" + value: null + - name: "userUniqueId" + value: null + - name: "userStatus" + value: null + - name: "userType" + value: null + - name: "credentialRule" + value: null + - name: "credentials" + value: null + - name: "creatorFabricIndex" + value: null + - name: "lastModifiedFabricIndex" + value: null + - name: "nextUserIndex" + value: 2 + + - label: "Make sure programming PIN credential is deleted" + command: "GetCredentialStatus" + arguments: + values: + - name: "credential" + value: { CredentialType: 0, CredentialIndex: 0 } + response: + values: + - name: "credentialExists" + value: false + - name: "userIndex" + value: null + - name: "nextCredentialIndex" + value: null diff --git a/src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml index 3c4201249e9673..84f62ddabce84a 100644 --- a/src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml @@ -267,7 +267,7 @@ limitations under the License. - + Request a log record. @@ -289,12 +289,12 @@ limitations under the License. Set a PIN Code into the lock. - - + + - + Retrieve a PIN Code. @@ -327,7 +327,7 @@ limitations under the License. - + Get the status of a user. @@ -352,7 +352,7 @@ limitations under the License. - + Retrieve the specific weekly schedule for the specific user. @@ -388,7 +388,7 @@ limitations under the License. - + Returns the year day schedule data for the specified schedule and user indexes. @@ -421,7 +421,7 @@ limitations under the License. - + Get the holiday schedule for the specified index. @@ -450,7 +450,7 @@ limitations under the License. - + Retrieve the user type for a specific user. @@ -467,12 +467,12 @@ limitations under the License. Set an ID for RFID access into the lock. - - + + - + Retrieve an RFID code. @@ -505,12 +505,12 @@ limitations under the License. - - - + + + - + Retrieve User. @@ -528,7 +528,7 @@ limitations under the License. - + @@ -559,14 +559,15 @@ limitations under the License. - + Set a credential (e.g. PIN, RFID, Fingerprint, etc.) into the lock for a new user, existing user, or ProgrammingUser. - - + + + @@ -577,7 +578,7 @@ limitations under the License. - + Retrieve the status of a particular credential (e.g. PIN, RFID, Fingerprint, etc.) by index. @@ -594,7 +595,7 @@ limitations under the License. Clear one, one type, or all credentials except ProgrammingPIN credential. - + @@ -706,12 +707,6 @@ limitations under the License. - - - - - - @@ -954,4 +949,18 @@ limitations under the License. + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 4c934e078aa241..3416858249ba43 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -958,11 +958,6 @@ client cluster DoorLock = 257 { kModify = 2; } - enum DlDoorLockStatus : ENUM8 { - kDuplicate = 2; - kOccupied = 3; - } - enum DlDoorState : ENUM8 { kDoorOpen = 0; kDoorClosed = 1; @@ -1167,8 +1162,11 @@ client cluster DoorLock = 257 { readonly attribute nullable DlDoorState doorState = 3; readonly attribute int16u numberOfTotalUsersSupported = 17; readonly attribute int16u numberOfPINUsersSupported = 18; + readonly attribute int16u numberOfRFIDUsersSupported = 19; readonly attribute int8u maxPINCodeLength = 23; readonly attribute int8u minPINCodeLength = 24; + readonly attribute int8u maxRFIDCodeLength = 25; + readonly attribute int8u minRFIDCodeLength = 26; attribute char_string<3> language = 33; attribute int32u autoRelockTime = 35; attribute int8u soundVolume = 36; @@ -1181,7 +1179,7 @@ client cluster DoorLock = 257 { readonly global attribute int16u clusterRevision = 65533; request struct ClearCredentialRequest { - DlCredential credential = 0; + nullable DlCredential credential = 0; } request struct ClearUserRequest { @@ -1204,8 +1202,9 @@ client cluster DoorLock = 257 { DlDataOperationType operationType = 0; DlCredential credential = 1; LONG_OCTET_STRING credentialData = 2; - INT16U userIndex = 3; - DlUserStatus userStatus = 4; + nullable INT16U userIndex = 3; + nullable DlUserStatus userStatus = 4; + nullable DlUserType userType = 5; } request struct SetUserRequest { @@ -1213,9 +1212,9 @@ client cluster DoorLock = 257 { INT16U userIndex = 1; nullable CHAR_STRING userName = 2; nullable INT32U userUniqueId = 3; - DlUserStatus userStatus = 4; - DlUserType userType = 5; - DlCredentialRule credentialRule = 6; + nullable DlUserStatus userStatus = 4; + nullable DlUserType userType = 5; + nullable DlCredentialRule credentialRule = 6; } request struct UnlockDoorRequest { @@ -1238,7 +1237,7 @@ client cluster DoorLock = 257 { nullable DlCredential credentials[] = 6; nullable fabric_idx creatorFabricIndex = 7; nullable fabric_idx lastModifiedFabricIndex = 8; - INT16U nextUserIndex = 9; + nullable INT16U nextUserIndex = 9; } response struct SetCredentialResponse { diff --git a/src/controller/data_model/controller-clusters.zap b/src/controller/data_model/controller-clusters.zap index 65a4e3888f25ed..78860accc08031 100644 --- a/src/controller/data_model/controller-clusters.zap +++ b/src/controller/data_model/controller-clusters.zap @@ -7296,6 +7296,21 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "NumberOfRFIDUsersSupported", + "code": 19, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "MaxPINCodeLength", "code": 23, @@ -7326,6 +7341,36 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "MaxRFIDCodeLength", + "code": 25, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinRFIDCodeLength", + "code": 26, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "Language", "code": 33, diff --git a/src/controller/java/zap-generated/CHIPCallbackTypes.h b/src/controller/java/zap-generated/CHIPCallbackTypes.h index 019a382ac63b75..a5292c1bee8010 100644 --- a/src/controller/java/zap-generated/CHIPCallbackTypes.h +++ b/src/controller/java/zap-generated/CHIPCallbackTypes.h @@ -349,10 +349,16 @@ typedef void (*CHIPDoorLockClusterNumberOfTotalUsersSupportedAttributeCallbackTy void *, chip::app::Clusters::DoorLock::Attributes::NumberOfTotalUsersSupported::TypeInfo::DecodableArgType); typedef void (*CHIPDoorLockClusterNumberOfPINUsersSupportedAttributeCallbackType)( void *, chip::app::Clusters::DoorLock::Attributes::NumberOfPINUsersSupported::TypeInfo::DecodableArgType); +typedef void (*CHIPDoorLockClusterNumberOfRFIDUsersSupportedAttributeCallbackType)( + void *, chip::app::Clusters::DoorLock::Attributes::NumberOfRFIDUsersSupported::TypeInfo::DecodableArgType); typedef void (*CHIPDoorLockClusterMaxPINCodeLengthAttributeCallbackType)( void *, chip::app::Clusters::DoorLock::Attributes::MaxPINCodeLength::TypeInfo::DecodableArgType); typedef void (*CHIPDoorLockClusterMinPINCodeLengthAttributeCallbackType)( void *, chip::app::Clusters::DoorLock::Attributes::MinPINCodeLength::TypeInfo::DecodableArgType); +typedef void (*CHIPDoorLockClusterMaxRFIDCodeLengthAttributeCallbackType)( + void *, chip::app::Clusters::DoorLock::Attributes::MaxRFIDCodeLength::TypeInfo::DecodableArgType); +typedef void (*CHIPDoorLockClusterMinRFIDCodeLengthAttributeCallbackType)( + void *, chip::app::Clusters::DoorLock::Attributes::MinRFIDCodeLength::TypeInfo::DecodableArgType); typedef void (*CHIPDoorLockClusterLanguageAttributeCallbackType)( void *, chip::app::Clusters::DoorLock::Attributes::Language::TypeInfo::DecodableArgType); typedef void (*CHIPDoorLockClusterAutoRelockTimeAttributeCallbackType)( diff --git a/src/controller/java/zap-generated/CHIPClusters-JNI.cpp b/src/controller/java/zap-generated/CHIPClusters-JNI.cpp index 8386384e4b57c1..a304888e223ede 100644 --- a/src/controller/java/zap-generated/CHIPClusters-JNI.cpp +++ b/src/controller/java/zap-generated/CHIPClusters-JNI.cpp @@ -8680,16 +8680,24 @@ JNI_METHOD(void, DoorLockCluster, clearCredential) std::vector> cleanupByteArrays; std::vector> cleanupStrings; - jobject credential_credentialTypeItem_0; - chip::JniReferences::GetInstance().GetObjectField(credential, "credentialType", "Ljava/lang/Integer;", - credential_credentialTypeItem_0); - request.credential.credentialType = static_cast>( - chip::JniReferences::GetInstance().IntegerToPrimitive(credential_credentialTypeItem_0)); - jobject credential_credentialIndexItem_0; - chip::JniReferences::GetInstance().GetObjectField(credential, "credentialIndex", "Ljava/lang/Integer;", - credential_credentialIndexItem_0); - request.credential.credentialIndex = static_cast>( - chip::JniReferences::GetInstance().IntegerToPrimitive(credential_credentialIndexItem_0)); + if (credential == nullptr) + { + request.credential.SetNull(); + } + else + { + auto & nonNullValue_0 = request.credential.SetNonNull(); + jobject credential_credentialTypeItem_1; + chip::JniReferences::GetInstance().GetObjectField(credential, "credentialType", "Ljava/lang/Integer;", + credential_credentialTypeItem_1); + nonNullValue_0.credentialType = static_cast>( + chip::JniReferences::GetInstance().IntegerToPrimitive(credential_credentialTypeItem_1)); + jobject credential_credentialIndexItem_1; + chip::JniReferences::GetInstance().GetObjectField(credential, "credentialIndex", "Ljava/lang/Integer;", + credential_credentialIndexItem_1); + nonNullValue_0.credentialIndex = static_cast>( + chip::JniReferences::GetInstance().IntegerToPrimitive(credential_credentialIndexItem_1)); + } std::unique_ptr onSuccess( Platform::New(callback), Platform::Delete); @@ -8946,7 +8954,7 @@ JNI_METHOD(void, DoorLockCluster, lockDoor) } JNI_METHOD(void, DoorLockCluster, setCredential) (JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jobject operationType, jobject credential, - jbyteArray credentialData, jobject userIndex, jobject userStatus, jobject timedInvokeTimeoutMs) + jbyteArray credentialData, jobject userIndex, jobject userStatus, jobject userType, jobject timedInvokeTimeoutMs) { chip::DeviceLayer::StackLock lock; CHIP_ERROR err = CHIP_NO_ERROR; @@ -8971,10 +8979,36 @@ JNI_METHOD(void, DoorLockCluster, setCredential) chip::JniReferences::GetInstance().IntegerToPrimitive(credential_credentialIndexItem_0)); cleanupByteArrays.push_back(chip::Platform::MakeUnique(env, static_cast(credentialData))); request.credentialData = cleanupByteArrays.back()->byteSpan(); - request.userIndex = static_cast>( - chip::JniReferences::GetInstance().IntegerToPrimitive(userIndex)); - request.userStatus = static_cast>( - chip::JniReferences::GetInstance().IntegerToPrimitive(userStatus)); + if (userIndex == nullptr) + { + request.userIndex.SetNull(); + } + else + { + auto & nonNullValue_0 = request.userIndex.SetNonNull(); + nonNullValue_0 = static_cast>( + chip::JniReferences::GetInstance().IntegerToPrimitive(userIndex)); + } + if (userStatus == nullptr) + { + request.userStatus.SetNull(); + } + else + { + auto & nonNullValue_0 = request.userStatus.SetNonNull(); + nonNullValue_0 = static_cast>( + chip::JniReferences::GetInstance().IntegerToPrimitive(userStatus)); + } + if (userType == nullptr) + { + request.userType.SetNull(); + } + else + { + auto & nonNullValue_0 = request.userType.SetNonNull(); + nonNullValue_0 = static_cast>( + chip::JniReferences::GetInstance().IntegerToPrimitive(userType)); + } std::unique_ptr onSuccess(Platform::New(callback), @@ -9050,12 +9084,36 @@ JNI_METHOD(void, DoorLockCluster, setUser) nonNullValue_0 = static_cast>( chip::JniReferences::GetInstance().LongToPrimitive(userUniqueId)); } - request.userStatus = static_cast>( - chip::JniReferences::GetInstance().IntegerToPrimitive(userStatus)); - request.userType = static_cast>( - chip::JniReferences::GetInstance().IntegerToPrimitive(userType)); - request.credentialRule = static_cast>( - chip::JniReferences::GetInstance().IntegerToPrimitive(credentialRule)); + if (userStatus == nullptr) + { + request.userStatus.SetNull(); + } + else + { + auto & nonNullValue_0 = request.userStatus.SetNonNull(); + nonNullValue_0 = static_cast>( + chip::JniReferences::GetInstance().IntegerToPrimitive(userStatus)); + } + if (userType == nullptr) + { + request.userType.SetNull(); + } + else + { + auto & nonNullValue_0 = request.userType.SetNonNull(); + nonNullValue_0 = static_cast>( + chip::JniReferences::GetInstance().IntegerToPrimitive(userType)); + } + if (credentialRule == nullptr) + { + request.credentialRule.SetNull(); + } + else + { + auto & nonNullValue_0 = request.credentialRule.SetNonNull(); + nonNullValue_0 = static_cast>( + chip::JniReferences::GetInstance().IntegerToPrimitive(credentialRule)); + } std::unique_ptr onSuccess( Platform::New(callback), Platform::Delete); @@ -9372,6 +9430,43 @@ JNI_METHOD(void, DoorLockCluster, subscribeNumberOfPINUsersSupportedAttribute) onSuccess.release(); onFailure.release(); } +JNI_METHOD(void, DoorLockCluster, subscribeNumberOfRFIDUsersSupportedAttribute) +(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval) +{ + chip::DeviceLayer::StackLock lock; + std::unique_ptr onSuccess( + Platform::New(callback, true), chip::Platform::Delete); + VerifyOrReturn(onSuccess.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY)); + + std::unique_ptr onFailure( + Platform::New(callback), chip::Platform::Delete); + VerifyOrReturn(onFailure.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY)); + + CHIP_ERROR err = CHIP_NO_ERROR; + DoorLockCluster * cppCluster = reinterpret_cast(clusterPtr); + VerifyOrReturn(cppCluster != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE)); + + using TypeInfo = chip::app::Clusters::DoorLock::Attributes::NumberOfRFIDUsersSupported::TypeInfo; + auto successFn = chip::Callback::Callback::FromCancelable( + onSuccess->Cancel()); + auto failureFn = chip::Callback::Callback::FromCancelable(onFailure->Cancel()); + + err = cppCluster->SubscribeAttribute(onSuccess->mContext, successFn->mCall, failureFn->mCall, + static_cast(minInterval), static_cast(maxInterval), + CHIPInt16uAttributeCallback::OnSubscriptionEstablished); + VerifyOrReturn(err == CHIP_NO_ERROR, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error subscribing to attribute", err)); + + onSuccess.release(); + onFailure.release(); +} JNI_METHOD(void, DoorLockCluster, subscribeMaxPINCodeLengthAttribute) (JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval) { @@ -9446,6 +9541,80 @@ JNI_METHOD(void, DoorLockCluster, subscribeMinPINCodeLengthAttribute) onSuccess.release(); onFailure.release(); } +JNI_METHOD(void, DoorLockCluster, subscribeMaxRFIDCodeLengthAttribute) +(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval) +{ + chip::DeviceLayer::StackLock lock; + std::unique_ptr onSuccess( + Platform::New(callback, true), chip::Platform::Delete); + VerifyOrReturn(onSuccess.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY)); + + std::unique_ptr onFailure( + Platform::New(callback), chip::Platform::Delete); + VerifyOrReturn(onFailure.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY)); + + CHIP_ERROR err = CHIP_NO_ERROR; + DoorLockCluster * cppCluster = reinterpret_cast(clusterPtr); + VerifyOrReturn(cppCluster != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE)); + + using TypeInfo = chip::app::Clusters::DoorLock::Attributes::MaxRFIDCodeLength::TypeInfo; + auto successFn = + chip::Callback::Callback::FromCancelable(onSuccess->Cancel()); + auto failureFn = chip::Callback::Callback::FromCancelable(onFailure->Cancel()); + + err = cppCluster->SubscribeAttribute(onSuccess->mContext, successFn->mCall, failureFn->mCall, + static_cast(minInterval), static_cast(maxInterval), + CHIPInt8uAttributeCallback::OnSubscriptionEstablished); + VerifyOrReturn(err == CHIP_NO_ERROR, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error subscribing to attribute", err)); + + onSuccess.release(); + onFailure.release(); +} +JNI_METHOD(void, DoorLockCluster, subscribeMinRFIDCodeLengthAttribute) +(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval) +{ + chip::DeviceLayer::StackLock lock; + std::unique_ptr onSuccess( + Platform::New(callback, true), chip::Platform::Delete); + VerifyOrReturn(onSuccess.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY)); + + std::unique_ptr onFailure( + Platform::New(callback), chip::Platform::Delete); + VerifyOrReturn(onFailure.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY)); + + CHIP_ERROR err = CHIP_NO_ERROR; + DoorLockCluster * cppCluster = reinterpret_cast(clusterPtr); + VerifyOrReturn(cppCluster != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE)); + + using TypeInfo = chip::app::Clusters::DoorLock::Attributes::MinRFIDCodeLength::TypeInfo; + auto successFn = + chip::Callback::Callback::FromCancelable(onSuccess->Cancel()); + auto failureFn = chip::Callback::Callback::FromCancelable(onFailure->Cancel()); + + err = cppCluster->SubscribeAttribute(onSuccess->mContext, successFn->mCall, failureFn->mCall, + static_cast(minInterval), static_cast(maxInterval), + CHIPInt8uAttributeCallback::OnSubscriptionEstablished); + VerifyOrReturn(err == CHIP_NO_ERROR, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error subscribing to attribute", err)); + + onSuccess.release(); + onFailure.release(); +} JNI_METHOD(void, DoorLockCluster, subscribeLanguageAttribute) (JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval) { diff --git a/src/controller/java/zap-generated/CHIPInvokeCallbacks.cpp b/src/controller/java/zap-generated/CHIPInvokeCallbacks.cpp index cf56de473b7468..c64cfa54169775 100644 --- a/src/controller/java/zap-generated/CHIPInvokeCallbacks.cpp +++ b/src/controller/java/zap-generated/CHIPInvokeCallbacks.cpp @@ -663,10 +663,17 @@ void CHIPDoorLockClusterGetUserResponseCallback::CallbackFn( dataResponse.lastModifiedFabricIndex.Value(), lastModifiedFabricIndex); } jobject nextUserIndex; - std::string nextUserIndexClassName = "java/lang/Integer"; - std::string nextUserIndexCtorSignature = "(I)V"; - chip::JniReferences::GetInstance().CreateBoxedObject( - nextUserIndexClassName.c_str(), nextUserIndexCtorSignature.c_str(), dataResponse.nextUserIndex, nextUserIndex); + if (dataResponse.nextUserIndex.IsNull()) + { + nextUserIndex = nullptr; + } + else + { + std::string nextUserIndexClassName = "java/lang/Integer"; + std::string nextUserIndexCtorSignature = "(I)V"; + chip::JniReferences::GetInstance().CreateBoxedObject( + nextUserIndexClassName.c_str(), nextUserIndexCtorSignature.c_str(), dataResponse.nextUserIndex.Value(), nextUserIndex); + } env->CallVoidMethod(javaCallbackRef, javaMethod, userIndex, userName, userUniqueId, userStatus, userType, credentialRule, credentials, creatorFabricIndex, lastModifiedFabricIndex, nextUserIndex); diff --git a/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java b/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java index 55ad3408ac7135..1285ba45bde897 100644 --- a/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java @@ -4699,13 +4699,14 @@ public DoorLockCluster(long devicePtr, int endpointId) { public native long initWithDevice(long devicePtr, int endpointId); public void clearCredential( - DefaultClusterCallback callback, ChipStructs.DoorLockClusterDlCredential credential) { + DefaultClusterCallback callback, + @Nullable ChipStructs.DoorLockClusterDlCredential credential) { clearCredential(chipClusterPtr, callback, credential, null); } public void clearCredential( DefaultClusterCallback callback, - ChipStructs.DoorLockClusterDlCredential credential, + @Nullable ChipStructs.DoorLockClusterDlCredential credential, int timedInvokeTimeoutMs) { clearCredential(chipClusterPtr, callback, credential, timedInvokeTimeoutMs); } @@ -4755,8 +4756,9 @@ public void setCredential( Integer operationType, ChipStructs.DoorLockClusterDlCredential credential, byte[] credentialData, - Integer userIndex, - Integer userStatus) { + @Nullable Integer userIndex, + @Nullable Integer userStatus, + @Nullable Integer userType) { setCredential( chipClusterPtr, callback, @@ -4765,6 +4767,7 @@ public void setCredential( credentialData, userIndex, userStatus, + userType, null); } @@ -4773,8 +4776,9 @@ public void setCredential( Integer operationType, ChipStructs.DoorLockClusterDlCredential credential, byte[] credentialData, - Integer userIndex, - Integer userStatus, + @Nullable Integer userIndex, + @Nullable Integer userStatus, + @Nullable Integer userType, int timedInvokeTimeoutMs) { setCredential( chipClusterPtr, @@ -4784,6 +4788,7 @@ public void setCredential( credentialData, userIndex, userStatus, + userType, timedInvokeTimeoutMs); } @@ -4793,9 +4798,9 @@ public void setUser( Integer userIndex, @Nullable String userName, @Nullable Long userUniqueId, - Integer userStatus, - Integer userType, - Integer credentialRule) { + @Nullable Integer userStatus, + @Nullable Integer userType, + @Nullable Integer credentialRule) { setUser( chipClusterPtr, callback, @@ -4815,9 +4820,9 @@ public void setUser( Integer userIndex, @Nullable String userName, @Nullable Long userUniqueId, - Integer userStatus, - Integer userType, - Integer credentialRule, + @Nullable Integer userStatus, + @Nullable Integer userType, + @Nullable Integer credentialRule, int timedInvokeTimeoutMs) { setUser( chipClusterPtr, @@ -4844,7 +4849,7 @@ public void unlockDoor( private native void clearCredential( long chipClusterPtr, DefaultClusterCallback Callback, - ChipStructs.DoorLockClusterDlCredential credential, + @Nullable ChipStructs.DoorLockClusterDlCredential credential, @Nullable Integer timedInvokeTimeoutMs); private native void clearUser( @@ -4877,8 +4882,9 @@ private native void setCredential( Integer operationType, ChipStructs.DoorLockClusterDlCredential credential, byte[] credentialData, - Integer userIndex, - Integer userStatus, + @Nullable Integer userIndex, + @Nullable Integer userStatus, + @Nullable Integer userType, @Nullable Integer timedInvokeTimeoutMs); private native void setUser( @@ -4888,9 +4894,9 @@ private native void setUser( Integer userIndex, @Nullable String userName, @Nullable Long userUniqueId, - Integer userStatus, - Integer userType, - Integer credentialRule, + @Nullable Integer userStatus, + @Nullable Integer userType, + @Nullable Integer credentialRule, @Nullable Integer timedInvokeTimeoutMs); private native void unlockDoor( @@ -4919,7 +4925,7 @@ void onSuccess( @Nullable ArrayList credentials, @Nullable Integer creatorFabricIndex, @Nullable Integer lastModifiedFabricIndex, - Integer nextUserIndex); + @Nullable Integer nextUserIndex); void onError(Exception error); } @@ -5011,6 +5017,16 @@ public void subscribeNumberOfPINUsersSupportedAttribute( chipClusterPtr, callback, minInterval, maxInterval); } + public void readNumberOfRFIDUsersSupportedAttribute(IntegerAttributeCallback callback) { + readNumberOfRFIDUsersSupportedAttribute(chipClusterPtr, callback); + } + + public void subscribeNumberOfRFIDUsersSupportedAttribute( + IntegerAttributeCallback callback, int minInterval, int maxInterval) { + subscribeNumberOfRFIDUsersSupportedAttribute( + chipClusterPtr, callback, minInterval, maxInterval); + } + public void readMaxPINCodeLengthAttribute(IntegerAttributeCallback callback) { readMaxPINCodeLengthAttribute(chipClusterPtr, callback); } @@ -5029,6 +5045,24 @@ public void subscribeMinPINCodeLengthAttribute( subscribeMinPINCodeLengthAttribute(chipClusterPtr, callback, minInterval, maxInterval); } + public void readMaxRFIDCodeLengthAttribute(IntegerAttributeCallback callback) { + readMaxRFIDCodeLengthAttribute(chipClusterPtr, callback); + } + + public void subscribeMaxRFIDCodeLengthAttribute( + IntegerAttributeCallback callback, int minInterval, int maxInterval) { + subscribeMaxRFIDCodeLengthAttribute(chipClusterPtr, callback, minInterval, maxInterval); + } + + public void readMinRFIDCodeLengthAttribute(IntegerAttributeCallback callback) { + readMinRFIDCodeLengthAttribute(chipClusterPtr, callback); + } + + public void subscribeMinRFIDCodeLengthAttribute( + IntegerAttributeCallback callback, int minInterval, int maxInterval) { + subscribeMinRFIDCodeLengthAttribute(chipClusterPtr, callback, minInterval, maxInterval); + } + public void readLanguageAttribute(CharStringAttributeCallback callback) { readLanguageAttribute(chipClusterPtr, callback); } @@ -5220,6 +5254,12 @@ private native void readNumberOfPINUsersSupportedAttribute( private native void subscribeNumberOfPINUsersSupportedAttribute( long chipClusterPtr, IntegerAttributeCallback callback, int minInterval, int maxInterval); + private native void readNumberOfRFIDUsersSupportedAttribute( + long chipClusterPtr, IntegerAttributeCallback callback); + + private native void subscribeNumberOfRFIDUsersSupportedAttribute( + long chipClusterPtr, IntegerAttributeCallback callback, int minInterval, int maxInterval); + private native void readMaxPINCodeLengthAttribute( long chipClusterPtr, IntegerAttributeCallback callback); @@ -5232,6 +5272,18 @@ private native void readMinPINCodeLengthAttribute( private native void subscribeMinPINCodeLengthAttribute( long chipClusterPtr, IntegerAttributeCallback callback, int minInterval, int maxInterval); + private native void readMaxRFIDCodeLengthAttribute( + long chipClusterPtr, IntegerAttributeCallback callback); + + private native void subscribeMaxRFIDCodeLengthAttribute( + long chipClusterPtr, IntegerAttributeCallback callback, int minInterval, int maxInterval); + + private native void readMinRFIDCodeLengthAttribute( + long chipClusterPtr, IntegerAttributeCallback callback); + + private native void subscribeMinRFIDCodeLengthAttribute( + long chipClusterPtr, IntegerAttributeCallback callback, int minInterval, int maxInterval); + private native void readLanguageAttribute( long chipClusterPtr, CharStringAttributeCallback callback); diff --git a/src/controller/java/zap-generated/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/zap-generated/chip/devicecontroller/ClusterInfoMapping.java index 4d6363d26e89b0..559ebd8349b03a 100644 --- a/src/controller/java/zap-generated/chip/devicecontroller/ClusterInfoMapping.java +++ b/src/controller/java/zap-generated/chip/devicecontroller/ClusterInfoMapping.java @@ -1166,7 +1166,7 @@ public void onSuccess( @Nullable ArrayList credentials, @Nullable Integer creatorFabricIndex, @Nullable Integer lastModifiedFabricIndex, - Integer nextUserIndex) { + @Nullable Integer nextUserIndex) { Map responseValues = new LinkedHashMap<>(); CommandResponseInfo userIndexResponseValue = new CommandResponseInfo("userIndex", "Integer"); responseValues.put(userIndexResponseValue, userIndex); @@ -6302,6 +6302,11 @@ public Map> getCommandMap() { doorLocksetCredentialCommandParams.put( "userStatus", doorLocksetCredentialuserStatusCommandParameterInfo); + CommandParameterInfo doorLocksetCredentialuserTypeCommandParameterInfo = + new CommandParameterInfo("userType", Integer.class); + doorLocksetCredentialCommandParams.put( + "userType", doorLocksetCredentialuserTypeCommandParameterInfo); + InteractionInfo doorLocksetCredentialInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { @@ -6312,7 +6317,8 @@ public Map> getCommandMap() { (ChipStructs.DoorLockClusterDlCredential) commandArguments.get("credential"), (byte[]) commandArguments.get("credentialData"), (Integer) commandArguments.get("userIndex"), - (Integer) commandArguments.get("userStatus")); + (Integer) commandArguments.get("userStatus"), + (Integer) commandArguments.get("userType")); }, () -> new DelegatedSetCredentialResponseCallback(), doorLocksetCredentialCommandParams); diff --git a/src/controller/java/zap-generated/chip/devicecontroller/ClusterReadMapping.java b/src/controller/java/zap-generated/chip/devicecontroller/ClusterReadMapping.java index 770959b6bc00be..3b835d42a6965f 100644 --- a/src/controller/java/zap-generated/chip/devicecontroller/ClusterReadMapping.java +++ b/src/controller/java/zap-generated/chip/devicecontroller/ClusterReadMapping.java @@ -1966,6 +1966,20 @@ public Map> getReadAttributeMap() { readDoorLockInteractionInfo.put( "readNumberOfPINUsersSupportedAttribute", readDoorLockNumberOfPINUsersSupportedAttributeInteractionInfo); + Map readDoorLockNumberOfRFIDUsersSupportedCommandParams = + new LinkedHashMap(); + InteractionInfo readDoorLockNumberOfRFIDUsersSupportedAttributeInteractionInfo = + new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.DoorLockCluster) cluster) + .readNumberOfRFIDUsersSupportedAttribute( + (ChipClusters.IntegerAttributeCallback) callback); + }, + () -> new ClusterInfoMapping.DelegatedIntegerAttributeCallback(), + readDoorLockNumberOfRFIDUsersSupportedCommandParams); + readDoorLockInteractionInfo.put( + "readNumberOfRFIDUsersSupportedAttribute", + readDoorLockNumberOfRFIDUsersSupportedAttributeInteractionInfo); Map readDoorLockMaxPINCodeLengthCommandParams = new LinkedHashMap(); InteractionInfo readDoorLockMaxPINCodeLengthAttributeInteractionInfo = @@ -1990,6 +2004,30 @@ public Map> getReadAttributeMap() { readDoorLockMinPINCodeLengthCommandParams); readDoorLockInteractionInfo.put( "readMinPINCodeLengthAttribute", readDoorLockMinPINCodeLengthAttributeInteractionInfo); + Map readDoorLockMaxRFIDCodeLengthCommandParams = + new LinkedHashMap(); + InteractionInfo readDoorLockMaxRFIDCodeLengthAttributeInteractionInfo = + new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.DoorLockCluster) cluster) + .readMaxRFIDCodeLengthAttribute((ChipClusters.IntegerAttributeCallback) callback); + }, + () -> new ClusterInfoMapping.DelegatedIntegerAttributeCallback(), + readDoorLockMaxRFIDCodeLengthCommandParams); + readDoorLockInteractionInfo.put( + "readMaxRFIDCodeLengthAttribute", readDoorLockMaxRFIDCodeLengthAttributeInteractionInfo); + Map readDoorLockMinRFIDCodeLengthCommandParams = + new LinkedHashMap(); + InteractionInfo readDoorLockMinRFIDCodeLengthAttributeInteractionInfo = + new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.DoorLockCluster) cluster) + .readMinRFIDCodeLengthAttribute((ChipClusters.IntegerAttributeCallback) callback); + }, + () -> new ClusterInfoMapping.DelegatedIntegerAttributeCallback(), + readDoorLockMinRFIDCodeLengthCommandParams); + readDoorLockInteractionInfo.put( + "readMinRFIDCodeLengthAttribute", readDoorLockMinRFIDCodeLengthAttributeInteractionInfo); Map readDoorLockLanguageCommandParams = new LinkedHashMap(); InteractionInfo readDoorLockLanguageAttributeInteractionInfo = diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py index e39c22c629a603..22b70972090017 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.py +++ b/src/controller/python/chip/clusters/CHIPClusters.py @@ -1565,6 +1565,7 @@ class ChipClusters: "credentialData": "bytes", "userIndex": "int", "userStatus": "int", + "userType": "int", }, }, 0x0000001A: { @@ -1625,6 +1626,12 @@ class ChipClusters: "type": "int", "reportable": True, }, + 0x00000013: { + "attributeName": "NumberOfRFIDUsersSupported", + "attributeId": 0x00000013, + "type": "int", + "reportable": True, + }, 0x00000017: { "attributeName": "MaxPINCodeLength", "attributeId": 0x00000017, @@ -1637,6 +1644,18 @@ class ChipClusters: "type": "int", "reportable": True, }, + 0x00000019: { + "attributeName": "MaxRFIDCodeLength", + "attributeId": 0x00000019, + "type": "int", + "reportable": True, + }, + 0x0000001A: { + "attributeName": "MinRFIDCodeLength", + "attributeId": 0x0000001A, + "type": "int", + "reportable": True, + }, 0x00000021: { "attributeName": "Language", "attributeId": 0x00000021, diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index 98511d704a25ee..cab7b48c8e77d1 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -14374,10 +14374,6 @@ class DlDataOperationType(IntEnum): kClear = 0x01 kModify = 0x02 - class DlDoorLockStatus(IntEnum): - kDuplicate = 0x02 - kOccupied = 0x03 - class DlDoorState(IntEnum): kDoorOpen = 0x00 kDoorClosed = 0x01 @@ -14636,14 +14632,14 @@ def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields = [ ClusterObjectFieldDescriptor(Label="userId", Tag=0, Type=uint), - ClusterObjectFieldDescriptor(Label="userStatus", Tag=1, Type=DoorLock.Enums.DlUserStatus), - ClusterObjectFieldDescriptor(Label="userType", Tag=2, Type=DoorLock.Enums.DlUserType), + ClusterObjectFieldDescriptor(Label="userStatus", Tag=1, Type=typing.Union[Nullable, DoorLock.Enums.DlUserStatus]), + ClusterObjectFieldDescriptor(Label="userType", Tag=2, Type=typing.Union[Nullable, DoorLock.Enums.DlUserType]), ClusterObjectFieldDescriptor(Label="pin", Tag=3, Type=bytes), ]) userId: 'uint' = 0 - userStatus: 'DoorLock.Enums.DlUserStatus' = 0 - userType: 'DoorLock.Enums.DlUserType' = 0 + userStatus: 'typing.Union[Nullable, DoorLock.Enums.DlUserStatus]' = NullValue + userType: 'typing.Union[Nullable, DoorLock.Enums.DlUserType]' = NullValue pin: 'bytes' = b"" @dataclass @@ -15061,14 +15057,14 @@ def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields = [ ClusterObjectFieldDescriptor(Label="userId", Tag=0, Type=uint), - ClusterObjectFieldDescriptor(Label="userStatus", Tag=1, Type=DoorLock.Enums.DlUserStatus), - ClusterObjectFieldDescriptor(Label="userType", Tag=2, Type=DoorLock.Enums.DlUserType), + ClusterObjectFieldDescriptor(Label="userStatus", Tag=1, Type=typing.Union[Nullable, DoorLock.Enums.DlUserStatus]), + ClusterObjectFieldDescriptor(Label="userType", Tag=2, Type=typing.Union[Nullable, DoorLock.Enums.DlUserType]), ClusterObjectFieldDescriptor(Label="rfidCode", Tag=3, Type=bytes), ]) userId: 'uint' = 0 - userStatus: 'DoorLock.Enums.DlUserStatus' = 0 - userType: 'DoorLock.Enums.DlUserType' = 0 + userStatus: 'typing.Union[Nullable, DoorLock.Enums.DlUserStatus]' = NullValue + userType: 'typing.Union[Nullable, DoorLock.Enums.DlUserType]' = NullValue rfidCode: 'bytes' = b"" @dataclass @@ -15149,18 +15145,18 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="userIndex", Tag=1, Type=uint), ClusterObjectFieldDescriptor(Label="userName", Tag=2, Type=typing.Union[Nullable, str]), ClusterObjectFieldDescriptor(Label="userUniqueId", Tag=3, Type=typing.Union[Nullable, uint]), - ClusterObjectFieldDescriptor(Label="userStatus", Tag=4, Type=DoorLock.Enums.DlUserStatus), - ClusterObjectFieldDescriptor(Label="userType", Tag=5, Type=DoorLock.Enums.DlUserType), - ClusterObjectFieldDescriptor(Label="credentialRule", Tag=6, Type=DoorLock.Enums.DlCredentialRule), + ClusterObjectFieldDescriptor(Label="userStatus", Tag=4, Type=typing.Union[Nullable, DoorLock.Enums.DlUserStatus]), + ClusterObjectFieldDescriptor(Label="userType", Tag=5, Type=typing.Union[Nullable, DoorLock.Enums.DlUserType]), + ClusterObjectFieldDescriptor(Label="credentialRule", Tag=6, Type=typing.Union[Nullable, DoorLock.Enums.DlCredentialRule]), ]) operationType: 'DoorLock.Enums.DlDataOperationType' = 0 userIndex: 'uint' = 0 userName: 'typing.Union[Nullable, str]' = NullValue userUniqueId: 'typing.Union[Nullable, uint]' = NullValue - userStatus: 'DoorLock.Enums.DlUserStatus' = 0 - userType: 'DoorLock.Enums.DlUserType' = 0 - credentialRule: 'DoorLock.Enums.DlCredentialRule' = 0 + userStatus: 'typing.Union[Nullable, DoorLock.Enums.DlUserStatus]' = NullValue + userType: 'typing.Union[Nullable, DoorLock.Enums.DlUserType]' = NullValue + credentialRule: 'typing.Union[Nullable, DoorLock.Enums.DlCredentialRule]' = NullValue @dataclass class GetUser(ClusterCommand): @@ -15196,7 +15192,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="credentials", Tag=6, Type=typing.Union[Nullable, typing.List[DoorLock.Structs.DlCredential]]), ClusterObjectFieldDescriptor(Label="creatorFabricIndex", Tag=7, Type=typing.Union[Nullable, uint]), ClusterObjectFieldDescriptor(Label="lastModifiedFabricIndex", Tag=8, Type=typing.Union[Nullable, uint]), - ClusterObjectFieldDescriptor(Label="nextUserIndex", Tag=9, Type=uint), + ClusterObjectFieldDescriptor(Label="nextUserIndex", Tag=9, Type=typing.Union[Nullable, uint]), ]) userIndex: 'uint' = 0 @@ -15208,7 +15204,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: credentials: 'typing.Union[Nullable, typing.List[DoorLock.Structs.DlCredential]]' = NullValue creatorFabricIndex: 'typing.Union[Nullable, uint]' = NullValue lastModifiedFabricIndex: 'typing.Union[Nullable, uint]' = NullValue - nextUserIndex: 'uint' = 0 + nextUserIndex: 'typing.Union[Nullable, uint]' = NullValue @dataclass class ClearUser(ClusterCommand): @@ -15292,15 +15288,17 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="operationType", Tag=0, Type=DoorLock.Enums.DlDataOperationType), ClusterObjectFieldDescriptor(Label="credential", Tag=1, Type=DoorLock.Structs.DlCredential), ClusterObjectFieldDescriptor(Label="credentialData", Tag=2, Type=bytes), - ClusterObjectFieldDescriptor(Label="userIndex", Tag=3, Type=uint), - ClusterObjectFieldDescriptor(Label="userStatus", Tag=4, Type=DoorLock.Enums.DlUserStatus), + ClusterObjectFieldDescriptor(Label="userIndex", Tag=3, Type=typing.Union[Nullable, uint]), + ClusterObjectFieldDescriptor(Label="userStatus", Tag=4, Type=typing.Union[Nullable, DoorLock.Enums.DlUserStatus]), + ClusterObjectFieldDescriptor(Label="userType", Tag=5, Type=typing.Union[Nullable, DoorLock.Enums.DlUserType]), ]) operationType: 'DoorLock.Enums.DlDataOperationType' = 0 credential: 'DoorLock.Structs.DlCredential' = field(default_factory=lambda: DoorLock.Structs.DlCredential()) credentialData: 'bytes' = b"" - userIndex: 'uint' = 0 - userStatus: 'DoorLock.Enums.DlUserStatus' = 0 + userIndex: 'typing.Union[Nullable, uint]' = NullValue + userStatus: 'typing.Union[Nullable, DoorLock.Enums.DlUserStatus]' = NullValue + userType: 'typing.Union[Nullable, DoorLock.Enums.DlUserType]' = NullValue @dataclass class SetCredentialResponse(ClusterCommand): @@ -15365,10 +15363,10 @@ class ClearCredential(ClusterCommand): def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields = [ - ClusterObjectFieldDescriptor(Label="credential", Tag=0, Type=DoorLock.Structs.DlCredential), + ClusterObjectFieldDescriptor(Label="credential", Tag=0, Type=typing.Union[Nullable, DoorLock.Structs.DlCredential]), ]) - credential: 'DoorLock.Structs.DlCredential' = field(default_factory=lambda: DoorLock.Structs.DlCredential()) + credential: 'typing.Union[Nullable, DoorLock.Structs.DlCredential]' = NullValue class Attributes: diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/CHIPAttributeTLVValueDecoder.mm index b484df2d8f9452..f33a9878158bb0 100644 --- a/src/darwin/Framework/CHIP/zap-generated/CHIPAttributeTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/CHIPAttributeTLVValueDecoder.mm @@ -2389,6 +2389,17 @@ id CHIPDecodeAttributeValue(const ConcreteAttributePath & aPath, TLV::TLVReader value = [NSNumber numberWithUnsignedShort:cppValue]; return value; } + case Attributes::NumberOfRFIDUsersSupported::Id: { + using TypeInfo = Attributes::NumberOfRFIDUsersSupported::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + NSNumber * _Nonnull value; + value = [NSNumber numberWithUnsignedShort:cppValue]; + return value; + } case Attributes::MaxPINCodeLength::Id: { using TypeInfo = Attributes::MaxPINCodeLength::TypeInfo; TypeInfo::DecodableType cppValue; @@ -2411,6 +2422,28 @@ id CHIPDecodeAttributeValue(const ConcreteAttributePath & aPath, TLV::TLVReader value = [NSNumber numberWithUnsignedChar:cppValue]; return value; } + case Attributes::MaxRFIDCodeLength::Id: { + using TypeInfo = Attributes::MaxRFIDCodeLength::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + NSNumber * _Nonnull value; + value = [NSNumber numberWithUnsignedChar:cppValue]; + return value; + } + case Attributes::MinRFIDCodeLength::Id: { + using TypeInfo = Attributes::MinRFIDCodeLength::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + NSNumber * _Nonnull value; + value = [NSNumber numberWithUnsignedChar:cppValue]; + return value; + } case Attributes::Language::Id: { using TypeInfo = Attributes::Language::TypeInfo; TypeInfo::DecodableType cppValue; diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge.mm b/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge.mm index 27d36872324f57..5d22279ff9ee56 100644 --- a/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge.mm +++ b/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge.mm @@ -5364,7 +5364,11 @@ } } { - response.nextUserIndex = [NSNumber numberWithUnsignedShort:data.nextUserIndex]; + if (data.nextUserIndex.IsNull()) { + response.nextUserIndex = nil; + } else { + response.nextUserIndex = [NSNumber numberWithUnsignedShort:data.nextUserIndex.Value()]; + } } DispatchSuccess(context, response); }; @@ -9543,58 +9547,6 @@ } } -void CHIPDoorLockClusterDlDoorLockStatusAttributeCallbackBridge::OnSuccessFn( - void * context, chip::app::Clusters::DoorLock::DlDoorLockStatus value) -{ - NSNumber * _Nonnull objCValue; - objCValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(value)]; - DispatchSuccess(context, objCValue); -}; - -void CHIPDoorLockClusterDlDoorLockStatusAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished(void * context) -{ - auto * self = static_cast(context); - if (!self->mQueue) { - return; - } - - if (self->mEstablishedHandler != nil) { - dispatch_async(self->mQueue, self->mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - self->mEstablishedHandler = nil; - } -} - -void CHIPNullableDoorLockClusterDlDoorLockStatusAttributeCallbackBridge::OnSuccessFn( - void * context, const chip::app::DataModel::Nullable & value) -{ - NSNumber * _Nullable objCValue; - if (value.IsNull()) { - objCValue = nil; - } else { - objCValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(value.Value())]; - } - DispatchSuccess(context, objCValue); -}; - -void CHIPNullableDoorLockClusterDlDoorLockStatusAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished(void * context) -{ - auto * self = static_cast(context); - if (!self->mQueue) { - return; - } - - if (self->mEstablishedHandler != nil) { - dispatch_async(self->mQueue, self->mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - self->mEstablishedHandler = nil; - } -} - void CHIPDoorLockClusterDlDoorStateAttributeCallbackBridge::OnSuccessFn( void * context, chip::app::Clusters::DoorLock::DlDoorState value) { diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge_internal.h b/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge_internal.h index 2edc0799ecf8a4..4e74c046e04f65 100644 --- a/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge_internal.h +++ b/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge_internal.h @@ -347,9 +347,6 @@ typedef void (*NullableDoorLockClusterDlCredentialTypeAttributeCallback)( typedef void (*DoorLockClusterDlDataOperationTypeAttributeCallback)(void *, chip::app::Clusters::DoorLock::DlDataOperationType); typedef void (*NullableDoorLockClusterDlDataOperationTypeAttributeCallback)( void *, const chip::app::DataModel::Nullable &); -typedef void (*DoorLockClusterDlDoorLockStatusAttributeCallback)(void *, chip::app::Clusters::DoorLock::DlDoorLockStatus); -typedef void (*NullableDoorLockClusterDlDoorLockStatusAttributeCallback)( - void *, const chip::app::DataModel::Nullable &); typedef void (*DoorLockClusterDlDoorStateAttributeCallback)(void *, chip::app::Clusters::DoorLock::DlDoorState); typedef void (*NullableDoorLockClusterDlDoorStateAttributeCallback)( void *, const chip::app::DataModel::Nullable &); @@ -8552,64 +8549,6 @@ class CHIPNullableDoorLockClusterDlDataOperationTypeAttributeCallbackSubscriptio SubscriptionEstablishedHandler mEstablishedHandler; }; -class CHIPDoorLockClusterDlDoorLockStatusAttributeCallbackBridge - : public CHIPCallbackBridge -{ -public: - CHIPDoorLockClusterDlDoorLockStatusAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - CHIPActionBlock action, bool keepAlive = false) : - CHIPCallbackBridge(queue, handler, action, OnSuccessFn, keepAlive){}; - - static void OnSuccessFn(void * context, chip::app::Clusters::DoorLock::DlDoorLockStatus value); -}; - -class CHIPDoorLockClusterDlDoorLockStatusAttributeCallbackSubscriptionBridge - : public CHIPDoorLockClusterDlDoorLockStatusAttributeCallbackBridge -{ -public: - CHIPDoorLockClusterDlDoorLockStatusAttributeCallbackSubscriptionBridge(dispatch_queue_t queue, ResponseHandler handler, - CHIPActionBlock action, - SubscriptionEstablishedHandler establishedHandler) : - CHIPDoorLockClusterDlDoorLockStatusAttributeCallbackBridge(queue, handler, action, true), - mEstablishedHandler(establishedHandler) - {} - - static void OnSubscriptionEstablished(void * context); - -private: - SubscriptionEstablishedHandler mEstablishedHandler; -}; - -class CHIPNullableDoorLockClusterDlDoorLockStatusAttributeCallbackBridge - : public CHIPCallbackBridge -{ -public: - CHIPNullableDoorLockClusterDlDoorLockStatusAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - CHIPActionBlock action, bool keepAlive = false) : - CHIPCallbackBridge(queue, handler, action, OnSuccessFn, - keepAlive){}; - - static void OnSuccessFn(void * context, - const chip::app::DataModel::Nullable & value); -}; - -class CHIPNullableDoorLockClusterDlDoorLockStatusAttributeCallbackSubscriptionBridge - : public CHIPNullableDoorLockClusterDlDoorLockStatusAttributeCallbackBridge -{ -public: - CHIPNullableDoorLockClusterDlDoorLockStatusAttributeCallbackSubscriptionBridge( - dispatch_queue_t queue, ResponseHandler handler, CHIPActionBlock action, - SubscriptionEstablishedHandler establishedHandler) : - CHIPNullableDoorLockClusterDlDoorLockStatusAttributeCallbackBridge(queue, handler, action, true), - mEstablishedHandler(establishedHandler) - {} - - static void OnSubscriptionEstablished(void * context); - -private: - SubscriptionEstablishedHandler mEstablishedHandler; -}; - class CHIPDoorLockClusterDlDoorStateAttributeCallbackBridge : public CHIPCallbackBridge { public: diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.h b/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.h index d6625a11159233..ce34654191f4b7 100644 --- a/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.h @@ -1471,6 +1471,15 @@ NS_ASSUME_NONNULL_BEGIN reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler; +- (void)readAttributeNumberOfRFIDUsersSupportedWithCompletionHandler:(void (^)(NSNumber * _Nullable value, + NSError * _Nullable error))completionHandler; +- (void)subscribeAttributeNumberOfRFIDUsersSupportedWithMinInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + subscriptionEstablished: + (SubscriptionEstablishedHandler _Nullable)subscriptionEstablishedHandler + reportHandler:(void (^)(NSNumber * _Nullable value, + NSError * _Nullable error))reportHandler; + - (void)readAttributeMaxPINCodeLengthWithCompletionHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completionHandler; - (void)subscribeAttributeMaxPINCodeLengthWithMinInterval:(uint16_t)minInterval @@ -1487,6 +1496,22 @@ NS_ASSUME_NONNULL_BEGIN reportHandler: (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler; +- (void)readAttributeMaxRFIDCodeLengthWithCompletionHandler:(void (^)(NSNumber * _Nullable value, + NSError * _Nullable error))completionHandler; +- (void)subscribeAttributeMaxRFIDCodeLengthWithMinInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + subscriptionEstablished:(SubscriptionEstablishedHandler _Nullable)subscriptionEstablishedHandler + reportHandler: + (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler; + +- (void)readAttributeMinRFIDCodeLengthWithCompletionHandler:(void (^)(NSNumber * _Nullable value, + NSError * _Nullable error))completionHandler; +- (void)subscribeAttributeMinRFIDCodeLengthWithMinInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + subscriptionEstablished:(SubscriptionEstablishedHandler _Nullable)subscriptionEstablishedHandler + reportHandler: + (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler; + - (void)readAttributeLanguageWithCompletionHandler:(void (^)( NSString * _Nullable value, NSError * _Nullable error))completionHandler; - (void)writeAttributeLanguageWithValue:(NSString * _Nonnull)value completionHandler:(StatusCompletion)completionHandler; diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.mm b/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.mm index c0b20af87816f4..612dca5c2b8a9a 100644 --- a/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.mm @@ -5951,9 +5951,14 @@ - (void)clearCredentialWithParams:(CHIPDoorLockClusterClearCredentialParams *)pa { ListFreer listFreer; DoorLock::Commands::ClearCredential::Type request; - request.credential.credentialType = static_cast>( - params.credential.credentialType.unsignedCharValue); - request.credential.credentialIndex = params.credential.credentialIndex.unsignedShortValue; + if (params.credential == nil) { + request.credential.SetNull(); + } else { + auto & nonNullValue_0 = request.credential.SetNonNull(); + nonNullValue_0.credentialType = static_cast>( + params.credential.credentialType.unsignedCharValue); + nonNullValue_0.credentialIndex = params.credential.credentialIndex.unsignedShortValue; + } new CHIPCommandSuccessCallbackBridge( self.callbackQueue, @@ -6055,8 +6060,24 @@ - (void)setCredentialWithParams:(CHIPDoorLockClusterSetCredentialParams *)params params.credential.credentialType.unsignedCharValue); request.credential.credentialIndex = params.credential.credentialIndex.unsignedShortValue; request.credentialData = [self asByteSpan:params.credentialData]; - request.userIndex = params.userIndex.unsignedShortValue; - request.userStatus = static_cast>(params.userStatus.unsignedCharValue); + if (params.userIndex == nil) { + request.userIndex.SetNull(); + } else { + auto & nonNullValue_0 = request.userIndex.SetNonNull(); + nonNullValue_0 = params.userIndex.unsignedShortValue; + } + if (params.userStatus == nil) { + request.userStatus.SetNull(); + } else { + auto & nonNullValue_0 = request.userStatus.SetNonNull(); + nonNullValue_0 = static_cast>(params.userStatus.unsignedCharValue); + } + if (params.userType == nil) { + request.userType.SetNull(); + } else { + auto & nonNullValue_0 = request.userType.SetNonNull(); + nonNullValue_0 = static_cast>(params.userType.unsignedCharValue); + } new CHIPDoorLockClusterSetCredentialResponseCallbackBridge( self.callbackQueue, completionHandler, ^(Cancelable * success, Cancelable * failure) { @@ -6085,10 +6106,24 @@ - (void)setUserWithParams:(CHIPDoorLockClusterSetUserParams *)params completionH auto & nonNullValue_0 = request.userUniqueId.SetNonNull(); nonNullValue_0 = params.userUniqueId.unsignedIntValue; } - request.userStatus = static_cast>(params.userStatus.unsignedCharValue); - request.userType = static_cast>(params.userType.unsignedCharValue); - request.credentialRule - = static_cast>(params.credentialRule.unsignedCharValue); + if (params.userStatus == nil) { + request.userStatus.SetNull(); + } else { + auto & nonNullValue_0 = request.userStatus.SetNonNull(); + nonNullValue_0 = static_cast>(params.userStatus.unsignedCharValue); + } + if (params.userType == nil) { + request.userType.SetNull(); + } else { + auto & nonNullValue_0 = request.userType.SetNonNull(); + nonNullValue_0 = static_cast>(params.userType.unsignedCharValue); + } + if (params.credentialRule == nil) { + request.credentialRule.SetNull(); + } else { + auto & nonNullValue_0 = request.credentialRule.SetNonNull(); + nonNullValue_0 = static_cast>(params.credentialRule.unsignedCharValue); + } new CHIPCommandSuccessCallbackBridge( self.callbackQueue, @@ -6305,6 +6340,36 @@ new CHIPInt16uAttributeCallbackSubscriptionBridge( subscriptionEstablishedHandler); } +- (void)readAttributeNumberOfRFIDUsersSupportedWithCompletionHandler:(void (^)(NSNumber * _Nullable value, + NSError * _Nullable error))completionHandler +{ + new CHIPInt16uAttributeCallbackBridge(self.callbackQueue, completionHandler, ^(Cancelable * success, Cancelable * failure) { + using TypeInfo = DoorLock::Attributes::NumberOfRFIDUsersSupported::TypeInfo; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.ReadAttribute(successFn->mContext, successFn->mCall, failureFn->mCall); + }); +} + +- (void)subscribeAttributeNumberOfRFIDUsersSupportedWithMinInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + subscriptionEstablished: + (SubscriptionEstablishedHandler _Nullable)subscriptionEstablishedHandler + reportHandler:(void (^)(NSNumber * _Nullable value, + NSError * _Nullable error))reportHandler +{ + new CHIPInt16uAttributeCallbackSubscriptionBridge( + self.callbackQueue, reportHandler, + ^(Cancelable * success, Cancelable * failure) { + using TypeInfo = DoorLock::Attributes::NumberOfRFIDUsersSupported::TypeInfo; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.SubscribeAttribute(successFn->mContext, successFn->mCall, failureFn->mCall, + minInterval, maxInterval, CHIPInt16uAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished); + }, + subscriptionEstablishedHandler); +} + - (void)readAttributeMaxPINCodeLengthWithCompletionHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completionHandler { @@ -6363,6 +6428,64 @@ new CHIPInt8uAttributeCallbackSubscriptionBridge( subscriptionEstablishedHandler); } +- (void)readAttributeMaxRFIDCodeLengthWithCompletionHandler:(void (^)(NSNumber * _Nullable value, + NSError * _Nullable error))completionHandler +{ + new CHIPInt8uAttributeCallbackBridge(self.callbackQueue, completionHandler, ^(Cancelable * success, Cancelable * failure) { + using TypeInfo = DoorLock::Attributes::MaxRFIDCodeLength::TypeInfo; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.ReadAttribute(successFn->mContext, successFn->mCall, failureFn->mCall); + }); +} + +- (void)subscribeAttributeMaxRFIDCodeLengthWithMinInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + subscriptionEstablished:(SubscriptionEstablishedHandler _Nullable)subscriptionEstablishedHandler + reportHandler: + (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler +{ + new CHIPInt8uAttributeCallbackSubscriptionBridge( + self.callbackQueue, reportHandler, + ^(Cancelable * success, Cancelable * failure) { + using TypeInfo = DoorLock::Attributes::MaxRFIDCodeLength::TypeInfo; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.SubscribeAttribute(successFn->mContext, successFn->mCall, failureFn->mCall, + minInterval, maxInterval, CHIPInt8uAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished); + }, + subscriptionEstablishedHandler); +} + +- (void)readAttributeMinRFIDCodeLengthWithCompletionHandler:(void (^)(NSNumber * _Nullable value, + NSError * _Nullable error))completionHandler +{ + new CHIPInt8uAttributeCallbackBridge(self.callbackQueue, completionHandler, ^(Cancelable * success, Cancelable * failure) { + using TypeInfo = DoorLock::Attributes::MinRFIDCodeLength::TypeInfo; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.ReadAttribute(successFn->mContext, successFn->mCall, failureFn->mCall); + }); +} + +- (void)subscribeAttributeMinRFIDCodeLengthWithMinInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + subscriptionEstablished:(SubscriptionEstablishedHandler _Nullable)subscriptionEstablishedHandler + reportHandler: + (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler +{ + new CHIPInt8uAttributeCallbackSubscriptionBridge( + self.callbackQueue, reportHandler, + ^(Cancelable * success, Cancelable * failure) { + using TypeInfo = DoorLock::Attributes::MinRFIDCodeLength::TypeInfo; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.SubscribeAttribute(successFn->mContext, successFn->mCall, failureFn->mCall, + minInterval, maxInterval, CHIPInt8uAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished); + }, + subscriptionEstablishedHandler); +} + - (void)readAttributeLanguageWithCompletionHandler:(void (^)( NSString * _Nullable value, NSError * _Nullable error))completionHandler { diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/CHIPCommandPayloadsObjc.h index 8cba799a633cdf..9dc0cbb1d4c30f 100644 --- a/src/darwin/Framework/CHIP/zap-generated/CHIPCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/CHIPCommandPayloadsObjc.h @@ -895,8 +895,8 @@ NS_ASSUME_NONNULL_BEGIN @interface CHIPDoorLockClusterSetPINCodeParams : NSObject @property (strong, nonatomic) NSNumber * _Nonnull userId; -@property (strong, nonatomic) NSNumber * _Nonnull userStatus; -@property (strong, nonatomic) NSNumber * _Nonnull userType; +@property (strong, nonatomic) NSNumber * _Nullable userStatus; +@property (strong, nonatomic) NSNumber * _Nullable userType; @property (strong, nonatomic) NSData * _Nonnull pin; - (instancetype)init; @end @@ -1046,8 +1046,8 @@ NS_ASSUME_NONNULL_BEGIN @interface CHIPDoorLockClusterSetRFIDCodeParams : NSObject @property (strong, nonatomic) NSNumber * _Nonnull userId; -@property (strong, nonatomic) NSNumber * _Nonnull userStatus; -@property (strong, nonatomic) NSNumber * _Nonnull userType; +@property (strong, nonatomic) NSNumber * _Nullable userStatus; +@property (strong, nonatomic) NSNumber * _Nullable userType; @property (strong, nonatomic) NSData * _Nonnull rfidCode; - (instancetype)init; @end @@ -1075,9 +1075,9 @@ NS_ASSUME_NONNULL_BEGIN @property (strong, nonatomic) NSNumber * _Nonnull userIndex; @property (strong, nonatomic) NSString * _Nullable userName; @property (strong, nonatomic) NSNumber * _Nullable userUniqueId; -@property (strong, nonatomic) NSNumber * _Nonnull userStatus; -@property (strong, nonatomic) NSNumber * _Nonnull userType; -@property (strong, nonatomic) NSNumber * _Nonnull credentialRule; +@property (strong, nonatomic) NSNumber * _Nullable userStatus; +@property (strong, nonatomic) NSNumber * _Nullable userType; +@property (strong, nonatomic) NSNumber * _Nullable credentialRule; - (instancetype)init; @end @@ -1096,7 +1096,7 @@ NS_ASSUME_NONNULL_BEGIN @property (strong, nonatomic) NSArray * _Nullable credentials; @property (strong, nonatomic) NSNumber * _Nullable creatorFabricIndex; @property (strong, nonatomic) NSNumber * _Nullable lastModifiedFabricIndex; -@property (strong, nonatomic) NSNumber * _Nonnull nextUserIndex; +@property (strong, nonatomic) NSNumber * _Nullable nextUserIndex; - (instancetype)init; @end @@ -1131,8 +1131,9 @@ NS_ASSUME_NONNULL_BEGIN @property (strong, nonatomic) NSNumber * _Nonnull operationType; @property (strong, nonatomic) CHIPDoorLockClusterDlCredential * _Nonnull credential; @property (strong, nonatomic) NSData * _Nonnull credentialData; -@property (strong, nonatomic) NSNumber * _Nonnull userIndex; -@property (strong, nonatomic) NSNumber * _Nonnull userStatus; +@property (strong, nonatomic) NSNumber * _Nullable userIndex; +@property (strong, nonatomic) NSNumber * _Nullable userStatus; +@property (strong, nonatomic) NSNumber * _Nullable userType; - (instancetype)init; @end @@ -1156,7 +1157,7 @@ NS_ASSUME_NONNULL_BEGIN @end @interface CHIPDoorLockClusterClearCredentialParams : NSObject -@property (strong, nonatomic) CHIPDoorLockClusterDlCredential * _Nonnull credential; +@property (strong, nonatomic) CHIPDoorLockClusterDlCredential * _Nullable credential; - (instancetype)init; @end diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/CHIPCommandPayloadsObjc.mm index 5fdba45b455bf0..685f2c4c7c0eb7 100644 --- a/src/darwin/Framework/CHIP/zap-generated/CHIPCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/CHIPCommandPayloadsObjc.mm @@ -1897,9 +1897,9 @@ - (instancetype)init _userId = @(0); - _userStatus = @(0); + _userStatus = nil; - _userType = @(0); + _userType = nil; _pin = [NSData data]; } @@ -2221,9 +2221,9 @@ - (instancetype)init _userId = @(0); - _userStatus = @(0); + _userStatus = nil; - _userType = @(0); + _userType = nil; _rfidCode = [NSData data]; } @@ -2283,11 +2283,11 @@ - (instancetype)init _userUniqueId = nil; - _userStatus = @(0); + _userStatus = nil; - _userType = @(0); + _userType = nil; - _credentialRule = @(0); + _credentialRule = nil; } return self; } @@ -2327,7 +2327,7 @@ - (instancetype)init _lastModifiedFabricIndex = nil; - _nextUserIndex = @(0); + _nextUserIndex = nil; } return self; } @@ -2401,9 +2401,11 @@ - (instancetype)init _credentialData = [NSData data]; - _userIndex = @(0); + _userIndex = nil; - _userStatus = @(0); + _userStatus = nil; + + _userType = nil; } return self; } @@ -2455,7 +2457,7 @@ - (instancetype)init { if (self = [super init]) { - _credential = [CHIPDoorLockClusterDlCredential new]; + _credential = nil; } return self; } diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPTestClustersObjc.h b/src/darwin/Framework/CHIP/zap-generated/CHIPTestClustersObjc.h index fbec03137189c7..b9b06a5b451f05 100644 --- a/src/darwin/Framework/CHIP/zap-generated/CHIPTestClustersObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/CHIPTestClustersObjc.h @@ -326,8 +326,12 @@ NS_ASSUME_NONNULL_BEGIN completionHandler:(StatusCompletion)completionHandler; - (void)writeAttributeNumberOfPINUsersSupportedWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler; +- (void)writeAttributeNumberOfRFIDUsersSupportedWithValue:(NSNumber * _Nonnull)value + completionHandler:(StatusCompletion)completionHandler; - (void)writeAttributeMaxPINCodeLengthWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler; - (void)writeAttributeMinPINCodeLengthWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler; +- (void)writeAttributeMaxRFIDCodeLengthWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler; +- (void)writeAttributeMinRFIDCodeLengthWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler; - (void)writeAttributeSupportedOperatingModesWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler; - (void)writeAttributeAttributeListWithValue:(NSArray * _Nonnull)value completionHandler:(StatusCompletion)completionHandler; diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPTestClustersObjc.mm b/src/darwin/Framework/CHIP/zap-generated/CHIPTestClustersObjc.mm index 59eaa52bbc4d95..ff579d49ed90ca 100644 --- a/src/darwin/Framework/CHIP/zap-generated/CHIPTestClustersObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/CHIPTestClustersObjc.mm @@ -3183,6 +3183,25 @@ new CHIPDefaultSuccessCallbackBridge( }); } +- (void)writeAttributeNumberOfRFIDUsersSupportedWithValue:(NSNumber * _Nonnull)value + completionHandler:(StatusCompletion)completionHandler +{ + new CHIPDefaultSuccessCallbackBridge( + self.callbackQueue, + ^(id _Nullable ignored, NSError * _Nullable error) { + completionHandler(error); + }, + ^(Cancelable * success, Cancelable * failure) { + ListFreer listFreer; + using TypeInfo = DoorLock::Attributes::NumberOfRFIDUsersSupported::TypeInfo; + TypeInfo::Type cppValue; + cppValue = value.unsignedShortValue; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.WriteAttribute(cppValue, successFn->mContext, successFn->mCall, failureFn->mCall); + }); +} + - (void)writeAttributeMaxPINCodeLengthWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler { new CHIPDefaultSuccessCallbackBridge( @@ -3219,6 +3238,42 @@ new CHIPDefaultSuccessCallbackBridge( }); } +- (void)writeAttributeMaxRFIDCodeLengthWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler +{ + new CHIPDefaultSuccessCallbackBridge( + self.callbackQueue, + ^(id _Nullable ignored, NSError * _Nullable error) { + completionHandler(error); + }, + ^(Cancelable * success, Cancelable * failure) { + ListFreer listFreer; + using TypeInfo = DoorLock::Attributes::MaxRFIDCodeLength::TypeInfo; + TypeInfo::Type cppValue; + cppValue = value.unsignedCharValue; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.WriteAttribute(cppValue, successFn->mContext, successFn->mCall, failureFn->mCall); + }); +} + +- (void)writeAttributeMinRFIDCodeLengthWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler +{ + new CHIPDefaultSuccessCallbackBridge( + self.callbackQueue, + ^(id _Nullable ignored, NSError * _Nullable error) { + completionHandler(error); + }, + ^(Cancelable * success, Cancelable * failure) { + ListFreer listFreer; + using TypeInfo = DoorLock::Attributes::MinRFIDCodeLength::TypeInfo; + TypeInfo::Type cppValue; + cppValue = value.unsignedCharValue; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.WriteAttribute(cppValue, successFn->mContext, successFn->mCall, failureFn->mCall); + }); +} + - (void)writeAttributeSupportedOperatingModesWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler { diff --git a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m index 329e3e320f3344..f536f0f3d43033 100644 --- a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m @@ -45719,6 +45719,31 @@ - (void)testSendClusterDoorLockReadAttributeNumberOfPINUsersSupportedWithComplet [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } +- (void)testSendClusterDoorLockReadAttributeNumberOfRFIDUsersSupportedWithCompletionHandler +{ + dispatch_queue_t queue = dispatch_get_main_queue(); + + XCTestExpectation * connectedExpectation = + [self expectationWithDescription:@"Wait for the commissioned device to be retrieved"]; + WaitForCommissionee(connectedExpectation, queue); + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; + + CHIPDevice * device = GetConnectedDevice(); + CHIPDoorLock * cluster = [[CHIPDoorLock alloc] initWithDevice:device endpoint:1 queue:queue]; + XCTAssertNotNil(cluster); + + XCTestExpectation * expectation = + [self expectationWithDescription:@"DoorLockReadAttributeNumberOfRFIDUsersSupportedWithCompletionHandler"]; + + [cluster readAttributeNumberOfRFIDUsersSupportedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"DoorLock NumberOfRFIDUsersSupported Error: %@", err); + XCTAssertEqual(err.code, 0); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} + - (void)testSendClusterDoorLockReadAttributeMaxPINCodeLengthWithCompletionHandler { dispatch_queue_t queue = dispatch_get_main_queue(); @@ -45769,6 +45794,56 @@ - (void)testSendClusterDoorLockReadAttributeMinPINCodeLengthWithCompletionHandle [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } +- (void)testSendClusterDoorLockReadAttributeMaxRFIDCodeLengthWithCompletionHandler +{ + dispatch_queue_t queue = dispatch_get_main_queue(); + + XCTestExpectation * connectedExpectation = + [self expectationWithDescription:@"Wait for the commissioned device to be retrieved"]; + WaitForCommissionee(connectedExpectation, queue); + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; + + CHIPDevice * device = GetConnectedDevice(); + CHIPDoorLock * cluster = [[CHIPDoorLock alloc] initWithDevice:device endpoint:1 queue:queue]; + XCTAssertNotNil(cluster); + + XCTestExpectation * expectation = + [self expectationWithDescription:@"DoorLockReadAttributeMaxRFIDCodeLengthWithCompletionHandler"]; + + [cluster readAttributeMaxRFIDCodeLengthWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"DoorLock MaxRFIDCodeLength Error: %@", err); + XCTAssertEqual(err.code, 0); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} + +- (void)testSendClusterDoorLockReadAttributeMinRFIDCodeLengthWithCompletionHandler +{ + dispatch_queue_t queue = dispatch_get_main_queue(); + + XCTestExpectation * connectedExpectation = + [self expectationWithDescription:@"Wait for the commissioned device to be retrieved"]; + WaitForCommissionee(connectedExpectation, queue); + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; + + CHIPDevice * device = GetConnectedDevice(); + CHIPDoorLock * cluster = [[CHIPDoorLock alloc] initWithDevice:device endpoint:1 queue:queue]; + XCTAssertNotNil(cluster); + + XCTestExpectation * expectation = + [self expectationWithDescription:@"DoorLockReadAttributeMinRFIDCodeLengthWithCompletionHandler"]; + + [cluster readAttributeMinRFIDCodeLengthWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"DoorLock MinRFIDCodeLength Error: %@", err); + XCTAssertEqual(err.code, 0); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} + - (void)testSendClusterDoorLockReadAttributeLanguageWithCompletionHandler { dispatch_queue_t queue = dispatch_get_main_queue(); diff --git a/zzz_generated/all-clusters-app/zap-generated/endpoint_config.h b/zzz_generated/all-clusters-app/zap-generated/endpoint_config.h index b0636e45052d32..c9005eba409698 100644 --- a/zzz_generated/all-clusters-app/zap-generated/endpoint_config.h +++ b/zzz_generated/all-clusters-app/zap-generated/endpoint_config.h @@ -381,38 +381,41 @@ /* 1223 - AutoRelockTime, */ \ 0x00, 0x00, 0x00, 0x60, \ \ + /* 1227 - FeatureMap, */ \ + 0x00, 0x00, 0x01, 0x03, \ + \ /* Endpoint: 1, Cluster: Window Covering (server), big-endian */ \ \ - /* 1227 - FeatureMap, */ \ + /* 1231 - FeatureMap, */ \ 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Pump Configuration and Control (server), big-endian */ \ \ - /* 1231 - LifetimeRunningHours, */ \ + /* 1235 - LifetimeRunningHours, */ \ 0x00, 0x00, 0x00, \ \ - /* 1234 - Power, */ \ + /* 1238 - Power, */ \ 0x00, 0x00, 0x00, \ \ - /* 1237 - LifetimeEnergyConsumed, */ \ + /* 1241 - LifetimeEnergyConsumed, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 1241 - FeatureMap, */ \ + /* 1245 - FeatureMap, */ \ 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Thermostat (server), big-endian */ \ \ - /* 1245 - FeatureMap, */ \ + /* 1249 - FeatureMap, */ \ 0x00, 0x00, 0x00, 0x0B, \ \ /* Endpoint: 1, Cluster: IAS Zone (server), big-endian */ \ \ - /* 1249 - IAS CIE address, */ \ + /* 1253 - IAS CIE address, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Channel (server), big-endian */ \ \ - /* 1257 - channel list, */ \ + /* 1261 - channel list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -430,7 +433,7 @@ \ /* Endpoint: 1, Cluster: Target Navigator (server), big-endian */ \ \ - /* 1511 - target navigator list, */ \ + /* 1515 - target navigator list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -448,24 +451,24 @@ \ /* Endpoint: 1, Cluster: Media Playback (server), big-endian */ \ \ - /* 1765 - start time, */ \ + /* 1769 - start time, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, \ \ - /* 1773 - duration, */ \ + /* 1777 - duration, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 1781 - playback speed, */ \ + /* 1785 - playback speed, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 1785 - seek range end, */ \ + /* 1789 - seek range end, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 1793 - seek range start, */ \ + /* 1797 - seek range start, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Media Input (server), big-endian */ \ \ - /* 1801 - media input list, */ \ + /* 1805 - media input list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -483,7 +486,7 @@ \ /* Endpoint: 1, Cluster: Content Launcher (server), big-endian */ \ \ - /* 2055 - accept header list, */ \ + /* 2059 - accept header list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -499,12 +502,12 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2309 - supported streaming protocols, */ \ + /* 2313 - supported streaming protocols, */ \ 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Audio Output (server), big-endian */ \ \ - /* 2313 - audio output list, */ \ + /* 2317 - audio output list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -522,7 +525,7 @@ \ /* Endpoint: 1, Cluster: Application Launcher (server), big-endian */ \ \ - /* 2567 - application launcher list, */ \ + /* 2571 - application launcher list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -540,67 +543,67 @@ \ /* Endpoint: 1, Cluster: Application Basic (server), big-endian */ \ \ - /* 2821 - allowed vendor list, */ \ + /* 2825 - allowed vendor list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Test Cluster (server), big-endian */ \ \ - /* 2853 - bitmap32, */ \ + /* 2857 - bitmap32, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 2857 - bitmap64, */ \ + /* 2861 - bitmap64, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2865 - int24u, */ \ + /* 2869 - int24u, */ \ 0x00, 0x00, 0x00, \ \ - /* 2868 - int32u, */ \ + /* 2872 - int32u, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 2872 - int40u, */ \ + /* 2876 - int40u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2877 - int48u, */ \ + /* 2881 - int48u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2883 - int56u, */ \ + /* 2887 - int56u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2890 - int64u, */ \ + /* 2894 - int64u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2898 - int24s, */ \ + /* 2902 - int24s, */ \ 0x00, 0x00, 0x00, \ \ - /* 2901 - int32s, */ \ + /* 2905 - int32s, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 2905 - int40s, */ \ + /* 2909 - int40s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2910 - int48s, */ \ + /* 2914 - int48s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2916 - int56s, */ \ + /* 2920 - int56s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2923 - int64s, */ \ + /* 2927 - int64s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2931 - float_single, */ \ + /* 2935 - float_single, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 2935 - float_double, */ \ + /* 2939 - float_double, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2943 - epoch_us, */ \ + /* 2947 - epoch_us, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2951 - epoch_s, */ \ + /* 2955 - epoch_s, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 2955 - list_long_octet_string, */ \ + /* 2959 - list_long_octet_string, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -655,65 +658,65 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 3955 - nullable_bitmap32, */ \ + /* 3959 - nullable_bitmap32, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 3959 - nullable_bitmap64, */ \ + /* 3963 - nullable_bitmap64, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 3967 - nullable_int24u, */ \ + /* 3971 - nullable_int24u, */ \ 0x00, 0x00, 0x00, \ \ - /* 3970 - nullable_int32u, */ \ + /* 3974 - nullable_int32u, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 3974 - nullable_int40u, */ \ + /* 3978 - nullable_int40u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 3979 - nullable_int48u, */ \ + /* 3983 - nullable_int48u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 3985 - nullable_int56u, */ \ + /* 3989 - nullable_int56u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 3992 - nullable_int64u, */ \ + /* 3996 - nullable_int64u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 4000 - nullable_int24s, */ \ + /* 4004 - nullable_int24s, */ \ 0x00, 0x00, 0x00, \ \ - /* 4003 - nullable_int32s, */ \ + /* 4007 - nullable_int32s, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 4007 - nullable_int40s, */ \ + /* 4011 - nullable_int40s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 4012 - nullable_int48s, */ \ + /* 4016 - nullable_int48s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 4018 - nullable_int56s, */ \ + /* 4022 - nullable_int56s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 4025 - nullable_int64s, */ \ + /* 4029 - nullable_int64s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 4033 - nullable_float_single, */ \ + /* 4037 - nullable_float_single, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 4037 - nullable_float_double, */ \ + /* 4041 - nullable_float_double, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Electrical Measurement (server), big-endian */ \ \ - /* 4045 - measurement type, */ \ + /* 4049 - measurement type, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 4049 - total active power, */ \ + /* 4053 - total active power, */ \ 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 2, Cluster: On/Off (server), big-endian */ \ \ - /* 4053 - FeatureMap, */ \ + /* 4057 - FeatureMap, */ \ 0x00, 0x00, 0x00, 0x00, \ } @@ -1075,38 +1078,41 @@ /* 1223 - AutoRelockTime, */ \ 0x60, 0x00, 0x00, 0x00, \ \ + /* 1227 - FeatureMap, */ \ + 0x03, 0x01, 0x00, 0x00, \ + \ /* Endpoint: 1, Cluster: Window Covering (server), little-endian */ \ \ - /* 1227 - FeatureMap, */ \ + /* 1231 - FeatureMap, */ \ 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Pump Configuration and Control (server), little-endian */ \ \ - /* 1231 - LifetimeRunningHours, */ \ + /* 1235 - LifetimeRunningHours, */ \ 0x00, 0x00, 0x00, \ \ - /* 1234 - Power, */ \ + /* 1238 - Power, */ \ 0x00, 0x00, 0x00, \ \ - /* 1237 - LifetimeEnergyConsumed, */ \ + /* 1241 - LifetimeEnergyConsumed, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 1241 - FeatureMap, */ \ + /* 1245 - FeatureMap, */ \ 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Thermostat (server), little-endian */ \ \ - /* 1245 - FeatureMap, */ \ + /* 1249 - FeatureMap, */ \ 0x0B, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: IAS Zone (server), little-endian */ \ \ - /* 1249 - IAS CIE address, */ \ + /* 1253 - IAS CIE address, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Channel (server), little-endian */ \ \ - /* 1257 - channel list, */ \ + /* 1261 - channel list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -1124,7 +1130,7 @@ \ /* Endpoint: 1, Cluster: Target Navigator (server), little-endian */ \ \ - /* 1511 - target navigator list, */ \ + /* 1515 - target navigator list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -1142,24 +1148,24 @@ \ /* Endpoint: 1, Cluster: Media Playback (server), little-endian */ \ \ - /* 1765 - start time, */ \ + /* 1769 - start time, */ \ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 1773 - duration, */ \ + /* 1777 - duration, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 1781 - playback speed, */ \ + /* 1785 - playback speed, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 1785 - seek range end, */ \ + /* 1789 - seek range end, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 1793 - seek range start, */ \ + /* 1797 - seek range start, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Media Input (server), little-endian */ \ \ - /* 1801 - media input list, */ \ + /* 1805 - media input list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -1177,7 +1183,7 @@ \ /* Endpoint: 1, Cluster: Content Launcher (server), little-endian */ \ \ - /* 2055 - accept header list, */ \ + /* 2059 - accept header list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -1193,12 +1199,12 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2309 - supported streaming protocols, */ \ + /* 2313 - supported streaming protocols, */ \ 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Audio Output (server), little-endian */ \ \ - /* 2313 - audio output list, */ \ + /* 2317 - audio output list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -1216,7 +1222,7 @@ \ /* Endpoint: 1, Cluster: Application Launcher (server), little-endian */ \ \ - /* 2567 - application launcher list, */ \ + /* 2571 - application launcher list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -1234,67 +1240,67 @@ \ /* Endpoint: 1, Cluster: Application Basic (server), little-endian */ \ \ - /* 2821 - allowed vendor list, */ \ + /* 2825 - allowed vendor list, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Test Cluster (server), little-endian */ \ \ - /* 2853 - bitmap32, */ \ + /* 2857 - bitmap32, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 2857 - bitmap64, */ \ + /* 2861 - bitmap64, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2865 - int24u, */ \ + /* 2869 - int24u, */ \ 0x00, 0x00, 0x00, \ \ - /* 2868 - int32u, */ \ + /* 2872 - int32u, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 2872 - int40u, */ \ + /* 2876 - int40u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2877 - int48u, */ \ + /* 2881 - int48u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2883 - int56u, */ \ + /* 2887 - int56u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2890 - int64u, */ \ + /* 2894 - int64u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2898 - int24s, */ \ + /* 2902 - int24s, */ \ 0x00, 0x00, 0x00, \ \ - /* 2901 - int32s, */ \ + /* 2905 - int32s, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 2905 - int40s, */ \ + /* 2909 - int40s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2910 - int48s, */ \ + /* 2914 - int48s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2916 - int56s, */ \ + /* 2920 - int56s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2923 - int64s, */ \ + /* 2927 - int64s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2931 - float_single, */ \ + /* 2935 - float_single, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 2935 - float_double, */ \ + /* 2939 - float_double, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2943 - epoch_us, */ \ + /* 2947 - epoch_us, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 2951 - epoch_s, */ \ + /* 2955 - epoch_s, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 2955 - list_long_octet_string, */ \ + /* 2959 - list_long_octet_string, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -1349,71 +1355,71 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 3955 - nullable_bitmap32, */ \ + /* 3959 - nullable_bitmap32, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 3959 - nullable_bitmap64, */ \ + /* 3963 - nullable_bitmap64, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 3967 - nullable_int24u, */ \ + /* 3971 - nullable_int24u, */ \ 0x00, 0x00, 0x00, \ \ - /* 3970 - nullable_int32u, */ \ + /* 3974 - nullable_int32u, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 3974 - nullable_int40u, */ \ + /* 3978 - nullable_int40u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 3979 - nullable_int48u, */ \ + /* 3983 - nullable_int48u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 3985 - nullable_int56u, */ \ + /* 3989 - nullable_int56u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 3992 - nullable_int64u, */ \ + /* 3996 - nullable_int64u, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 4000 - nullable_int24s, */ \ + /* 4004 - nullable_int24s, */ \ 0x00, 0x00, 0x00, \ \ - /* 4003 - nullable_int32s, */ \ + /* 4007 - nullable_int32s, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 4007 - nullable_int40s, */ \ + /* 4011 - nullable_int40s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 4012 - nullable_int48s, */ \ + /* 4016 - nullable_int48s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 4018 - nullable_int56s, */ \ + /* 4022 - nullable_int56s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 4025 - nullable_int64s, */ \ + /* 4029 - nullable_int64s, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ - /* 4033 - nullable_float_single, */ \ + /* 4037 - nullable_float_single, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 4037 - nullable_float_double, */ \ + /* 4041 - nullable_float_double, */ \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 1, Cluster: Electrical Measurement (server), little-endian */ \ \ - /* 4045 - measurement type, */ \ + /* 4049 - measurement type, */ \ 0x00, 0x00, 0x00, 0x00, \ \ - /* 4049 - total active power, */ \ + /* 4053 - total active power, */ \ 0x00, 0x00, 0x00, 0x00, \ \ /* Endpoint: 2, Cluster: On/Off (server), little-endian */ \ \ - /* 4053 - FeatureMap, */ \ + /* 4057 - FeatureMap, */ \ 0x00, 0x00, 0x00, 0x00, \ } #endif // BIGENDIAN_CPU -#define GENERATED_DEFAULTS_COUNT (151) +#define GENERATED_DEFAULTS_COUNT (152) #define ZAP_TYPE(type) ZCL_##type##_ATTRIBUTE_TYPE #define ZAP_LONG_DEFAULTS_INDEX(index) \ @@ -1509,7 +1515,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 625 +#define GENERATED_ATTRIBUTE_COUNT 629 #define GENERATED_ATTRIBUTES \ { \ \ @@ -1938,11 +1944,14 @@ { 0x00000006, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_EMPTY_DEFAULT() }, /* OpenPeriod */ \ { 0x00000011, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(10) }, /* NumberOfTotalUsersSupported */ \ { 0x00000012, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(10) }, /* NumberOfPINUsersSupported */ \ + { 0x00000013, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(10) }, /* NumberOfRFIDUsersSupported */ \ { 0x00000014, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0) }, /* NumberOfWeekDaySchedulesSupportedPerUser */ \ { 0x00000015, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0) }, /* NumberOfYearDaySchedulesSupportedPerUser */ \ { 0x00000016, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0) }, /* NumberOfHolidaySchedulesSupported */ \ { 0x00000017, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(6) }, /* MaxPINCodeLength */ \ { 0x00000018, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(6) }, /* MinPINCodeLength */ \ + { 0x00000019, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(20) }, /* MaxRFIDCodeLength */ \ + { 0x0000001A, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(10) }, /* MinRFIDCodeLength */ \ { 0x0000001B, ZAP_TYPE(BITMAP8), 1, 0, ZAP_SIMPLE_DEFAULT(1) }, /* CredentialRulesSupport */ \ { 0x00000021, ZAP_TYPE(CHAR_STRING), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(1220) }, /* Language */ \ { 0x00000023, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(1223) }, /* AutoRelockTime */ \ @@ -1962,8 +1971,9 @@ { 0x00000031, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ ZAP_MIN_MAX_DEFAULTS_INDEX(9) }, /* UserCodeTemporaryDisableTime */ \ { 0x00000033, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(WRITABLE), \ - ZAP_SIMPLE_DEFAULT(0) }, /* RequirePINforRemoteOperation */ \ - { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(3) }, /* ClusterRevision */ \ + ZAP_SIMPLE_DEFAULT(0) }, /* RequirePINforRemoteOperation */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_LONG_DEFAULTS_INDEX(1227) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(3) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Window Covering (server) */ \ { 0x00000000, ZAP_TYPE(ENUM8), 1, 0, ZAP_SIMPLE_DEFAULT(0x00) }, /* Type */ \ @@ -1998,7 +2008,7 @@ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ ZAP_MIN_MAX_DEFAULTS_INDEX(10) }, /* Mode */ \ { 0x0000001A, ZAP_TYPE(BITMAP16), 2, 0, ZAP_SIMPLE_DEFAULT(0x00) }, /* SafetyStatus */ \ - { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_LONG_DEFAULTS_INDEX(1227) }, /* FeatureMap */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_LONG_DEFAULTS_INDEX(1231) }, /* FeatureMap */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(5) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Barrier Control (server) */ \ @@ -2028,16 +2038,16 @@ { 0x00000013, ZAP_TYPE(INT16S), 2, 0, ZAP_EMPTY_DEFAULT() }, /* Capacity */ \ { 0x00000014, ZAP_TYPE(INT16U), 2, 0, ZAP_EMPTY_DEFAULT() }, /* Speed */ \ { 0x00000015, ZAP_TYPE(INT24U), 3, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(1231) }, /* LifetimeRunningHours */ \ - { 0x00000016, ZAP_TYPE(INT24U), 3, 0, ZAP_LONG_DEFAULTS_INDEX(1234) }, /* Power */ \ + ZAP_LONG_DEFAULTS_INDEX(1235) }, /* LifetimeRunningHours */ \ + { 0x00000016, ZAP_TYPE(INT24U), 3, 0, ZAP_LONG_DEFAULTS_INDEX(1238) }, /* Power */ \ { 0x00000017, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(1237) }, /* LifetimeEnergyConsumed */ \ + ZAP_LONG_DEFAULTS_INDEX(1241) }, /* LifetimeEnergyConsumed */ \ { 0x00000020, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ ZAP_MIN_MAX_DEFAULTS_INDEX(11) }, /* OperationMode */ \ { 0x00000021, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ ZAP_MIN_MAX_DEFAULTS_INDEX(12) }, /* ControlMode */ \ { 0x00000022, ZAP_TYPE(BITMAP16), 2, 0, ZAP_EMPTY_DEFAULT() }, /* AlarmMask */ \ - { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_LONG_DEFAULTS_INDEX(1241) }, /* FeatureMap */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_LONG_DEFAULTS_INDEX(1245) }, /* FeatureMap */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Thermostat (server) */ \ @@ -2067,7 +2077,7 @@ { 0x00000020, ZAP_TYPE(ENUM8), 1, 0, ZAP_SIMPLE_DEFAULT(0) }, /* start of week */ \ { 0x00000021, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(7) }, /* number of weekly transitions */ \ { 0x00000022, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(4) }, /* number of daily transitions */ \ - { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_LONG_DEFAULTS_INDEX(1245) }, /* FeatureMap */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_LONG_DEFAULTS_INDEX(1249) }, /* FeatureMap */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(3) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Thermostat User Interface Configuration (server) */ \ @@ -2190,7 +2200,7 @@ { 0x00000001, ZAP_TYPE(ENUM16), 2, 0, ZAP_EMPTY_DEFAULT() }, /* zone type */ \ { 0x00000002, ZAP_TYPE(BITMAP16), 2, 0, ZAP_SIMPLE_DEFAULT(0x0000) }, /* zone status */ \ { 0x00000010, ZAP_TYPE(NODE_ID), 8, ZAP_ATTRIBUTE_MASK(WRITABLE), \ - ZAP_LONG_DEFAULTS_INDEX(1249) }, /* IAS CIE address */ \ + ZAP_LONG_DEFAULTS_INDEX(1253) }, /* IAS CIE address */ \ { 0x00000011, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(0xff) }, /* Zone ID */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(2) }, /* ClusterRevision */ \ \ @@ -2199,25 +2209,25 @@ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Channel (server) */ \ - { 0x00000000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(1257) }, /* channel list */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(1261) }, /* channel list */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Target Navigator (server) */ \ - { 0x00000000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(1511) }, /* target navigator list */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(1515) }, /* target navigator list */ \ { 0x00000001, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(0x00) }, /* current navigator target */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Media Playback (server) */ \ { 0x00000000, ZAP_TYPE(ENUM8), 1, 0, ZAP_SIMPLE_DEFAULT(0x00) }, /* playback state */ \ - { 0x00000001, ZAP_TYPE(EPOCH_US), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1765) }, /* start time */ \ - { 0x00000002, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1773) }, /* duration */ \ - { 0x00000004, ZAP_TYPE(SINGLE), 4, 0, ZAP_LONG_DEFAULTS_INDEX(1781) }, /* playback speed */ \ - { 0x00000005, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1785) }, /* seek range end */ \ - { 0x00000006, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1793) }, /* seek range start */ \ + { 0x00000001, ZAP_TYPE(EPOCH_US), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1769) }, /* start time */ \ + { 0x00000002, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1777) }, /* duration */ \ + { 0x00000004, ZAP_TYPE(SINGLE), 4, 0, ZAP_LONG_DEFAULTS_INDEX(1785) }, /* playback speed */ \ + { 0x00000005, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1789) }, /* seek range end */ \ + { 0x00000006, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1797) }, /* seek range start */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Media Input (server) */ \ - { 0x00000000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(1801) }, /* media input list */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(1805) }, /* media input list */ \ { 0x00000001, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(0x00) }, /* current media input */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* ClusterRevision */ \ \ @@ -2228,18 +2238,18 @@ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Content Launcher (server) */ \ - { 0x00000000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(2055) }, /* accept header list */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(2059) }, /* accept header list */ \ { 0x00000001, ZAP_TYPE(BITMAP32), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), \ - ZAP_LONG_DEFAULTS_INDEX(2309) }, /* supported streaming protocols */ \ + ZAP_LONG_DEFAULTS_INDEX(2313) }, /* supported streaming protocols */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Audio Output (server) */ \ - { 0x00000000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(2313) }, /* audio output list */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(2317) }, /* audio output list */ \ { 0x00000001, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(0x00) }, /* current audio output */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Application Launcher (server) */ \ - { 0x00000000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(2567) }, /* application launcher list */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(2571) }, /* application launcher list */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Application Basic (server) */ \ @@ -2249,7 +2259,7 @@ { 0x00000003, ZAP_TYPE(INT16U), 2, 0, ZAP_EMPTY_DEFAULT() }, /* product id */ \ { 0x00000005, ZAP_TYPE(ENUM8), 1, 0, ZAP_EMPTY_DEFAULT() }, /* application status */ \ { 0x00000006, ZAP_TYPE(CHAR_STRING), 33, 0, ZAP_EMPTY_DEFAULT() }, /* application version */ \ - { 0x00000007, ZAP_TYPE(ARRAY), 32, 0, ZAP_LONG_DEFAULTS_INDEX(2821) }, /* allowed vendor list */ \ + { 0x00000007, ZAP_TYPE(ARRAY), 32, 0, ZAP_LONG_DEFAULTS_INDEX(2825) }, /* allowed vendor list */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Account Login (server) */ \ @@ -2259,28 +2269,28 @@ { 0x00000000, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(false) }, /* boolean */ \ { 0x00000001, ZAP_TYPE(BITMAP8), 1, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(0) }, /* bitmap8 */ \ { 0x00000002, ZAP_TYPE(BITMAP16), 2, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(0) }, /* bitmap16 */ \ - { 0x00000003, ZAP_TYPE(BITMAP32), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2853) }, /* bitmap32 */ \ - { 0x00000004, ZAP_TYPE(BITMAP64), 8, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2857) }, /* bitmap64 */ \ + { 0x00000003, ZAP_TYPE(BITMAP32), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2857) }, /* bitmap32 */ \ + { 0x00000004, ZAP_TYPE(BITMAP64), 8, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2861) }, /* bitmap64 */ \ { 0x00000005, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(0) }, /* int8u */ \ { 0x00000006, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(0) }, /* int16u */ \ - { 0x00000007, ZAP_TYPE(INT24U), 3, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2865) }, /* int24u */ \ - { 0x00000008, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2868) }, /* int32u */ \ - { 0x00000009, ZAP_TYPE(INT40U), 5, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2872) }, /* int40u */ \ - { 0x0000000A, ZAP_TYPE(INT48U), 6, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2877) }, /* int48u */ \ - { 0x0000000B, ZAP_TYPE(INT56U), 7, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2883) }, /* int56u */ \ - { 0x0000000C, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2890) }, /* int64u */ \ + { 0x00000007, ZAP_TYPE(INT24U), 3, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2869) }, /* int24u */ \ + { 0x00000008, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2872) }, /* int32u */ \ + { 0x00000009, ZAP_TYPE(INT40U), 5, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2876) }, /* int40u */ \ + { 0x0000000A, ZAP_TYPE(INT48U), 6, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2881) }, /* int48u */ \ + { 0x0000000B, ZAP_TYPE(INT56U), 7, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2887) }, /* int56u */ \ + { 0x0000000C, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2894) }, /* int64u */ \ { 0x0000000D, ZAP_TYPE(INT8S), 1, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(0) }, /* int8s */ \ { 0x0000000E, ZAP_TYPE(INT16S), 2, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(0) }, /* int16s */ \ - { 0x0000000F, ZAP_TYPE(INT24S), 3, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2898) }, /* int24s */ \ - { 0x00000010, ZAP_TYPE(INT32S), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2901) }, /* int32s */ \ - { 0x00000011, ZAP_TYPE(INT40S), 5, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2905) }, /* int40s */ \ - { 0x00000012, ZAP_TYPE(INT48S), 6, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2910) }, /* int48s */ \ - { 0x00000013, ZAP_TYPE(INT56S), 7, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2916) }, /* int56s */ \ - { 0x00000014, ZAP_TYPE(INT64S), 8, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2923) }, /* int64s */ \ + { 0x0000000F, ZAP_TYPE(INT24S), 3, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2902) }, /* int24s */ \ + { 0x00000010, ZAP_TYPE(INT32S), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2905) }, /* int32s */ \ + { 0x00000011, ZAP_TYPE(INT40S), 5, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2909) }, /* int40s */ \ + { 0x00000012, ZAP_TYPE(INT48S), 6, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2914) }, /* int48s */ \ + { 0x00000013, ZAP_TYPE(INT56S), 7, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2920) }, /* int56s */ \ + { 0x00000014, ZAP_TYPE(INT64S), 8, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2927) }, /* int64s */ \ { 0x00000015, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(0) }, /* enum8 */ \ { 0x00000016, ZAP_TYPE(ENUM16), 2, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(0) }, /* enum16 */ \ - { 0x00000017, ZAP_TYPE(SINGLE), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2931) }, /* float_single */ \ - { 0x00000018, ZAP_TYPE(DOUBLE), 8, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2935) }, /* float_double */ \ + { 0x00000017, ZAP_TYPE(SINGLE), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2935) }, /* float_single */ \ + { 0x00000018, ZAP_TYPE(DOUBLE), 8, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2939) }, /* float_double */ \ { 0x00000019, ZAP_TYPE(OCTET_STRING), 11, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_EMPTY_DEFAULT() }, /* octet_string */ \ { 0x0000001A, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ ZAP_EMPTY_DEFAULT() }, /* list_int8u */ \ @@ -2293,8 +2303,8 @@ { 0x0000001E, ZAP_TYPE(CHAR_STRING), 11, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_EMPTY_DEFAULT() }, /* char_string */ \ { 0x0000001F, ZAP_TYPE(LONG_CHAR_STRING), 1002, ZAP_ATTRIBUTE_MASK(WRITABLE), \ ZAP_EMPTY_DEFAULT() }, /* long_char_string */ \ - { 0x00000020, ZAP_TYPE(EPOCH_US), 8, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2943) }, /* epoch_us */ \ - { 0x00000021, ZAP_TYPE(EPOCH_S), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2951) }, /* epoch_s */ \ + { 0x00000020, ZAP_TYPE(EPOCH_US), 8, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2947) }, /* epoch_us */ \ + { 0x00000021, ZAP_TYPE(EPOCH_S), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(2955) }, /* epoch_s */ \ { 0x00000022, ZAP_TYPE(VENDOR_ID), 2, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_EMPTY_DEFAULT() }, /* vendor_id */ \ { 0x00000023, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ ZAP_EMPTY_DEFAULT() }, /* list_nullables_and_optionals_struct */ \ @@ -2309,7 +2319,7 @@ ZAP_MIN_MAX_DEFAULTS_INDEX(34) }, /* range_restricted_int16u */ \ { 0x00000029, ZAP_TYPE(INT16S), 2, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ ZAP_MIN_MAX_DEFAULTS_INDEX(35) }, /* range_restricted_int16s */ \ - { 0x0000002A, ZAP_TYPE(ARRAY), 1000, 0, ZAP_LONG_DEFAULTS_INDEX(2955) }, /* list_long_octet_string */ \ + { 0x0000002A, ZAP_TYPE(ARRAY), 1000, 0, ZAP_LONG_DEFAULTS_INDEX(2959) }, /* list_long_octet_string */ \ { 0x0000002B, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ ZAP_EMPTY_DEFAULT() }, /* list_fabric_scoped */ \ { 0x00000030, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(MUST_USE_TIMED_WRITE), \ @@ -2325,49 +2335,49 @@ { 0x00008002, ZAP_TYPE(BITMAP16), 2, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ ZAP_SIMPLE_DEFAULT(0) }, /* nullable_bitmap16 */ \ { 0x00008003, ZAP_TYPE(BITMAP32), 4, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(3955) }, /* nullable_bitmap32 */ \ + ZAP_LONG_DEFAULTS_INDEX(3959) }, /* nullable_bitmap32 */ \ { 0x00008004, ZAP_TYPE(BITMAP64), 8, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(3959) }, /* nullable_bitmap64 */ \ + ZAP_LONG_DEFAULTS_INDEX(3963) }, /* nullable_bitmap64 */ \ { 0x00008005, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ ZAP_SIMPLE_DEFAULT(0) }, /* nullable_int8u */ \ { 0x00008006, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ ZAP_SIMPLE_DEFAULT(0) }, /* nullable_int16u */ \ { 0x00008007, ZAP_TYPE(INT24U), 3, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(3967) }, /* nullable_int24u */ \ + ZAP_LONG_DEFAULTS_INDEX(3971) }, /* nullable_int24u */ \ { 0x00008008, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(3970) }, /* nullable_int32u */ \ + ZAP_LONG_DEFAULTS_INDEX(3974) }, /* nullable_int32u */ \ { 0x00008009, ZAP_TYPE(INT40U), 5, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(3974) }, /* nullable_int40u */ \ + ZAP_LONG_DEFAULTS_INDEX(3978) }, /* nullable_int40u */ \ { 0x0000800A, ZAP_TYPE(INT48U), 6, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(3979) }, /* nullable_int48u */ \ + ZAP_LONG_DEFAULTS_INDEX(3983) }, /* nullable_int48u */ \ { 0x0000800B, ZAP_TYPE(INT56U), 7, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(3985) }, /* nullable_int56u */ \ + ZAP_LONG_DEFAULTS_INDEX(3989) }, /* nullable_int56u */ \ { 0x0000800C, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(3992) }, /* nullable_int64u */ \ + ZAP_LONG_DEFAULTS_INDEX(3996) }, /* nullable_int64u */ \ { 0x0000800D, ZAP_TYPE(INT8S), 1, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ ZAP_SIMPLE_DEFAULT(0) }, /* nullable_int8s */ \ { 0x0000800E, ZAP_TYPE(INT16S), 2, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ ZAP_SIMPLE_DEFAULT(0) }, /* nullable_int16s */ \ { 0x0000800F, ZAP_TYPE(INT24S), 3, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(4000) }, /* nullable_int24s */ \ + ZAP_LONG_DEFAULTS_INDEX(4004) }, /* nullable_int24s */ \ { 0x00008010, ZAP_TYPE(INT32S), 4, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(4003) }, /* nullable_int32s */ \ + ZAP_LONG_DEFAULTS_INDEX(4007) }, /* nullable_int32s */ \ { 0x00008011, ZAP_TYPE(INT40S), 5, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(4007) }, /* nullable_int40s */ \ + ZAP_LONG_DEFAULTS_INDEX(4011) }, /* nullable_int40s */ \ { 0x00008012, ZAP_TYPE(INT48S), 6, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(4012) }, /* nullable_int48s */ \ + ZAP_LONG_DEFAULTS_INDEX(4016) }, /* nullable_int48s */ \ { 0x00008013, ZAP_TYPE(INT56S), 7, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(4018) }, /* nullable_int56s */ \ + ZAP_LONG_DEFAULTS_INDEX(4022) }, /* nullable_int56s */ \ { 0x00008014, ZAP_TYPE(INT64S), 8, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(4025) }, /* nullable_int64s */ \ + ZAP_LONG_DEFAULTS_INDEX(4029) }, /* nullable_int64s */ \ { 0x00008015, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ ZAP_SIMPLE_DEFAULT(0) }, /* nullable_enum8 */ \ { 0x00008016, ZAP_TYPE(ENUM16), 2, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ ZAP_SIMPLE_DEFAULT(0) }, /* nullable_enum16 */ \ { 0x00008017, ZAP_TYPE(SINGLE), 4, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(4033) }, /* nullable_float_single */ \ + ZAP_LONG_DEFAULTS_INDEX(4037) }, /* nullable_float_single */ \ { 0x00008018, ZAP_TYPE(DOUBLE), 8, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_LONG_DEFAULTS_INDEX(4037) }, /* nullable_float_double */ \ + ZAP_LONG_DEFAULTS_INDEX(4041) }, /* nullable_float_double */ \ { 0x00008019, ZAP_TYPE(OCTET_STRING), 11, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ ZAP_EMPTY_DEFAULT() }, /* nullable_octet_string */ \ { 0x0000801E, ZAP_TYPE(CHAR_STRING), 11, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ @@ -2392,8 +2402,8 @@ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Electrical Measurement (server) */ \ - { 0x00000000, ZAP_TYPE(BITMAP32), 4, 0, ZAP_LONG_DEFAULTS_INDEX(4045) }, /* measurement type */ \ - { 0x00000304, ZAP_TYPE(INT32S), 4, 0, ZAP_LONG_DEFAULTS_INDEX(4049) }, /* total active power */ \ + { 0x00000000, ZAP_TYPE(BITMAP32), 4, 0, ZAP_LONG_DEFAULTS_INDEX(4049) }, /* measurement type */ \ + { 0x00000304, ZAP_TYPE(INT32S), 4, 0, ZAP_LONG_DEFAULTS_INDEX(4053) }, /* total active power */ \ { 0x00000505, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0xffff) }, /* rms voltage */ \ { 0x00000506, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x8000) }, /* rms voltage min */ \ { 0x00000507, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x8000) }, /* rms voltage max */ \ @@ -2415,7 +2425,7 @@ { 0x00004001, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(0) }, /* OnTime */ \ { 0x00004002, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(0) }, /* OffWaitTime */ \ { 0x00004003, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_EMPTY_DEFAULT() }, /* StartUpOnOff */ \ - { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_LONG_DEFAULTS_INDEX(4053) }, /* FeatureMap */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_LONG_DEFAULTS_INDEX(4057) }, /* FeatureMap */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(4) }, /* ClusterRevision */ \ \ /* Endpoint: 2, Cluster: Descriptor (server) */ \ @@ -2664,132 +2674,132 @@ }, /* Endpoint: 1, Cluster: Mode Select (server) */ \ { 0x00000101, \ ZAP_ATTRIBUTE_INDEX(288), \ - 28, \ - 49, \ + 32, \ + 57, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION) | \ ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayDoorLockServer }, /* Endpoint: 1, Cluster: Door Lock (server) */ \ { \ - 0x00000102, ZAP_ATTRIBUTE_INDEX(316), 20, 35, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000102, ZAP_ATTRIBUTE_INDEX(320), 20, 35, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Window Covering (server) */ \ { \ - 0x00000103, ZAP_ATTRIBUTE_INDEX(336), 5, 7, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000103, ZAP_ATTRIBUTE_INDEX(340), 5, 7, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Barrier Control (server) */ \ { \ 0x00000200, \ - ZAP_ATTRIBUTE_INDEX(341), \ + ZAP_ATTRIBUTE_INDEX(345), \ 26, \ 54, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayPumpConfigurationAndControlServer \ }, /* Endpoint: 1, Cluster: Pump Configuration and Control (server) */ \ { 0x00000201, \ - ZAP_ATTRIBUTE_INDEX(367), \ + ZAP_ATTRIBUTE_INDEX(371), \ 19, \ 34, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayThermostatServer }, /* Endpoint: 1, Cluster: Thermostat (server) */ \ { \ 0x00000204, \ - ZAP_ATTRIBUTE_INDEX(386), \ + ZAP_ATTRIBUTE_INDEX(390), \ 4, \ 5, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayThermostatUserInterfaceConfigurationServer \ }, /* Endpoint: 1, Cluster: Thermostat User Interface Configuration (server) */ \ { 0x00000300, \ - ZAP_ATTRIBUTE_INDEX(390), \ + ZAP_ATTRIBUTE_INDEX(394), \ 53, \ 341, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayColorControlServer }, /* Endpoint: 1, Cluster: Color Control (server) */ \ { \ - 0x00000400, ZAP_ATTRIBUTE_INDEX(443), 6, 11, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000400, ZAP_ATTRIBUTE_INDEX(447), 6, 11, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Illuminance Measurement (server) */ \ { \ - 0x00000402, ZAP_ATTRIBUTE_INDEX(449), 5, 10, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000402, ZAP_ATTRIBUTE_INDEX(453), 5, 10, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Temperature Measurement (server) */ \ { \ - 0x00000403, ZAP_ATTRIBUTE_INDEX(454), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000403, ZAP_ATTRIBUTE_INDEX(458), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Pressure Measurement (server) */ \ { \ - 0x00000404, ZAP_ATTRIBUTE_INDEX(458), 5, 10, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000404, ZAP_ATTRIBUTE_INDEX(462), 5, 10, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Flow Measurement (server) */ \ { \ - 0x00000405, ZAP_ATTRIBUTE_INDEX(463), 5, 10, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000405, ZAP_ATTRIBUTE_INDEX(467), 5, 10, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Relative Humidity Measurement (server) */ \ { 0x00000406, \ - ZAP_ATTRIBUTE_INDEX(468), \ + ZAP_ATTRIBUTE_INDEX(472), \ 4, \ 5, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOccupancySensingServer }, /* Endpoint: 1, Cluster: Occupancy Sensing (server) */ \ { 0x00000500, \ - ZAP_ATTRIBUTE_INDEX(472), \ + ZAP_ATTRIBUTE_INDEX(476), \ 6, \ 16, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION) | \ ZAP_CLUSTER_MASK(MESSAGE_SENT_FUNCTION), \ chipFuncArrayIasZoneServer }, /* Endpoint: 1, Cluster: IAS Zone (server) */ \ { \ - 0x00000503, ZAP_ATTRIBUTE_INDEX(478), 2, 35, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000503, ZAP_ATTRIBUTE_INDEX(482), 2, 35, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Wake on LAN (server) */ \ { \ - 0x00000504, ZAP_ATTRIBUTE_INDEX(480), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000504, ZAP_ATTRIBUTE_INDEX(484), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Channel (server) */ \ { \ - 0x00000505, ZAP_ATTRIBUTE_INDEX(482), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000505, ZAP_ATTRIBUTE_INDEX(486), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Target Navigator (server) */ \ { \ - 0x00000506, ZAP_ATTRIBUTE_INDEX(485), 7, 39, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000506, ZAP_ATTRIBUTE_INDEX(489), 7, 39, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Media Playback (server) */ \ { \ - 0x00000507, ZAP_ATTRIBUTE_INDEX(492), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000507, ZAP_ATTRIBUTE_INDEX(496), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Media Input (server) */ \ { \ - 0x00000508, ZAP_ATTRIBUTE_INDEX(495), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000508, ZAP_ATTRIBUTE_INDEX(499), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Low Power (server) */ \ { \ - 0x00000509, ZAP_ATTRIBUTE_INDEX(496), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000509, ZAP_ATTRIBUTE_INDEX(500), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Keypad Input (server) */ \ { \ - 0x0000050A, ZAP_ATTRIBUTE_INDEX(497), 3, 260, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000050A, ZAP_ATTRIBUTE_INDEX(501), 3, 260, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Content Launcher (server) */ \ { \ - 0x0000050B, ZAP_ATTRIBUTE_INDEX(500), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000050B, ZAP_ATTRIBUTE_INDEX(504), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Audio Output (server) */ \ { \ - 0x0000050C, ZAP_ATTRIBUTE_INDEX(503), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000050C, ZAP_ATTRIBUTE_INDEX(507), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Application Launcher (server) */ \ { \ - 0x0000050D, ZAP_ATTRIBUTE_INDEX(505), 8, 138, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000050D, ZAP_ATTRIBUTE_INDEX(509), 8, 138, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Application Basic (server) */ \ { \ - 0x0000050E, ZAP_ATTRIBUTE_INDEX(513), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000050E, ZAP_ATTRIBUTE_INDEX(517), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Account Login (server) */ \ { \ - 0x0000050F, ZAP_ATTRIBUTE_INDEX(514), 81, 3285, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000050F, ZAP_ATTRIBUTE_INDEX(518), 81, 3285, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Test Cluster (server) */ \ { \ - 0x00000B04, ZAP_ATTRIBUTE_INDEX(595), 12, 28, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000B04, ZAP_ATTRIBUTE_INDEX(599), 12, 28, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Electrical Measurement (server) */ \ { 0x00000004, \ - ZAP_ATTRIBUTE_INDEX(607), \ + ZAP_ATTRIBUTE_INDEX(611), \ 2, \ 3, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayGroupsServer }, /* Endpoint: 2, Cluster: Groups (server) */ \ { 0x00000006, \ - ZAP_ATTRIBUTE_INDEX(609), \ + ZAP_ATTRIBUTE_INDEX(613), \ 7, \ 13, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOnOffServer }, /* Endpoint: 2, Cluster: On/Off (server) */ \ { \ - 0x0000001D, ZAP_ATTRIBUTE_INDEX(616), 5, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000001D, ZAP_ATTRIBUTE_INDEX(620), 5, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 2, Cluster: Descriptor (server) */ \ { 0x00000406, \ - ZAP_ATTRIBUTE_INDEX(621), \ + ZAP_ATTRIBUTE_INDEX(625), \ 4, \ 5, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ @@ -2801,7 +2811,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 26, 1768 }, { ZAP_CLUSTER_INDEX(26), 46, 6194 }, { ZAP_CLUSTER_INDEX(72), 4, 21 }, \ + { ZAP_CLUSTER_INDEX(0), 26, 1768 }, { ZAP_CLUSTER_INDEX(26), 46, 6202 }, { ZAP_CLUSTER_INDEX(72), 4, 21 }, \ } // Largest attribute size is needed for various buffers @@ -2811,7 +2821,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (689) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (7983) +#define ATTRIBUTE_MAX_SIZE (7991) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (3) diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp index 0fc750fec78ec5..ff5097fbc75517 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp @@ -13061,6 +13061,7 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & writer, TLV::Tag tag) const ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kCredentialData)), credentialData)); ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kUserIndex)), userIndex)); ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kUserStatus)), userStatus)); + ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kUserType)), userType)); ReturnErrorOnFailure(writer.EndContainer(outer)); return CHIP_NO_ERROR; } @@ -13091,6 +13092,9 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) case to_underlying(Fields::kUserStatus): ReturnErrorOnFailure(DataModel::Decode(reader, userStatus)); break; + case to_underlying(Fields::kUserType): + ReturnErrorOnFailure(DataModel::Decode(reader, userType)); + break; default: break; } diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h index 780e67670786ce..5a63a778a195f1 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h @@ -16587,12 +16587,6 @@ enum class DlDataOperationType : uint8_t kClear = 0x01, kModify = 0x02, }; -// Enum for DlDoorLockStatus -enum class DlDoorLockStatus : uint8_t -{ - kDuplicate = 0x02, - kOccupied = 0x03, -}; // Enum for DlDoorState enum class DlDoorState : uint8_t { @@ -16947,6 +16941,21 @@ enum class DoorLockDayOfWeek : uint8_t kSaturday = 0x40, }; +// Bitmap for DoorLockFeature +enum class DoorLockFeature : uint32_t +{ + kPINCredentials = 0x1, + kRFIDCredentials = 0x2, + kFingerCredentials = 0x4, + kLogging = 0x8, + kAccessSchedules = 0x10, + kDoorPositionSensor = 0x20, + kFaceCredentials = 0x40, + kCredentialsOTA = 0x80, + kUsersManagement = 0x100, + kNotifications = 0x200, +}; + namespace Structs { namespace DlCredential { enum class Fields @@ -17393,9 +17402,9 @@ struct Type static constexpr CommandId GetCommandId() { return Commands::SetPINCode::Id; } static constexpr ClusterId GetClusterId() { return Clusters::DoorLock::Id; } - uint16_t userId = static_cast(0); - DlUserStatus userStatus = static_cast(0); - DlUserType userType = static_cast(0); + uint16_t userId = static_cast(0); + DataModel::Nullable userStatus; + DataModel::Nullable userType; chip::ByteSpan pin; CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) const; @@ -17411,9 +17420,9 @@ struct DecodableType static constexpr CommandId GetCommandId() { return Commands::SetPINCode::Id; } static constexpr ClusterId GetClusterId() { return Clusters::DoorLock::Id; } - uint16_t userId = static_cast(0); - DlUserStatus userStatus = static_cast(0); - DlUserType userType = static_cast(0); + uint16_t userId = static_cast(0); + DataModel::Nullable userStatus; + DataModel::Nullable userType; chip::ByteSpan pin; CHIP_ERROR Decode(TLV::TLVReader & reader); }; @@ -18248,9 +18257,9 @@ struct Type static constexpr CommandId GetCommandId() { return Commands::SetRFIDCode::Id; } static constexpr ClusterId GetClusterId() { return Clusters::DoorLock::Id; } - uint16_t userId = static_cast(0); - DlUserStatus userStatus = static_cast(0); - DlUserType userType = static_cast(0); + uint16_t userId = static_cast(0); + DataModel::Nullable userStatus; + DataModel::Nullable userType; chip::ByteSpan rfidCode; CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) const; @@ -18266,9 +18275,9 @@ struct DecodableType static constexpr CommandId GetCommandId() { return Commands::SetRFIDCode::Id; } static constexpr ClusterId GetClusterId() { return Clusters::DoorLock::Id; } - uint16_t userId = static_cast(0); - DlUserStatus userStatus = static_cast(0); - DlUserType userType = static_cast(0); + uint16_t userId = static_cast(0); + DataModel::Nullable userStatus; + DataModel::Nullable userType; chip::ByteSpan rfidCode; CHIP_ERROR Decode(TLV::TLVReader & reader); }; @@ -18429,9 +18438,9 @@ struct Type uint16_t userIndex = static_cast(0); DataModel::Nullable userName; DataModel::Nullable userUniqueId; - DlUserStatus userStatus = static_cast(0); - DlUserType userType = static_cast(0); - DlCredentialRule credentialRule = static_cast(0); + DataModel::Nullable userStatus; + DataModel::Nullable userType; + DataModel::Nullable credentialRule; CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) const; @@ -18450,9 +18459,9 @@ struct DecodableType uint16_t userIndex = static_cast(0); DataModel::Nullable userName; DataModel::Nullable userUniqueId; - DlUserStatus userStatus = static_cast(0); - DlUserType userType = static_cast(0); - DlCredentialRule credentialRule = static_cast(0); + DataModel::Nullable userStatus; + DataModel::Nullable userType; + DataModel::Nullable credentialRule; CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace SetUser @@ -18519,7 +18528,7 @@ struct Type DataModel::Nullable> credentials; DataModel::Nullable creatorFabricIndex; DataModel::Nullable lastModifiedFabricIndex; - uint16_t nextUserIndex = static_cast(0); + DataModel::Nullable nextUserIndex; CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) const; @@ -18543,7 +18552,7 @@ struct DecodableType DataModel::Nullable> credentials; DataModel::Nullable creatorFabricIndex; DataModel::Nullable lastModifiedFabricIndex; - uint16_t nextUserIndex = static_cast(0); + DataModel::Nullable nextUserIndex; CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace GetUserResponse @@ -18687,6 +18696,7 @@ enum class Fields kCredentialData = 2, kUserIndex = 3, kUserStatus = 4, + kUserType = 5, }; struct Type @@ -18699,8 +18709,9 @@ struct Type DlDataOperationType operationType = static_cast(0); Structs::DlCredential::Type credential; chip::ByteSpan credentialData; - uint16_t userIndex = static_cast(0); - DlUserStatus userStatus = static_cast(0); + DataModel::Nullable userIndex; + DataModel::Nullable userStatus; + DataModel::Nullable userType; CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) const; @@ -18718,8 +18729,9 @@ struct DecodableType DlDataOperationType operationType = static_cast(0); Structs::DlCredential::DecodableType credential; chip::ByteSpan credentialData; - uint16_t userIndex = static_cast(0); - DlUserStatus userStatus = static_cast(0); + DataModel::Nullable userIndex; + DataModel::Nullable userStatus; + DataModel::Nullable userType; CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace SetCredential @@ -18844,7 +18856,7 @@ struct Type static constexpr CommandId GetCommandId() { return Commands::ClearCredential::Id; } static constexpr ClusterId GetClusterId() { return Clusters::DoorLock::Id; } - Structs::DlCredential::Type credential; + DataModel::Nullable credential; CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) const; @@ -18859,7 +18871,7 @@ struct DecodableType static constexpr CommandId GetCommandId() { return Commands::ClearCredential::Id; } static constexpr ClusterId GetClusterId() { return Clusters::DoorLock::Id; } - Structs::DlCredential::DecodableType credential; + DataModel::Nullable credential; CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace ClearCredential diff --git a/zzz_generated/app-common/app-common/zap-generated/enums.h b/zzz_generated/app-common/app-common/zap-generated/enums.h index 217663673ef183..1b1bc9256aab6d 100644 --- a/zzz_generated/app-common/app-common/zap-generated/enums.h +++ b/zzz_generated/app-common/app-common/zap-generated/enums.h @@ -856,6 +856,26 @@ enum EmberAfWiFiVersionType : uint8_t #define EMBER_AF_DOOR_LOCK_DAY_OF_WEEK_FRIDAY_OFFSET (5) #define EMBER_AF_DOOR_LOCK_DAY_OF_WEEK_SATURDAY (64) #define EMBER_AF_DOOR_LOCK_DAY_OF_WEEK_SATURDAY_OFFSET (6) +#define EMBER_AF_DOOR_LOCK_FEATURE_PIN_CREDENTIALS (1) +#define EMBER_AF_DOOR_LOCK_FEATURE_PIN_CREDENTIALS_OFFSET (0) +#define EMBER_AF_DOOR_LOCK_FEATURE_RFID_CREDENTIALS (2) +#define EMBER_AF_DOOR_LOCK_FEATURE_RFID_CREDENTIALS_OFFSET (1) +#define EMBER_AF_DOOR_LOCK_FEATURE_FINGER_CREDENTIALS (4) +#define EMBER_AF_DOOR_LOCK_FEATURE_FINGER_CREDENTIALS_OFFSET (2) +#define EMBER_AF_DOOR_LOCK_FEATURE_LOGGING (8) +#define EMBER_AF_DOOR_LOCK_FEATURE_LOGGING_OFFSET (3) +#define EMBER_AF_DOOR_LOCK_FEATURE_ACCESS_SCHEDULES (16) +#define EMBER_AF_DOOR_LOCK_FEATURE_ACCESS_SCHEDULES_OFFSET (4) +#define EMBER_AF_DOOR_LOCK_FEATURE_DOOR_POSITION_SENSOR (32) +#define EMBER_AF_DOOR_LOCK_FEATURE_DOOR_POSITION_SENSOR_OFFSET (5) +#define EMBER_AF_DOOR_LOCK_FEATURE_FACE_CREDENTIALS (64) +#define EMBER_AF_DOOR_LOCK_FEATURE_FACE_CREDENTIALS_OFFSET (6) +#define EMBER_AF_DOOR_LOCK_FEATURE_CREDENTIALS_OTA (128) +#define EMBER_AF_DOOR_LOCK_FEATURE_CREDENTIALS_OTA_OFFSET (7) +#define EMBER_AF_DOOR_LOCK_FEATURE_USERS_MANAGEMENT (256) +#define EMBER_AF_DOOR_LOCK_FEATURE_USERS_MANAGEMENT_OFFSET (8) +#define EMBER_AF_DOOR_LOCK_FEATURE_NOTIFICATIONS (512) +#define EMBER_AF_DOOR_LOCK_FEATURE_NOTIFICATIONS_OFFSET (9) #define EMBER_AF_ENERGY_FORMATTING_NUMBER_OF_DIGITS_TO_THE_RIGHT_OF_THE_DECIMAL_POINT (7) #define EMBER_AF_ENERGY_FORMATTING_NUMBER_OF_DIGITS_TO_THE_RIGHT_OF_THE_DECIMAL_POINT_OFFSET (0) #define EMBER_AF_ENERGY_FORMATTING_NUMBER_OF_DIGITS_TO_THE_LEFT_OF_THE_DECIMAL_POINT (120) diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index e608fea197369f..2c36446ad0fd69 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -2263,8 +2263,11 @@ class DiagnosticLogsRetrieveLogsRequest : public ClusterCommand | * DoorState | 0x0003 | | * NumberOfTotalUsersSupported | 0x0011 | | * NumberOfPINUsersSupported | 0x0012 | +| * NumberOfRFIDUsersSupported | 0x0013 | | * MaxPINCodeLength | 0x0017 | | * MinPINCodeLength | 0x0018 | +| * MaxRFIDCodeLength | 0x0019 | +| * MinRFIDCodeLength | 0x001A | | * Language | 0x0021 | | * AutoRelockTime | 0x0023 | | * SoundVolume | 0x0024 | @@ -2305,7 +2308,8 @@ class DoorLockClearCredential : public ClusterCommand private: chip::app::Clusters::DoorLock::Commands::ClearCredential::Type mRequest; - TypedComplexArgument mComplex_Credential; + TypedComplexArgument> + mComplex_Credential; }; /* @@ -2414,8 +2418,8 @@ class DoorLockSetCredential : public ClusterCommand AddArgument("Credential", &mComplex_Credential); AddArgument("CredentialData", &mRequest.credentialData); AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex); - AddArgument("UserStatus", 0, UINT8_MAX, - reinterpret_cast *>(&mRequest.userStatus)); + AddArgument("UserStatus", 0, UINT8_MAX, &mRequest.userStatus); + AddArgument("UserType", 0, UINT8_MAX, &mRequest.userType); ClusterCommand::AddArguments(); } @@ -2444,12 +2448,9 @@ class DoorLockSetUser : public ClusterCommand AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex); AddArgument("UserName", &mRequest.userName); AddArgument("UserUniqueId", 0, UINT32_MAX, &mRequest.userUniqueId); - AddArgument("UserStatus", 0, UINT8_MAX, - reinterpret_cast *>(&mRequest.userStatus)); - AddArgument("UserType", 0, UINT8_MAX, - reinterpret_cast *>(&mRequest.userType)); - AddArgument("CredentialRule", 0, UINT8_MAX, - reinterpret_cast *>(&mRequest.credentialRule)); + AddArgument("UserStatus", 0, UINT8_MAX, &mRequest.userStatus); + AddArgument("UserType", 0, UINT8_MAX, &mRequest.userType); + AddArgument("CredentialRule", 0, UINT8_MAX, &mRequest.credentialRule); ClusterCommand::AddArguments(); } @@ -9434,8 +9435,11 @@ void registerClusterDoorLock(Commands & commands) make_unique(Id, "door-state", Attributes::DoorState::Id), // make_unique(Id, "number-of-total-users-supported", Attributes::NumberOfTotalUsersSupported::Id), // make_unique(Id, "number-of-pinusers-supported", Attributes::NumberOfPINUsersSupported::Id), // + make_unique(Id, "number-of-rfidusers-supported", Attributes::NumberOfRFIDUsersSupported::Id), // make_unique(Id, "max-pincode-length", Attributes::MaxPINCodeLength::Id), // make_unique(Id, "min-pincode-length", Attributes::MinPINCodeLength::Id), // + make_unique(Id, "max-rfidcode-length", Attributes::MaxRFIDCodeLength::Id), // + make_unique(Id, "min-rfidcode-length", Attributes::MinRFIDCodeLength::Id), // make_unique(Id, "language", Attributes::Language::Id), // make_unique(Id, "auto-relock-time", Attributes::AutoRelockTime::Id), // make_unique(Id, "sound-volume", Attributes::SoundVolume::Id), // @@ -9460,8 +9464,11 @@ void registerClusterDoorLock(Commands & commands) make_unique(Id, "door-state", Attributes::DoorState::Id), // make_unique(Id, "number-of-total-users-supported", Attributes::NumberOfTotalUsersSupported::Id), // make_unique(Id, "number-of-pinusers-supported", Attributes::NumberOfPINUsersSupported::Id), // + make_unique(Id, "number-of-rfidusers-supported", Attributes::NumberOfRFIDUsersSupported::Id), // make_unique(Id, "max-pincode-length", Attributes::MaxPINCodeLength::Id), // make_unique(Id, "min-pincode-length", Attributes::MinPINCodeLength::Id), // + make_unique(Id, "max-rfidcode-length", Attributes::MaxRFIDCodeLength::Id), // + make_unique(Id, "min-rfidcode-length", Attributes::MinRFIDCodeLength::Id), // make_unique(Id, "language", Attributes::Language::Id), // make_unique(Id, "auto-relock-time", Attributes::AutoRelockTime::Id), // make_unique(Id, "sound-volume", Attributes::SoundVolume::Id), // diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp index f76979192d3b37..d44ecdb72bf642 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp @@ -4651,6 +4651,11 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); return DataModelLogger::LogValue("NumberOfPINUsersSupported", 1, value); } + case DoorLock::Attributes::NumberOfRFIDUsersSupported::Id: { + uint16_t value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("NumberOfRFIDUsersSupported", 1, value); + } case DoorLock::Attributes::MaxPINCodeLength::Id: { uint8_t value; ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); @@ -4661,6 +4666,16 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); return DataModelLogger::LogValue("MinPINCodeLength", 1, value); } + case DoorLock::Attributes::MaxRFIDCodeLength::Id: { + uint8_t value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("MaxRFIDCodeLength", 1, value); + } + case DoorLock::Attributes::MinRFIDCodeLength::Id: { + uint8_t value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("MinRFIDCodeLength", 1, value); + } case DoorLock::Attributes::Language::Id: { chip::CharSpan value; ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index bace8e66b9e25d..345b1425fc5f57 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -177,6 +177,8 @@ class TestList : public Command printf("Test_TC_SWDIAG_2_1\n"); printf("Test_TC_SWDIAG_3_1\n"); printf("TestSubscribe_OnOff\n"); + printf("DL_UsersAndCredentials\n"); + printf("DL_LockUnlock\n"); return CHIP_NO_ERROR; } @@ -75026,6 +75028,5780 @@ class TestSubscribe_OnOff : public TestCommand } }; +class DL_UsersAndCredentials : public TestCommand +{ +public: + DL_UsersAndCredentials() : TestCommand("DL_UsersAndCredentials"), mTestIndex(0) + { + AddArgument("cluster", &mCluster); + AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); + } + + ~DL_UsersAndCredentials() {} + + /////////// TestCommand Interface ///////// + void NextTest() override + { + CHIP_ERROR err = CHIP_NO_ERROR; + + if (0 == mTestIndex) + { + ChipLogProgress(chipTool, " **** Test Start: DL_UsersAndCredentials\n"); + } + + if (mTestCount == mTestIndex) + { + ChipLogProgress(chipTool, " **** Test Complete: DL_UsersAndCredentials\n"); + SetCommandExitStatus(CHIP_NO_ERROR); + return; + } + + Wait(); + + // Ensure we increment mTestIndex before we start running the relevant + // command. That way if we lose the timeslice after we send the message + // but before our function call returns, we won't end up with an + // incorrect mTestIndex value observed when we get the response. + switch (mTestIndex++) + { + case 0: + ChipLogProgress(chipTool, " ***** Test Step 0 : Wait for the commissioned device to be retrieved\n"); + err = TestWaitForTheCommissionedDeviceToBeRetrieved_0(); + break; + case 1: + ChipLogProgress(chipTool, " ***** Test Step 1 : Read available user slot and verify response fields\n"); + err = TestReadAvailableUserSlotAndVerifyResponseFields_1(); + break; + case 2: + ChipLogProgress(chipTool, " ***** Test Step 2 : Get number of supported users and verify default value\n"); + err = TestGetNumberOfSupportedUsersAndVerifyDefaultValue_2(); + break; + case 3: + ChipLogProgress(chipTool, " ***** Test Step 3 : Read fails for user with index 0\n"); + err = TestReadFailsForUserWithIndex0_3(); + break; + case 4: + ChipLogProgress(chipTool, + " ***** Test Step 4 : Read fails for user with index greater than Number Of Users Supported\n"); + err = TestReadFailsForUserWithIndexGreaterThanNumberOfUsersSupported_4(); + break; + case 5: + ChipLogProgress(chipTool, " ***** Test Step 5 : Create new user with default parameters\n"); + err = TestCreateNewUserWithDefaultParameters_5(); + break; + case 6: + ChipLogProgress(chipTool, " ***** Test Step 6 : Read the user back and verify its fields\n"); + err = TestReadTheUserBackAndVerifyItsFields_6(); + break; + case 7: + ChipLogProgress(chipTool, " ***** Test Step 7 : Set user at the occupied index fails with appropriate response\n"); + err = TestSetUserAtTheOccupiedIndexFailsWithAppropriateResponse_7(); + break; + case 8: + ChipLogProgress(chipTool, " ***** Test Step 8 : Modify userName for existing user\n"); + err = TestModifyUserNameForExistingUser_8(); + break; + case 9: + ChipLogProgress(chipTool, " ***** Test Step 9 : Read the modified user back and verify its fields\n"); + err = TestReadTheModifiedUserBackAndVerifyItsFields_9(); + break; + case 10: + ChipLogProgress(chipTool, " ***** Test Step 10 : Modify userUniqueId for existing user\n"); + err = TestModifyUserUniqueIdForExistingUser_10(); + break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Read the modified user back and verify its fields\n"); + err = TestReadTheModifiedUserBackAndVerifyItsFields_11(); + break; + case 12: + ChipLogProgress(chipTool, " ***** Test Step 12 : Modify userStatus for existing user\n"); + err = TestModifyUserStatusForExistingUser_12(); + break; + case 13: + ChipLogProgress(chipTool, " ***** Test Step 13 : Read the modified user back and verify its fields\n"); + err = TestReadTheModifiedUserBackAndVerifyItsFields_13(); + break; + case 14: + ChipLogProgress(chipTool, " ***** Test Step 14 : Modify userType for existing user\n"); + err = TestModifyUserTypeForExistingUser_14(); + break; + case 15: + ChipLogProgress(chipTool, " ***** Test Step 15 : Read the modified user back and verify its fields\n"); + err = TestReadTheModifiedUserBackAndVerifyItsFields_15(); + break; + case 16: + ChipLogProgress(chipTool, " ***** Test Step 16 : Modify credentialRule for existing user\n"); + err = TestModifyCredentialRuleForExistingUser_16(); + break; + case 17: + ChipLogProgress(chipTool, " ***** Test Step 17 : Read the modified user back and verify its fields\n"); + err = TestReadTheModifiedUserBackAndVerifyItsFields_17(); + break; + case 18: + ChipLogProgress(chipTool, " ***** Test Step 18 : Modify all fields for existing user\n"); + err = TestModifyAllFieldsForExistingUser_18(); + break; + case 19: + ChipLogProgress(chipTool, " ***** Test Step 19 : Read the modified user back and verify its fields\n"); + err = TestReadTheModifiedUserBackAndVerifyItsFields_19(); + break; + case 20: + ChipLogProgress(chipTool, " ***** Test Step 20 : Add another user with non-default fields\n"); + err = TestAddAnotherUserWithNonDefaultFields_20(); + break; + case 21: + ChipLogProgress(chipTool, " ***** Test Step 21 : Read the new user back and verify its fields\n"); + err = TestReadTheNewUserBackAndVerifyItsFields_21(); + break; + case 22: + ChipLogProgress(chipTool, " ***** Test Step 22 : Create user in the last slot\n"); + err = TestCreateUserInTheLastSlot_22(); + break; + case 23: + ChipLogProgress(chipTool, " ***** Test Step 23 : Read the last user back and verify its fields\n"); + err = TestReadTheLastUserBackAndVerifyItsFields_23(); + break; + case 24: + ChipLogProgress(chipTool, " ***** Test Step 24 : User creation in the 0 slot fails\n"); + err = TestUserCreationInThe0SlotFails_24(); + break; + case 25: + ChipLogProgress(chipTool, " ***** Test Step 25 : User creation in the out-of-bounds slot fails\n"); + err = TestUserCreationInTheOutOfBoundsSlotFails_25(); + break; + case 26: + ChipLogProgress(chipTool, " ***** Test Step 26 : Clear first user\n"); + err = TestClearFirstUser_26(); + break; + case 27: + ChipLogProgress(chipTool, " ***** Test Step 27 : Read cleared user and verify it is available\n"); + err = TestReadClearedUserAndVerifyItIsAvailable_27(); + break; + case 28: + ChipLogProgress(chipTool, " ***** Test Step 28 : Create new user in the cleared slot\n"); + err = TestCreateNewUserInTheClearedSlot_28(); + break; + case 29: + ChipLogProgress(chipTool, " ***** Test Step 29 : Read the user in the previously cleared slot and verify its fields\n"); + err = TestReadTheUserInThePreviouslyClearedSlotAndVerifyItsFields_29(); + break; + case 30: + ChipLogProgress(chipTool, " ***** Test Step 30 : Clear user with index 0 fails\n"); + err = TestClearUserWithIndex0Fails_30(); + break; + case 31: + ChipLogProgress(chipTool, " ***** Test Step 31 : Clear user with out-of-bounds index fails\n"); + err = TestClearUserWithOutOfBoundsIndexFails_31(); + break; + case 32: + ChipLogProgress(chipTool, " ***** Test Step 32 : Clear all users\n"); + err = TestClearAllUsers_32(); + break; + case 33: + ChipLogProgress(chipTool, " ***** Test Step 33 : Read first cleared user and verify it is available\n"); + err = TestReadFirstClearedUserAndVerifyItIsAvailable_33(); + break; + case 34: + ChipLogProgress(chipTool, " ***** Test Step 34 : Read last cleared user and verify it is available\n"); + err = TestReadLastClearedUserAndVerifyItIsAvailable_34(); + break; + case 35: + ChipLogProgress(chipTool, " ***** Test Step 35 : Get number of supported PIN credentials and verify default value\n"); + err = TestGetNumberOfSupportedPinCredentialsAndVerifyDefaultValue_35(); + break; + case 36: + ChipLogProgress(chipTool, " ***** Test Step 36 : Check that PIN credential does not exist\n"); + err = TestCheckThatPinCredentialDoesNotExist_36(); + break; + case 37: + ChipLogProgress(chipTool, " ***** Test Step 37 : Reading PIN credential with index 0 fails\n"); + err = TestReadingPinCredentialWithIndex0Fails_37(); + break; + case 38: + ChipLogProgress(chipTool, " ***** Test Step 38 : Reading PIN credential with out-of-bounds index fails\n"); + err = TestReadingPinCredentialWithOutOfBoundsIndexFails_38(); + break; + case 39: + ChipLogProgress(chipTool, " ***** Test Step 39 : Create new PIN credential and user\n"); + err = TestCreateNewPinCredentialAndUser_39(); + break; + case 40: + ChipLogProgress(chipTool, " ***** Test Step 40 : Verify created user\n"); + err = TestVerifyCreatedUser_40(); + break; + case 41: + ChipLogProgress(chipTool, " ***** Test Step 41 : Verify created PIN credential\n"); + err = TestVerifyCreatedPinCredential_41(); + break; + case 42: + ChipLogProgress(chipTool, " ***** Test Step 42 : Create new PIN credential and user with index 0 fails\n"); + err = TestCreateNewPinCredentialAndUserWithIndex0Fails_42(); + break; + case 43: + ChipLogProgress(chipTool, " ***** Test Step 43 : Create new PIN credential and user with out-of-bounds index fails\n"); + err = TestCreateNewPinCredentialAndUserWithOutOfBoundsIndexFails_43(); + break; + case 44: + ChipLogProgress(chipTool, " ***** Test Step 44 : Get number of supported RFID credentials and verify default value\n"); + err = TestGetNumberOfSupportedRfidCredentialsAndVerifyDefaultValue_44(); + break; + case 45: + ChipLogProgress(chipTool, " ***** Test Step 45 : Reading RFID credential with index 0 fails\n"); + err = TestReadingRfidCredentialWithIndex0Fails_45(); + break; + case 46: + ChipLogProgress(chipTool, " ***** Test Step 46 : Reading RFID credential with out-of-bounds index fails\n"); + err = TestReadingRfidCredentialWithOutOfBoundsIndexFails_46(); + break; + case 47: + ChipLogProgress(chipTool, " ***** Test Step 47 : Check that RFID credential does not exist\n"); + err = TestCheckThatRfidCredentialDoesNotExist_47(); + break; + case 48: + ChipLogProgress(chipTool, " ***** Test Step 48 : Create new RFID credential and add it to existing user\n"); + err = TestCreateNewRfidCredentialAndAddItToExistingUser_48(); + break; + case 49: + ChipLogProgress(chipTool, " ***** Test Step 49 : Verify modified user\n"); + err = TestVerifyModifiedUser_49(); + break; + case 50: + ChipLogProgress(chipTool, " ***** Test Step 50 : Verify created credential\n"); + err = TestVerifyCreatedCredential_50(); + break; + case 51: + ChipLogProgress(chipTool, " ***** Test Step 51 : Create new RFID credential and user with index 0 fails\n"); + err = TestCreateNewRfidCredentialAndUserWithIndex0Fails_51(); + break; + case 52: + ChipLogProgress(chipTool, " ***** Test Step 52 : Create new RFID credential and user with out-of-bounds index fails\n"); + err = TestCreateNewRfidCredentialAndUserWithOutOfBoundsIndexFails_52(); + break; + case 53: + ChipLogProgress(chipTool, " ***** Test Step 53 : Create new PIN credential and try to add it to existing user\n"); + err = TestCreateNewPinCredentialAndTryToAddItToExistingUser_53(); + break; + case 54: + ChipLogProgress(chipTool, " ***** Test Step 54 : Create new credential and try to add it to 0 user\n"); + err = TestCreateNewCredentialAndTryToAddItTo0User_54(); + break; + case 55: + ChipLogProgress(chipTool, " ***** Test Step 55 : Create new credential and try to add it to out-of-bounds user\n"); + err = TestCreateNewCredentialAndTryToAddItToOutOfBoundsUser_55(); + break; + case 56: + ChipLogProgress(chipTool, " ***** Test Step 56 : Create new PIN with too short data\n"); + err = TestCreateNewPinWithTooShortData_56(); + break; + case 57: + ChipLogProgress(chipTool, " ***** Test Step 57 : Create new PIN with too long data\n"); + err = TestCreateNewPinWithTooLongData_57(); + break; + case 58: + ChipLogProgress(chipTool, " ***** Test Step 58 : Create new RFID with too short data\n"); + err = TestCreateNewRfidWithTooShortData_58(); + break; + case 59: + ChipLogProgress(chipTool, " ***** Test Step 59 : Create new PIN with Programming user type fails\n"); + err = TestCreateNewPinWithProgrammingUserTypeFails_59(); + break; + case 60: + ChipLogProgress(chipTool, " ***** Test Step 60 : Create new RFID with too short data\n"); + err = TestCreateNewRfidWithTooShortData_60(); + break; + case 61: + ChipLogProgress(chipTool, " ***** Test Step 61 : Create new PIN credential with data the would cause duplicate\n"); + err = TestCreateNewPinCredentialWithDataTheWouldCauseDuplicate_61(); + break; + case 62: + ChipLogProgress(chipTool, " ***** Test Step 62 : Create new RFID credential with data the would cause duplicate\n"); + err = TestCreateNewRfidCredentialWithDataTheWouldCauseDuplicate_62(); + break; + case 63: + ChipLogProgress(chipTool, " ***** Test Step 63 : Modify credentialData of existing PIN credential\n"); + err = TestModifyCredentialDataOfExistingPinCredential_63(); + break; + case 64: + ChipLogProgress(chipTool, + " ***** Test Step 64 : Verify that credential was changed by creating new credential with old data\n"); + err = TestVerifyThatCredentialWasChangedByCreatingNewCredentialWithOldData_64(); + break; + case 65: + ChipLogProgress(chipTool, + " ***** Test Step 65 : Verify that credential was changed by creating new credential with new data\n"); + err = TestVerifyThatCredentialWasChangedByCreatingNewCredentialWithNewData_65(); + break; + case 66: + ChipLogProgress(chipTool, " ***** Test Step 66 : Clear first PIN credential\n"); + err = TestClearFirstPinCredential_66(); + break; + case 67: + ChipLogProgress(chipTool, " ***** Test Step 67 : Read back the credential and make sure it is deleted\n"); + err = TestReadBackTheCredentialAndMakeSureItIsDeleted_67(); + break; + case 68: + ChipLogProgress(chipTool, " ***** Test Step 68 : Read the user back and make sure PIN credential is deleted\n"); + err = TestReadTheUserBackAndMakeSurePinCredentialIsDeleted_68(); + break; + case 69: + ChipLogProgress(chipTool, " ***** Test Step 69 : Clear the second PIN credential\n"); + err = TestClearTheSecondPinCredential_69(); + break; + case 70: + ChipLogProgress(chipTool, " ***** Test Step 70 : Read back the credential and make sure it is deleted\n"); + err = TestReadBackTheCredentialAndMakeSureItIsDeleted_70(); + break; + case 71: + ChipLogProgress(chipTool, " ***** Test Step 71 : Read the user back and make sure related user is deleted\n"); + err = TestReadTheUserBackAndMakeSureRelatedUserIsDeleted_71(); + break; + case 72: + ChipLogProgress(chipTool, " ***** Test Step 72 : Create new RFID credential with user\n"); + err = TestCreateNewRfidCredentialWithUser_72(); + break; + case 73: + ChipLogProgress(chipTool, " ***** Test Step 73 : Clear all the RFID credentials\n"); + err = TestClearAllTheRfidCredentials_73(); + break; + case 74: + ChipLogProgress(chipTool, " ***** Test Step 74 : Read back the fist RFID credential and make sure it is deleted\n"); + err = TestReadBackTheFistRfidCredentialAndMakeSureItIsDeleted_74(); + break; + case 75: + ChipLogProgress(chipTool, " ***** Test Step 75 : Read back the second RFID credential and make sure it is deleted\n"); + err = TestReadBackTheSecondRfidCredentialAndMakeSureItIsDeleted_75(); + break; + case 76: + ChipLogProgress(chipTool, + " ***** Test Step 76 : Read the user related with first RFID back and make sure it is deleted\n"); + err = TestReadTheUserRelatedWithFirstRfidBackAndMakeSureItIsDeleted_76(); + break; + case 77: + ChipLogProgress(chipTool, + " ***** Test Step 77 : Read the user related with second RFID back and make sure it is deleted\n"); + err = TestReadTheUserRelatedWithSecondRfidBackAndMakeSureItIsDeleted_77(); + break; + case 78: + ChipLogProgress(chipTool, " ***** Test Step 78 : Create new PIN credential with user\n"); + err = TestCreateNewPinCredentialWithUser_78(); + break; + case 79: + ChipLogProgress(chipTool, " ***** Test Step 79 : Create new RFID credential with user\n"); + err = TestCreateNewRfidCredentialWithUser_79(); + break; + case 80: + ChipLogProgress(chipTool, " ***** Test Step 80 : Create another RFID credential with user\n"); + err = TestCreateAnotherRfidCredentialWithUser_80(); + break; + case 81: + ChipLogProgress(chipTool, " ***** Test Step 81 : Clear all the credentials\n"); + err = TestClearAllTheCredentials_81(); + break; + case 82: + ChipLogProgress(chipTool, " ***** Test Step 82 : Read back the first PIN credential and make sure it is deleted\n"); + err = TestReadBackTheFirstPinCredentialAndMakeSureItIsDeleted_82(); + break; + case 83: + ChipLogProgress(chipTool, " ***** Test Step 83 : Read back the first RFID credential and make sure it is deleted\n"); + err = TestReadBackTheFirstRfidCredentialAndMakeSureItIsDeleted_83(); + break; + case 84: + ChipLogProgress(chipTool, " ***** Test Step 84 : Read back the second PIN credential and make sure it is deleted\n"); + err = TestReadBackTheSecondPinCredentialAndMakeSureItIsDeleted_84(); + break; + case 85: + ChipLogProgress(chipTool, + " ***** Test Step 85 : Read the user related with first PIN back and make sure it is deleted\n"); + err = TestReadTheUserRelatedWithFirstPinBackAndMakeSureItIsDeleted_85(); + break; + case 86: + ChipLogProgress(chipTool, + " ***** Test Step 86 : Read the user related with first RFID back and make sure it is deleted\n"); + err = TestReadTheUserRelatedWithFirstRfidBackAndMakeSureItIsDeleted_86(); + break; + case 87: + ChipLogProgress(chipTool, + " ***** Test Step 87 : Read the user related with second PIN back and make sure it is deleted\n"); + err = TestReadTheUserRelatedWithSecondPinBackAndMakeSureItIsDeleted_87(); + break; + case 88: + ChipLogProgress(chipTool, " ***** Test Step 88 : Create new Programming PIN credential with invalid index\n"); + err = TestCreateNewProgrammingPinCredentialWithInvalidIndex_88(); + break; + case 89: + ChipLogProgress(chipTool, " ***** Test Step 89 : Create new Programming PIN credential with valid index\n"); + err = TestCreateNewProgrammingPinCredentialWithValidIndex_89(); + break; + case 90: + ChipLogProgress(chipTool, " ***** Test Step 90 : Verify created user\n"); + err = TestVerifyCreatedUser_90(); + break; + case 91: + ChipLogProgress(chipTool, " ***** Test Step 91 : Verify created programming PIN credential\n"); + err = TestVerifyCreatedProgrammingPinCredential_91(); + break; + case 92: + ChipLogProgress(chipTool, " ***** Test Step 92 : Modify the Programming PIN credential\n"); + err = TestModifyTheProgrammingPinCredential_92(); + break; + case 93: + ChipLogProgress(chipTool, " ***** Test Step 93 : Clearing Programming PIN fails\n"); + err = TestClearingProgrammingPinFails_93(); + break; + case 94: + ChipLogProgress(chipTool, " ***** Test Step 94 : Clearing Programming PIN with invalid index fails\n"); + err = TestClearingProgrammingPinWithInvalidIndexFails_94(); + break; + case 95: + ChipLogProgress(chipTool, " ***** Test Step 95 : Clearing PIN credential with zero index fails\n"); + err = TestClearingPinCredentialWithZeroIndexFails_95(); + break; + case 96: + ChipLogProgress(chipTool, " ***** Test Step 96 : Clearing PIN credential with out-of-bound index fails\n"); + err = TestClearingPinCredentialWithOutOfBoundIndexFails_96(); + break; + case 97: + ChipLogProgress(chipTool, " ***** Test Step 97 : Clearing RFID credential with zero index fails\n"); + err = TestClearingRfidCredentialWithZeroIndexFails_97(); + break; + case 98: + ChipLogProgress(chipTool, " ***** Test Step 98 : Clearing RFID credential with out-of-bound index fails\n"); + err = TestClearingRfidCredentialWithOutOfBoundIndexFails_98(); + break; + case 99: + ChipLogProgress(chipTool, " ***** Test Step 99 : Clear the Programming PIN user\n"); + err = TestClearTheProgrammingPinUser_99(); + break; + case 100: + ChipLogProgress(chipTool, " ***** Test Step 100 : Make sure Programming PIN user is deleted\n"); + err = TestMakeSureProgrammingPinUserIsDeleted_100(); + break; + case 101: + ChipLogProgress(chipTool, " ***** Test Step 101 : Make sure programming PIN credential is deleted\n"); + err = TestMakeSureProgrammingPinCredentialIsDeleted_101(); + break; + } + + if (CHIP_NO_ERROR != err) + { + ChipLogError(chipTool, " ***** Test Failure: %s\n", chip::ErrorStr(err)); + SetCommandExitStatus(err); + } + } + +private: + std::atomic_uint16_t mTestIndex; + const uint16_t mTestCount = 102; + + chip::Optional mCluster; + chip::Optional mEndpoint; + + uint16_t NumberOfTotalUsersSupported; + uint16_t NumberOfPINUsersSupported; + uint16_t NumberOfRFIDUsersSupported; + + static void OnFailureCallback_2(void * context, CHIP_ERROR error) + { + (static_cast(context))->OnFailureResponse_2(error); + } + + static void OnSuccessCallback_2(void * context, uint16_t numberOfTotalUsersSupported) + { + (static_cast(context))->OnSuccessResponse_2(numberOfTotalUsersSupported); + } + + static void OnFailureCallback_35(void * context, CHIP_ERROR error) + { + (static_cast(context))->OnFailureResponse_35(error); + } + + static void OnSuccessCallback_35(void * context, uint16_t numberOfPINUsersSupported) + { + (static_cast(context))->OnSuccessResponse_35(numberOfPINUsersSupported); + } + + static void OnFailureCallback_44(void * context, CHIP_ERROR error) + { + (static_cast(context))->OnFailureResponse_44(error); + } + + static void OnSuccessCallback_44(void * context, uint16_t numberOfRFIDUsersSupported) + { + (static_cast(context))->OnSuccessResponse_44(numberOfRFIDUsersSupported); + } + + // + // Tests methods + // + + CHIP_ERROR TestWaitForTheCommissionedDeviceToBeRetrieved_0() + { + SetIdentity(kIdentityAlpha); + return WaitForCommissionee(); + } + + CHIP_ERROR TestReadAvailableUserSlotAndVerifyResponseFields_1() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_1(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_1(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_1(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_1( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNull("userName", userName)); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNull("userStatus", userStatus)); + + VerifyOrReturn(CheckValueNull("userType", userType)); + + VerifyOrReturn(CheckValueNull("credentialRule", credentialRule)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNull("creatorFabricIndex", creatorFabricIndex)); + + VerifyOrReturn(CheckValueNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestGetNumberOfSupportedUsersAndVerifyDefaultValue_2() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::DoorLockClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure( + cluster.ReadAttribute( + this, OnSuccessCallback_2, OnFailureCallback_2)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_2(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_2(uint16_t numberOfTotalUsersSupported) + { + VerifyOrReturn(CheckValue("numberOfTotalUsersSupported", numberOfTotalUsersSupported, 10U)); + + NumberOfTotalUsersSupported = numberOfTotalUsersSupported; + NextTest(); + } + + CHIP_ERROR TestReadFailsForUserWithIndex0_3() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 0U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_3(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_3(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_3(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_3( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + ThrowSuccessResponse(); + } + + CHIP_ERROR TestReadFailsForUserWithIndexGreaterThanNumberOfUsersSupported_4() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = static_cast(NumberOfTotalUsersSupported + 1); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_4(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_4(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_4(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_4( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + ThrowSuccessResponse(); + } + + CHIP_ERROR TestCreateNewUserWithDefaultParameters_5() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(0); + request.userIndex = 1U; + request.userName.SetNull(); + request.userUniqueId.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + request.credentialRule.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_5(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_5(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_5(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_5() { NextTest(); } + + CHIP_ERROR TestReadTheUserBackAndVerifyItsFields_6() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_6(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_6(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_6(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_6( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("", 0))); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 0)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestSetUserAtTheOccupiedIndexFailsWithAppropriateResponse_7() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(0); + request.userIndex = 1U; + request.userName.SetNull(); + request.userUniqueId.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + request.credentialRule.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_7(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_7(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_7(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 1)); + NextTest(); + } + + void OnSuccessResponse_7() { ThrowSuccessResponse(); } + + CHIP_ERROR TestModifyUserNameForExistingUser_8() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(2); + request.userIndex = 1U; + request.userName.SetNonNull(); + request.userName.Value() = chip::Span("new_usergarbage: not in length on purpose", 8); + request.userUniqueId.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + request.credentialRule.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_8(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_8(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_8(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_8() { NextTest(); } + + CHIP_ERROR TestReadTheModifiedUserBackAndVerifyItsFields_9() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_9(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_9(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_9(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_9( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("new_user", 8))); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 0)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestModifyUserUniqueIdForExistingUser_10() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(2); + request.userIndex = 1U; + request.userName.SetNull(); + request.userUniqueId.SetNonNull(); + request.userUniqueId.Value() = 305441741UL; + request.userStatus.SetNull(); + request.userType.SetNull(); + request.credentialRule.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_10(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_10(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_10(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_10() { NextTest(); } + + CHIP_ERROR TestReadTheModifiedUserBackAndVerifyItsFields_11() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_11(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_11(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_11(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_11( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("new_user", 8))); + + VerifyOrReturn(CheckValueNonNull("userUniqueId", userUniqueId)); + VerifyOrReturn(CheckValue("userUniqueId.Value()", userUniqueId.Value(), 305441741UL)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 0)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestModifyUserStatusForExistingUser_12() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(2); + request.userIndex = 1U; + request.userName.SetNull(); + request.userUniqueId.SetNull(); + request.userStatus.SetNonNull(); + request.userStatus.Value() = static_cast(3); + request.userType.SetNull(); + request.credentialRule.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_12(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_12(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_12(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_12() { NextTest(); } + + CHIP_ERROR TestReadTheModifiedUserBackAndVerifyItsFields_13() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_13(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_13(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_13(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_13( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("new_user", 8))); + + VerifyOrReturn(CheckValueNonNull("userUniqueId", userUniqueId)); + VerifyOrReturn(CheckValue("userUniqueId.Value()", userUniqueId.Value(), 305441741UL)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 3)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 0)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestModifyUserTypeForExistingUser_14() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(2); + request.userIndex = 1U; + request.userName.SetNull(); + request.userUniqueId.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNonNull(); + request.userType.Value() = static_cast(6); + request.credentialRule.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_14(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_14(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_14(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_14() { NextTest(); } + + CHIP_ERROR TestReadTheModifiedUserBackAndVerifyItsFields_15() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_15(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_15(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_15(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_15( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("new_user", 8))); + + VerifyOrReturn(CheckValueNonNull("userUniqueId", userUniqueId)); + VerifyOrReturn(CheckValue("userUniqueId.Value()", userUniqueId.Value(), 305441741UL)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 3)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 6)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 0)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestModifyCredentialRuleForExistingUser_16() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(2); + request.userIndex = 1U; + request.userName.SetNull(); + request.userUniqueId.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + request.credentialRule.SetNonNull(); + request.credentialRule.Value() = static_cast(2); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_16(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_16(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_16(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_16() { NextTest(); } + + CHIP_ERROR TestReadTheModifiedUserBackAndVerifyItsFields_17() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_17(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_17(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_17(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_17( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("new_user", 8))); + + VerifyOrReturn(CheckValueNonNull("userUniqueId", userUniqueId)); + VerifyOrReturn(CheckValue("userUniqueId.Value()", userUniqueId.Value(), 305441741UL)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 3)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 6)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 2)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestModifyAllFieldsForExistingUser_18() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(2); + request.userIndex = 1U; + request.userName.SetNonNull(); + request.userName.Value() = chip::Span("test_usergarbage: not in length on purpose", 9); + request.userUniqueId.SetNonNull(); + request.userUniqueId.Value() = 466460832UL; + request.userStatus.SetNonNull(); + request.userStatus.Value() = static_cast(1); + request.userType.SetNonNull(); + request.userType.Value() = static_cast(0); + request.credentialRule.SetNonNull(); + request.credentialRule.Value() = static_cast(1); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_18(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_18(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_18(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_18() { NextTest(); } + + CHIP_ERROR TestReadTheModifiedUserBackAndVerifyItsFields_19() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_19(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_19(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_19(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_19( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("test_user", 9))); + + VerifyOrReturn(CheckValueNonNull("userUniqueId", userUniqueId)); + VerifyOrReturn(CheckValue("userUniqueId.Value()", userUniqueId.Value(), 466460832UL)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 1)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestAddAnotherUserWithNonDefaultFields_20() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(0); + request.userIndex = 2U; + request.userName.SetNonNull(); + request.userName.Value() = chip::Span("test_user2garbage: not in length on purpose", 10); + request.userUniqueId.SetNonNull(); + request.userUniqueId.Value() = 12648430UL; + request.userStatus.SetNonNull(); + request.userStatus.Value() = static_cast(1); + request.userType.SetNonNull(); + request.userType.Value() = static_cast(1); + request.credentialRule.SetNonNull(); + request.credentialRule.Value() = static_cast(2); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_20(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_20(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_20(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_20() { NextTest(); } + + CHIP_ERROR TestReadTheNewUserBackAndVerifyItsFields_21() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 2U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_21(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_21(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_21(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_21( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 2U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("test_user2", 10))); + + VerifyOrReturn(CheckValueNonNull("userUniqueId", userUniqueId)); + VerifyOrReturn(CheckValue("userUniqueId.Value()", userUniqueId.Value(), 12648430UL)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 2)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestCreateUserInTheLastSlot_22() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(0); + request.userIndex = NumberOfTotalUsersSupported; + request.userName.SetNonNull(); + request.userName.Value() = chip::Span("last_usergarbage: not in length on purpose", 9); + request.userUniqueId.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + request.credentialRule.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_22(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_22(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_22(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_22() { NextTest(); } + + CHIP_ERROR TestReadTheLastUserBackAndVerifyItsFields_23() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = NumberOfTotalUsersSupported; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_23(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_23(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_23(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_23( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, NumberOfTotalUsersSupported)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("last_user", 9))); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 0)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNull("nextUserIndex", nextUserIndex)); + + NextTest(); + } + + CHIP_ERROR TestUserCreationInThe0SlotFails_24() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(0); + request.userIndex = 0U; + request.userName.SetNull(); + request.userUniqueId.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + request.credentialRule.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_24(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_24(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_24(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_24() { ThrowSuccessResponse(); } + + CHIP_ERROR TestUserCreationInTheOutOfBoundsSlotFails_25() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(0); + request.userIndex = static_cast(NumberOfTotalUsersSupported + 1); + request.userName.SetNull(); + request.userUniqueId.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + request.credentialRule.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_25(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_25(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_25(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_25() { ThrowSuccessResponse(); } + + CHIP_ERROR TestClearFirstUser_26() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_26(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_26(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_26(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_26() { NextTest(); } + + CHIP_ERROR TestReadClearedUserAndVerifyItIsAvailable_27() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_27(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_27(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_27(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_27( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNull("userName", userName)); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNull("userStatus", userStatus)); + + VerifyOrReturn(CheckValueNull("userType", userType)); + + VerifyOrReturn(CheckValueNull("credentialRule", credentialRule)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNull("creatorFabricIndex", creatorFabricIndex)); + + VerifyOrReturn(CheckValueNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewUserInTheClearedSlot_28() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetUser::Type; + + RequestType request; + request.operationType = static_cast(0); + request.userIndex = 1U; + request.userName.SetNull(); + request.userUniqueId.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + request.credentialRule.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_28(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_28(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_28(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_28() { NextTest(); } + + CHIP_ERROR TestReadTheUserInThePreviouslyClearedSlotAndVerifyItsFields_29() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_29(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_29(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_29(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_29( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("", 0))); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 0)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestClearUserWithIndex0Fails_30() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearUser::Type; + + RequestType request; + request.userIndex = 0U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_30(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_30(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_30(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_30() { ThrowSuccessResponse(); } + + CHIP_ERROR TestClearUserWithOutOfBoundsIndexFails_31() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearUser::Type; + + RequestType request; + request.userIndex = static_cast(NumberOfTotalUsersSupported + 1); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_31(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_31(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_31(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_31() { ThrowSuccessResponse(); } + + CHIP_ERROR TestClearAllUsers_32() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearUser::Type; + + RequestType request; + request.userIndex = 65534U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_32(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_32(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_32(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_32() { NextTest(); } + + CHIP_ERROR TestReadFirstClearedUserAndVerifyItIsAvailable_33() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 2U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_33(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_33(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_33(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_33( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 2U)); + + VerifyOrReturn(CheckValueNull("userName", userName)); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNull("userStatus", userStatus)); + + VerifyOrReturn(CheckValueNull("userType", userType)); + + VerifyOrReturn(CheckValueNull("credentialRule", credentialRule)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNull("creatorFabricIndex", creatorFabricIndex)); + + VerifyOrReturn(CheckValueNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestReadLastClearedUserAndVerifyItIsAvailable_34() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = NumberOfTotalUsersSupported; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_34(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_34(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_34(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_34( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, NumberOfTotalUsersSupported)); + + VerifyOrReturn(CheckValueNull("userName", userName)); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNull("userStatus", userStatus)); + + VerifyOrReturn(CheckValueNull("userType", userType)); + + VerifyOrReturn(CheckValueNull("credentialRule", credentialRule)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNull("creatorFabricIndex", creatorFabricIndex)); + + VerifyOrReturn(CheckValueNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + + VerifyOrReturn(CheckValueNull("nextUserIndex", nextUserIndex)); + + NextTest(); + } + + CHIP_ERROR TestGetNumberOfSupportedPinCredentialsAndVerifyDefaultValue_35() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::DoorLockClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_35, OnFailureCallback_35)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_35(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_35(uint16_t numberOfPINUsersSupported) + { + VerifyOrReturn(CheckValue("numberOfPINUsersSupported", numberOfPINUsersSupported, 10U)); + + NumberOfPINUsersSupported = numberOfPINUsersSupported; + NextTest(); + } + + CHIP_ERROR TestCheckThatPinCredentialDoesNotExist_36() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_36(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_36(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_36(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_36(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, false)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestReadingPinCredentialWithIndex0Fails_37() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 0U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_37(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_37(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_37(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_37(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + ThrowSuccessResponse(); + } + + CHIP_ERROR TestReadingPinCredentialWithOutOfBoundsIndexFails_38() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = static_cast(NumberOfPINUsersSupported + 1); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_38(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_38(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_38(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_38(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + ThrowSuccessResponse(); + } + + CHIP_ERROR TestCreateNewPinCredentialAndUser_39() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 1U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("000000garbage: not in length on purpose"), 6); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_39(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_39(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_39(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_39(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValueNonNull("userIndex", userIndex)); + VerifyOrReturn(CheckValue("userIndex.Value()", userIndex.Value(), 1U)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestVerifyCreatedUser_40() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_40(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_40(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_40(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_40( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("", 0))); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentials", credentials)); + { + auto iter_1 = credentials.Value().begin(); + VerifyOrReturn(CheckNextListItemDecodes("credentials.Value()", iter_1, 0)); + VerifyOrReturn(CheckValue("credentials.Value()[0].credentialType", iter_1.GetValue().credentialType, 1)); + VerifyOrReturn(CheckValue("credentials.Value()[0].credentialIndex", iter_1.GetValue().credentialIndex, 1U)); + VerifyOrReturn(CheckNoMoreListItems("credentials.Value()", iter_1, 1)); + } + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestVerifyCreatedPinCredential_41() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_41(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_41(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_41(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_41(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, true)); + + VerifyOrReturn(CheckValueNonNull("userIndex", userIndex)); + VerifyOrReturn(CheckValue("userIndex.Value()", userIndex.Value(), 1U)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewPinCredentialAndUserWithIndex0Fails_42() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 0U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123456garbage: not in length on purpose"), 6); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_42(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_42(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_42(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_42(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 133)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewPinCredentialAndUserWithOutOfBoundsIndexFails_43() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = static_cast(NumberOfPINUsersSupported + 1); + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123456garbage: not in length on purpose"), 6); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_43(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_43(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_43(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_43(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 133)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNull("nextCredentialIndex", nextCredentialIndex)); + + NextTest(); + } + + CHIP_ERROR TestGetNumberOfSupportedRfidCredentialsAndVerifyDefaultValue_44() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::DoorLockClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_44, OnFailureCallback_44)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_44(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_44(uint16_t numberOfRFIDUsersSupported) + { + VerifyOrReturn(CheckValue("numberOfRFIDUsersSupported", numberOfRFIDUsersSupported, 10U)); + + NumberOfRFIDUsersSupported = numberOfRFIDUsersSupported; + NextTest(); + } + + CHIP_ERROR TestReadingRfidCredentialWithIndex0Fails_45() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 0U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_45(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_45(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_45(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_45(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + ThrowSuccessResponse(); + } + + CHIP_ERROR TestReadingRfidCredentialWithOutOfBoundsIndexFails_46() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = static_cast(NumberOfRFIDUsersSupported + 1); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_46(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_46(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_46(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_46(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + ThrowSuccessResponse(); + } + + CHIP_ERROR TestCheckThatRfidCredentialDoesNotExist_47() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 2U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_47(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_47(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_47(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_47(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, false)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewRfidCredentialAndAddItToExistingUser_48() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 2U; + + request.credentialData = + chip::ByteSpan(chip::Uint8::from_const_char("rfid_data_123456garbage: not in length on purpose"), 16); + request.userIndex.SetNonNull(); + request.userIndex.Value() = 1U; + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_48(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_48(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_48(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_48(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestVerifyModifiedUser_49() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_49(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_49(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_49(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_49( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("", 0))); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentials", credentials)); + { + auto iter_1 = credentials.Value().begin(); + VerifyOrReturn(CheckNextListItemDecodes("credentials.Value()", iter_1, 0)); + VerifyOrReturn(CheckValue("credentials.Value()[0].credentialType", iter_1.GetValue().credentialType, 1)); + VerifyOrReturn(CheckValue("credentials.Value()[0].credentialIndex", iter_1.GetValue().credentialIndex, 1U)); + VerifyOrReturn(CheckNextListItemDecodes("credentials.Value()", iter_1, 1)); + VerifyOrReturn(CheckValue("credentials.Value()[1].credentialType", iter_1.GetValue().credentialType, 2)); + VerifyOrReturn(CheckValue("credentials.Value()[1].credentialIndex", iter_1.GetValue().credentialIndex, 2U)); + VerifyOrReturn(CheckNoMoreListItems("credentials.Value()", iter_1, 2)); + } + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestVerifyCreatedCredential_50() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 2U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_50(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_50(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_50(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_50(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, true)); + + VerifyOrReturn(CheckValueNonNull("userIndex", userIndex)); + VerifyOrReturn(CheckValue("userIndex.Value()", userIndex.Value(), 1U)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewRfidCredentialAndUserWithIndex0Fails_51() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 0U; + + request.credentialData = + chip::ByteSpan(chip::Uint8::from_const_char("new_rfid_data_fieldgarbage: not in length on purpose"), 19); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_51(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_51(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_51(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_51(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 133)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewRfidCredentialAndUserWithOutOfBoundsIndexFails_52() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = static_cast(NumberOfRFIDUsersSupported + 1); + + request.credentialData = + chip::ByteSpan(chip::Uint8::from_const_char("new_rfid_data_fieldgarbage: not in length on purpose"), 19); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_52(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_52(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_52(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_52(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 133)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNull("nextCredentialIndex", nextCredentialIndex)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewPinCredentialAndTryToAddItToExistingUser_53() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 3U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123465garbage: not in length on purpose"), 6); + request.userIndex.SetNonNull(); + request.userIndex.Value() = 1U; + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_53(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_53(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_53(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_53(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 3)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 4U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewCredentialAndTryToAddItTo0User_54() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 3U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123465garbage: not in length on purpose"), 6); + request.userIndex.SetNonNull(); + request.userIndex.Value() = 0U; + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_54(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_54(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_54(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_54(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 133)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 4U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewCredentialAndTryToAddItToOutOfBoundsUser_55() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 3U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123465garbage: not in length on purpose"), 6); + request.userIndex.SetNonNull(); + request.userIndex.Value() = static_cast(NumberOfTotalUsersSupported + 1); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_55(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_55(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_55(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_55(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 133)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 4U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewPinWithTooShortData_56() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 3U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("12345garbage: not in length on purpose"), 5); + request.userIndex.SetNonNull(); + request.userIndex.Value() = 0U; + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_56(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_56(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_56(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_56(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 133)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 4U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewPinWithTooLongData_57() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 3U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123456789garbage: not in length on purpose"), 9); + request.userIndex.SetNonNull(); + request.userIndex.Value() = 0U; + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_57(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_57(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_57(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_57(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 133)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 4U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewRfidWithTooShortData_58() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 3U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("rfid_datagarbage: not in length on purpose"), 9); + request.userIndex.SetNonNull(); + request.userIndex.Value() = 0U; + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_58(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_58(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_58(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_58(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 133)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 4U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewPinWithProgrammingUserTypeFails_59() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 3U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123456garbage: not in length on purpose"), 6); + request.userIndex.SetNonNull(); + request.userIndex.Value() = 0U; + request.userStatus.SetNull(); + request.userType.SetNonNull(); + request.userType.Value() = static_cast(3); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_59(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_59(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_59(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_59(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 133)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 4U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewRfidWithTooShortData_60() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 3U; + + request.credentialData = chip::ByteSpan( + chip::Uint8::from_const_char("very_long_rfid_data_to_test_boundariesgarbage: not in length on purpose"), 38); + request.userIndex.SetNonNull(); + request.userIndex.Value() = 0U; + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_60(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_60(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_60(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_60(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 133)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 4U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewPinCredentialWithDataTheWouldCauseDuplicate_61() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 4U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("000000garbage: not in length on purpose"), 6); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_61(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_61(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_61(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_61(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 2)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 5U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewRfidCredentialWithDataTheWouldCauseDuplicate_62() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 4U; + + request.credentialData = + chip::ByteSpan(chip::Uint8::from_const_char("rfid_data_123456garbage: not in length on purpose"), 16); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_62(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_62(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_62(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_62(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 2)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 5U)); + + NextTest(); + } + + CHIP_ERROR TestModifyCredentialDataOfExistingPinCredential_63() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(2); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 1U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123456garbage: not in length on purpose"), 6); + request.userIndex.SetNonNull(); + request.userIndex.Value() = 1U; + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_63(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_63(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_63(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_63(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestVerifyThatCredentialWasChangedByCreatingNewCredentialWithOldData_64() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 3U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("000000garbage: not in length on purpose"), 6); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_64(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_64(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_64(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_64(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValueNonNull("userIndex", userIndex)); + VerifyOrReturn(CheckValue("userIndex.Value()", userIndex.Value(), 2U)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 4U)); + + NextTest(); + } + + CHIP_ERROR TestVerifyThatCredentialWasChangedByCreatingNewCredentialWithNewData_65() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 4U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123456garbage: not in length on purpose"), 6); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_65(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_65(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_65(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_65(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 2)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 5U)); + + NextTest(); + } + + CHIP_ERROR TestClearFirstPinCredential_66() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearCredential::Type; + + RequestType request; + request.credential.SetNonNull(); + + request.credential.Value().credentialType = static_cast(1); + request.credential.Value().credentialIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_66(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_66(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_66(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_66() { NextTest(); } + + CHIP_ERROR TestReadBackTheCredentialAndMakeSureItIsDeleted_67() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_67(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_67(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_67(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_67(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, false)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 4U)); + + NextTest(); + } + + CHIP_ERROR TestReadTheUserBackAndMakeSurePinCredentialIsDeleted_68() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_68(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_68(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_68(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_68( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("", 0))); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentials", credentials)); + { + auto iter_1 = credentials.Value().begin(); + VerifyOrReturn(CheckNextListItemDecodes("credentials.Value()", iter_1, 0)); + VerifyOrReturn(CheckValue("credentials.Value()[0].credentialType", iter_1.GetValue().credentialType, 2)); + VerifyOrReturn(CheckValue("credentials.Value()[0].credentialIndex", iter_1.GetValue().credentialIndex, 2U)); + VerifyOrReturn(CheckNoMoreListItems("credentials.Value()", iter_1, 1)); + } + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestClearTheSecondPinCredential_69() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearCredential::Type; + + RequestType request; + request.credential.SetNonNull(); + + request.credential.Value().credentialType = static_cast(1); + request.credential.Value().credentialIndex = 3U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_69(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_69(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_69(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_69() { NextTest(); } + + CHIP_ERROR TestReadBackTheCredentialAndMakeSureItIsDeleted_70() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 3U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_70(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_70(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_70(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_70(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, false)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 4U)); + + NextTest(); + } + + CHIP_ERROR TestReadTheUserBackAndMakeSureRelatedUserIsDeleted_71() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 2U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_71(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_71(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_71(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_71( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 2U)); + + VerifyOrReturn(CheckValueNull("userName", userName)); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNull("userStatus", userStatus)); + + VerifyOrReturn(CheckValueNull("userType", userType)); + + VerifyOrReturn(CheckValueNull("credentialRule", credentialRule)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNull("creatorFabricIndex", creatorFabricIndex)); + + VerifyOrReturn(CheckValueNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewRfidCredentialWithUser_72() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 1U; + + request.credentialData = + chip::ByteSpan(chip::Uint8::from_const_char("rfid_data_12345garbage: not in length on purpose"), 15); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_72(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_72(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_72(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_72(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValueNonNull("userIndex", userIndex)); + VerifyOrReturn(CheckValue("userIndex.Value()", userIndex.Value(), 2U)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestClearAllTheRfidCredentials_73() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearCredential::Type; + + RequestType request; + request.credential.SetNonNull(); + + request.credential.Value().credentialType = static_cast(2); + request.credential.Value().credentialIndex = 65534U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_73(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_73(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_73(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_73() { NextTest(); } + + CHIP_ERROR TestReadBackTheFistRfidCredentialAndMakeSureItIsDeleted_74() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_74(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_74(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_74(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_74(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, false)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestReadBackTheSecondRfidCredentialAndMakeSureItIsDeleted_75() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 2U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_75(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_75(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_75(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_75(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, false)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestReadTheUserRelatedWithFirstRfidBackAndMakeSureItIsDeleted_76() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_76(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_76(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_76(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_76( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNull("userName", userName)); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNull("userStatus", userStatus)); + + VerifyOrReturn(CheckValueNull("userType", userType)); + + VerifyOrReturn(CheckValueNull("credentialRule", credentialRule)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNull("creatorFabricIndex", creatorFabricIndex)); + + VerifyOrReturn(CheckValueNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestReadTheUserRelatedWithSecondRfidBackAndMakeSureItIsDeleted_77() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 2U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_77(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_77(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_77(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_77( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 2U)); + + VerifyOrReturn(CheckValueNull("userName", userName)); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNull("userStatus", userStatus)); + + VerifyOrReturn(CheckValueNull("userType", userType)); + + VerifyOrReturn(CheckValueNull("credentialRule", credentialRule)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNull("creatorFabricIndex", creatorFabricIndex)); + + VerifyOrReturn(CheckValueNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewPinCredentialWithUser_78() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 1U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123456garbage: not in length on purpose"), 6); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_78(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_78(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_78(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_78(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValueNonNull("userIndex", userIndex)); + VerifyOrReturn(CheckValue("userIndex.Value()", userIndex.Value(), 1U)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewRfidCredentialWithUser_79() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 2U; + + request.credentialData = + chip::ByteSpan(chip::Uint8::from_const_char("rfid_data_1234garbage: not in length on purpose"), 14); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_79(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_79(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_79(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_79(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValueNonNull("userIndex", userIndex)); + VerifyOrReturn(CheckValue("userIndex.Value()", userIndex.Value(), 2U)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestCreateAnotherRfidCredentialWithUser_80() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 6U; + + request.credentialData = + chip::ByteSpan(chip::Uint8::from_const_char("rfid_data_9876garbage: not in length on purpose"), 14); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_80(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_80(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_80(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_80(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValueNonNull("userIndex", userIndex)); + VerifyOrReturn(CheckValue("userIndex.Value()", userIndex.Value(), 3U)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 7U)); + + NextTest(); + } + + CHIP_ERROR TestClearAllTheCredentials_81() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearCredential::Type; + + RequestType request; + request.credential.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_81(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_81(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_81(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_81() { NextTest(); } + + CHIP_ERROR TestReadBackTheFirstPinCredentialAndMakeSureItIsDeleted_82() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_82(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_82(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_82(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_82(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, false)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestReadBackTheFirstRfidCredentialAndMakeSureItIsDeleted_83() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(2); + request.credential.credentialIndex = 2U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_83(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_83(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_83(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_83(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, false)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestReadBackTheSecondPinCredentialAndMakeSureItIsDeleted_84() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 6U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_84(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_84(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_84(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_84(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, false)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 7U)); + + NextTest(); + } + + CHIP_ERROR TestReadTheUserRelatedWithFirstPinBackAndMakeSureItIsDeleted_85() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_85(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_85(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_85(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_85( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNull("userName", userName)); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNull("userStatus", userStatus)); + + VerifyOrReturn(CheckValueNull("userType", userType)); + + VerifyOrReturn(CheckValueNull("credentialRule", credentialRule)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNull("creatorFabricIndex", creatorFabricIndex)); + + VerifyOrReturn(CheckValueNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestReadTheUserRelatedWithFirstRfidBackAndMakeSureItIsDeleted_86() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 2U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_86(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_86(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_86(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_86( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 2U)); + + VerifyOrReturn(CheckValueNull("userName", userName)); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNull("userStatus", userStatus)); + + VerifyOrReturn(CheckValueNull("userType", userType)); + + VerifyOrReturn(CheckValueNull("credentialRule", credentialRule)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNull("creatorFabricIndex", creatorFabricIndex)); + + VerifyOrReturn(CheckValueNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 3U)); + + NextTest(); + } + + CHIP_ERROR TestReadTheUserRelatedWithSecondPinBackAndMakeSureItIsDeleted_87() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 3U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_87(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_87(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_87(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_87( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 3U)); + + VerifyOrReturn(CheckValueNull("userName", userName)); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNull("userStatus", userStatus)); + + VerifyOrReturn(CheckValueNull("userType", userType)); + + VerifyOrReturn(CheckValueNull("credentialRule", credentialRule)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNull("creatorFabricIndex", creatorFabricIndex)); + + VerifyOrReturn(CheckValueNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 4U)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewProgrammingPinCredentialWithInvalidIndex_88() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(0); + request.credential.credentialIndex = 1U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123456garbage: not in length on purpose"), 6); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_88(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_88(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_88(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_88(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 133)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNull("nextCredentialIndex", nextCredentialIndex)); + + NextTest(); + } + + CHIP_ERROR TestCreateNewProgrammingPinCredentialWithValidIndex_89() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(0); + request.credential.credentialIndex = 0U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123456garbage: not in length on purpose"), 6); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_89(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_89(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_89(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_89(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValueNonNull("userIndex", userIndex)); + VerifyOrReturn(CheckValue("userIndex.Value()", userIndex.Value(), 1U)); + + VerifyOrReturn(CheckValueNull("nextCredentialIndex", nextCredentialIndex)); + + NextTest(); + } + + CHIP_ERROR TestVerifyCreatedUser_90() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_90(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, data.lastModifiedFabricIndex, + data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_90(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_90(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_90( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNonNull("userName", userName)); + VerifyOrReturn(CheckValueAsString("userName.Value()", userName.Value(), chip::CharSpan("", 0))); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNonNull("userStatus", userStatus)); + VerifyOrReturn(CheckValue("userStatus.Value()", userStatus.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("userType", userType)); + VerifyOrReturn(CheckValue("userType.Value()", userType.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentialRule", credentialRule)); + VerifyOrReturn(CheckValue("credentialRule.Value()", credentialRule.Value(), 0)); + + VerifyOrReturn(CheckValueNonNull("credentials", credentials)); + { + auto iter_1 = credentials.Value().begin(); + VerifyOrReturn(CheckNextListItemDecodes("credentials.Value()", iter_1, 0)); + VerifyOrReturn(CheckValue("credentials.Value()[0].credentialType", iter_1.GetValue().credentialType, 0)); + VerifyOrReturn(CheckValue("credentials.Value()[0].credentialIndex", iter_1.GetValue().credentialIndex, 0U)); + VerifyOrReturn(CheckNoMoreListItems("credentials.Value()", iter_1, 1)); + } + + VerifyOrReturn(CheckValueNonNull("creatorFabricIndex", creatorFabricIndex)); + VerifyOrReturn(CheckValue("creatorFabricIndex.Value()", creatorFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + VerifyOrReturn(CheckValue("lastModifiedFabricIndex.Value()", lastModifiedFabricIndex.Value(), 1)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestVerifyCreatedProgrammingPinCredential_91() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(0); + request.credential.credentialIndex = 0U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_91(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_91(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_91(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_91(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, true)); + + VerifyOrReturn(CheckValueNonNull("userIndex", userIndex)); + VerifyOrReturn(CheckValue("userIndex.Value()", userIndex.Value(), 1U)); + + VerifyOrReturn(CheckValueNull("nextCredentialIndex", nextCredentialIndex)); + + NextTest(); + } + + CHIP_ERROR TestModifyTheProgrammingPinCredential_92() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(2); + + request.credential.credentialType = static_cast(0); + request.credential.credentialIndex = 0U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("654321garbage: not in length on purpose"), 6); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_92(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_92(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_92(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_92(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNull("nextCredentialIndex", nextCredentialIndex)); + + NextTest(); + } + + CHIP_ERROR TestClearingProgrammingPinFails_93() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearCredential::Type; + + RequestType request; + request.credential.SetNonNull(); + + request.credential.Value().credentialType = static_cast(0); + request.credential.Value().credentialIndex = 0U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_93(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_93(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_93(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_93() { ThrowSuccessResponse(); } + + CHIP_ERROR TestClearingProgrammingPinWithInvalidIndexFails_94() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearCredential::Type; + + RequestType request; + request.credential.SetNonNull(); + + request.credential.Value().credentialType = static_cast(0); + request.credential.Value().credentialIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_94(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_94(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_94(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_94() { ThrowSuccessResponse(); } + + CHIP_ERROR TestClearingPinCredentialWithZeroIndexFails_95() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearCredential::Type; + + RequestType request; + request.credential.SetNonNull(); + + request.credential.Value().credentialType = static_cast(1); + request.credential.Value().credentialIndex = 0U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_95(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_95(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_95(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_95() { ThrowSuccessResponse(); } + + CHIP_ERROR TestClearingPinCredentialWithOutOfBoundIndexFails_96() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearCredential::Type; + + RequestType request; + request.credential.SetNonNull(); + + request.credential.Value().credentialType = static_cast(1); + request.credential.Value().credentialIndex = static_cast(NumberOfPINUsersSupported + 1); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_96(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_96(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_96(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_96() { ThrowSuccessResponse(); } + + CHIP_ERROR TestClearingRfidCredentialWithZeroIndexFails_97() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearCredential::Type; + + RequestType request; + request.credential.SetNonNull(); + + request.credential.Value().credentialType = static_cast(2); + request.credential.Value().credentialIndex = 0U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_97(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_97(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_97(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_97() { ThrowSuccessResponse(); } + + CHIP_ERROR TestClearingRfidCredentialWithOutOfBoundIndexFails_98() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearCredential::Type; + + RequestType request; + request.credential.SetNonNull(); + + request.credential.Value().credentialType = static_cast(2); + request.credential.Value().credentialIndex = static_cast(NumberOfRFIDUsersSupported + 1); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_98(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_98(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_98(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + } + + void OnSuccessResponse_98() { ThrowSuccessResponse(); } + + CHIP_ERROR TestClearTheProgrammingPinUser_99() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_99(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_99(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_99(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_99() { NextTest(); } + + CHIP_ERROR TestMakeSureProgrammingPinUserIsDeleted_100() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetUser::Type; + + RequestType request; + request.userIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_100(data.userIndex, data.userName, data.userUniqueId, data.userStatus, data.userType, + data.credentialRule, data.credentials, data.creatorFabricIndex, + data.lastModifiedFabricIndex, data.nextUserIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_100(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_100(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_100( + uint16_t userIndex, const chip::app::DataModel::Nullable & userName, + const chip::app::DataModel::Nullable & userUniqueId, + const chip::app::DataModel::Nullable & userStatus, + const chip::app::DataModel::Nullable & userType, + const chip::app::DataModel::Nullable & credentialRule, + const chip::app::DataModel::Nullable< + chip::app::DataModel::DecodableList> & credentials, + const chip::app::DataModel::Nullable & creatorFabricIndex, + const chip::app::DataModel::Nullable & lastModifiedFabricIndex, + const chip::app::DataModel::Nullable & nextUserIndex) + { + VerifyOrReturn(CheckValue("userIndex", userIndex, 1U)); + + VerifyOrReturn(CheckValueNull("userName", userName)); + + VerifyOrReturn(CheckValueNull("userUniqueId", userUniqueId)); + + VerifyOrReturn(CheckValueNull("userStatus", userStatus)); + + VerifyOrReturn(CheckValueNull("userType", userType)); + + VerifyOrReturn(CheckValueNull("credentialRule", credentialRule)); + + VerifyOrReturn(CheckValueNull("credentials", credentials)); + + VerifyOrReturn(CheckValueNull("creatorFabricIndex", creatorFabricIndex)); + + VerifyOrReturn(CheckValueNull("lastModifiedFabricIndex", lastModifiedFabricIndex)); + + VerifyOrReturn(CheckValueNonNull("nextUserIndex", nextUserIndex)); + VerifyOrReturn(CheckValue("nextUserIndex.Value()", nextUserIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestMakeSureProgrammingPinCredentialIsDeleted_101() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type; + + RequestType request; + + request.credential.credentialType = static_cast(0); + request.credential.credentialIndex = 0U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context)) + ->OnSuccessResponse_101(data.credentialExists, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_101(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_101(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_101(bool credentialExists, const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("credentialExists", credentialExists, false)); + + VerifyOrReturn(CheckValueNull("userIndex", userIndex)); + + VerifyOrReturn(CheckValueNull("nextCredentialIndex", nextCredentialIndex)); + + NextTest(); + } +}; + +class DL_LockUnlock : public TestCommand +{ +public: + DL_LockUnlock() : TestCommand("DL_LockUnlock"), mTestIndex(0) + { + AddArgument("cluster", &mCluster); + AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); + } + + ~DL_LockUnlock() {} + + /////////// TestCommand Interface ///////// + void NextTest() override + { + CHIP_ERROR err = CHIP_NO_ERROR; + + if (0 == mTestIndex) + { + ChipLogProgress(chipTool, " **** Test Start: DL_LockUnlock\n"); + } + + if (mTestCount == mTestIndex) + { + ChipLogProgress(chipTool, " **** Test Complete: DL_LockUnlock\n"); + SetCommandExitStatus(CHIP_NO_ERROR); + return; + } + + Wait(); + + // Ensure we increment mTestIndex before we start running the relevant + // command. That way if we lose the timeslice after we send the message + // but before our function call returns, we won't end up with an + // incorrect mTestIndex value observed when we get the response. + switch (mTestIndex++) + { + case 0: + ChipLogProgress(chipTool, " ***** Test Step 0 : Wait for the commissioned device to be retrieved\n"); + err = TestWaitForTheCommissionedDeviceToBeRetrieved_0(); + break; + case 1: + ChipLogProgress(chipTool, " ***** Test Step 1 : Create new PIN credential and lock/unlock user\n"); + err = TestCreateNewPinCredentialAndLockUnlockUser_1(); + break; + case 2: + ChipLogProgress(chipTool, " ***** Test Step 2 : Try to unlock the door with invalid PIN\n"); + err = TestTryToUnlockTheDoorWithInvalidPin_2(); + break; + case 3: + ChipLogProgress(chipTool, " ***** Test Step 3 : Verify that lock state attribute value is set to Locked\n"); + err = TestVerifyThatLockStateAttributeValueIsSetToLocked_3(); + break; + case 4: + ChipLogProgress(chipTool, " ***** Test Step 4 : Try to unlock the door with valid PIN\n"); + err = TestTryToUnlockTheDoorWithValidPin_4(); + break; + case 5: + ChipLogProgress(chipTool, " ***** Test Step 5 : Verify that lock state attribute value is set to Unlocked\n"); + err = TestVerifyThatLockStateAttributeValueIsSetToUnlocked_5(); + break; + case 6: + ChipLogProgress(chipTool, " ***** Test Step 6 : Try to lock the door with invalid PIN\n"); + err = TestTryToLockTheDoorWithInvalidPin_6(); + break; + case 7: + ChipLogProgress(chipTool, " ***** Test Step 7 : Verify that lock state attribute value is set to Unlocked\n"); + err = TestVerifyThatLockStateAttributeValueIsSetToUnlocked_7(); + break; + case 8: + ChipLogProgress(chipTool, " ***** Test Step 8 : Try to unlock the door with valid PIN\n"); + err = TestTryToUnlockTheDoorWithValidPin_8(); + break; + case 9: + ChipLogProgress(chipTool, " ***** Test Step 9 : Verify that lock state attribute value is set to Locked\n"); + err = TestVerifyThatLockStateAttributeValueIsSetToLocked_9(); + break; + case 10: + ChipLogProgress(chipTool, " ***** Test Step 10 : Clean the created credential\n"); + err = TestCleanTheCreatedCredential_10(); + break; + } + + if (CHIP_NO_ERROR != err) + { + ChipLogError(chipTool, " ***** Test Failure: %s\n", chip::ErrorStr(err)); + SetCommandExitStatus(err); + } + } + +private: + std::atomic_uint16_t mTestIndex; + const uint16_t mTestCount = 11; + + chip::Optional mCluster; + chip::Optional mEndpoint; + + static void OnFailureCallback_3(void * context, CHIP_ERROR error) + { + (static_cast(context))->OnFailureResponse_3(error); + } + + static void OnSuccessCallback_3(void * context, + const chip::app::DataModel::Nullable & lockState) + { + (static_cast(context))->OnSuccessResponse_3(lockState); + } + + static void OnFailureCallback_5(void * context, CHIP_ERROR error) + { + (static_cast(context))->OnFailureResponse_5(error); + } + + static void OnSuccessCallback_5(void * context, + const chip::app::DataModel::Nullable & lockState) + { + (static_cast(context))->OnSuccessResponse_5(lockState); + } + + static void OnFailureCallback_7(void * context, CHIP_ERROR error) + { + (static_cast(context))->OnFailureResponse_7(error); + } + + static void OnSuccessCallback_7(void * context, + const chip::app::DataModel::Nullable & lockState) + { + (static_cast(context))->OnSuccessResponse_7(lockState); + } + + static void OnFailureCallback_9(void * context, CHIP_ERROR error) + { + (static_cast(context))->OnFailureResponse_9(error); + } + + static void OnSuccessCallback_9(void * context, + const chip::app::DataModel::Nullable & lockState) + { + (static_cast(context))->OnSuccessResponse_9(lockState); + } + + // + // Tests methods + // + + CHIP_ERROR TestWaitForTheCommissionedDeviceToBeRetrieved_0() + { + SetIdentity(kIdentityAlpha); + return WaitForCommissionee(); + } + + CHIP_ERROR TestCreateNewPinCredentialAndLockUnlockUser_1() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::SetCredential::Type; + + RequestType request; + request.operationType = static_cast(0); + + request.credential.credentialType = static_cast(1); + request.credential.credentialIndex = 1U; + + request.credentialData = chip::ByteSpan(chip::Uint8::from_const_char("123456garbage: not in length on purpose"), 6); + request.userIndex.SetNull(); + request.userStatus.SetNull(); + request.userType.SetNull(); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_1(data.status, data.userIndex, data.nextCredentialIndex); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_1(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_1(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_1(chip::app::Clusters::DoorLock::DlStatus status, + const chip::app::DataModel::Nullable & userIndex, + const chip::app::DataModel::Nullable & nextCredentialIndex) + { + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValueNonNull("userIndex", userIndex)); + VerifyOrReturn(CheckValue("userIndex.Value()", userIndex.Value(), 1U)); + + VerifyOrReturn(CheckValueNonNull("nextCredentialIndex", nextCredentialIndex)); + VerifyOrReturn(CheckValue("nextCredentialIndex.Value()", nextCredentialIndex.Value(), 2U)); + + NextTest(); + } + + CHIP_ERROR TestTryToUnlockTheDoorWithInvalidPin_2() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::UnlockDoor::Type; + + RequestType request; + request.pinCode.Emplace(); + request.pinCode.Value() = chip::ByteSpan(chip::Uint8::from_const_char("000000garbage: not in length on purpose"), 6); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_2(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_2(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_2(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_FAILURE)); + NextTest(); + } + + void OnSuccessResponse_2() { ThrowSuccessResponse(); } + + CHIP_ERROR TestVerifyThatLockStateAttributeValueIsSetToLocked_3() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::DoorLockClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_3, OnFailureCallback_3)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_3(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_3(const chip::app::DataModel::Nullable & lockState) + { + VerifyOrReturn(CheckValueNonNull("lockState", lockState)); + VerifyOrReturn(CheckValue("lockState.Value()", lockState.Value(), 1)); + + NextTest(); + } + + CHIP_ERROR TestTryToUnlockTheDoorWithValidPin_4() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::UnlockDoor::Type; + + RequestType request; + request.pinCode.Emplace(); + request.pinCode.Value() = chip::ByteSpan(chip::Uint8::from_const_char("123456garbage: not in length on purpose"), 6); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_4(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_4(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_4(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_4() { NextTest(); } + + CHIP_ERROR TestVerifyThatLockStateAttributeValueIsSetToUnlocked_5() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::DoorLockClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_5, OnFailureCallback_5)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_5(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_5(const chip::app::DataModel::Nullable & lockState) + { + VerifyOrReturn(CheckValueNonNull("lockState", lockState)); + VerifyOrReturn(CheckValue("lockState.Value()", lockState.Value(), 2)); + + NextTest(); + } + + CHIP_ERROR TestTryToLockTheDoorWithInvalidPin_6() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::LockDoor::Type; + + RequestType request; + request.pinCode.Emplace(); + request.pinCode.Value() = chip::ByteSpan(chip::Uint8::from_const_char("000000garbage: not in length on purpose"), 6); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_6(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_6(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_6(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_FAILURE)); + NextTest(); + } + + void OnSuccessResponse_6() { ThrowSuccessResponse(); } + + CHIP_ERROR TestVerifyThatLockStateAttributeValueIsSetToUnlocked_7() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::DoorLockClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_7, OnFailureCallback_7)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_7(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_7(const chip::app::DataModel::Nullable & lockState) + { + VerifyOrReturn(CheckValueNonNull("lockState", lockState)); + VerifyOrReturn(CheckValue("lockState.Value()", lockState.Value(), 2)); + + NextTest(); + } + + CHIP_ERROR TestTryToUnlockTheDoorWithValidPin_8() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::LockDoor::Type; + + RequestType request; + request.pinCode.Emplace(); + request.pinCode.Value() = chip::ByteSpan(chip::Uint8::from_const_char("123456garbage: not in length on purpose"), 6); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_8(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_8(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_8(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_8() { NextTest(); } + + CHIP_ERROR TestVerifyThatLockStateAttributeValueIsSetToLocked_9() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::DoorLockClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_9, OnFailureCallback_9)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_9(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_9(const chip::app::DataModel::Nullable & lockState) + { + VerifyOrReturn(CheckValueNonNull("lockState", lockState)); + VerifyOrReturn(CheckValue("lockState.Value()", lockState.Value(), 1)); + + NextTest(); + } + + CHIP_ERROR TestCleanTheCreatedCredential_10() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::DoorLock::Commands::ClearCredential::Type; + + RequestType request; + request.credential.SetNonNull(); + + request.credential.Value().credentialType = static_cast(1); + request.credential.Value().credentialIndex = 1U; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_10(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_10(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_10(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_10() { NextTest(); } +}; + void registerCommandsTests(Commands & commands) { const char * clusterName = "Tests"; @@ -75177,6 +80953,8 @@ void registerCommandsTests(Commands & commands) make_unique(), make_unique(), make_unique(), + make_unique(), + make_unique(), }; commands.Register(clusterName, clusterCommands); diff --git a/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp b/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp index 3c00e31c0d586a..c5aefdb5d05581 100644 --- a/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp +++ b/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp @@ -2669,7 +2669,7 @@ CHIP_ERROR DoorLockCluster::LockDoor(Callback::Cancelable * onSuccessCallback, C CHIP_ERROR DoorLockCluster::SetCredential(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t operationType, uint8_t credentialType, uint16_t credentialIndex, - chip::ByteSpan credentialData, uint16_t userIndex, uint8_t userStatus) + chip::ByteSpan credentialData, uint16_t userIndex, uint8_t userStatus, uint8_t userType) { CHIP_ERROR err = CHIP_NO_ERROR; TLV::TLVWriter * writer = nullptr; @@ -2704,6 +2704,8 @@ CHIP_ERROR DoorLockCluster::SetCredential(Callback::Cancelable * onSuccessCallba SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), userIndex)); // userStatus: dlUserStatus SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), userStatus)); + // userType: dlUserType + SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), userType)); SuccessOrExit(err = sender->FinishCommand()); diff --git a/zzz_generated/controller-clusters/zap-generated/CHIPClusters.h b/zzz_generated/controller-clusters/zap-generated/CHIPClusters.h index bd8bccabf73dca..43db038e095240 100644 --- a/zzz_generated/controller-clusters/zap-generated/CHIPClusters.h +++ b/zzz_generated/controller-clusters/zap-generated/CHIPClusters.h @@ -303,7 +303,7 @@ class DLL_EXPORT DoorLockCluster : public ClusterBase CHIP_ERROR LockDoor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan pinCode); CHIP_ERROR SetCredential(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t operationType, uint8_t credentialType, uint16_t credentialIndex, chip::ByteSpan credentialData, - uint16_t userIndex, uint8_t userStatus); + uint16_t userIndex, uint8_t userStatus, uint8_t userType); CHIP_ERROR SetUser(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t operationType, uint16_t userIndex, chip::CharSpan userName, uint32_t userUniqueId, uint8_t userStatus, uint8_t userType, uint8_t credentialRule); diff --git a/zzz_generated/door-lock-app/zap-generated/endpoint_config.h b/zzz_generated/door-lock-app/zap-generated/endpoint_config.h index e2ad3368d49fa9..4abfe2f4556390 100644 --- a/zzz_generated/door-lock-app/zap-generated/endpoint_config.h +++ b/zzz_generated/door-lock-app/zap-generated/endpoint_config.h @@ -309,6 +309,9 @@ \ /* 668 - AutoRelockTime, */ \ 0x00, 0x00, 0x00, 0x60, \ + \ + /* 672 - FeatureMap, */ \ + 0x00, 0x00, 0x01, 0x03, \ } #else // !BIGENDIAN_CPU @@ -597,11 +600,14 @@ \ /* 668 - AutoRelockTime, */ \ 0x60, 0x00, 0x00, 0x00, \ + \ + /* 672 - FeatureMap, */ \ + 0x03, 0x01, 0x00, 0x00, \ } #endif // BIGENDIAN_CPU -#define GENERATED_DEFAULTS_COUNT (82) +#define GENERATED_DEFAULTS_COUNT (83) #define ZAP_TYPE(type) ZCL_##type##_ATTRIBUTE_TYPE #define ZAP_LONG_DEFAULTS_INDEX(index) \ @@ -640,7 +646,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 210 +#define GENERATED_ATTRIBUTE_COUNT 214 #define GENERATED_ATTRIBUTES \ { \ \ @@ -900,8 +906,11 @@ { 0x00000003, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(NULLABLE), ZAP_EMPTY_DEFAULT() }, /* DoorState */ \ { 0x00000011, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(10) }, /* NumberOfTotalUsersSupported */ \ { 0x00000012, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(10) }, /* NumberOfPINUsersSupported */ \ - { 0x00000017, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(6) }, /* MaxPINCodeLength */ \ + { 0x00000013, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(10) }, /* NumberOfRFIDUsersSupported */ \ + { 0x00000017, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(8) }, /* MaxPINCodeLength */ \ { 0x00000018, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(6) }, /* MinPINCodeLength */ \ + { 0x00000019, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(20) }, /* MaxRFIDCodeLength */ \ + { 0x0000001A, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(10) }, /* MinRFIDCodeLength */ \ { 0x0000001B, ZAP_TYPE(BITMAP8), 1, 0, ZAP_SIMPLE_DEFAULT(1) }, /* CredentialRulesSupport */ \ { 0x00000021, ZAP_TYPE(CHAR_STRING), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(665) }, /* Language */ \ { 0x00000023, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(668) }, /* AutoRelockTime */ \ @@ -917,8 +926,9 @@ { 0x00000030, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ ZAP_MIN_MAX_DEFAULTS_INDEX(3) }, /* WrongCodeEntryLimit */ \ { 0x00000031, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ - ZAP_MIN_MAX_DEFAULTS_INDEX(4) }, /* UserCodeTemporaryDisableTime */ \ - { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(3) }, /* ClusterRevision */ \ + ZAP_MIN_MAX_DEFAULTS_INDEX(4) }, /* UserCodeTemporaryDisableTime */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_LONG_DEFAULTS_INDEX(672) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(3) }, /* ClusterRevision */ \ } // This is an array of EmberAfCluster structures. @@ -1017,8 +1027,8 @@ }, /* Endpoint: 1, Cluster: Power Source (server) */ \ { 0x00000101, \ ZAP_ATTRIBUTE_INDEX(191), \ - 19, \ - 29, \ + 23, \ + 37, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION) | \ ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayDoorLockServer }, /* Endpoint: 1, Cluster: Door Lock (server) */ \ @@ -1029,7 +1039,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 18, 1553 }, { ZAP_CLUSTER_INDEX(18), 3, 162 }, \ + { ZAP_CLUSTER_INDEX(0), 18, 1553 }, { ZAP_CLUSTER_INDEX(18), 3, 170 }, \ } // Largest attribute size is needed for various buffers @@ -1039,7 +1049,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (687) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (1715) +#define ATTRIBUTE_MAX_SIZE (1723) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (2)