diff --git a/drivers/SmartThings/matter-switch/src/init.lua b/drivers/SmartThings/matter-switch/src/init.lua index d2bf9aa22e..57bc1ef153 100644 --- a/drivers/SmartThings/matter-switch/src/init.lua +++ b/drivers/SmartThings/matter-switch/src/init.lua @@ -44,19 +44,12 @@ local SWITCH_LEVEL_LIGHTING_MIN = 1 local CURRENT_HUESAT_ATTR_MIN = 0 local CURRENT_HUESAT_ATTR_MAX = 254 -local SWITCH_INITIALIZED = "__switch_intialized" --- COMPONENT_TO_ENDPOINT_MAP is here only to preserve the endpoint mapping for +-- COMPONENT_TO_ENDPOINT_MAP is here to preserve the endpoint mapping for -- devices that were joined to this driver as MCD devices before the transition --- to join all matter-switch devices as parent-child. This value will only exist --- in the device table for devices that joined prior to this transition, and it --- will not be set for new devices. +-- to join switch devices as parent-child. This value will exist in the device +-- table for devices that joined prior to this transition, and is also used for +-- button devices that require component mapping. local COMPONENT_TO_ENDPOINT_MAP = "__component_to_endpoint_map" --- COMPONENT_TO_ENDPOINT_MAP_BUTTON is for devices with button endpoints, to --- preserve the MCD functionality for button devices from the matter-button --- driver after it was merged into the matter-switch driver. Note that devices --- containing both button endpoints and switch endpoints will use this field --- rather than COMPONENT_TO_ENDPOINT_MAP. -local COMPONENT_TO_ENDPOINT_MAP_BUTTON = "__component_to_endpoint_map_button" local ENERGY_MANAGEMENT_ENDPOINT = "__energy_management_endpoint" local IS_PARENT_CHILD_DEVICE = "__is_parent_child_device" local COLOR_TEMP_BOUND_RECEIVED_KELVIN = "__colorTemp_bound_received_kelvin" @@ -67,6 +60,12 @@ local LEVEL_BOUND_RECEIVED = "__level_bound_received" local LEVEL_MIN = "__level_min" local LEVEL_MAX = "__level_max" local COLOR_MODE = "__color_mode" + +local updated_fields = { + { field_name = "__component_to_endpoint_map_button", updated_field_name = COMPONENT_TO_ENDPOINT_MAP }, + { field_name = "__switch_intialized", updated_field_name = nil } +} + local HUE_SAT_COLOR_MODE = clusters.ColorControl.types.ColorMode.CURRENT_HUE_AND_CURRENT_SATURATION local X_Y_COLOR_MODE = clusters.ColorControl.types.ColorMode.CURRENTX_AND_CURRENTY @@ -292,8 +291,6 @@ local HELD_THRESHOLD = 1 -- this is the number of buttons for which we have a static profile already made local STATIC_BUTTON_PROFILE_SUPPORTED = {1, 2, 3, 4, 5, 6, 7, 8} -local BUTTON_DEVICE_PROFILED = "__button_device_profiled" - -- Some switches will send a MultiPressComplete event as part of a long press sequence. Normally the driver will create a -- button capability event on receipt of MultiPressComplete, but in this case that would result in an extra event because -- the "held" capability event is generated when the LongPress event is received. The IGNORE_NEXT_MPC flag is used @@ -406,6 +403,7 @@ local function device_type_supports_button_switch_combination(device, endpoint_i end local function get_first_non_zero_endpoint(endpoints) + table.sort(endpoints) for _,ep in ipairs(endpoints) do if ep ~= 0 then -- 0 is the matter RootNode endpoint return ep @@ -425,8 +423,6 @@ local function find_default_endpoint(device) local switch_eps = device:get_endpoints(clusters.OnOff.ID) local button_eps = device:get_endpoints(clusters.Switch.ID, {feature_bitmap=clusters.Switch.types.SwitchFeature.MOMENTARY_SWITCH}) - table.sort(switch_eps) - table.sort(button_eps) -- Return the first switch endpoint as the default endpoint if no button endpoints are present if #button_eps == 0 and #switch_eps > 0 then @@ -456,7 +452,7 @@ local function find_default_endpoint(device) end local function component_to_endpoint(device, component) - local map = device:get_field(COMPONENT_TO_ENDPOINT_MAP_BUTTON) or device:get_field(COMPONENT_TO_ENDPOINT_MAP) or {} + local map = device:get_field(COMPONENT_TO_ENDPOINT_MAP) or {} if map[component] then return map[component] end @@ -464,7 +460,7 @@ local function component_to_endpoint(device, component) end local function endpoint_to_component(device, ep) - local map = device:get_field(COMPONENT_TO_ENDPOINT_MAP_BUTTON) or device:get_field(COMPONENT_TO_ENDPOINT_MAP) or {} + local map = device:get_field(COMPONENT_TO_ENDPOINT_MAP) or {} for component, endpoint in pairs(map) do if endpoint == ep then return component @@ -473,6 +469,17 @@ local function endpoint_to_component(device, ep) return "main" end +local function check_field_name_updates(device) + for _, field in ipairs(updated_fields) do + if device:get_field(field.field_name) then + if field.updated_field_name ~= nil then + device:set_field(field.updated_field_name, device:get_field(field.field_name), {persist = true}) + end + device:set_field(field.field_name, nil) + end + end +end + local function assign_child_profile(device, child_ep) local profile @@ -512,41 +519,6 @@ local function assign_child_profile(device, child_ep) return profile or "switch-binary" end -local function do_configure(driver, device) - if device:get_field(BUTTON_DEVICE_PROFILED) then - return - end - local fan_eps = device:get_endpoints(clusters.FanControl.ID) - local level_eps = device:get_endpoints(clusters.LevelControl.ID) - local energy_eps = embedded_cluster_utils.get_endpoints(device, clusters.ElectricalEnergyMeasurement.ID) - local power_eps = embedded_cluster_utils.get_endpoints(device, clusters.ElectricalPowerMeasurement.ID) - local valve_eps = embedded_cluster_utils.get_endpoints(device, clusters.ValveConfigurationAndControl.ID) - local profile_name = nil - local level_support = "" - if #level_eps > 0 then - level_support = "-level" - end - if #energy_eps > 0 and #power_eps > 0 then - profile_name = "plug" .. level_support .. "-power-energy-powerConsumption" - elseif #energy_eps > 0 then - profile_name = "plug" .. level_support .. "-energy-powerConsumption" - elseif #power_eps > 0 then - profile_name = "plug" .. level_support .. "-power" - elseif #valve_eps > 0 then - profile_name = "water-valve" - if #embedded_cluster_utils.get_endpoints(device, clusters.ValveConfigurationAndControl.ID, - {feature_bitmap = clusters.ValveConfigurationAndControl.types.Feature.LEVEL}) > 0 then - profile_name = profile_name .. "-level" - end - elseif #fan_eps > 0 then - profile_name = "light-color-level-fan" - end - - if profile_name then - device:try_update_metadata({ profile = profile_name }) - end -end - local function configure_buttons(device) if device.network_type == device_lib.NETWORK_TYPE_CHILD then return @@ -603,7 +575,7 @@ local function build_button_component_map(device, main_endpoint, button_eps) component_map[button_component] = ep end end - device:set_field(COMPONENT_TO_ENDPOINT_MAP_BUTTON, component_map, {persist = true}) + device:set_field(COMPONENT_TO_ENDPOINT_MAP, component_map, {persist = true}) end local function build_button_profile(device, main_endpoint, num_button_eps) @@ -613,13 +585,10 @@ local function build_button_profile(device, main_endpoint, num_button_eps) end local battery_supported = #device:get_endpoints(clusters.PowerSource.ID, {feature_bitmap = clusters.PowerSource.types.PowerSourceFeature.BATTERY}) > 0 if battery_supported then -- battery profiles are configured later, in power_source_attribute_list_handler - local attribute_list_read = im.InteractionRequest(im.InteractionRequest.RequestType.READ, {}) - attribute_list_read:merge(clusters.PowerSource.attributes.AttributeList:read()) - device:send(attribute_list_read) + device:send(clusters.PowerSource.attributes.AttributeList:read(device)) else device:try_update_metadata({profile = profile_name}) end - device:set_field(BUTTON_DEVICE_PROFILED, true) end local function build_child_switch_profiles(driver, device, main_endpoint) @@ -683,13 +652,15 @@ local function handle_light_switch_with_onOff_server_clusters(device, main_endpo end local function initialize_buttons_and_switches(driver, device, main_endpoint) + local profile_found = false local button_eps = device:get_endpoints(clusters.Switch.ID, {feature_bitmap=clusters.Switch.types.SwitchFeature.MOMENTARY_SWITCH}) if tbl_contains(STATIC_BUTTON_PROFILE_SUPPORTED, #button_eps) then build_button_profile(device, main_endpoint, #button_eps) -- All button endpoints found will be added as additional components in the profile containing the main_endpoint. - -- The resulting endpoint to component map is saved in the COMPONENT_TO_ENDPOINT_MAP_BUTTON field + -- The resulting endpoint to component map is saved in the COMPONENT_TO_ENDPOINT_MAP field build_button_component_map(device, main_endpoint, button_eps) configure_buttons(device) + profile_found = true end -- Without support for bindings, only clusters that are implemented as server are counted. This count is handled @@ -701,9 +672,9 @@ local function initialize_buttons_and_switches(driver, device, main_endpoint) -- Note: since their device type isn't supported, these devices join as a matter-thing. if num_switch_server_eps > 0 and detect_matter_thing(device) then handle_light_switch_with_onOff_server_clusters(device, main_endpoint) + profile_found = true end - - device:set_field(SWITCH_INITIALIZED, true, {persist = true}) + return profile_found end local function detect_bridge(device) @@ -721,20 +692,13 @@ local function device_init(driver, device) if device.network_type ~= device_lib.NETWORK_TYPE_MATTER then return end - + check_field_name_updates(device) device:set_component_to_endpoint_fn(component_to_endpoint) device:set_endpoint_to_component_fn(endpoint_to_component) - - local main_endpoint = find_default_endpoint(device) - if not device:get_field(COMPONENT_TO_ENDPOINT_MAP) and -- this field is only set for old MCD devices. See comments in the field def. - not device:get_field(SWITCH_INITIALIZED) and - not detect_bridge(device) then - -- initialize the main device card with buttons if applicable, and create child devices as needed for multi-switch devices. - initialize_buttons_and_switches(driver, device, main_endpoint) - end if device:get_field(IS_PARENT_CHILD_DEVICE) then device:set_find_child(find_child) end + local main_endpoint = 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 ~= main_endpoint then @@ -756,6 +720,50 @@ local function device_init(driver, device) device:subscribe() end +local function do_configure(driver, device) + if detect_bridge(device) then + return + end + local main_endpoint = find_default_endpoint(device) + -- initialize the main device card with buttons if applicable, and create child devices as needed for multi-switch devices. + local profile_found = initialize_buttons_and_switches(driver, device, main_endpoint) + if device:get_field(IS_PARENT_CHILD_DEVICE) then + device:set_find_child(find_child) + end + if profile_found then + return + end + + local fan_eps = device:get_endpoints(clusters.FanControl.ID) + local level_eps = device:get_endpoints(clusters.LevelControl.ID) + local energy_eps = embedded_cluster_utils.get_endpoints(device, clusters.ElectricalEnergyMeasurement.ID) + local power_eps = embedded_cluster_utils.get_endpoints(device, clusters.ElectricalPowerMeasurement.ID) + local valve_eps = embedded_cluster_utils.get_endpoints(device, clusters.ValveConfigurationAndControl.ID) + local profile_name = nil + local level_support = "" + if #level_eps > 0 then + level_support = "-level" + end + if #energy_eps > 0 and #power_eps > 0 then + profile_name = "plug" .. level_support .. "-power-energy-powerConsumption" + elseif #energy_eps > 0 then + profile_name = "plug" .. level_support .. "-energy-powerConsumption" + elseif #power_eps > 0 then + profile_name = "plug" .. level_support .. "-power" + elseif #valve_eps > 0 then + profile_name = "water-valve" + if #embedded_cluster_utils.get_endpoints(device, clusters.ValveConfigurationAndControl.ID, + {feature_bitmap = clusters.ValveConfigurationAndControl.types.Feature.LEVEL}) > 0 then + profile_name = profile_name .. "-level" + end + elseif #fan_eps > 0 then + profile_name = "light-color-level-fan" + end + if profile_name then + device:try_update_metadata({ profile = profile_name }) + end +end + local function device_removed(driver, device) log.info("device removed") delete_import_poll_schedule(device) diff --git a/drivers/SmartThings/matter-switch/src/test/test_aqara_climate_sensor_w100.lua b/drivers/SmartThings/matter-switch/src/test/test_aqara_climate_sensor_w100.lua index 270bc6febb..830a9b99f8 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_aqara_climate_sensor_w100.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_aqara_climate_sensor_w100.lua @@ -133,10 +133,6 @@ local function test_init() clusters.Switch.server.events.MultiPressComplete, } - local read_attribute_list = clusters.PowerSource.attributes.AttributeList:read() - test.socket.matter:__expect_send({aqara_mock_device.id, read_attribute_list}) - test.socket.matter:__queue_receive({aqara_mock_device.id, clusters.PowerSource.attributes.AttributeList:build_test_report_data(aqara_mock_device, 6, {uint32(0x0C)})}) - local subscribe_request = cluster_subscribe_list[1]:subscribe(aqara_mock_device) for i, cluster in ipairs(cluster_subscribe_list) do if i > 1 then @@ -144,16 +140,17 @@ local function test_init() end end - configure_buttons() test.socket.matter:__expect_send({aqara_mock_device.id, subscribe_request}) + test.socket.device_lifecycle:__queue_receive({ aqara_mock_device.id, "doConfigure" }) + local read_attribute_list = clusters.PowerSource.attributes.AttributeList:read() + test.socket.matter:__expect_send({aqara_mock_device.id, read_attribute_list}) + configure_buttons() + aqara_mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) test.mock_device.add_test_device(aqara_mock_device) test.set_rpc_version(5) test.socket.device_lifecycle:__queue_receive({ aqara_mock_device.id, "added" }) test.socket.matter:__expect_send({aqara_mock_device.id, subscribe_request}) - test.mock_devices_api._expected_device_updates[aqara_mock_device.device_id] = "00000000-1111-2222-3333-000000000001" - test.mock_devices_api._expected_device_updates[1] = {device_id = "00000000-1111-2222-3333-000000000001"} - test.mock_devices_api._expected_device_updates[1].metadata = {deviceId="00000000-1111-2222-3333-000000000001", profileReference="3-button-battery-temperature-humidity"} local device_info_copy = utils.deep_copy(aqara_mock_device.raw_st_data) device_info_copy.profile.id = "3-button-battery-temperature-humidity" @@ -165,9 +162,15 @@ end test.set_test_init_function(test_init) +local function update_profile() + test.socket.matter:__queue_receive({aqara_mock_device.id, clusters.PowerSource.attributes.AttributeList:build_test_report_data(aqara_mock_device, 6, {uint32(0x0C)})}) + aqara_mock_device:expect_metadata_update({ profile = "3-button-battery-temperature-humidity" }) +end + test.register_coroutine_test( "Temperature reports should generate correct messages", function () + update_profile() test.socket.matter:__queue_receive( { aqara_mock_device.id, @@ -183,6 +186,7 @@ test.register_coroutine_test( test.register_coroutine_test( "Min and max temperature attributes set capability constraint", function () + update_profile() test.socket.matter:__queue_receive( { aqara_mock_device.id, @@ -204,6 +208,7 @@ test.register_coroutine_test( test.register_coroutine_test( "Relative humidity reports should generate correct messages", function () + update_profile() test.socket.matter:__queue_receive( { aqara_mock_device.id, @@ -228,6 +233,7 @@ test.register_coroutine_test( test.register_coroutine_test( "Battery percent reports should generate correct messages", function () + update_profile() test.socket.matter:__queue_receive( { aqara_mock_device.id, @@ -243,6 +249,7 @@ test.register_coroutine_test( test.register_coroutine_test( "Handle single press sequence for a long hold on long-release-capable button", -- only a long press event should generate a held event function () + update_profile() test.timer.__create_and_queue_test_time_advance_timer(2, "oneshot") test.socket.matter:__queue_receive( { @@ -264,6 +271,7 @@ test.register_coroutine_test( test.register_coroutine_test( "Handle single press sequence for a long hold on multi button", -- pushes should only be generated from multiPressComplete events function () + update_profile() test.timer.__create_and_queue_test_time_advance_timer(2, "oneshot") test.socket.matter:__queue_receive( { @@ -285,6 +293,7 @@ test.register_coroutine_test( test.register_coroutine_test( "Handle single press sequence for a multi press on multi button", function() + update_profile() test.socket.matter:__queue_receive( { aqara_mock_device.id, @@ -322,6 +331,7 @@ test.register_coroutine_test( test.register_coroutine_test( "Handle long press sequence for a long hold on long-release-capable button", -- only a long press event should generate a held event function () + update_profile() test.socket.matter:__queue_receive( { aqara_mock_device.id, @@ -347,6 +357,7 @@ test.register_coroutine_test( test.register_coroutine_test( "Handle long press sequence for a long hold on multi button", function () + update_profile() test.socket.matter:__queue_receive( { aqara_mock_device.id, @@ -372,6 +383,7 @@ test.register_coroutine_test( test.register_coroutine_test( "Handle double press", function() + update_profile() test.socket.matter:__queue_receive( { aqara_mock_device.id, @@ -387,6 +399,7 @@ test.register_coroutine_test( test.register_coroutine_test( "Receiving a max press attribute of 2 should emit correct event", function() + update_profile() test.socket.matter:__queue_receive( { aqara_mock_device.id, @@ -402,6 +415,7 @@ test.register_coroutine_test( test.register_coroutine_test( "Handle single press sequence for emulated hold on short-release-only button", function () + update_profile() test.timer.__create_and_queue_test_time_advance_timer(2, "oneshot") test.socket.matter:__queue_receive( { @@ -420,46 +434,44 @@ test.register_coroutine_test( end ) -test.register_message_test( - "Receiving a max press attribute of 3 should emit correct event", { - { - channel = "matter", - direction = "receive", - message = { +test.register_coroutine_test( + "Receiving a max press attribute of 3 should emit correct event", + function () + update_profile() + test.socket.matter:__queue_receive( + { aqara_mock_device.id, clusters.Switch.attributes.MultiPressMax:build_test_report_data( aqara_mock_device, 5, 3 ) - }, - }, - { - channel = "capability", - direction = "send", - message = aqara_mock_device:generate_test_message("button3", - capabilities.button.supportedButtonValues({"pushed", "double", "held", "pushed_3x"}, {visibility = {displayed = false}})) - }, - } + } + ) + test.socket.capability:__expect_send( + aqara_mock_device:generate_test_message( + "button3", capabilities.button.supportedButtonValues({"pushed", "double", "held", "pushed_3x"}, {visibility = {displayed = false}}) + ) + ) + end ) -test.register_message_test( - "Receiving a max press attribute of greater than 6 should only emit up to pushed_6x", { - { - channel = "matter", - direction = "receive", - message = { +test.register_coroutine_test( + "Receiving a max press attribute of 3 should emit correct event", + function () + update_profile() + test.socket.matter:__queue_receive( + { aqara_mock_device.id, clusters.Switch.attributes.MultiPressMax:build_test_report_data( aqara_mock_device, 3, 7 ) - }, - }, - { - channel = "capability", - direction = "send", - message = aqara_mock_device:generate_test_message("button1", - capabilities.button.supportedButtonValues({"pushed", "double", "held", "pushed_3x", "pushed_4x", "pushed_5x", "pushed_6x"}, {visibility = {displayed = false}})) - }, - } + } + ) + test.socket.capability:__expect_send( + aqara_mock_device:generate_test_message( + "button1", capabilities.button.supportedButtonValues({"pushed", "double", "held", "pushed_3x", "pushed_4x", "pushed_5x", "pushed_6x"}, {visibility = {displayed = false}}) + ) + ) + end ) test.run_registered_tests() diff --git a/drivers/SmartThings/matter-switch/src/test/test_aqara_light_switch_h2.lua b/drivers/SmartThings/matter-switch/src/test/test_aqara_light_switch_h2.lua index 3ed95aa15f..369689e181 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_aqara_light_switch_h2.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_aqara_light_switch_h2.lua @@ -177,6 +177,11 @@ local function test_init() end end test.socket.matter:__expect_send({aqara_mock_device.id, subscribe_request}) + test.socket.device_lifecycle:__queue_receive({ aqara_mock_device.id, "doConfigure" }) + test.mock_devices_api._expected_device_updates[aqara_mock_device.device_id] = "00000000-1111-2222-3333-000000000001" + test.mock_devices_api._expected_device_updates[1] = {device_id = "00000000-1111-2222-3333-000000000001"} + test.mock_devices_api._expected_device_updates[1].metadata = {deviceId="00000000-1111-2222-3333-000000000001", profileReference="4-button"} + aqara_mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) test.mock_device.add_test_device(aqara_mock_device) -- to test powerConsumptionReport test.timer.__create_and_queue_test_time_advance_timer(60 * 15, "interval", "create_poll_report_schedule") @@ -204,9 +209,6 @@ local function test_init() test.socket.device_lifecycle:__queue_receive({ aqara_mock_device.id, "added" }) configure_buttons() test.socket.matter:__expect_send({aqara_mock_device.id, subscribe_request}) - test.mock_devices_api._expected_device_updates[aqara_mock_device.device_id] = "00000000-1111-2222-3333-000000000001" - test.mock_devices_api._expected_device_updates[1] = {device_id = "00000000-1111-2222-3333-000000000001"} - test.mock_devices_api._expected_device_updates[1].metadata = {deviceId="00000000-1111-2222-3333-000000000001", profileReference="4-button"} aqara_mock_device:set_field(DEFERRED_CONFIGURE, true, opts) local device_info_copy = utils.deep_copy(aqara_mock_device.raw_st_data) diff --git a/drivers/SmartThings/matter-switch/src/test/test_matter_button.lua b/drivers/SmartThings/matter-switch/src/test/test_matter_button.lua index ae6f0017b5..f34f432ec7 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_matter_button.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_matter_button.lua @@ -62,11 +62,13 @@ local function test_init() for i, clus in ipairs(CLUSTER_SUBSCRIBE_LIST) do if i > 1 then subscribe_request:merge(clus:subscribe(mock_device)) end end + 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" }) + test.mock_device.add_test_device(mock_device) local read_attribute_list = clusters.PowerSource.attributes.AttributeList:read() test.socket.matter:__expect_send({mock_device.id, read_attribute_list}) configure_buttons() - test.socket.matter:__expect_send({mock_device.id, subscribe_request}) - test.mock_device.add_test_device(mock_device) test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) test.socket.matter:__expect_send({mock_device.id, subscribe_request}) local device_info_copy = utils.deep_copy(mock_device.raw_st_data) diff --git a/drivers/SmartThings/matter-switch/src/test/test_matter_multi_button.lua b/drivers/SmartThings/matter-switch/src/test/test_matter_multi_button.lua index d74eaf04a9..624a3ab205 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_matter_multi_button.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_matter_multi_button.lua @@ -121,11 +121,13 @@ local function test_init() for i, clus in ipairs(CLUSTER_SUBSCRIBE_LIST) do if i > 1 then subscribe_request:merge(clus:subscribe(mock_device)) end end + 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" }) + test.mock_device.add_test_device(mock_device) local read_attribute_list = clusters.PowerSource.attributes.AttributeList:read() test.socket.matter:__expect_send({mock_device.id, read_attribute_list}) configure_buttons() - test.socket.matter:__expect_send({mock_device.id, subscribe_request}) - test.mock_device.add_test_device(mock_device) test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) test.socket.matter:__expect_send({mock_device.id, subscribe_request}) local device_info_copy = utils.deep_copy(mock_device.raw_st_data) 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 dde176de98..962ac6c167 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 @@ -198,6 +198,15 @@ local function test_init() if i > 1 then subscribe_request:merge(clus:subscribe(mock_device)) end end 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({ profile = "light-level-3-button" }) + mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + local device_info_copy = utils.deep_copy(mock_device.raw_st_data) + device_info_copy.profile.id = "3-button" + 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}) + configure_buttons() test.mock_device.add_test_device(mock_device) test.mock_device.add_test_device(mock_child) mock_device:expect_device_create({ @@ -210,13 +219,6 @@ local function test_init() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) configure_buttons() test.socket.matter:__expect_send({mock_device.id, subscribe_request}) - mock_device:expect_metadata_update({ profile = "light-level-3-button" }) - local device_info_copy = utils.deep_copy(mock_device.raw_st_data) - device_info_copy.profile.id = "3-button" - 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}) - configure_buttons() end local function test_init_mcd_unsupported_switch_device_type() @@ -233,7 +235,10 @@ local function test_init_mcd_unsupported_switch_device_type() subscribe_request:merge(cluster:subscribe(mock_device_mcd_unsupported_switch_device_type)) end end + test.socket.matter:__expect_send({mock_device_mcd_unsupported_switch_device_type.id, subscribe_request}) + test.socket.device_lifecycle:__queue_receive({ mock_device_mcd_unsupported_switch_device_type.id, "doConfigure" }) mock_device_mcd_unsupported_switch_device_type:expect_metadata_update({ profile = "2-button" }) + mock_device_mcd_unsupported_switch_device_type:expect_metadata_update({ provisioning_state = "PROVISIONED" }) mock_device_mcd_unsupported_switch_device_type:expect_device_create({ type = "EDGE_CHILD", label = "Matter Switch 1", @@ -242,7 +247,6 @@ local function test_init_mcd_unsupported_switch_device_type() parent_assigned_child_key = string.format("%d", 7) }) test.mock_device.add_test_device(mock_device_mcd_unsupported_switch_device_type) - test.socket.matter:__expect_send({mock_device_mcd_unsupported_switch_device_type.id, subscribe_request}) end test.set_test_init_function(test_init) 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 4d8325d2fa..6debff2163 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 @@ -365,8 +365,12 @@ local mock_device_parent_child_unsupported_device_type = test.mock_device.build_ local function test_init_parent_child_switch_types() local subscribe_request = clusters.OnOff.attributes.OnOff:subscribe(mock_device_parent_child_switch_types) test.socket.matter:__expect_send({mock_device_parent_child_switch_types.id, subscribe_request}) - test.mock_device.add_test_device(mock_device_parent_child_switch_types) + + test.socket.device_lifecycle:__queue_receive({ mock_device_parent_child_switch_types.id, "doConfigure" }) mock_device_parent_child_switch_types:expect_metadata_update({ profile = "switch-level" }) + mock_device_parent_child_switch_types:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + + test.mock_device.add_test_device(mock_device_parent_child_switch_types) mock_device_parent_child_switch_types:expect_device_create({ type = "EDGE_CHILD", @@ -379,7 +383,9 @@ end local function test_init_onoff() test.mock_device.add_test_device(mock_device_onoff) + test.socket.device_lifecycle:__queue_receive({ mock_device_onoff.id, "doConfigure" }) mock_device_onoff:expect_metadata_update({ profile = "switch-binary" }) + mock_device_onoff:expect_metadata_update({ provisioning_state = "PROVISIONED" }) end local function test_init_onoff_client() @@ -389,18 +395,24 @@ end local function test_init_parent_client_child_server() local subscribe_request = clusters.OnOff.attributes.OnOff:subscribe(mock_device_parent_client_child_server) test.socket.matter:__expect_send({mock_device_parent_client_child_server.id, subscribe_request}) - test.mock_device.add_test_device(mock_device_parent_client_child_server) + 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" }) + mock_device_parent_client_child_server:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + test.mock_device.add_test_device(mock_device_parent_client_child_server) end local function test_init_dimmer() test.mock_device.add_test_device(mock_device_dimmer) + test.socket.device_lifecycle:__queue_receive({ mock_device_dimmer.id, "doConfigure" }) mock_device_dimmer:expect_metadata_update({ profile = "switch-level" }) + mock_device_dimmer:expect_metadata_update({ provisioning_state = "PROVISIONED" }) end local function test_init_color_dimmer() test.mock_device.add_test_device(mock_device_color_dimmer) + test.socket.device_lifecycle:__queue_receive({ mock_device_color_dimmer.id, "doConfigure" }) mock_device_color_dimmer:expect_metadata_update({ profile = "switch-color-level" }) + mock_device_color_dimmer:expect_metadata_update({ provisioning_state = "PROVISIONED" }) end local function test_init_mounted_on_off_control() @@ -414,6 +426,8 @@ local function test_init_mounted_on_off_control() end end test.socket.matter:__expect_send({mock_device_mounted_on_off_control.id, subscribe_request}) + test.socket.device_lifecycle:__queue_receive({ mock_device_mounted_on_off_control.id, "doConfigure" }) + mock_device_mounted_on_off_control:expect_metadata_update({ provisioning_state = "PROVISIONED" }) test.mock_device.add_test_device(mock_device_mounted_on_off_control) end @@ -428,6 +442,8 @@ local function test_init_mounted_dimmable_load_control() end end test.socket.matter:__expect_send({mock_device_mounted_dimmable_load_control.id, subscribe_request}) + test.socket.device_lifecycle:__queue_receive({ mock_device_mounted_dimmable_load_control.id, "doConfigure" }) + mock_device_mounted_dimmable_load_control:expect_metadata_update({ provisioning_state = "PROVISIONED" }) test.mock_device.add_test_device(mock_device_mounted_dimmable_load_control) end @@ -460,6 +476,9 @@ local function test_init_parent_child_different_types() end test.socket.matter:__expect_send({mock_device_parent_child_different_types.id, subscribe_request}) + test.socket.device_lifecycle:__queue_receive({ mock_device_parent_child_different_types.id, "doConfigure" }) + mock_device_parent_child_different_types:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + test.mock_device.add_test_device(mock_device_parent_child_different_types) mock_device_parent_child_different_types:expect_device_create({ @@ -472,8 +491,10 @@ local function test_init_parent_child_different_types() end local function test_init_parent_child_unsupported_device_type() - test.mock_device.add_test_device(mock_device_parent_child_unsupported_device_type) + test.socket.device_lifecycle:__queue_receive({ mock_device_parent_child_unsupported_device_type.id, "doConfigure" }) mock_device_parent_child_unsupported_device_type:expect_metadata_update({ profile = "switch-binary" }) + mock_device_parent_child_unsupported_device_type:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + test.mock_device.add_test_device(mock_device_parent_child_unsupported_device_type) mock_device_parent_child_unsupported_device_type:expect_device_create({ type = "EDGE_CHILD", 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 065b364998..ec403a0a6d 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 @@ -180,6 +180,9 @@ local function test_init() end 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" }) + test.mock_device.add_test_device(mock_device) for _, child in pairs(mock_children) do test.mock_device.add_test_device(child) @@ -243,6 +246,9 @@ local function test_init_parent_child_endpoints_non_sequential() end test.socket.matter:__expect_send({mock_device_parent_child_endpoints_non_sequential.id, subscribe_request}) + test.socket.device_lifecycle:__queue_receive({ mock_device_parent_child_endpoints_non_sequential.id, "doConfigure" }) + mock_device_parent_child_endpoints_non_sequential:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + test.mock_device.add_test_device(mock_device_parent_child_endpoints_non_sequential) for _, child in pairs(mock_children_non_sequential) do test.mock_device.add_test_device(child) 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 5b2e080713..9152d947d0 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 @@ -138,6 +138,9 @@ local function test_init() local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device) 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" }) + test.mock_device.add_test_device(mock_device) for _, child in pairs(mock_children) do test.mock_device.add_test_device(child) @@ -172,6 +175,7 @@ for i, endpoint in ipairs(mock_device_child_profile_override.endpoints) do mock_children_child_profile_override[endpoint.endpoint_id] = test.mock_device.build_test_child_device(child_data) end end + local function test_init_child_profile_override() local cluster_subscribe_list = { clusters.OnOff.attributes.OnOff, @@ -179,6 +183,9 @@ local function test_init_child_profile_override() local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device_child_profile_override) test.socket.matter:__expect_send({mock_device_child_profile_override.id, subscribe_request}) + test.socket.device_lifecycle:__queue_receive({ mock_device_child_profile_override.id, "doConfigure" }) + mock_device_child_profile_override:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + test.mock_device.add_test_device(mock_device_child_profile_override) for _, child in pairs(mock_children_child_profile_override) do test.mock_device.add_test_device(child)