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 670b9dc63b..3850d71380 100644 --- a/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua +++ b/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua @@ -1671,6 +1671,7 @@ local function handle_update_credential(driver, device, command) device:set_field(lock_utils.COMMAND_NAME, cmdName, {persist = true}) device:set_field(lock_utils.USER_INDEX, userIdx, {persist = true}) device:set_field(lock_utils.CRED_INDEX, credIdx, {persist = true}) + device:set_field(lock_utils.USER_TYPE, nil, {persist = true}) -- Send command local ep = device:component_to_endpoint(command.component) @@ -1728,7 +1729,7 @@ local function set_pin_response_handler(driver, device, ib, response) -- If User Type is Guest and device support schedule, add default schedule local week_schedule_eps = device:get_endpoints(DoorLock.ID, {feature_bitmap = DoorLock.types.Feature.WEEK_DAY_ACCESS_SCHEDULES}) local year_schedule_eps = device:get_endpoints(DoorLock.ID, {feature_bitmap = DoorLock.types.Feature.YEAR_DAY_ACCESS_SCHEDULES}) - if userType == "guest" and (#week_schedule_eps > 0 or #year_schedule_eps > 0) then + if userType == "guest" and (#week_schedule_eps > 0 or #year_schedule_eps > 0) and cmdName ~= "updateCredential" then local cmdName = "defaultSchedule" local scheduleIdx = 1 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 0b7535223b..492a3c2805 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 @@ -1666,15 +1666,106 @@ test.register_coroutine_test( ) test.register_coroutine_test( - "Handle Update Credential command received from SmartThings.", + "Update Credential for Guest user should not add default schedule again", function() + -- Add Guest user with credential. This sets the USER_TYPE field to "guest". + 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.SUCCESS -- status + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.commandResult( + {commandName="addCredential", credentialIndex=1, statusCode="success", userIndex=1}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + test.wait_for_events() + -- Update the Guest user's credential. The stale "guest" USER_TYPE field must + -- be cleared so the default schedule is not added again on the response. test.socket.capability:__queue_receive( { mock_device.id, { capability = capabilities.lockCredentials.ID, command = "updateCredential", - args = {1, 1, "pin", "654123"} + args = {1, 1, "pin", "111213"} }, } ) @@ -1687,7 +1778,7 @@ test.register_coroutine_test( DoorLock.types.CredentialStruct( {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1} ), -- credential - "654123", -- credential_data + "111213", -- credential_data 1, -- user_index nil, -- user_status nil -- user_type @@ -1706,6 +1797,7 @@ test.register_coroutine_test( ), } ) + -- The commandResult must be emitted without sending SetYearDaySchedule test.socket.capability:__expect_send( mock_device:generate_test_message( "main",