Skip to content

Commit 951333e

Browse files
Matter Switch move initialization to doConfigure
This change moves the initialization logic for buttons and switches to doConfigure. This keeps all of the profile selection logic all within doConfigure and allows the removal of logic gates from device_init that were there to ensure init code only ran one time. Also added is a new function that runs at init that can rename or delete persisted fields on the device.
1 parent e4762f5 commit 951333e

9 files changed

+176
-117
lines changed

drivers/SmartThings/matter-switch/src/init.lua

+64-61
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ local lua_socket = require "socket"
2121
local utils = require "st.utils"
2222
local device_lib = require "st.device"
2323
local embedded_cluster_utils = require "embedded-cluster-utils"
24-
-- Include driver-side definitions when lua libs api version is < 11
2524
local version = require "version"
25+
26+
-- Include driver-side definitions when lua libs api version is < 11
2627
if version.api < 11 then
2728
clusters.ElectricalEnergyMeasurement = require "ElectricalEnergyMeasurement"
2829
clusters.ElectricalPowerMeasurement = require "ElectricalPowerMeasurement"
@@ -43,19 +44,7 @@ local SWITCH_LEVEL_LIGHTING_MIN = 1
4344
local CURRENT_HUESAT_ATTR_MIN = 0
4445
local CURRENT_HUESAT_ATTR_MAX = 254
4546

46-
local SWITCH_INITIALIZED = "__switch_intialized"
47-
-- COMPONENT_TO_ENDPOINT_MAP is here only to preserve the endpoint mapping for
48-
-- devices that were joined to this driver as MCD devices before the transition
49-
-- to join all matter-switch devices as parent-child. This value will only exist
50-
-- in the device table for devices that joined prior to this transition, and it
51-
-- will not be set for new devices.
5247
local COMPONENT_TO_ENDPOINT_MAP = "__component_to_endpoint_map"
53-
-- COMPONENT_TO_ENDPOINT_MAP_BUTTON is for devices with button endpoints, to
54-
-- preserve the MCD functionality for button devices from the matter-button
55-
-- driver after it was merged into the matter-switch driver. Note that devices
56-
-- containing both button endpoints and switch endpoints will use this field
57-
-- rather than COMPONENT_TO_ENDPOINT_MAP.
58-
local COMPONENT_TO_ENDPOINT_MAP_BUTTON = "__component_to_endpoint_map_button"
5948
local ENERGY_MANAGEMENT_ENDPOINT = "__energy_management_endpoint"
6049
local IS_PARENT_CHILD_DEVICE = "__is_parent_child_device"
6150
local COLOR_TEMP_BOUND_RECEIVED_KELVIN = "__colorTemp_bound_received_kelvin"
@@ -66,6 +55,12 @@ local LEVEL_BOUND_RECEIVED = "__level_bound_received"
6655
local LEVEL_MIN = "__level_min"
6756
local LEVEL_MAX = "__level_max"
6857
local COLOR_MODE = "__color_mode"
58+
59+
local updated_fields = {
60+
{ field_name = "__component_to_endpoint_map_button", updated_field_name = COMPONENT_TO_ENDPOINT_MAP },
61+
{ field_name = "__switch_intialized", updated_field_name = nil }
62+
}
63+
6964
local HUE_SAT_COLOR_MODE = clusters.ColorControl.types.ColorMode.CURRENT_HUE_AND_CURRENT_SATURATION
7065
local X_Y_COLOR_MODE = clusters.ColorControl.types.ColorMode.CURRENTX_AND_CURRENTY
7166

@@ -455,15 +450,15 @@ local function find_default_endpoint(device)
455450
end
456451

457452
local function component_to_endpoint(device, component)
458-
local map = device:get_field(COMPONENT_TO_ENDPOINT_MAP_BUTTON) or device:get_field(COMPONENT_TO_ENDPOINT_MAP) or {}
453+
local map = device:get_field(COMPONENT_TO_ENDPOINT_MAP) or {}
459454
if map[component] then
460455
return map[component]
461456
end
462457
return find_default_endpoint(device)
463458
end
464459

465460
local function endpoint_to_component(device, ep)
466-
local map = device:get_field(COMPONENT_TO_ENDPOINT_MAP_BUTTON) or device:get_field(COMPONENT_TO_ENDPOINT_MAP) or {}
461+
local map = device:get_field(COMPONENT_TO_ENDPOINT_MAP) or {}
467462
for component, endpoint in pairs(map) do
468463
if endpoint == ep then
469464
return component
@@ -472,6 +467,17 @@ local function endpoint_to_component(device, ep)
472467
return "main"
473468
end
474469

470+
local function check_field_name_updates(device)
471+
for _, field in ipairs(updated_fields) do
472+
if device:get_field(field.field_name) then
473+
if field.updated_field_name ~= nil then
474+
device:set_field(field.updated_field_name, device:get_field(field.field_name), {persist = true})
475+
end
476+
device:set_field(field.field_name, nil)
477+
end
478+
end
479+
end
480+
475481
local function assign_child_profile(device, child_ep)
476482
local profile
477483

@@ -511,38 +517,6 @@ local function assign_child_profile(device, child_ep)
511517
return profile or "switch-binary"
512518
end
513519

