From 9b916c741c56c59e493b2593153a29cf2ae8c7ef Mon Sep 17 00:00:00 2001 From: Hunsup Jung Date: Mon, 6 Apr 2026 14:46:27 +0900 Subject: [PATCH] Delete guest user when SetYearDaySchedule is failed Signed-off-by: Hunsup Jung --- .../matter-lock/src/new-matter-lock/init.lua | 40 ++++-- .../src/test/test_new_matter_lock.lua | 136 +++++++++++++++++- 2 files changed, 163 insertions(+), 13 deletions(-) diff --git a/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua b/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua index 1e7d461eda..899f364b78 100644 --- a/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua +++ b/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua @@ -1550,6 +1550,19 @@ local function clear_user_response_handler(driver, device, ib, response) delete_aliro_from_table_as_user(device, userIdx) delete_week_schedule_from_table_as_user(device, userIdx) delete_year_schedule_from_table_as_user(device, userIdx) + if cmdName == "defaultSchedule" then + -- Update commandResult + local command_result_info = { + commandName = "addCredential", + userIndex = userIdx, + statusCode = "failure" + } + device:emit_event(capabilities.lockCredentials.commandResult( + command_result_info, {state_change = true, visibility = {displayed = false}} + )) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) + return + end else device.log.warn(string.format("Failed to clear user: %s", status)) end @@ -2418,17 +2431,22 @@ local function set_year_day_schedule_handler(driver, device, ib, response) local cmdName = "addCredential" local credIdx = device:get_field(lock_utils.CRED_INDEX) - -- Update commandResult - local command_result_info = { - commandName = cmdName, - userIndex = userIdx, - credentialIndex = credIdx, - statusCode = status - } - device:emit_event(capabilities.lockCredentials.commandResult( - command_result_info, {state_change = true, visibility = {displayed = false}} - )) - device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) + if status == "success" then + -- Update commandResult + local command_result_info = { + commandName = cmdName, + userIndex = userIdx, + credentialIndex = credIdx, + statusCode = status + } + device:emit_event(capabilities.lockCredentials.commandResult( + command_result_info, {state_change = true, visibility = {displayed = false}} + )) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) + else + local ep = find_default_endpoint(device, clusters.DoorLock.ID) + device:send(DoorLock.server.commands.ClearUser(device, ep, userIdx)) + end return end diff --git a/drivers/SmartThings/matter-lock/src/test/test_new_matter_lock.lua b/drivers/SmartThings/matter-lock/src/test/test_new_matter_lock.lua index 3154e18cbd..bc9f5751c6 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_new_matter_lock.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_new_matter_lock.lua @@ -35,7 +35,7 @@ local mock_device = test.mock_device.build_test_matter_device({ cluster_id = DoorLock.ID, cluster_type = "SERVER", cluster_revision = 1, - feature_map = 0x0181, -- PIN & USR & COTA + feature_map = 0x0591, -- PIN & WDSCH & USR & COTA & YDSCH } }, device_types = { @@ -76,7 +76,7 @@ local function test_init() test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.lock.supportedLockCommands({"lock", "unlock"}, {visibility = {displayed = false}})) ) - mock_device:expect_metadata_update({ profile = "lock-user-pin" }) + mock_device:expect_metadata_update({ profile = "lock-user-pin-schedule" }) mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) end @@ -2100,4 +2100,136 @@ test.register_coroutine_test( } ) +-- mock_device:set_field(lock_utils.COTA_CRED, "654123", {persist = true}) --overwrite random cred for test expectation +test.register_coroutine_test( + "Add Guest User and failure response ", + function() + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockCredentials.ID, + command = "addCredential", + args = {0, "guest", "pin", "654123"} + }, + } + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetCredential( + mock_device, 1, -- endpoint + DoorLock.types.DataOperationTypeEnum.ADD, -- operation_type + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1} + ), -- credential + "654123", -- credential_data + nil, -- user_index + nil, -- user_status + DoorLock.types.UserTypeEnum.SCHEDULE_RESTRICTED_USER -- user_type + ), + } + ) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.client.commands.SetCredentialResponse:build_test_command_response( + mock_device, 1, + DoorLock.types.DlStatus.SUCCESS, -- status + 1, -- user_index + 2 -- next_credential_index + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.users({{userIndex = 1, userType = "guest"}}, {visibility={displayed=false}}) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.credentials( + {{credentialIndex=1, credentialType="pin", userIndex=1}}, {visibility={displayed=false}} + ) + ) + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetYearDaySchedule( + mock_device, 1, -- endpoint + 1, -- year_day_index + 1, -- user_index + 0, -- local_start_time + 0xffffffff -- local_end_time + ), + } + ) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.server.commands.SetYearDaySchedule:build_test_command_response( + mock_device, 1, + DoorLock.types.DlStatus.FAILURE -- status + ), + } + ) + test.socket.matter:__expect_send({ + mock_device.id, + DoorLock.server.commands.ClearUser( + mock_device, 1, + 1 + ) + }) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.server.commands.ClearUser:build_test_command_response( + mock_device, 1 + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.users({}, {visibility={displayed=false}}) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.credentials({}, {visibility={displayed=false}}) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockSchedules.weekDaySchedules({}, {visibility={displayed=false}}) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockSchedules.yearDaySchedules({}, {visibility={displayed=false}}) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.commandResult( + {commandName="addCredential", statusCode="failure", userIndex=1}, {state_change=true, visibility={displayed=false}} + ) + ) + ) + end, + { + min_api_version = 17 + } +) + test.run_registered_tests()