diff --git a/drivers/SmartThings/matter-lock/capabilities/lockAlarm.yml b/drivers/SmartThings/matter-lock/capabilities/lockAlarm.yml deleted file mode 100644 index c10f387dbf..0000000000 --- a/drivers/SmartThings/matter-lock/capabilities/lockAlarm.yml +++ /dev/null @@ -1,27 +0,0 @@ -id: lockAlarm -version: 1 -status: proposed -name: Lock Alarm -ephemeral: false -attributes: - alarm: - schema: - type: object - properties: - value: - type: string - enum: - - clear - - lockFactoryReset - - damaged - - forcedOpeningAttempt - - unableToLockTheDoor - - notClosedForALongTime - - highTemperature - - attemptsExceeded - - physicalImpact - additionalProperties: false - required: - - value - enumCommands: [] -commands: {} \ No newline at end of file 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 7ae8a26e6f..880f33b4ee 100644 --- a/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua +++ b/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua @@ -285,9 +285,29 @@ local function match_profile_switch(driver, device) device:try_update_metadata({profile = profile_name}) end +local function compare_components(synced_components, prev_components) + if #synced_components ~= #prev_components then + return false + end + for _, component in pairs(synced_components) do + if (prev_components[component.id] == nil) or + (#component.capabilities ~= #prev_components[component.id].capabilities) then + return false + end + for _, capability in pairs(component.capabilities) do + if prev_components[component.id][capability.id] == nil then + return false + end + end + end + return true +end + local function info_changed(driver, device, event, args) - if device.profile.id == args.old_st_store.profile.id then - return + if device.profile.id == args.old_st_store.profile.id and + version.api >= 15 and version.rpc >= 9 and -- ignore component check for FW<58 + compare_components(device.profile.components, args.old_st_store.profile.components) then + return end for cap_id, attributes in pairs(subscribed_attributes) do if device:supports_capability_by_id(cap_id) then diff --git a/drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua b/drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua index 41ab9840fb..5c4add0ff5 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua @@ -15,7 +15,6 @@ local test = require "integration_test" test.set_rpc_version(0) local capabilities = require "st.capabilities" -test.add_package_capability("lockAlarm.yml") local t_utils = require "integration_test.utils" local clusters = require "st.matter.clusters" diff --git a/drivers/SmartThings/matter-lock/src/test/test_bridged_matter_lock.lua b/drivers/SmartThings/matter-lock/src/test/test_bridged_matter_lock.lua index 41ecbd612e..0d17cafda6 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_bridged_matter_lock.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_bridged_matter_lock.lua @@ -13,7 +13,6 @@ -- limitations under the License. local test = require "integration_test" -test.add_package_capability("lockAlarm.yml") local t_utils = require "integration_test.utils" local capabilities = require "st.capabilities" local clusters = require "st.matter.clusters" diff --git a/drivers/SmartThings/matter-lock/src/test/test_matter_lock.lua b/drivers/SmartThings/matter-lock/src/test/test_matter_lock.lua index 0123d43239..0db34172d5 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_matter_lock.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_matter_lock.lua @@ -14,7 +14,6 @@ local test = require "integration_test" local capabilities = require "st.capabilities" -test.add_package_capability("lockAlarm.yml") local t_utils = require "integration_test.utils" local clusters = require "st.matter.clusters" diff --git a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_battery.lua b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_battery.lua index 92af7fcabc..8e0be6359d 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_battery.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_battery.lua @@ -13,7 +13,6 @@ -- limitations under the License. local test = require "integration_test" -test.add_package_capability("lockAlarm.yml") local t_utils = require "integration_test.utils" local capabilities = require "st.capabilities" local clusters = require "st.matter.clusters" diff --git a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_batteryLevel.lua b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_batteryLevel.lua index d76556a42d..c53547025c 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_batteryLevel.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_batteryLevel.lua @@ -14,7 +14,6 @@ local test = require "integration_test" local capabilities = require "st.capabilities" -test.add_package_capability("lockAlarm.yml") local t_utils = require "integration_test.utils" local clusters = require "st.matter.clusters" diff --git a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_codes.lua b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_codes.lua index ad68ffbe3b..2960d905c2 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_codes.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_codes.lua @@ -14,7 +14,6 @@ local test = require "integration_test" local capabilities = require "st.capabilities" -test.add_package_capability("lockAlarm.yml") local t_utils = require "integration_test.utils" local json = require "st.json" local clusters = require "st.matter.clusters" diff --git a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_cota.lua b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_cota.lua index f25fe2a19c..57468ef2fc 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_cota.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_cota.lua @@ -14,7 +14,6 @@ local test = require "integration_test" local capabilities = require "st.capabilities" -test.add_package_capability("lockAlarm.yml") local t_utils = require "integration_test.utils" local json = require "st.json" local clusters = require "st.matter.clusters" diff --git a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_modular.lua b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_modular.lua index 5dd117a70e..d6382faa06 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_modular.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_modular.lua @@ -14,7 +14,6 @@ local test = require "integration_test" local capabilities = require "st.capabilities" -test.add_package_capability("lockAlarm.yml") local clusters = require "st.matter.clusters" local t_utils = require "integration_test.utils" local uint32 = require "st.matter.data_types.Uint32" @@ -173,6 +172,45 @@ local mock_device_user_pin_schedule_unlatch = test.mock_device.build_test_matter } }) +local mock_device_modular = test.mock_device.build_test_matter_device({ + profile = t_utils.get_profile_definition("lock-modular-embedded-unlatch.yml"), + manufacturer_info = { + vendor_id = 0x147F, + product_id = 0x0001, + }, + endpoints = { + { + endpoint_id = 0, + clusters = { + { cluster_id = clusters.Basic.ID, cluster_type = "SERVER" }, + }, + device_types = { + { device_type_id = 0x0016, device_type_revision = 1 } -- RootNode + } + }, + { + endpoint_id = 1, + clusters = { + { + cluster_id = DoorLock.ID, + cluster_type = "SERVER", + cluster_revision = 1, + feature_map = 0x1591, -- PIN & USR & COTA & WDSCH & YDSCH & UNLATCH + }, + { + cluster_id = clusters.PowerSource.ID, + cluster_type = "SERVER", + feature_map = 10 + }, + }, + device_types = { + { device_type_id = 0x000A, device_type_revision = 1 } -- Door Lock + } + } + } +}) + + local function test_init() test.disable_startup_messages() -- subscribe request @@ -271,6 +309,27 @@ local function test_init_user_pin_schedule_unlatch() mock_device_user_pin_schedule_unlatch:expect_metadata_update({ provisioning_state = "PROVISIONED" }) end +local function test_init_modular() + test.disable_startup_messages() + -- subscribe request + local subscribe_request = DoorLock.attributes.LockState:subscribe(mock_device_modular) + subscribe_request:merge(DoorLock.attributes.OperatingMode:subscribe(mock_device_modular)) + subscribe_request:merge(DoorLock.events.LockOperation:subscribe(mock_device_modular)) + subscribe_request:merge(DoorLock.events.DoorLockAlarm:subscribe(mock_device_modular)) + -- add test device + test.mock_device.add_test_device(mock_device_modular) + -- actual onboarding flow + test.socket.device_lifecycle:__queue_receive({ mock_device_modular.id, "added" }) + test.socket.capability:__expect_send( + mock_device_modular:generate_test_message("main", capabilities.lockAlarm.alarm.clear({state_change = true})) + ) + test.socket.matter:__expect_send({mock_device_modular.id, clusters.PowerSource.attributes.AttributeList:read()}) + test.socket.device_lifecycle:__queue_receive({ mock_device_modular.id, "init" }) + test.socket.matter:__expect_send({mock_device_modular.id, subscribe_request}) + test.socket.device_lifecycle:__queue_receive({ mock_device_modular.id, "doConfigure" }) + mock_device_modular:expect_metadata_update({ provisioning_state = "PROVISIONED" }) +end + test.set_test_init_function(test_init) test.register_coroutine_test( @@ -517,7 +576,7 @@ test.register_coroutine_test( }) } ) - test.socket.capability:__expect_send( + test.socket.capability:__expect_send( mock_device_user_pin_schedule_unlatch:generate_test_message("main", capabilities.lock.supportedLockValues({"locked", "unlocked", "unlatched", "not fully locked"}, {visibility = {displayed = false}})) ) test.socket.capability:__expect_send( @@ -529,4 +588,67 @@ test.register_coroutine_test( { test_init = test_init_user_pin_schedule_unlatch } ) +test.register_coroutine_test( + "Test modular lock profile update (modular to modular) with user, pin. schedule, and unlatch supported. Ensure infoChanged updates subscription", + function() + test.socket.matter:__queue_receive( + { + mock_device_modular.id, + clusters.PowerSource.attributes.AttributeList:build_test_report_data(mock_device_modular, 1, + { + uint32(0), + uint32(1), + uint32(2), + uint32(12), -- BatPercentRemaining + uint32(14), -- BatChargeLevel + uint32(31), + uint32(65528), + uint32(65529), + uint32(65531), + uint32(65532), + uint32(65533), + }) + } + ) + test.socket.capability:__expect_send( + mock_device_modular:generate_test_message("main", capabilities.lock.supportedLockValues({"locked", "unlocked", "unlatched", "not fully locked"}, {visibility = {displayed = false}})) + ) + test.socket.capability:__expect_send( + mock_device_modular:generate_test_message("main", capabilities.lock.supportedLockCommands({"lock", "unlock", "unlatch"}, {visibility = {displayed = false}})) + ) + mock_device_modular:expect_metadata_update({ profile = "lock-modular-embedded-unlatch", optional_component_capabilities = {{"main", {"lockUsers", "lockCredentials", "lockSchedules", "battery"}}} }) + + local updated_device_profile = t_utils.get_profile_definition("lock-modular-embedded-unlatch.yml", + {enabled_optional_capabilities = {{ "main", {"lockUsers", "lockCredentials", "lockSchedules", "battery"}}, + },} + ) + updated_device_profile.id = "00000000-1111-2222-3333-000000000010" + + test.wait_for_events() + test.socket.device_lifecycle:__queue_receive(mock_device_modular:generate_info_changed({ profile = updated_device_profile })) + + local subscribe_request = DoorLock.attributes.LockState:subscribe(mock_device_modular) + subscribe_request:merge(DoorLock.attributes.OperatingMode:subscribe(mock_device_modular)) + subscribe_request:merge(DoorLock.attributes.NumberOfTotalUsersSupported:subscribe(mock_device_modular)) + subscribe_request:merge(DoorLock.attributes.NumberOfPINUsersSupported:subscribe(mock_device_modular)) + subscribe_request:merge(DoorLock.attributes.MaxPINCodeLength:subscribe(mock_device_modular)) + subscribe_request:merge(DoorLock.attributes.MinPINCodeLength:subscribe(mock_device_modular)) + subscribe_request:merge(DoorLock.attributes.RequirePINforRemoteOperation:subscribe(mock_device_modular)) + subscribe_request:merge(DoorLock.attributes.NumberOfWeekDaySchedulesSupportedPerUser:subscribe(mock_device_modular)) + subscribe_request:merge(DoorLock.attributes.NumberOfYearDaySchedulesSupportedPerUser:subscribe(mock_device_modular)) + subscribe_request:merge(DoorLock.events.LockOperation:subscribe(mock_device_modular)) + subscribe_request:merge(DoorLock.events.DoorLockAlarm:subscribe(mock_device_modular)) + subscribe_request:merge(DoorLock.events.LockUserChange:subscribe(mock_device_modular)) + subscribe_request:merge(clusters.PowerSource.attributes.BatPercentRemaining:subscribe(mock_device_modular)) + test.socket.matter:__expect_send({mock_device_modular.id, subscribe_request}) + test.socket.capability:__expect_send( + mock_device_modular:generate_test_message("main", capabilities.lockAlarm.alarm.clear({state_change = true})) + ) + test.socket.capability:__expect_send( + mock_device_modular:generate_test_message("main", capabilities.lockAlarm.supportedAlarmValues({"unableToLockTheDoor"}, {visibility = {displayed = false}})) + ) + end, + { test_init = test_init_modular } +) + test.run_registered_tests() diff --git a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_unlatch.lua b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_unlatch.lua index 421134ec2a..38154d7b04 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_unlatch.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_unlatch.lua @@ -15,7 +15,6 @@ local test = require "integration_test" test.set_rpc_version(0) local capabilities = require "st.capabilities" -test.add_package_capability("lockAlarm.yml") local t_utils = require "integration_test.utils" local clusters = require "st.matter.clusters" local DoorLock = clusters.DoorLock 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 ab9ac68c88..7d5a59ff32 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 @@ -15,7 +15,6 @@ local test = require "integration_test" test.set_rpc_version(0) local capabilities = require "st.capabilities" -test.add_package_capability("lockAlarm.yml") local t_utils = require "integration_test.utils" local clusters = require "st.matter.clusters" local DoorLock = clusters.DoorLock diff --git a/drivers/SmartThings/matter-lock/src/test/test_new_matter_lock_battery.lua b/drivers/SmartThings/matter-lock/src/test/test_new_matter_lock_battery.lua index d58bfb1bdd..6926f1d62d 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_new_matter_lock_battery.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_new_matter_lock_battery.lua @@ -15,7 +15,6 @@ local test = require "integration_test" test.set_rpc_version(0) local capabilities = require "st.capabilities" -test.add_package_capability("lockAlarm.yml") local clusters = require "st.matter.clusters" local t_utils = require "integration_test.utils" local uint32 = require "st.matter.data_types.Uint32"