514-
local function do_configure(driver, device)
515-
if device:get_field(BUTTON_DEVICE_PROFILED) then
516-
return
517-
end
518-
local level_eps = embedded_cluster_utils.get_endpoints(device, clusters.LevelControl.ID)
519-
local energy_eps = embedded_cluster_utils.get_endpoints(device, clusters.ElectricalEnergyMeasurement.ID)
520-
local power_eps = embedded_cluster_utils.get_endpoints(device, clusters.ElectricalPowerMeasurement.ID)
521-
local valve_eps = embedded_cluster_utils.get_endpoints(device, clusters.ValveConfigurationAndControl.ID)
522-
local profile_name = nil
523-
local level_support = ""
524-
if #level_eps > 0 then
525-
level_support = "-level"
526-
end
527-
if #energy_eps > 0 and #power_eps > 0 then
528-
profile_name = "plug" .. level_support .. "-power-energy-powerConsumption"
529-
elseif #energy_eps > 0 then
530-
profile_name = "plug" .. level_support .. "-energy-powerConsumption"
531-
elseif #power_eps > 0 then
532-
profile_name = "plug" .. level_support .. "-power"
533-
elseif #valve_eps > 0 then
534-
profile_name = "water-valve"
535-
if #embedded_cluster_utils.get_endpoints(device, clusters.ValveConfigurationAndControl.ID,
536-
{feature_bitmap = clusters.ValveConfigurationAndControl.types.Feature.LEVEL}) > 0 then
537-
profile_name = profile_name .. "-level"
538-
end
539-
end
540-
541-
if profile_name then
542-
device:try_update_metadata({ profile = profile_name })
543-
end
544-
end
545-
546520
local function configure_buttons(device)
547521
if device.network_type == device_lib.NETWORK_TYPE_CHILD then
548522
return
@@ -596,7 +570,7 @@ local function try_build_button_component_map(device, main_endpoint, button_eps)
596570
component_map[button_component] = ep
597571
end
598572
end
599-
device:set_field(COMPONENT_TO_ENDPOINT_MAP_BUTTON, component_map, {persist = true})
573+
device:set_field(COMPONENT_TO_ENDPOINT_MAP, component_map, {persist = true})
600574
end
601575
end
602576

@@ -656,8 +630,6 @@ local function try_build_child_switch_profiles(driver, device, switch_eps, main_
656630
device:set_field(IS_PARENT_CHILD_DEVICE, true, {persist = true})
657631
end
658632

659-
device:set_field(SWITCH_INITIALIZED, true, {persist = true})
660-
661633
-- this is needed in initialize_buttons_and_switches
662634
return num_switch_server_eps
663635
end
@@ -725,20 +697,10 @@ local function device_init(driver, device)
725697
if device.network_type ~= device_lib.NETWORK_TYPE_MATTER then
726698
return
727699
end
728-
700+
check_field_name_updates(device)
729701
device:set_component_to_endpoint_fn(component_to_endpoint)
730702
device:set_endpoint_to_component_fn(endpoint_to_component)
731-
732703
local main_endpoint = find_default_endpoint(device)
733-
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.
734-
not device:get_field(SWITCH_INITIALIZED) and
735-
not detect_bridge(device) then
736-
-- initialize the main device card with buttons if applicable, and create child devices as needed for multi-switch devices.
737-
initialize_buttons_and_switches(driver, device, main_endpoint)
738-
end
739-
if device:get_field(IS_PARENT_CHILD_DEVICE) then
740-
device:set_find_child(find_child)
741-
end
742704
-- ensure subscription to all endpoint attributes- including those mapped to child devices
743705
for _, ep in ipairs(device.endpoints) do
744706
if ep.endpoint_id ~= main_endpoint then
@@ -760,6 +722,47 @@ local function device_init(driver, device)
760722
device:subscribe()
761723
end
762724

725+
local function do_configure(driver, device)
726+
if not detect_bridge(device) then
727+
local main_endpoint = find_default_endpoint(device)
728+
-- initialize the main device card with buttons if applicable, and create child devices as needed for multi-switch devices.
729+
initialize_buttons_and_switches(driver, device, main_endpoint)
730+
if device:get_field(IS_PARENT_CHILD_DEVICE) then
731+
device:set_find_child(find_child)
732+
end
733+
if device:get_field(BUTTON_DEVICE_PROFILED) then
734+
return
735+
end
736+
end
737+
738+
local level_eps = embedded_cluster_utils.get_endpoints(device, clusters.LevelControl.ID)
739+
local energy_eps = embedded_cluster_utils.get_endpoints(device, clusters.ElectricalEnergyMeasurement.ID)
740+
local power_eps = embedded_cluster_utils.get_endpoints(device, clusters.ElectricalPowerMeasurement.ID)
741+
local valve_eps = embedded_cluster_utils.get_endpoints(device, clusters.ValveConfigurationAndControl.ID)
742+
local profile_name = nil
743+
local level_support = ""
744+
if #level_eps > 0 then
745+
level_support = "-level"
746+
end
747+
if #energy_eps > 0 and #power_eps > 0 then
748+
profile_name = "plug" .. level_support .. "-power-energy-powerConsumption"
749+
elseif #energy_eps > 0 then
750+
profile_name = "plug" .. level_support .. "-energy-powerConsumption"
751+
elseif #power_eps > 0 then
752+
profile_name = "plug" .. level_support .. "-power"
753+
elseif #valve_eps > 0 then
754+
profile_name = "water-valve"
755+
if #embedded_cluster_utils.get_endpoints(device, clusters.ValveConfigurationAndControl.ID,
756+
{feature_bitmap = clusters.ValveConfigurationAndControl.types.Feature.LEVEL}) > 0 then
757+
profile_name = profile_name .. "-level"
758+
end
759+
end
760+
761+
if profile_name then
762+
device:try_update_metadata({ profile = profile_name })
763+
end
764+
end
765+
763766
local function device_removed(driver, device)
764767
log.info("device removed")
765768
delete_import_poll_schedule(device)

0 commit comments

Comments
 (0)