From 30ec193508d3f914c219d3caed5c95cb58c7305b Mon Sep 17 00:00:00 2001 From: Cooper Towns Date: Mon, 30 Mar 2026 13:09:53 -0500 Subject: [PATCH] Revert "Support DPS feature (#2750)" This reverts commit edfba7e5004731486a88d61024e6657df674294b. Also removes the 'IS_MODULAR_PROFILE' field which is no longer needed. --- .../lock-modular-embedded-unlatch.yml | 3 - .../matter-lock/profiles/lock-modular.yml | 3 - .../matter-lock/src/lock_utils.lua | 2 +- .../matter-lock/src/new-matter-lock/init.lua | 64 +--- .../matter-lock/src/test/test_door_state.lua | 278 ------------------ 5 files changed, 2 insertions(+), 348 deletions(-) delete mode 100644 drivers/SmartThings/matter-lock/src/test/test_door_state.lua diff --git a/drivers/SmartThings/matter-lock/profiles/lock-modular-embedded-unlatch.yml b/drivers/SmartThings/matter-lock/profiles/lock-modular-embedded-unlatch.yml index 253374212b..3d9e68b44c 100644 --- a/drivers/SmartThings/matter-lock/profiles/lock-modular-embedded-unlatch.yml +++ b/drivers/SmartThings/matter-lock/profiles/lock-modular-embedded-unlatch.yml @@ -6,9 +6,6 @@ components: version: 1 - id: lockAlarm version: 1 - - id: doorState - version: 1 - optional: true - id: remoteControlStatus version: 1 - id: lockUsers diff --git a/drivers/SmartThings/matter-lock/profiles/lock-modular.yml b/drivers/SmartThings/matter-lock/profiles/lock-modular.yml index 7a664767dd..3a8a53bf70 100644 --- a/drivers/SmartThings/matter-lock/profiles/lock-modular.yml +++ b/drivers/SmartThings/matter-lock/profiles/lock-modular.yml @@ -4,9 +4,6 @@ components: capabilities: - id: lock version: 1 - - id: doorState - version: 1 - optional: true - id: lockAlarm version: 1 - id: remoteControlStatus diff --git a/drivers/SmartThings/matter-lock/src/lock_utils.lua b/drivers/SmartThings/matter-lock/src/lock_utils.lua index 94a0e747c4..ed804363b6 100644 --- a/drivers/SmartThings/matter-lock/src/lock_utils.lua +++ b/drivers/SmartThings/matter-lock/src/lock_utils.lua @@ -45,7 +45,7 @@ local lock_utils = { COMMAND_REQUEST_ID = "commandRequestId", MODULAR_PROFILE_UPDATED = "__MODULAR_PROFILE_UPDATED", ALIRO_READER_CONFIG_UPDATED = "aliroReaderConfigUpdated", - LATEST_DOOR_LOCK_FEATURE_MAP = "latestDoorLockFeatureMap" + LATEST_DOOR_LOCK_FEATURE_MAP = "latestDoorLockFeatureMap", } local capabilities = require "st.capabilities" local json = require "st.json" 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 5720856242..cca7a56b27 100644 --- a/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua +++ b/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua @@ -56,7 +56,6 @@ local battery_support = { local profiling_data = { BATTERY_SUPPORT = "__BATTERY_SUPPORT", - ENABLE_DOOR_STATE = "__ENABLE_DOOR_STATE" } local DoorLockFeatureMapAttr = {ID = 0xFFFC, cluster = DoorLock.ID} @@ -64,9 +63,6 @@ local subscribed_attributes = { [capabilities.lock.ID] = { DoorLock.attributes.LockState }, - [capabilities.doorState.ID] = { - DoorLock.attributes.DoorState - }, [capabilities.remoteControlStatus.ID] = { DoorLock.attributes.OperatingMode }, @@ -133,11 +129,6 @@ end local function device_init(driver, device) device:set_component_to_endpoint_fn(component_to_endpoint) - if #device:get_endpoints(clusters.DoorLock.ID, {feature_bitmap = clusters.DoorLock.types.Feature.DOOR_POSITION_SENSOR}) == 0 then - device:set_field(profiling_data.ENABLE_DOOR_STATE, false, {persist = true}) - else - device:add_subscribed_attribute(clusters.DoorLock.attributes.DoorState) - end if #device:get_endpoints(clusters.PowerSource.ID, {feature_bitmap = clusters.PowerSource.types.PowerSourceFeature.BATTERY}) == 0 then device:set_field(profiling_data.BATTERY_SUPPORT, battery_support.NO_BATTERY, {persist = true}) elseif device:get_field(profiling_data.BATTERY_SUPPORT) == nil then @@ -267,10 +258,6 @@ local function match_profile_modular(driver, device) table.insert(main_component_capabilities, capabilities.battery.ID) end - if device:get_field(profiling_data.ENABLE_DOOR_STATE) then - table.insert(main_component_capabilities, capabilities.doorState.ID) - end - table.insert(enabled_optional_component_capability_pairs, {"main", main_component_capabilities}) if lock_utils.optional_capabilities_list_changed(enabled_optional_component_capability_pairs, device.profile.components) then device:try_update_metadata({profile = modular_profile_name, optional_component_capabilities = enabled_optional_component_capability_pairs}) @@ -378,10 +365,7 @@ local function info_changed(driver, device, event, args) if device:supports_capability_by_id(capabilities.lockAliro.ID) then set_reader_config(device) end - if device:supports_capability(capabilities.doorState) and device:get_latest_state("main", capabilities.doorState.ID, capabilities.doorState.supportedDoorStates.NAME) == nil then - device:emit_event(capabilities.doorState.supportedDoorStates({"open", "closed"}, {visibility = {displayed = false}})) -- open and closed are mandatory - end - if device:supports_capability(capabilities.lockAlarm) and device:get_latest_state("main", capabilities.lockAlarm.ID, capabilities.lockAlarm.supportedAlarmValues.NAME) == nil then + if device:get_latest_state("main", capabilities.lockAlarm.ID, capabilities.lockAlarm.supportedAlarmValues.NAME) == nil then device:emit_event(capabilities.lockAlarm.alarm.clear({state_change = true})) device:emit_event(capabilities.lockAlarm.supportedAlarmValues({"unableToLockTheDoor"}, {visibility = {displayed = false}})) -- lockJammed is mandatory end @@ -443,45 +427,6 @@ local function lock_state_handler(driver, device, ib, response) end) end -local function door_state_handler(driver, device, ib, response) - if ib.data.value == nil then - -- early return on nil data. Also, if ENABLE_DOOR_STATE is unset, set it to false and attempt profile matching. - if device:get_field(profiling_data.ENABLE_DOOR_STATE) == nil then - device:set_field(profiling_data.ENABLE_DOOR_STATE, false, {persist = true}) - match_profile(driver, device) - end - return - elseif device:supports_capability(capabilities.doorState) == false then - -- if a non-nil report comes in and the doorState capability is unsupported, set ENABLE_DOOR_STATE to true and attempt profile matching. - device:set_field(profiling_data.ENABLE_DOOR_STATE, true, {persist = true}) - match_profile(driver, device) - return - end - - local DoorStateEnum = DoorLock.types.DoorStateEnum - local doorState = capabilities.doorState.doorState - local DOOR_STATE_MAP = { - [DoorStateEnum.DOOR_OPEN] = doorState.open, - [DoorStateEnum.DOOR_CLOSED] = doorState.closed, - [DoorStateEnum.DOOR_JAMMED] = doorState.jammed, - [DoorStateEnum.DOOR_FORCED_OPEN] = doorState.forcedOpen, - [DoorStateEnum.DOOR_UNSPECIFIED_ERROR] = doorState.unspecifiedError, - [DoorStateEnum.DOOR_AJAR] = doorState.ajar - } - local door_state = DOOR_STATE_MAP[ib.data.value] or doorState.unspecifiedError -- fallback to unspecifiedError if we receive a value we don't recognize - device:emit_event(door_state()) - - -- add new door states to supportedDoorStates list if not already present. - local supported_door_states = utils.deep_copy(device:get_latest_state("main", capabilities.doorState.ID, capabilities.doorState.supportedDoorStates.NAME) or {}) - for _, state in pairs(supported_door_states) do - if state == door_state.NAME then - return - end - end - table.insert(supported_door_states, door_state.NAME) - device:emit_event(capabilities.doorState.supportedDoorStates(supported_door_states, {visibility = {displayed = false}})) -end - --------------------- -- Operating Modes -- --------------------- @@ -730,12 +675,6 @@ local function door_lock_feature_map_handler(driver, device, ib, response) local feature_map = lock_utils.get_field_for_endpoint(device, lock_utils.LATEST_DOOR_LOCK_FEATURE_MAP, ib.endpoint_id) or nil if feature_map ~= ib.data.value then lock_utils.set_field_for_endpoint(device, lock_utils.LATEST_DOOR_LOCK_FEATURE_MAP, ib.endpoint_id, ib.data.value, { persist = true }) - -- If the DPS feature is changed, check the DoorState value and call the match_profile. - if ib.data.value & clusters.DoorLock.types.Feature.DOOR_POSITION_SENSOR == 0 then - device:set_field(profiling_data.ENABLE_DOOR_STATE, false, {persist = true}) - else - device:set_field(profiling_data.ENABLE_DOOR_STATE, true, {persist = true}) - end match_profile(driver, device, true) end end @@ -2992,7 +2931,6 @@ local new_matter_lock_handler = { attr = { [DoorLock.ID] = { [DoorLock.attributes.LockState.ID] = lock_state_handler, - [DoorLock.attributes.DoorState.ID] = door_state_handler, [DoorLock.attributes.OperatingMode.ID] = operating_modes_handler, [DoorLock.attributes.NumberOfTotalUsersSupported.ID] = total_users_supported_handler, [DoorLock.attributes.NumberOfPINUsersSupported.ID] = pin_users_supported_handler, diff --git a/drivers/SmartThings/matter-lock/src/test/test_door_state.lua b/drivers/SmartThings/matter-lock/src/test/test_door_state.lua deleted file mode 100644 index c105346b15..0000000000 --- a/drivers/SmartThings/matter-lock/src/test/test_door_state.lua +++ /dev/null @@ -1,278 +0,0 @@ --- Copyright 2023 SmartThings, Inc. --- Licensed under the Apache License, Version 2.0 - - -local test = require "integration_test" -local capabilities = require "st.capabilities" -local t_utils = require "integration_test.utils" -local clusters = require "st.matter.clusters" -local cluster_base = require "st.matter.cluster_base" -local DoorLock = clusters.DoorLock - -local mock_device_door_state_disabled = test.mock_device.build_test_matter_device({ - profile = t_utils.get_profile_definition("lock-modular.yml"), - manufacturer_info = { - vendor_id = 0x115f, - product_id = 0x2802, - }, - endpoints = { - { - endpoint_id = 0, - clusters = { - { cluster_id = clusters.BasicInformation.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 = 0x20, -- DPS - } - }, - device_types = { - { device_type_id = 0x000A, device_type_revision = 1 } -- Door Lock - } - } - } -}) - -local enabled_optional_component_capability_pairs = {{ "main", {capabilities.doorState.ID} }} -local mock_device = test.mock_device.build_test_matter_device({ - profile = t_utils.get_profile_definition( - "lock-modular.yml", - {enabled_optional_capabilities = enabled_optional_component_capability_pairs} - ), - manufacturer_info = { - vendor_id = 0x115f, - product_id = 0x2802, - }, - endpoints = { - { - endpoint_id = 0, - clusters = { - { cluster_id = clusters.BasicInformation.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 = 0x20, -- DPS - } - }, - device_types = { - { device_type_id = 0x000A, device_type_revision = 1 } -- Door Lock - } - } - } -}) - -local DoorLockFeatureMapAttr = {ID = 0xFFFC, cluster = DoorLock.ID} -local function test_init() - test.disable_startup_messages() - local subscribe_request = DoorLock.attributes.LockState:subscribe(mock_device) - subscribe_request:merge(DoorLock.attributes.DoorState:subscribe(mock_device)) - subscribe_request:merge(DoorLock.attributes.OperatingMode:subscribe(mock_device)) - subscribe_request:merge(cluster_base.subscribe(mock_device_door_state_disabled, nil, DoorLockFeatureMapAttr.cluster, DoorLockFeatureMapAttr.ID)) - subscribe_request:merge(DoorLock.events.LockOperation:subscribe(mock_device)) - subscribe_request:merge(DoorLock.events.DoorLockAlarm:subscribe(mock_device)) - test.mock_device.add_test_device(mock_device) - test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.lockAlarm.alarm.clear({state_change = true})) - ) - test.socket.device_lifecycle:__queue_receive({ mock_device.id, "init" }) - test.socket.matter:__expect_send({mock_device.id, subscribe_request}) - test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) - mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) -end - -test.set_test_init_function(test_init) - -local function test_init_door_state_disabled() - test.disable_startup_messages() - local subscribe_request = DoorLock.attributes.LockState:subscribe(mock_device_door_state_disabled) - subscribe_request:merge(DoorLock.attributes.DoorState:subscribe(mock_device_door_state_disabled)) - subscribe_request:merge(DoorLock.attributes.OperatingMode:subscribe(mock_device_door_state_disabled)) - subscribe_request:merge(cluster_base.subscribe(mock_device_door_state_disabled, nil, DoorLockFeatureMapAttr.cluster, DoorLockFeatureMapAttr.ID)) - subscribe_request:merge(DoorLock.events.LockOperation:subscribe(mock_device_door_state_disabled)) - subscribe_request:merge(DoorLock.events.DoorLockAlarm:subscribe(mock_device_door_state_disabled)) - test.mock_device.add_test_device(mock_device_door_state_disabled) - test.socket.device_lifecycle:__queue_receive({ mock_device_door_state_disabled.id, "added" }) - test.socket.capability:__expect_send( - mock_device_door_state_disabled:generate_test_message("main", capabilities.lockAlarm.alarm.clear({state_change = true})) - ) - test.socket.device_lifecycle:__queue_receive({ mock_device_door_state_disabled.id, "init" }) - test.socket.matter:__expect_send({mock_device_door_state_disabled.id, subscribe_request}) - test.socket.device_lifecycle:__queue_receive({ mock_device_door_state_disabled.id, "doConfigure" }) - mock_device_door_state_disabled:expect_metadata_update({ provisioning_state = "PROVISIONED" }) -end - -test.register_coroutine_test( - "Check that the device is updated with correct capabilities based on the profile and attributes.", - function () - test.socket.matter:__queue_receive({ - mock_device_door_state_disabled.id, - DoorLock.attributes.DoorState:build_test_report_data(mock_device_door_state_disabled, 1, DoorLock.attributes.DoorState.DOOR_CLOSED) - }) - test.socket.capability:__expect_send( - mock_device_door_state_disabled:generate_test_message("main", capabilities.lock.supportedLockValues({"locked", "unlocked", "not fully locked"}, {visibility = {displayed = false}})) - ) - test.socket.capability:__expect_send( - mock_device_door_state_disabled:generate_test_message("main", capabilities.lock.supportedLockCommands({"lock", "unlock"}, {visibility = {displayed = false}})) - ) - - mock_device_door_state_disabled:expect_metadata_update({ profile = "lock-modular", optional_component_capabilities = {{"main", {"doorState"}}}}) - end, - { test_init = test_init_door_state_disabled } -) - - -test.register_coroutine_test( - "Handle received DoorState.DOOR_CLOSED from Matter device.", - function() - test.socket.matter:__queue_receive( - { - mock_device.id, - DoorLock.attributes.DoorState:build_test_report_data( - mock_device, 1, DoorLock.attributes.DoorState.DOOR_CLOSED - ), - } - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.doorState.closed()) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.supportedDoorStates({"closed"}, {visibility={displayed=false}})) - ) - end -) - -test.register_coroutine_test( - "Handle received DoorState.DOOR_JAMMED from Matter device.", - function() - test.socket.matter:__queue_receive( - { - mock_device.id, - DoorLock.attributes.DoorState:build_test_report_data( - mock_device, 1, DoorLock.attributes.DoorState.DOOR_JAMMED - ), - } - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.doorState.jammed()) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.supportedDoorStates({"jammed"}, {visibility={displayed=false}})) - ) - end -) - -test.register_coroutine_test( - "Handle received DoorState.DOOR_FORCED_OPEN from Matter device.", - function() - test.socket.matter:__queue_receive( - { - mock_device.id, - DoorLock.attributes.DoorState:build_test_report_data( - mock_device, 1, DoorLock.attributes.DoorState.DOOR_FORCED_OPEN - ), - } - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.doorState.forcedOpen()) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.supportedDoorStates({"forcedOpen"}, {visibility={displayed=false}})) - ) - end -) - -test.register_coroutine_test( - "Handle received DoorState.DOOR_UNSPECIFIED_ERROR from Matter device.", - function() - test.socket.matter:__queue_receive( - { - mock_device.id, - DoorLock.attributes.DoorState:build_test_report_data( - mock_device, 1, DoorLock.attributes.DoorState.DOOR_UNSPECIFIED_ERROR - ), - } - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.doorState.unspecifiedError()) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.supportedDoorStates({"unspecifiedError"}, {visibility={displayed=false}})) - ) - end -) - -test.register_coroutine_test( - "Handle received DoorState.DOOR_AJAR from Matter device.", - function() - test.socket.matter:__queue_receive( - { - mock_device.id, - DoorLock.attributes.DoorState:build_test_report_data( - mock_device, 1, DoorLock.attributes.DoorState.DOOR_AJAR - ), - } - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.doorState.ajar()) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.supportedDoorStates({"ajar"}, {visibility={displayed=false}})) - ) - end -) - -test.register_coroutine_test( - "Handle received DoorState.DOOR_OPEN from Matter device, and then DoorState.DOOR_AJAR, ensuring supportedDoorStates is updated to include both states.", - function() - test.socket.matter:__queue_receive( - { - mock_device.id, - DoorLock.attributes.DoorState:build_test_report_data( - mock_device, 1, DoorLock.attributes.DoorState.DOOR_OPEN - ), - } - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.doorState.open()) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.supportedDoorStates({"open"}, {visibility={displayed=false}})) - ) - test.wait_for_events() - test.socket.matter:__queue_receive( - { - mock_device.id, - DoorLock.attributes.DoorState:build_test_report_data( - mock_device, 1, DoorLock.attributes.DoorState.DOOR_AJAR - ), - } - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.doorState.ajar()) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.doorState.supportedDoorStates({"open", "ajar"}, {visibility={displayed=false}})) - ) - end -) - -test.run_registered_tests()