diff --git a/drivers/SmartThings/matter-switch/src/init.lua b/drivers/SmartThings/matter-switch/src/init.lua index 5436d57baf..04ae8448f5 100644 --- a/drivers/SmartThings/matter-switch/src/init.lua +++ b/drivers/SmartThings/matter-switch/src/init.lua @@ -49,6 +49,10 @@ function SwitchLifecycleHandlers.do_configure(driver, device) if device.network_type == device_lib.NETWORK_TYPE_MATTER and not switch_utils.detect_bridge(device) then switch_cfg.set_device_control_options(device) device_cfg.match_profile(driver, device) + elseif device.network_type == device_lib.NETWORK_TYPE_CHILD then + -- because get_parent_device() may cause race conditions if used in init, an initial child subscribe is handled in doConfigure. + -- all future calls to subscribe will be handled by the parent device in init + device:subscribe() end end @@ -80,25 +84,7 @@ function SwitchLifecycleHandlers.device_init(driver, device) if device:get_field(fields.IS_PARENT_CHILD_DEVICE) then device:set_find_child(switch_utils.find_child) end - local default_endpoint_id = switch_utils.find_default_endpoint(device) - -- ensure subscription to all endpoint attributes- including those mapped to child devices - for _, ep in ipairs(device.endpoints) do - if ep.endpoint_id ~= default_endpoint_id then - local id = 0 - for _, dt in ipairs(ep.device_types) do - id = math.max(id, dt.device_type_id) - end - for _, attr in pairs(fields.device_type_attribute_map[id] or {}) do - if id == fields.DEVICE_TYPE_ID.GENERIC_SWITCH and - attr ~= clusters.PowerSource.attributes.BatPercentRemaining and - attr ~= clusters.PowerSource.attributes.BatChargeLevel then - device:add_subscribed_event(attr) - else - device:add_subscribed_attribute(attr) - end - end - end - end + device:extend_device("subscribe", switch_utils.subscribe) device:subscribe() -- device energy reporting must be handled cumulatively, periodically, or by both simulatanously. @@ -298,7 +284,40 @@ local matter_driver_template = { [capabilities.valve.commands.open.NAME] = capability_handlers.handle_valve_open, }, }, - supported_capabilities = fields.supported_capabilities, + supported_capabilities = { + capabilities.audioMute, + capabilities.audioRecording, + capabilities.audioVolume, + capabilities.battery, + capabilities.batteryLevel, + capabilities.button, + capabilities.cameraPrivacyMode, + capabilities.cameraViewportSettings, + capabilities.colorControl, + capabilities.colorTemperature, + capabilities.energyMeter, + capabilities.fanMode, + capabilities.fanSpeedPercent, + capabilities.hdr, + capabilities.illuminanceMeasurement, + capabilities.imageControl, + capabilities.level, + capabilities.localMediaStorage, + capabilities.mechanicalPanTiltZoom, + capabilities.motionSensor, + capabilities.nightVision, + capabilities.powerMeter, + capabilities.powerConsumptionReport, + capabilities.relativeHumidityMeasurement, + capabilities.sounds, + capabilities.switch, + capabilities.switchLevel, + capabilities.temperatureMeasurement, + capabilities.valve, + capabilities.videoStreamSettings, + capabilities.webrtc, + capabilities.zoneManagement + }, sub_drivers = { switch_utils.lazy_load_if_possible("sub_drivers.aqara_cube"), switch_utils.lazy_load("sub_drivers.camera"), diff --git a/drivers/SmartThings/matter-switch/src/sub_drivers/camera/camera_utils/utils.lua b/drivers/SmartThings/matter-switch/src/sub_drivers/camera/camera_utils/utils.lua index dcdd936950..f08e757553 100644 --- a/drivers/SmartThings/matter-switch/src/sub_drivers/camera/camera_utils/utils.lua +++ b/drivers/SmartThings/matter-switch/src/sub_drivers/camera/camera_utils/utils.lua @@ -193,7 +193,8 @@ function CameraUtils.subscribe(device) clusters.CameraAvStreamManagement.attributes.StatusLightBrightness }, [capabilities.switch.ID] = { - clusters.CameraAvStreamManagement.attributes.StatusLightEnabled + clusters.CameraAvStreamManagement.attributes.StatusLightEnabled, + clusters.OnOff.attributes.OnOff }, [capabilities.videoStreamSettings.ID] = { clusters.CameraAvStreamManagement.attributes.RateDistortionTradeOffPoints, @@ -223,8 +224,26 @@ function CameraUtils.subscribe(device) }, [capabilities.motionSensor.ID] = { clusters.OccupancySensing.attributes.Occupancy - } + }, + [capabilities.switchLevel.ID] = { + clusters.LevelControl.attributes.CurrentLevel, + clusters.LevelControl.attributes.MaxLevel, + clusters.LevelControl.attributes.MinLevel, + }, + [capabilities.colorControl.ID] = { + clusters.ColorControl.attributes.ColorMode, + clusters.ColorControl.attributes.CurrentHue, + clusters.ColorControl.attributes.CurrentSaturation, + clusters.ColorControl.attributes.CurrentX, + clusters.ColorControl.attributes.CurrentY, + }, + [capabilities.colorTemperature.ID] = { + clusters.ColorControl.attributes.ColorTemperatureMireds, + clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds, + clusters.ColorControl.attributes.ColorTempPhysicalMinMireds, + }, } + local camera_subscribed_events = { [capabilities.zoneManagement.ID] = { clusters.ZoneManagement.events.ZoneTriggered, @@ -238,56 +257,26 @@ function CameraUtils.subscribe(device) } } - for capability, attr_list in pairs(camera_subscribed_attributes) do - if device:supports_capability_by_id(capability) then - for _, attr in pairs(attr_list) do - device:add_subscribed_attribute(attr) - end - end - end - for capability, event_list in pairs(camera_subscribed_events) do - if device:supports_capability_by_id(capability) then - for _, event in pairs(event_list) do - device:add_subscribed_event(event) - end - end - end + local im = require "st.matter.interaction_model" + + local subscribe_request = im.InteractionRequest(im.InteractionRequest.RequestType.SUBSCRIBE, {}) + local devices_seen, capabilities_seen, attributes_seen, events_seen = {}, {}, {}, {} - -- match_profile is called from the CameraAvStreamManagement AttributeList handler, - -- so the subscription needs to be added here first if #device:get_endpoints(clusters.CameraAvStreamManagement.ID) > 0 then - device:add_subscribed_attribute(clusters.CameraAvStreamManagement.attributes.AttributeList) + local ib = im.InteractionInfoBlock(nil, clusters.CameraAvStreamManagement.ID, clusters.CameraAvStreamManagement.attributes.AttributeList.ID) + subscribe_request:with_info_block(ib) end - -- Add subscription for attributes specific to child devices - if device:get_field(fields.IS_PARENT_CHILD_DEVICE) then - for _, ep in ipairs(device.endpoints or {}) do - local id = 0 - for _, dt in ipairs(ep.device_types or {}) do - if dt.device_type_id ~= fields.DEVICE_TYPE_ID.GENERIC_SWITCH then - id = math.max(id, dt.device_type_id) - end - end - for _, attr in pairs(fields.device_type_attribute_map[id] or {}) do - device:add_subscribed_attribute(attr) - end + for _, endpoint_info in ipairs(device.endpoints) do + local checked_device = switch_utils.find_child(device, endpoint_info.endpoint_id) or device + if not devices_seen[checked_device.id] then + switch_utils.populate_subscribe_request_for_device(checked_device, subscribe_request, capabilities_seen, attributes_seen, events_seen, + camera_subscribed_attributes, camera_subscribed_events + ) + devices_seen[checked_device.id] = true -- only loop through any device once end end - local im = require "st.matter.interaction_model" - local subscribed_attributes = device:get_field("__subscribed_attributes") or {} - local subscribed_events = device:get_field("__subscribed_events") or {} - local subscribe_request = im.InteractionRequest(im.InteractionRequest.RequestType.SUBSCRIBE, {}) - for _, attributes in pairs(subscribed_attributes) do - for _, ib in pairs(attributes) do - subscribe_request:with_info_block(ib) - end - end - for _, events in pairs(subscribed_events) do - for _, ib in pairs(events) do - subscribe_request:with_info_block(ib) - end - end if #subscribe_request.info_blocks > 0 then device:send(subscribe_request) end diff --git a/drivers/SmartThings/matter-switch/src/sub_drivers/camera/init.lua b/drivers/SmartThings/matter-switch/src/sub_drivers/camera/init.lua index 8244f4fd62..effd7fd049 100644 --- a/drivers/SmartThings/matter-switch/src/sub_drivers/camera/init.lua +++ b/drivers/SmartThings/matter-switch/src/sub_drivers/camera/init.lua @@ -42,10 +42,10 @@ end function CameraLifecycleHandlers.info_changed(driver, device, event, args) if camera_utils.profile_changed(device.profile.components, args.old_st_store.profile.components) then camera_cfg.initialize_camera_capabilities(device) + device:subscribe() if #switch_utils.get_endpoints_by_device_type(device, fields.DEVICE_TYPE_ID.DOORBELL) > 0 then button_cfg.configure_buttons(device) end - device:subscribe() end end diff --git a/drivers/SmartThings/matter-switch/src/switch_handlers/attribute_handlers.lua b/drivers/SmartThings/matter-switch/src/switch_handlers/attribute_handlers.lua index 756a402de6..c775da78ad 100644 --- a/drivers/SmartThings/matter-switch/src/switch_handlers/attribute_handlers.lua +++ b/drivers/SmartThings/matter-switch/src/switch_handlers/attribute_handlers.lua @@ -83,7 +83,7 @@ end -- [[ COLOR CONTROL CLUSTER ATTRIBUTES ]] -- function AttributeHandlers.current_hue_handler(driver, device, ib, response) - if device:get_field(fields.COLOR_MODE) == fields.X_Y_COLOR_MODE or ib.data.value == nil then + if device:get_field(fields.COLOR_MODE) == clusters.ColorControl.types.ColorMode.CURRENTX_AND_CURRENTY or ib.data.value == nil then return end local hue = math.floor((ib.data.value / 0xFE * 100) + 0.5) @@ -91,7 +91,7 @@ function AttributeHandlers.current_hue_handler(driver, device, ib, response) end function AttributeHandlers.current_saturation_handler(driver, device, ib, response) - if device:get_field(fields.COLOR_MODE) == fields.X_Y_COLOR_MODE or ib.data.value == nil then + if device:get_field(fields.COLOR_MODE) == clusters.ColorControl.types.ColorMode.CURRENTX_AND_CURRENTY or ib.data.value == nil then return end local sat = math.floor((ib.data.value / 0xFE * 100) + 0.5) @@ -132,7 +132,7 @@ function AttributeHandlers.color_temperature_mireds_handler(driver, device, ib, end function AttributeHandlers.current_x_handler(driver, device, ib, response) - if device:get_field(fields.COLOR_MODE) == fields.HUE_SAT_COLOR_MODE then + if device:get_field(fields.COLOR_MODE) == clusters.ColorControl.types.ColorMode.CURRENT_HUE_AND_CURRENT_SATURATION then return end local y = device:get_field(fields.RECEIVED_Y) @@ -150,7 +150,7 @@ function AttributeHandlers.current_x_handler(driver, device, ib, response) end function AttributeHandlers.current_y_handler(driver, device, ib, response) - if device:get_field(fields.COLOR_MODE) == fields.HUE_SAT_COLOR_MODE then + if device:get_field(fields.COLOR_MODE) == clusters.ColorControl.types.ColorMode.CURRENT_HUE_AND_CURRENT_SATURATION then return end local x = device:get_field(fields.RECEIVED_X) @@ -166,15 +166,17 @@ function AttributeHandlers.current_y_handler(driver, device, ib, response) end function AttributeHandlers.color_mode_handler(driver, device, ib, response) - if ib.data.value == device:get_field(fields.COLOR_MODE) or (ib.data.value ~= fields.HUE_SAT_COLOR_MODE and ib.data.value ~= fields.X_Y_COLOR_MODE) then - return + if ib.data.value == device:get_field(fields.COLOR_MODE) + or (ib.data.value ~= clusters.ColorControl.types.ColorMode.CURRENT_HUE_AND_CURRENT_SATURATION + and ib.data.value ~= clusters.ColorControl.types.ColorMode.CURRENTX_AND_CURRENTY) then + return end device:set_field(fields.COLOR_MODE, ib.data.value) local req = im.InteractionRequest(im.InteractionRequest.RequestType.READ, {}) - if ib.data.value == fields.HUE_SAT_COLOR_MODE then + if ib.data.value == clusters.ColorControl.types.ColorMode.CURRENT_HUE_AND_CURRENT_SATURATION then req:merge(clusters.ColorControl.attributes.CurrentHue:read()) req:merge(clusters.ColorControl.attributes.CurrentSaturation:read()) - elseif ib.data.value == fields.X_Y_COLOR_MODE then + elseif ib.data.value == clusters.ColorControl.types.ColorMode.CURRENTX_AND_CURRENTY then req:merge(clusters.ColorControl.attributes.CurrentX:read()) req:merge(clusters.ColorControl.attributes.CurrentY:read()) end diff --git a/drivers/SmartThings/matter-switch/src/switch_utils/fields.lua b/drivers/SmartThings/matter-switch/src/switch_utils/fields.lua index f0fd0166b4..b536acdbbf 100644 --- a/drivers/SmartThings/matter-switch/src/switch_utils/fields.lua +++ b/drivers/SmartThings/matter-switch/src/switch_utils/fields.lua @@ -1,27 +1,13 @@ -- Copyright © 2025 SmartThings, Inc. -- Licensed under the Apache License, Version 2.0 -local clusters = require "st.matter.clusters" -local capabilities = require "st.capabilities" -local version = require "version" - --- Include driver-side definitions when lua libs api version is < 11 -if version.api < 11 then - clusters.ElectricalEnergyMeasurement = require "embedded_clusters.ElectricalEnergyMeasurement" - clusters.ElectricalPowerMeasurement = require "embedded_clusters.ElectricalPowerMeasurement" -end - local SwitchFields = {} -SwitchFields.HUE_SAT_COLOR_MODE = clusters.ColorControl.types.ColorMode.CURRENT_HUE_AND_CURRENT_SATURATION -SwitchFields.X_Y_COLOR_MODE = clusters.ColorControl.types.ColorMode.CURRENTX_AND_CURRENTY - SwitchFields.MOST_RECENT_TEMP = "mostRecentTemp" SwitchFields.RECEIVED_X = "receivedX" SwitchFields.RECEIVED_Y = "receivedY" SwitchFields.HUESAT_SUPPORT = "huesatSupport" - SwitchFields.MIRED_KELVIN_CONVERSION_CONSTANT = 1000000 -- These values are a "sanity check" to check that values we are getting are reasonable @@ -189,117 +175,4 @@ SwitchFields.TRANSITION_TIME = 0 --1/10ths of a second SwitchFields.OPTIONS_MASK = 0x01 SwitchFields.OPTIONS_OVERRIDE = 0x01 - -SwitchFields.supported_capabilities = { - capabilities.audioMute, - capabilities.audioRecording, - capabilities.audioVolume, - capabilities.battery, - capabilities.batteryLevel, - capabilities.button, - capabilities.cameraPrivacyMode, - capabilities.cameraViewportSettings, - capabilities.colorControl, - capabilities.colorTemperature, - capabilities.energyMeter, - capabilities.fanMode, - capabilities.fanSpeedPercent, - capabilities.hdr, - capabilities.illuminanceMeasurement, - capabilities.imageControl, - capabilities.level, - capabilities.localMediaStorage, - capabilities.mechanicalPanTiltZoom, - capabilities.motionSensor, - capabilities.nightVision, - capabilities.powerMeter, - capabilities.powerConsumptionReport, - capabilities.relativeHumidityMeasurement, - capabilities.sounds, - capabilities.switch, - capabilities.switchLevel, - capabilities.temperatureMeasurement, - capabilities.valve, - capabilities.videoStreamSettings, - capabilities.webrtc, - capabilities.zoneManagement -} - -SwitchFields.device_type_attribute_map = { - [SwitchFields.DEVICE_TYPE_ID.LIGHT.ON_OFF] = { - clusters.OnOff.attributes.OnOff - }, - [SwitchFields.DEVICE_TYPE_ID.LIGHT.DIMMABLE] = { - clusters.OnOff.attributes.OnOff, - clusters.LevelControl.attributes.CurrentLevel, - clusters.LevelControl.attributes.MaxLevel, - clusters.LevelControl.attributes.MinLevel - }, - [SwitchFields.DEVICE_TYPE_ID.LIGHT.COLOR_TEMPERATURE] = { - clusters.OnOff.attributes.OnOff, - clusters.LevelControl.attributes.CurrentLevel, - clusters.LevelControl.attributes.MaxLevel, - clusters.LevelControl.attributes.MinLevel, - clusters.ColorControl.attributes.ColorTemperatureMireds, - clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds, - clusters.ColorControl.attributes.ColorTempPhysicalMinMireds - }, - [SwitchFields.DEVICE_TYPE_ID.LIGHT.EXTENDED_COLOR] = { - clusters.OnOff.attributes.OnOff, - clusters.LevelControl.attributes.CurrentLevel, - clusters.LevelControl.attributes.MaxLevel, - clusters.LevelControl.attributes.MinLevel, - clusters.ColorControl.attributes.ColorTemperatureMireds, - clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds, - clusters.ColorControl.attributes.ColorTempPhysicalMinMireds, - clusters.ColorControl.attributes.CurrentHue, - clusters.ColorControl.attributes.CurrentSaturation, - clusters.ColorControl.attributes.CurrentX, - clusters.ColorControl.attributes.CurrentY - }, - [SwitchFields.DEVICE_TYPE_ID.ON_OFF_PLUG_IN_UNIT] = { - clusters.OnOff.attributes.OnOff - }, - [SwitchFields.DEVICE_TYPE_ID.DIMMABLE_PLUG_IN_UNIT] = { - clusters.OnOff.attributes.OnOff, - clusters.LevelControl.attributes.CurrentLevel, - clusters.LevelControl.attributes.MaxLevel, - clusters.LevelControl.attributes.MinLevel - }, - [SwitchFields.DEVICE_TYPE_ID.SWITCH.ON_OFF_LIGHT] = { - clusters.OnOff.attributes.OnOff - }, - [SwitchFields.DEVICE_TYPE_ID.SWITCH.DIMMER] = { - clusters.OnOff.attributes.OnOff, - clusters.LevelControl.attributes.CurrentLevel, - clusters.LevelControl.attributes.MaxLevel, - clusters.LevelControl.attributes.MinLevel - }, - [SwitchFields.DEVICE_TYPE_ID.SWITCH.COLOR_DIMMER] = { - clusters.OnOff.attributes.OnOff, - clusters.LevelControl.attributes.CurrentLevel, - clusters.LevelControl.attributes.MaxLevel, - clusters.LevelControl.attributes.MinLevel, - clusters.ColorControl.attributes.ColorTemperatureMireds, - clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds, - clusters.ColorControl.attributes.ColorTempPhysicalMinMireds, - clusters.ColorControl.attributes.CurrentHue, - clusters.ColorControl.attributes.CurrentSaturation, - clusters.ColorControl.attributes.CurrentX, - clusters.ColorControl.attributes.CurrentY - }, - [SwitchFields.DEVICE_TYPE_ID.GENERIC_SWITCH] = { - clusters.PowerSource.attributes.BatPercentRemaining, - clusters.Switch.events.InitialPress, - clusters.Switch.events.LongPress, - clusters.Switch.events.ShortRelease, - clusters.Switch.events.MultiPressComplete - }, - [SwitchFields.DEVICE_TYPE_ID.ELECTRICAL_SENSOR] = { - clusters.ElectricalPowerMeasurement.attributes.ActivePower, - clusters.ElectricalEnergyMeasurement.attributes.CumulativeEnergyImported, - clusters.ElectricalEnergyMeasurement.attributes.PeriodicEnergyImported - } -} - -return SwitchFields \ No newline at end of file +return SwitchFields diff --git a/drivers/SmartThings/matter-switch/src/switch_utils/utils.lua b/drivers/SmartThings/matter-switch/src/switch_utils/utils.lua index b258688234..7059b869d6 100644 --- a/drivers/SmartThings/matter-switch/src/switch_utils/utils.lua +++ b/drivers/SmartThings/matter-switch/src/switch_utils/utils.lua @@ -427,4 +427,62 @@ function utils.lazy_load_if_possible(sub_driver_name) end end +--- helper for the switch subscribe override, which adds to a subscribed request for a checked device +--- +--- @param checked_device any a Matter device object, either a parent or child device, so not necessarily the same as device +--- @param subscribe_request table a subscribe request that will be appended to as needed for the device +--- @param capabilities_seen any a list of capabilities that have already been checked by already checked devices +-- @param matter_elements_seen table a list of attribute and event ids that have been added already +--- @param subscribed_attributes table key-value pairs mapping capability ids to subscribed attributes +--- @param subscribed_events table key-value pairs mapping capability ids to subscribed events +function utils.populate_subscribe_request_for_device(checked_device, subscribe_request, capabilities_seen, attributes_seen, events_seen, subscribed_attributes, subscribed_events) + for _, component in pairs(checked_device.st_store.profile.components) do + for _, capability in pairs(component.capabilities) do + if not capabilities_seen[capability.id] then + for _, attr in ipairs(subscribed_attributes[capability.id] or {}) do + local cluster_id = attr.cluster or attr._cluster.ID + local attr_id = attr.ID or attr.attribute + if not attributes_seen[cluster_id..attr_id] then + local ib = im.InteractionInfoBlock(nil, cluster_id, attr_id) + subscribe_request:with_info_block(ib) + attributes_seen[cluster_id..attr_id] = true + end + end + for _, event in ipairs(subscribed_events[capability.id] or {}) do + local cluster_id = event.cluster or event._cluster.ID + local event_id = event.ID or event.event + if not events_seen[cluster_id..event_id] then + local ib = im.InteractionInfoBlock(nil, cluster_id, nil, event_id) + subscribe_request:with_info_block(ib) + events_seen[cluster_id..event_id] = true + end + end + capabilities_seen[capability.id] = true -- only loop through any capability once + end + end + end +end + +--- create and send a subscription request by checking all devices, accounting for both parent and child devices +--- +--- @param device any a Matter device object +function utils.subscribe(device) + local subscribe_request = im.InteractionRequest(im.InteractionRequest.RequestType.SUBSCRIBE, {}) + local devices_seen, capabilities_seen, attributes_seen, events_seen = {}, {}, {}, {} + + for _, endpoint_info in ipairs(device.endpoints) do + local checked_device = utils.find_child(device, endpoint_info.endpoint_id) or device + if not devices_seen[checked_device.id] then + utils.populate_subscribe_request_for_device(checked_device, subscribe_request, capabilities_seen, attributes_seen, events_seen, + device.driver.subscribed_attributes, device.driver.subscribed_events + ) + devices_seen[checked_device.id] = true -- only loop through any device once + end + end + + if #subscribe_request.info_blocks > 0 then + device:send(subscribe_request) + end +end + return utils diff --git a/drivers/SmartThings/matter-switch/src/test/test_eve_energy.lua b/drivers/SmartThings/matter-switch/src/test/test_eve_energy.lua index 1598f953a4..a189b1e5fc 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_eve_energy.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_eve_energy.lua @@ -55,7 +55,7 @@ local mock_device = test.mock_device.build_test_matter_device({ }) local mock_device_electrical_sensor = test.mock_device.build_test_matter_device({ - profile = t_utils.get_profile_definition("power-energy-powerConsumption.yml"), + profile = t_utils.get_profile_definition("plug-energy-powerConsumption.yml"), manufacturer_info = { vendor_id = 0x130A, product_id = 0x0050, diff --git a/drivers/SmartThings/matter-switch/src/test/test_matter_bridge.lua b/drivers/SmartThings/matter-switch/src/test/test_matter_bridge.lua index 1aaef32d37..c696815a3e 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_matter_bridge.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_matter_bridge.lua @@ -59,34 +59,15 @@ local mock_bridge = test.mock_device.build_test_matter_device({ } }) -local cluster_subscribe_list = { - clusters.OnOff.attributes.OnOff -} - local function test_init_mock_bridge() - local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_bridge) - for i, cluster in ipairs(cluster_subscribe_list) do - if i > 1 then - subscribe_request:merge(cluster:subscribe(mock_bridge)) - end - end - test.socket.matter:__expect_send({mock_bridge.id, subscribe_request}) test.mock_device.add_test_device(mock_bridge) end test.register_coroutine_test( "Profile should not change for devices with aggregator device type (bridges)", function() - local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_bridge) - for i, cluster in ipairs(cluster_subscribe_list) do - if i > 1 then - subscribe_request:merge(cluster:subscribe(mock_bridge)) - end - end test.socket.device_lifecycle:__queue_receive({ mock_bridge.id, "added" }) - test.socket.matter:__expect_send({mock_bridge.id, subscribe_request}) test.socket.device_lifecycle:__queue_receive({ mock_bridge.id, "init" }) - test.socket.matter:__expect_send({mock_bridge.id, subscribe_request}) test.socket.device_lifecycle:__queue_receive({ mock_bridge.id, "doConfigure" }) mock_bridge:expect_metadata_update({ provisioning_state = "PROVISIONED" }) end, diff --git a/drivers/SmartThings/matter-switch/src/test/test_matter_camera.lua b/drivers/SmartThings/matter-switch/src/test/test_matter_camera.lua index b9804a2a76..2ba554276e 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_matter_camera.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_matter_camera.lua @@ -117,6 +117,19 @@ local mock_device = test.mock_device.build_test_matter_device({ local subscribe_request local subscribed_attributes = { clusters.CameraAvStreamManagement.attributes.AttributeList, + clusters.CameraAvStreamManagement.attributes.StatusLightEnabled, + clusters.OnOff.attributes.OnOff, + clusters.LevelControl.attributes.CurrentLevel, + clusters.LevelControl.attributes.MaxLevel, + clusters.LevelControl.attributes.MinLevel, + clusters.ColorControl.attributes.ColorTemperatureMireds, + clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds, + clusters.ColorControl.attributes.ColorTempPhysicalMinMireds, + clusters.ColorControl.attributes.CurrentHue, + clusters.ColorControl.attributes.CurrentSaturation, + clusters.ColorControl.attributes.CurrentX, + clusters.ColorControl.attributes.CurrentY, + clusters.ColorControl.attributes.ColorMode, } local function test_init() @@ -148,60 +161,125 @@ end test.set_test_init_function(test_init) -local function update_device_profile() - test.socket.matter:__set_channel_ordering("relaxed") - local uint32 = require "st.matter.data_types.Uint32" - local expected_metadata = { - optional_component_capabilities = { - { - "main", - { - "videoCapture2", - "cameraViewportSettings", - "localMediaStorage", - "audioRecording", - "cameraPrivacyMode", - "imageControl", - "hdr", - "nightVision", - "mechanicalPanTiltZoom", - "videoStreamSettings", - "zoneManagement", - "webrtc", - "motionSensor", - "sounds", - } - }, +local additional_subscribed_attributes = { + clusters.CameraAvStreamManagement.attributes.HDRModeEnabled, + clusters.CameraAvStreamManagement.attributes.ImageRotation, + clusters.CameraAvStreamManagement.attributes.NightVision, + clusters.CameraAvStreamManagement.attributes.NightVisionIllum, + clusters.CameraAvStreamManagement.attributes.ImageFlipHorizontal, + clusters.CameraAvStreamManagement.attributes.ImageFlipVertical, + clusters.CameraAvStreamManagement.attributes.SoftRecordingPrivacyModeEnabled, + clusters.CameraAvStreamManagement.attributes.SoftLivestreamPrivacyModeEnabled, + clusters.CameraAvStreamManagement.attributes.HardPrivacyModeOn, + clusters.CameraAvStreamManagement.attributes.TwoWayTalkSupport, + clusters.CameraAvStreamManagement.attributes.SpeakerMuted, + clusters.CameraAvStreamManagement.attributes.MicrophoneMuted, + clusters.CameraAvStreamManagement.attributes.SpeakerVolumeLevel, + clusters.CameraAvStreamManagement.attributes.SpeakerMaxLevel, + clusters.CameraAvStreamManagement.attributes.SpeakerMinLevel, + clusters.CameraAvStreamManagement.attributes.MicrophoneVolumeLevel, + clusters.CameraAvStreamManagement.attributes.MicrophoneMaxLevel, + clusters.CameraAvStreamManagement.attributes.MicrophoneMinLevel, + clusters.CameraAvStreamManagement.attributes.StatusLightBrightness, + clusters.CameraAvStreamManagement.attributes.StatusLightEnabled, + clusters.CameraAvStreamManagement.attributes.RateDistortionTradeOffPoints, + clusters.CameraAvStreamManagement.attributes.LocalSnapshotRecordingEnabled, + clusters.CameraAvStreamManagement.attributes.LocalVideoRecordingEnabled, + clusters.CameraAvStreamManagement.attributes.MaxEncodedPixelRate, + clusters.CameraAvStreamManagement.attributes.VideoSensorParams, + clusters.CameraAvStreamManagement.attributes.AllocatedVideoStreams, + clusters.CameraAvStreamManagement.attributes.Viewport, + clusters.CameraAvStreamManagement.attributes.MinViewportResolution, + clusters.CameraAvStreamManagement.attributes.AttributeList, + clusters.CameraAvSettingsUserLevelManagement.attributes.MPTZPosition, + clusters.CameraAvSettingsUserLevelManagement.attributes.MPTZPresets, + clusters.CameraAvSettingsUserLevelManagement.attributes.MaxPresets, + clusters.CameraAvSettingsUserLevelManagement.attributes.ZoomMax, + clusters.CameraAvSettingsUserLevelManagement.attributes.PanMax, + clusters.CameraAvSettingsUserLevelManagement.attributes.PanMin, + clusters.CameraAvSettingsUserLevelManagement.attributes.TiltMax, + clusters.CameraAvSettingsUserLevelManagement.attributes.TiltMin, + clusters.Chime.attributes.InstalledChimeSounds, + clusters.Chime.attributes.SelectedChime, + clusters.ZoneManagement.attributes.MaxZones, + clusters.ZoneManagement.attributes.Zones, + clusters.ZoneManagement.attributes.Triggers, + clusters.ZoneManagement.attributes.SensitivityMax, + clusters.ZoneManagement.attributes.Sensitivity, + clusters.ZoneManagement.events.ZoneTriggered, + clusters.ZoneManagement.events.ZoneStopped, + clusters.OnOff.attributes.OnOff, + clusters.LevelControl.attributes.CurrentLevel, + clusters.LevelControl.attributes.MaxLevel, + clusters.LevelControl.attributes.MinLevel, + clusters.ColorControl.attributes.ColorTemperatureMireds, + clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds, + clusters.ColorControl.attributes.ColorTempPhysicalMinMireds, + clusters.ColorControl.attributes.CurrentHue, + clusters.ColorControl.attributes.CurrentSaturation, + clusters.ColorControl.attributes.CurrentX, + clusters.ColorControl.attributes.CurrentY, + clusters.OccupancySensing.attributes.Occupancy, + clusters.Switch.server.events.InitialPress, + clusters.Switch.server.events.LongPress, + clusters.Switch.server.events.ShortRelease, + clusters.Switch.server.events.MultiPressComplete +} + +local expected_metadata = { + optional_component_capabilities = { + { + "main", { - "statusLed", - { - "switch", - "mode" - } - }, + "videoCapture2", + "cameraViewportSettings", + "localMediaStorage", + "audioRecording", + "cameraPrivacyMode", + "imageControl", + "hdr", + "nightVision", + "mechanicalPanTiltZoom", + "videoStreamSettings", + "zoneManagement", + "webrtc", + "motionSensor", + "sounds", + } + }, + { + "statusLed", { - "speaker", - { - "audioMute", - "audioVolume" - } - }, + "switch", + "mode" + } + }, + { + "speaker", { - "microphone", - { - "audioMute", - "audioVolume" - } - }, + "audioMute", + "audioVolume" + } + }, + { + "microphone", { - "doorbell", - { - "button" - } + "audioMute", + "audioVolume" } }, - profile = "camera" - } + { + "doorbell", + { + "button" + } + } + }, + profile = "camera" +} + +local function update_device_profile() + local uint32 = require "st.matter.data_types.Uint32" test.socket.matter:__queue_receive({ mock_device.id, clusters.CameraAvStreamManagement.attributes.AttributeList:build_test_report_data(mock_device, CAMERA_EP, { @@ -214,6 +292,7 @@ local function update_device_profile() local updated_device_profile = t_utils.get_profile_definition( "camera.yml", {enabled_optional_capabilities = expected_metadata.optional_component_capabilities} ) + test.wait_for_events() test.socket.device_lifecycle:__queue_receive(mock_device:generate_info_changed({ profile = updated_device_profile })) test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.webrtc.supportedFeatures( @@ -253,76 +332,12 @@ local function update_device_profile() {"setSoftRecordingPrivacyMode", "setSoftLivestreamPrivacyMode"} )) ) - local additional_subscribed_attributes = { - clusters.CameraAvStreamManagement.attributes.HDRModeEnabled, - clusters.CameraAvStreamManagement.attributes.ImageRotation, - clusters.CameraAvStreamManagement.attributes.NightVision, - clusters.CameraAvStreamManagement.attributes.NightVisionIllum, - clusters.CameraAvStreamManagement.attributes.ImageFlipHorizontal, - clusters.CameraAvStreamManagement.attributes.ImageFlipVertical, - clusters.CameraAvStreamManagement.attributes.SoftRecordingPrivacyModeEnabled, - clusters.CameraAvStreamManagement.attributes.SoftLivestreamPrivacyModeEnabled, - clusters.CameraAvStreamManagement.attributes.HardPrivacyModeOn, - clusters.CameraAvStreamManagement.attributes.TwoWayTalkSupport, - clusters.CameraAvStreamManagement.attributes.SpeakerMuted, - clusters.CameraAvStreamManagement.attributes.MicrophoneMuted, - clusters.CameraAvStreamManagement.attributes.SpeakerVolumeLevel, - clusters.CameraAvStreamManagement.attributes.SpeakerMaxLevel, - clusters.CameraAvStreamManagement.attributes.SpeakerMinLevel, - clusters.CameraAvStreamManagement.attributes.MicrophoneVolumeLevel, - clusters.CameraAvStreamManagement.attributes.MicrophoneMaxLevel, - clusters.CameraAvStreamManagement.attributes.MicrophoneMinLevel, - clusters.CameraAvStreamManagement.attributes.StatusLightBrightness, - clusters.CameraAvStreamManagement.attributes.StatusLightEnabled, - clusters.CameraAvStreamManagement.attributes.RateDistortionTradeOffPoints, - clusters.CameraAvStreamManagement.attributes.LocalSnapshotRecordingEnabled, - clusters.CameraAvStreamManagement.attributes.LocalVideoRecordingEnabled, - clusters.CameraAvStreamManagement.attributes.MaxEncodedPixelRate, - clusters.CameraAvStreamManagement.attributes.VideoSensorParams, - clusters.CameraAvStreamManagement.attributes.AllocatedVideoStreams, - clusters.CameraAvStreamManagement.attributes.Viewport, - clusters.CameraAvStreamManagement.attributes.MinViewportResolution, - clusters.CameraAvStreamManagement.attributes.AttributeList, - clusters.CameraAvSettingsUserLevelManagement.attributes.MPTZPosition, - clusters.CameraAvSettingsUserLevelManagement.attributes.MPTZPresets, - clusters.CameraAvSettingsUserLevelManagement.attributes.MaxPresets, - clusters.CameraAvSettingsUserLevelManagement.attributes.ZoomMax, - clusters.CameraAvSettingsUserLevelManagement.attributes.PanMax, - clusters.CameraAvSettingsUserLevelManagement.attributes.PanMin, - clusters.CameraAvSettingsUserLevelManagement.attributes.TiltMax, - clusters.CameraAvSettingsUserLevelManagement.attributes.TiltMin, - clusters.Chime.attributes.InstalledChimeSounds, - clusters.Chime.attributes.SelectedChime, - clusters.ZoneManagement.attributes.MaxZones, - clusters.ZoneManagement.attributes.Zones, - clusters.ZoneManagement.attributes.Triggers, - clusters.ZoneManagement.attributes.SensitivityMax, - clusters.ZoneManagement.attributes.Sensitivity, - clusters.ZoneManagement.events.ZoneTriggered, - clusters.ZoneManagement.events.ZoneStopped, - clusters.OnOff.attributes.OnOff, - clusters.LevelControl.attributes.CurrentLevel, - clusters.LevelControl.attributes.MaxLevel, - clusters.LevelControl.attributes.MinLevel, - clusters.ColorControl.attributes.ColorTemperatureMireds, - clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds, - clusters.ColorControl.attributes.ColorTempPhysicalMinMireds, - clusters.ColorControl.attributes.CurrentHue, - clusters.ColorControl.attributes.CurrentSaturation, - clusters.ColorControl.attributes.CurrentX, - clusters.ColorControl.attributes.CurrentY, - clusters.OccupancySensing.attributes.Occupancy, - clusters.Switch.server.events.InitialPress, - clusters.Switch.server.events.LongPress, - clusters.Switch.server.events.ShortRelease, - clusters.Switch.server.events.MultiPressComplete - } for _, attr in ipairs(additional_subscribed_attributes) do subscribe_request:merge(attr:subscribe(mock_device)) end + test.socket.matter:__expect_send({mock_device.id, subscribe_request}) test.socket.matter:__expect_send({mock_device.id, clusters.Switch.attributes.MultiPressMax:read(mock_device, DOORBELL_EP)}) test.socket.capability:__expect_send(mock_device:generate_test_message("doorbell", capabilities.button.button.pushed({state_change = false}))) - test.socket.matter:__expect_send({mock_device.id, subscribe_request}) end -- Matter Handler UTs diff --git a/drivers/SmartThings/matter-switch/src/test/test_matter_multi_button_switch_mcd.lua b/drivers/SmartThings/matter-switch/src/test/test_matter_multi_button_switch_mcd.lua index a036a79f18..e0de8df26f 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_matter_multi_button_switch_mcd.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_matter_multi_button_switch_mcd.lua @@ -103,7 +103,7 @@ local mock_device = test.mock_device.build_test_matter_device({ local mock_device_mcd_unsupported_switch_device_type = test.mock_device.build_test_matter_device({ label = "Matter Switch", - profile = t_utils.get_profile_definition("matter-thing.yml"), + profile = t_utils.get_profile_definition("button.yml"), manufacturer_info = { vendor_id = 0x0000, product_id = 0x0000, @@ -178,6 +178,7 @@ local CLUSTER_SUBSCRIBE_LIST ={ clusters.ColorControl.attributes.CurrentSaturation, clusters.ColorControl.attributes.CurrentX, clusters.ColorControl.attributes.CurrentY, + clusters.ColorControl.attributes.ColorMode, clusters.Switch.server.events.InitialPress, clusters.Switch.server.events.LongPress, clusters.Switch.server.events.ShortRelease, @@ -230,20 +231,6 @@ local function test_init() test.socket.matter:__expect_send({mock_device.id, clusters.LevelControl.attributes.Options:write(mock_device, mock_device_ep5, clusters.LevelControl.types.OptionsBitmap.EXECUTE_IF_OFF)}) test.socket.matter:__expect_send({mock_device.id, clusters.ColorControl.attributes.Options:write(mock_device, mock_device_ep5, clusters.ColorControl.types.OptionsBitmap.EXECUTE_IF_OFF)}) test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) - - -- simulate the profile change update taking affect and the device info changing - local device_info_copy = utils.deep_copy(mock_device.raw_st_data) - device_info_copy.profile.id = "5-buttons-battery" - local device_info_json = dkjson.encode(device_info_copy) - test.socket.device_lifecycle:__queue_receive({ mock_device.id, "infoChanged", device_info_json }) - test.socket.matter:__expect_send({mock_device.id, subscribe_request}) - expect_configure_buttons() - - test.socket.matter:__expect_send({mock_device.id, clusters.OnOff.attributes.OnOff:read(mock_device)}) - test.socket.device_lifecycle:__queue_receive({ mock_child.id, "added" }) - test.socket.device_lifecycle:__queue_receive({ mock_child.id, "init" }) - mock_child:expect_metadata_update({ provisioning_state = "PROVISIONED" }) - test.socket.device_lifecycle:__queue_receive({ mock_child.id, "doConfigure" }) end -- All messages queued and expectations set are done before the driver is actually run @@ -409,15 +396,15 @@ test.register_message_test( test.register_coroutine_test( "Test MCD configuration not including switch for unsupported switch device type, create child device instead", function() + local unsup_mock_device = mock_device_mcd_unsupported_switch_device_type -- added sets a bunch of fields on the device, and calls init local cluster_subscribe_list = { - clusters.OnOff.attributes.OnOff, + -- clusters.OnOff.attributes.OnOff, clusters.Switch.server.events.InitialPress, clusters.Switch.server.events.LongPress, clusters.Switch.server.events.ShortRelease, clusters.Switch.server.events.MultiPressComplete, } - local unsup_mock_device = mock_device_mcd_unsupported_switch_device_type local subscribe_request = cluster_subscribe_list[1]:subscribe(unsup_mock_device) for _, cluster in ipairs(cluster_subscribe_list) do subscribe_request:merge(cluster:subscribe(unsup_mock_device)) @@ -436,12 +423,23 @@ test.register_coroutine_test( parent_device_id = unsup_mock_device.id, parent_assigned_child_key = string.format("%d", 7) }) + test.socket.capability:__expect_send(unsup_mock_device:generate_test_message("main", capabilities.button.supportedButtonValues({"pushed", "held"}, {visibility = {displayed = false}}))) + test.socket.capability:__expect_send(unsup_mock_device:generate_test_message("main", button_attr.pushed({state_change = false}))) unsup_mock_device:expect_metadata_update({ profile = "2-button" }) unsup_mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + test.wait_for_events() local updated_device_profile = t_utils.get_profile_definition("2-button.yml") test.socket.device_lifecycle:__queue_receive(unsup_mock_device:generate_info_changed({ profile = updated_device_profile })) + + local cluster_subscribe_list = { + -- clusters.OnOff.attributes.OnOff, + clusters.Switch.server.events.InitialPress, + clusters.Switch.server.events.LongPress, + clusters.Switch.server.events.ShortRelease, + clusters.Switch.server.events.MultiPressComplete, + } local subscribe_request = cluster_subscribe_list[1]:subscribe(unsup_mock_device) for i, cluster in ipairs(cluster_subscribe_list) do if i > 1 then @@ -475,5 +473,28 @@ test.register_coroutine_test( end ) +test.register_coroutine_test( + "Test infoChanged event", + function () + -- simulate the profile change update taking affect and the device info changing + local subscribe_request = CLUSTER_SUBSCRIBE_LIST[1]:subscribe(mock_device) + for i, clus in ipairs(CLUSTER_SUBSCRIBE_LIST) do + if i > 1 then subscribe_request:merge(clus:subscribe(mock_device)) end + end + local device_info_copy = utils.deep_copy(mock_device.raw_st_data) + device_info_copy.profile.id = "5-buttons-battery" + local device_info_json = dkjson.encode(device_info_copy) + test.socket.matter:__expect_send({mock_device.id, subscribe_request}) + expect_configure_buttons() + test.socket.device_lifecycle:__queue_receive({ mock_device.id, "infoChanged", device_info_json }) + test.socket.matter:__expect_send({mock_device.id, clusters.OnOff.attributes.OnOff:read(mock_device)}) + test.socket.device_lifecycle:__queue_receive({ mock_child.id, "added" }) + test.socket.device_lifecycle:__queue_receive({ mock_child.id, "init" }) + test.socket.matter:__expect_send({mock_device.id, subscribe_request}) + mock_child:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + test.socket.device_lifecycle:__queue_receive({ mock_child.id, "doConfigure" }) + end +) + -- run the tests test.run_registered_tests() diff --git a/drivers/SmartThings/matter-switch/src/test/test_matter_switch.lua b/drivers/SmartThings/matter-switch/src/test/test_matter_switch.lua index e38003ce5a..5a693d2f79 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_matter_switch.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_matter_switch.lua @@ -125,6 +125,7 @@ local cluster_subscribe_list = { clusters.ColorControl.attributes.ColorTemperatureMireds, clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds, clusters.ColorControl.attributes.ColorTempPhysicalMinMireds, + clusters.ColorControl.attributes.ColorMode, } local function set_color_mode(device, endpoint, color_mode) diff --git a/drivers/SmartThings/matter-switch/src/test/test_matter_switch_device_types.lua b/drivers/SmartThings/matter-switch/src/test/test_matter_switch_device_types.lua index 9cee75d69d..5824995802 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_matter_switch_device_types.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_matter_switch_device_types.lua @@ -435,14 +435,8 @@ local mock_device_light_level_motion = test.mock_device.build_test_matter_device local function test_init_parent_child_switch_types() test.mock_device.add_test_device(mock_device_parent_child_switch_types) - local subscribe_request = clusters.OnOff.attributes.OnOff:subscribe(mock_device_parent_child_switch_types) - test.socket.device_lifecycle:__queue_receive({ mock_device_parent_child_switch_types.id, "added" }) - test.socket.matter:__expect_send({mock_device_parent_child_switch_types.id, subscribe_request}) - test.socket.device_lifecycle:__queue_receive({ mock_device_parent_child_switch_types.id, "init" }) - test.socket.matter:__expect_send({mock_device_parent_child_switch_types.id, subscribe_request}) - test.socket.device_lifecycle:__queue_receive({ mock_device_parent_child_switch_types.id, "doConfigure" }) test.socket.matter:__expect_send({ mock_device_parent_child_switch_types.id, @@ -479,13 +473,10 @@ end local function test_init_parent_client_child_server() test.mock_device.add_test_device(mock_device_parent_client_child_server) - local subscribe_request = clusters.OnOff.attributes.OnOff:subscribe(mock_device_parent_client_child_server) test.socket.device_lifecycle:__queue_receive({ mock_device_parent_client_child_server.id, "added" }) - test.socket.matter:__expect_send({mock_device_parent_client_child_server.id, subscribe_request}) test.socket.device_lifecycle:__queue_receive({ mock_device_parent_client_child_server.id, "init" }) - test.socket.matter:__expect_send({mock_device_parent_client_child_server.id, subscribe_request}) test.socket.device_lifecycle:__queue_receive({ mock_device_parent_client_child_server.id, "doConfigure" }) mock_device_parent_client_child_server:expect_metadata_update({ profile = "switch-binary" }) @@ -594,16 +585,17 @@ local function test_init_parent_child_different_types() test.mock_device.add_test_device(mock_device_parent_child_different_types) local cluster_subscribe_list = { clusters.OnOff.attributes.OnOff, - clusters.LevelControl.attributes.CurrentLevel, - clusters.LevelControl.attributes.MaxLevel, - clusters.LevelControl.attributes.MinLevel, - clusters.ColorControl.attributes.ColorTemperatureMireds, - clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds, - clusters.ColorControl.attributes.ColorTempPhysicalMinMireds, - clusters.ColorControl.attributes.CurrentHue, - clusters.ColorControl.attributes.CurrentSaturation, - clusters.ColorControl.attributes.CurrentX, - clusters.ColorControl.attributes.CurrentY + -- clusters.LevelControl.attributes.CurrentLevel, + -- clusters.LevelControl.attributes.MaxLevel, + -- clusters.LevelControl.attributes.MinLevel, + -- clusters.ColorControl.attributes.ColorTemperatureMireds, + -- clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds, + -- clusters.ColorControl.attributes.ColorTempPhysicalMinMireds, + -- clusters.ColorControl.attributes.CurrentHue, + -- clusters.ColorControl.attributes.CurrentSaturation, + -- clusters.ColorControl.attributes.CurrentX, + -- clusters.ColorControl.attributes.CurrentY, + -- clusters.ColorControl.attributes.ColorMode, } local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device_parent_child_different_types) for i, cluster in ipairs(cluster_subscribe_list) do diff --git a/drivers/SmartThings/matter-switch/src/test/test_multi_switch_parent_child_lights.lua b/drivers/SmartThings/matter-switch/src/test/test_multi_switch_parent_child_lights.lua index 4a5787346f..ad3070f5b5 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_multi_switch_parent_child_lights.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_multi_switch_parent_child_lights.lua @@ -162,7 +162,8 @@ local function test_init() clusters.ColorControl.attributes.CurrentHue, clusters.ColorControl.attributes.CurrentSaturation, clusters.ColorControl.attributes.CurrentX, - clusters.ColorControl.attributes.CurrentY + clusters.ColorControl.attributes.CurrentY, + clusters.ColorControl.attributes.ColorMode, } local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device) for i, cluster in ipairs(cluster_subscribe_list) do @@ -239,7 +240,8 @@ local function test_init_parent_child_endpoints_non_sequential() clusters.ColorControl.attributes.CurrentHue, clusters.ColorControl.attributes.CurrentSaturation, clusters.ColorControl.attributes.CurrentX, - clusters.ColorControl.attributes.CurrentY + clusters.ColorControl.attributes.CurrentY, + clusters.ColorControl.attributes.ColorMode, } local subscribe_request = cluster_subscribe_list[1]:subscribe(unsup_mock_device) for i, cluster in ipairs(cluster_subscribe_list) do diff --git a/drivers/SmartThings/matter-switch/src/test/test_multi_switch_parent_child_plugs.lua b/drivers/SmartThings/matter-switch/src/test/test_multi_switch_parent_child_plugs.lua index 215c8f34ed..09fa39c4f6 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_multi_switch_parent_child_plugs.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_multi_switch_parent_child_plugs.lua @@ -162,7 +162,8 @@ local function test_init() clusters.ColorControl.attributes.CurrentHue, clusters.ColorControl.attributes.CurrentSaturation, clusters.ColorControl.attributes.CurrentX, - clusters.ColorControl.attributes.CurrentY + clusters.ColorControl.attributes.CurrentY, + clusters.ColorControl.attributes.ColorMode, } local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device) for i, cluster in ipairs(cluster_subscribe_list) do @@ -237,7 +238,8 @@ local function test_init_parent_child_endpoints_non_sequential() clusters.ColorControl.attributes.CurrentHue, clusters.ColorControl.attributes.CurrentSaturation, clusters.ColorControl.attributes.CurrentX, - clusters.ColorControl.attributes.CurrentY + clusters.ColorControl.attributes.CurrentY, + clusters.ColorControl.attributes.ColorMode, } local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device_parent_child_endpoints_non_sequential) for i, cluster in ipairs(cluster_subscribe_list) do