From 4d11fed2aaf8b4bdc7ae739744ebaa9ab1f018f4 Mon Sep 17 00:00:00 2001 From: cjswedes Date: Thu, 9 Oct 2025 15:04:40 -0500 Subject: [PATCH 1/4] Move top level requires into functions --- .../SmartThings/zigbee-switch/src/init.lua | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/SmartThings/zigbee-switch/src/init.lua b/drivers/SmartThings/zigbee-switch/src/init.lua index 15241cd004..5d5a575cdd 100644 --- a/drivers/SmartThings/zigbee-switch/src/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/init.lua @@ -12,16 +12,14 @@ -- See the License for the specific language governing permissions and -- limitations under the License. +-- The only reason we need this is because of supported_capabilities on the driver template local capabilities = require "st.capabilities" local ZigbeeDriver = require "st.zigbee" local defaults = require "st.zigbee.defaults" -local clusters = require "st.zigbee.zcl.clusters" local configurationMap = require "configurations" -local zcl_global_commands = require "st.zigbee.zcl.global_commands" -local SimpleMetering = clusters.SimpleMetering -local ElectricalMeasurement = clusters.ElectricalMeasurement -local preferences = require "preferences" -local device_lib = require "st.device" +local CONFIGURE_REPORTING_RESPONSE_ID = 0x07 +local SIMPLE_METERING_ID = 0x0702 +local ELECTRICAL_MEASUREMENT_ID = 0x0B04 local function lazy_load_if_possible(sub_driver_name) -- gets the current lua libs api version @@ -37,6 +35,7 @@ local function lazy_load_if_possible(sub_driver_name) end local function info_changed(self, device, event, args) + local preferences = require "preferences" preferences.update_preferences(self, device, args) end @@ -46,9 +45,10 @@ local do_configure = function(self, device) -- Additional one time configuration if device:supports_capability(capabilities.energyMeter) or device:supports_capability(capabilities.powerMeter) then + local clusters = require "st.zigbee.zcl.clusters" -- Divisor and multipler for EnergyMeter - device:send(SimpleMetering.attributes.Divisor:read(device)) - device:send(SimpleMetering.attributes.Multiplier:read(device)) + device:send(clusters.SimpleMetering.attributes.Divisor:read(device)) + device:send(clusters.SimpleMetering.attributes.Multiplier:read(device)) end end @@ -85,6 +85,7 @@ local device_init = function(driver, device) if ias_zone_config_method ~= nil then device:set_ias_zone_config_method(ias_zone_config_method) end + local device_lib = require "st.device" if device.network_type == device_lib.NETWORK_TYPE_ZIGBEE then device:set_find_child(find_child) end @@ -102,6 +103,9 @@ local function is_mcd_device(device) end local function device_added(driver, device, event) + local clusters = require "st.zigbee.zcl.clusters" + local device_lib = require "st.device" + local main_endpoint = device:get_endpoint(clusters.OnOff.ID) if is_mcd_device(device) == false and device.network_type == device_lib.NETWORK_TYPE_ZIGBEE then for _, ep in ipairs(device.zigbee_endpoints) do @@ -171,11 +175,11 @@ local zigbee_switch_driver_template = { }, zigbee_handlers = { global = { - [SimpleMetering.ID] = { - [zcl_global_commands.CONFIGURE_REPORTING_RESPONSE_ID] = configurationMap.handle_reporting_config_response + [SIMPLE_METERING_ID] = { + [CONFIGURE_REPORTING_RESPONSE_ID] = configurationMap.handle_reporting_config_response }, - [ElectricalMeasurement.ID] = { - [zcl_global_commands.CONFIGURE_REPORTING_RESPONSE_ID] = configurationMap.handle_reporting_config_response + [ELECTRICAL_MEASUREMENT_ID] = { + [CONFIGURE_REPORTING_RESPONSE_ID] = configurationMap.handle_reporting_config_response } } }, From 5710939fc8506eeac133e820516864643a378048 Mon Sep 17 00:00:00 2001 From: cjswedes Date: Thu, 9 Oct 2025 15:05:52 -0500 Subject: [PATCH 2/4] Move configurations so it can be optimized --- .../src/{configurations.lua => configurations/init.lua} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename drivers/SmartThings/zigbee-switch/src/{configurations.lua => configurations/init.lua} (100%) diff --git a/drivers/SmartThings/zigbee-switch/src/configurations.lua b/drivers/SmartThings/zigbee-switch/src/configurations/init.lua similarity index 100% rename from drivers/SmartThings/zigbee-switch/src/configurations.lua rename to drivers/SmartThings/zigbee-switch/src/configurations/init.lua From 629f45c9cd49b03352567fa51dfe32b5fb501c33 Mon Sep 17 00:00:00 2001 From: cjswedes Date: Thu, 9 Oct 2025 15:07:00 -0500 Subject: [PATCH 3/4] Optimize configurations module to avoid devices table penalty on startup --- .../src/configurations/devices.lua | 112 +++++++++++++ .../zigbee-switch/src/configurations/init.lua | 158 +++--------------- 2 files changed, 137 insertions(+), 133 deletions(-) create mode 100644 drivers/SmartThings/zigbee-switch/src/configurations/devices.lua diff --git a/drivers/SmartThings/zigbee-switch/src/configurations/devices.lua b/drivers/SmartThings/zigbee-switch/src/configurations/devices.lua new file mode 100644 index 0000000000..b26478884a --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/src/configurations/devices.lua @@ -0,0 +1,112 @@ +local clusters = require "st.zigbee.zcl.clusters" +local ColorControl = clusters.ColorControl +local IASZone = clusters.IASZone +local ElectricalMeasurement = clusters.ElectricalMeasurement +local SimpleMetering = clusters.SimpleMetering +local Alarms = clusters.Alarms +local constants = require "st.zigbee.constants" + +local devices = { + IKEA_RGB_BULB = { + FINGERPRINTS = { + { mfr = "IKEA of Sweden", model = "TRADFRI bulb E27 CWS opal 600lm" }, + { mfr = "IKEA of Sweden", model = "TRADFRI bulb E26 CWS opal 600lm" } + }, + CONFIGURATION = { + { + cluster = ColorControl.ID, + attribute = ColorControl.attributes.CurrentX.ID, + minimum_interval = 1, + maximum_interval = 3600, + data_type = ColorControl.attributes.CurrentX.base_type, + reportable_change = 16 + }, + { + cluster = ColorControl.ID, + attribute = ColorControl.attributes.CurrentY.ID, + minimum_interval = 1, + maximum_interval = 3600, + data_type = ColorControl.attributes.CurrentY.base_type, + reportable_change = 16 + } + } + }, + SENGLED_BULB_WITH_MOTION_SENSOR = { + FINGERPRINTS = { + { mfr = "sengled", model = "E13-N11" } + }, + CONFIGURATION = { + { + cluster = IASZone.ID, + attribute = IASZone.attributes.ZoneStatus.ID, + minimum_interval = 30, + maximum_interval = 300, + data_type = IASZone.attributes.ZoneStatus.base_type + } + }, + IAS_ZONE_CONFIG_METHOD = constants.IAS_ZONE_CONFIGURE_TYPE.AUTO_ENROLL_RESPONSE + }, + FRIENT_SWITCHES = { + FINGERPRINTS = { + { mfr = "frient A/S", model = "SPLZB-131" }, + { mfr = "frient A/S", model = "SPLZB-132" }, + { mfr = "frient A/S", model = "SPLZB-134" }, + { mfr = "frient A/S", model = "SPLZB-137" }, + { mfr = "frient A/S", model = "SPLZB-141" }, + { mfr = "frient A/S", model = "SPLZB-142" }, + { mfr = "frient A/S", model = "SPLZB-144" }, + { mfr = "frient A/S", model = "SPLZB-147" }, + { mfr = "frient A/S", model = "SMRZB-143" }, + { mfr = "frient A/S", model = "SMRZB-153" }, + { mfr = "frient A/S", model = "SMRZB-332" }, + { mfr = "frient A/S", model = "SMRZB-342" } + }, + CONFIGURATION = { + { + cluster = ElectricalMeasurement.ID, + attribute = ElectricalMeasurement.attributes.RMSVoltage.ID, + minimum_interval = 5, + maximum_interval = 3600, + data_type = ElectricalMeasurement.attributes.RMSVoltage.base_type, + reportable_change = 1 + },{ + cluster = ElectricalMeasurement.ID, + attribute = ElectricalMeasurement.attributes.RMSCurrent.ID, + minimum_interval = 5, + maximum_interval = 3600, + data_type = ElectricalMeasurement.attributes.RMSCurrent.base_type, + reportable_change = 1 + },{ + cluster = ElectricalMeasurement.ID, + attribute = ElectricalMeasurement.attributes.ActivePower.ID, + minimum_interval = 5, + maximum_interval = 3600, + data_type = ElectricalMeasurement.attributes.ActivePower.base_type, + reportable_change = 1 + },{ + cluster = SimpleMetering.ID, + attribute = SimpleMetering.attributes.InstantaneousDemand.ID, + minimum_interval = 5, + maximum_interval = 3600, + data_type = SimpleMetering.attributes.InstantaneousDemand.base_type, + reportable_change = 1 + },{ + cluster = SimpleMetering.ID, + attribute = SimpleMetering.attributes.CurrentSummationDelivered.ID, + minimum_interval = 5, + maximum_interval = 3600, + data_type = SimpleMetering.attributes.CurrentSummationDelivered.base_type, + reportable_change = 1 + },{ + cluster = Alarms.ID, + attribute = Alarms.attributes.AlarmCount.ID, + minimum_interval = 1, + maximum_interval = 3600, + data_type = Alarms.attributes.AlarmCount.base_type, + reportable_change = 1, + }, + } + }, +} + +return devices \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-switch/src/configurations/init.lua b/drivers/SmartThings/zigbee-switch/src/configurations/init.lua index f465046e72..2e1c4e2fc9 100644 --- a/drivers/SmartThings/zigbee-switch/src/configurations/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/configurations/init.lua @@ -12,146 +12,32 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -local clusters = require "st.zigbee.zcl.clusters" -local constants = require "st.zigbee.constants" -local capabilities = require "st.capabilities" -local device_def = require "st.device" - -local ColorControl = clusters.ColorControl -local IASZone = clusters.IASZone -local ElectricalMeasurement = clusters.ElectricalMeasurement -local SimpleMetering = clusters.SimpleMetering -local Alarms = clusters.Alarms -local Status = require "st.zigbee.generated.types.ZclStatus" local CONFIGURATION_VERSION_KEY = "_configuration_version" local CONFIGURATION_ATTEMPTED = "_reconfiguration_attempted" -local devices = { - IKEA_RGB_BULB = { - FINGERPRINTS = { - { mfr = "IKEA of Sweden", model = "TRADFRI bulb E27 CWS opal 600lm" }, - { mfr = "IKEA of Sweden", model = "TRADFRI bulb E26 CWS opal 600lm" } - }, - CONFIGURATION = { - { - cluster = ColorControl.ID, - attribute = ColorControl.attributes.CurrentX.ID, - minimum_interval = 1, - maximum_interval = 3600, - data_type = ColorControl.attributes.CurrentX.base_type, - reportable_change = 16 - }, - { - cluster = ColorControl.ID, - attribute = ColorControl.attributes.CurrentY.ID, - minimum_interval = 1, - maximum_interval = 3600, - data_type = ColorControl.attributes.CurrentY.base_type, - reportable_change = 16 - } - } - }, - SENGLED_BULB_WITH_MOTION_SENSOR = { - FINGERPRINTS = { - { mfr = "sengled", model = "E13-N11" } - }, - CONFIGURATION = { - { - cluster = IASZone.ID, - attribute = IASZone.attributes.ZoneStatus.ID, - minimum_interval = 30, - maximum_interval = 300, - data_type = IASZone.attributes.ZoneStatus.base_type - } - }, - IAS_ZONE_CONFIG_METHOD = constants.IAS_ZONE_CONFIGURE_TYPE.AUTO_ENROLL_RESPONSE - }, - FRIENT_SWITCHES = { - FINGERPRINTS = { - { mfr = "frient A/S", model = "SPLZB-131" }, - { mfr = "frient A/S", model = "SPLZB-132" }, - { mfr = "frient A/S", model = "SPLZB-134" }, - { mfr = "frient A/S", model = "SPLZB-137" }, - { mfr = "frient A/S", model = "SPLZB-141" }, - { mfr = "frient A/S", model = "SPLZB-142" }, - { mfr = "frient A/S", model = "SPLZB-144" }, - { mfr = "frient A/S", model = "SPLZB-147" }, - { mfr = "frient A/S", model = "SMRZB-143" }, - { mfr = "frient A/S", model = "SMRZB-153" }, - { mfr = "frient A/S", model = "SMRZB-332" }, - { mfr = "frient A/S", model = "SMRZB-342" } - }, - CONFIGURATION = { - { - cluster = ElectricalMeasurement.ID, - attribute = ElectricalMeasurement.attributes.RMSVoltage.ID, - minimum_interval = 5, - maximum_interval = 3600, - data_type = ElectricalMeasurement.attributes.RMSVoltage.base_type, - reportable_change = 1 - },{ - cluster = ElectricalMeasurement.ID, - attribute = ElectricalMeasurement.attributes.RMSCurrent.ID, - minimum_interval = 5, - maximum_interval = 3600, - data_type = ElectricalMeasurement.attributes.RMSCurrent.base_type, - reportable_change = 1 - },{ - cluster = ElectricalMeasurement.ID, - attribute = ElectricalMeasurement.attributes.ActivePower.ID, - minimum_interval = 5, - maximum_interval = 3600, - data_type = ElectricalMeasurement.attributes.ActivePower.base_type, - reportable_change = 1 - },{ - cluster = SimpleMetering.ID, - attribute = SimpleMetering.attributes.InstantaneousDemand.ID, - minimum_interval = 5, - maximum_interval = 3600, - data_type = SimpleMetering.attributes.InstantaneousDemand.base_type, - reportable_change = 1 - },{ - cluster = SimpleMetering.ID, - attribute = SimpleMetering.attributes.CurrentSummationDelivered.ID, - minimum_interval = 5, - maximum_interval = 3600, - data_type = SimpleMetering.attributes.CurrentSummationDelivered.base_type, - reportable_change = 1 - },{ - cluster = Alarms.ID, - attribute = Alarms.attributes.AlarmCount.ID, - minimum_interval = 1, - maximum_interval = 3600, - data_type = Alarms.attributes.AlarmCount.base_type, - reportable_change = 1, - }, - } - }, -} - - local configurations = {} -local active_power_configuration = { - cluster = clusters.ElectricalMeasurement.ID, - attribute = clusters.ElectricalMeasurement.attributes.ActivePower.ID, - minimum_interval = 5, - maximum_interval = 3600, - data_type = clusters.ElectricalMeasurement.attributes.ActivePower.base_type, - reportable_change = 5 -} - -local instantaneous_demand_configuration = { - cluster = clusters.SimpleMetering.ID, - attribute = clusters.SimpleMetering.attributes.InstantaneousDemand.ID, - minimum_interval = 5, - maximum_interval = 3600, - data_type = clusters.SimpleMetering.attributes.InstantaneousDemand.base_type, - reportable_change = 5 -} - configurations.check_and_reconfig_devices = function(driver) + local clusters = require "st.zigbee.zcl.clusters" + local capabilities = require "st.capabilities" + local instantaneous_demand_configuration = { + cluster = clusters.SimpleMetering.ID, + attribute = clusters.SimpleMetering.attributes.InstantaneousDemand.ID, + minimum_interval = 5, + maximum_interval = 3600, + data_type = clusters.SimpleMetering.attributes.InstantaneousDemand.base_type, + reportable_change = 5 + } + local active_power_configuration = { + cluster = clusters.ElectricalMeasurement.ID, + attribute = clusters.ElectricalMeasurement.attributes.ActivePower.ID, + minimum_interval = 5, + maximum_interval = 3600, + data_type = clusters.ElectricalMeasurement.attributes.ActivePower.base_type, + reportable_change = 5 + } + for device_id, device in pairs(driver.device_cache) do local config_version = device:get_field(CONFIGURATION_VERSION_KEY) if config_version == nil or config_version < driver.current_config_version then @@ -174,6 +60,10 @@ configurations.check_and_reconfig_devices = function(driver) end configurations.handle_reporting_config_response = function(driver, device, zb_mess) + local Status = require "st.zigbee.generated.types.ZclStatus" + local clusters = require "st.zigbee.zcl.clusters" + local device_def = require "st.device" + local dev = device local find_child_fn = device:get_field(device_def.FIND_CHILD_KEY) if find_child_fn ~= nil then @@ -219,6 +109,7 @@ configurations.power_reconfig_wrapper = function(orig_function) end configurations.get_device_configuration = function(zigbee_device) + local devices = require "configurations.devices" for _, device in pairs(devices) do for _, fingerprint in pairs(device.FINGERPRINTS) do if zigbee_device:get_manufacturer() == fingerprint.mfr and zigbee_device:get_model() == fingerprint.model then @@ -230,6 +121,7 @@ configurations.get_device_configuration = function(zigbee_device) end configurations.get_ias_zone_config_method = function(zigbee_device) + local devices = require "configurations.devices" for _, device in pairs(devices) do for _, fingerprint in pairs(device.FINGERPRINTS) do if zigbee_device:get_manufacturer() == fingerprint.mfr and zigbee_device:get_model() == fingerprint.model then From bd1b06f55385f72bdb097bbab460f1b66ee55045 Mon Sep 17 00:00:00 2001 From: cjswedes Date: Fri, 10 Oct 2025 09:39:24 -0500 Subject: [PATCH 4/4] Use lazy handler for some lifecycle handlers at the top level driver --- .../src/configurations/devices.lua | 14 ++++ .../SmartThings/zigbee-switch/src/init.lua | 80 +++---------------- .../src/lifecycle_handlers/device_added.lua | 56 +++++++++++++ .../src/lifecycle_handlers/do_configure.lua | 27 +++++++ .../src/lifecycle_handlers/find_child.lua | 17 ++++ .../src/lifecycle_handlers/info_changed.lua | 18 +++++ 6 files changed, 144 insertions(+), 68 deletions(-) create mode 100644 drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/device_added.lua create mode 100644 drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/do_configure.lua create mode 100644 drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/find_child.lua create mode 100644 drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/info_changed.lua diff --git a/drivers/SmartThings/zigbee-switch/src/configurations/devices.lua b/drivers/SmartThings/zigbee-switch/src/configurations/devices.lua index b26478884a..51fd1c3665 100644 --- a/drivers/SmartThings/zigbee-switch/src/configurations/devices.lua +++ b/drivers/SmartThings/zigbee-switch/src/configurations/devices.lua @@ -1,3 +1,17 @@ +-- Copyright 2025 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + local clusters = require "st.zigbee.zcl.clusters" local ColorControl = clusters.ColorControl local IASZone = clusters.IASZone diff --git a/drivers/SmartThings/zigbee-switch/src/init.lua b/drivers/SmartThings/zigbee-switch/src/init.lua index 5d5a575cdd..81c39297e3 100644 --- a/drivers/SmartThings/zigbee-switch/src/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/init.lua @@ -20,10 +20,17 @@ local configurationMap = require "configurations" local CONFIGURE_REPORTING_RESPONSE_ID = 0x07 local SIMPLE_METERING_ID = 0x0702 local ELECTRICAL_MEASUREMENT_ID = 0x0B04 +local version = require "version" + +local lazy_handler +if version.api >= 15 then + lazy_handler = require "st.utils.lazy_handler" +else + lazy_handler = require +end local function lazy_load_if_possible(sub_driver_name) -- gets the current lua libs api version - local version = require "version" -- version 9 will include the lazy loading functions if version.api >= 9 then @@ -34,24 +41,6 @@ local function lazy_load_if_possible(sub_driver_name) end -local function info_changed(self, device, event, args) - local preferences = require "preferences" - preferences.update_preferences(self, device, args) -end - -local do_configure = function(self, device) - device:refresh() - device:configure() - - -- Additional one time configuration - if device:supports_capability(capabilities.energyMeter) or device:supports_capability(capabilities.powerMeter) then - local clusters = require "st.zigbee.zcl.clusters" - -- Divisor and multipler for EnergyMeter - device:send(clusters.SimpleMetering.attributes.Divisor:read(device)) - device:send(clusters.SimpleMetering.attributes.Multiplier:read(device)) - end -end - local function component_to_endpoint(device, component_id) local ep_num = component_id:match("switch(%d)") return ep_num and tonumber(ep_num) or device.fingerprinted_endpoint_id @@ -66,10 +55,6 @@ local function endpoint_to_component(device, ep) end end -local function find_child(parent, ep_id) - return parent:get_child_by_parent_assigned_key(string.format("%02X", ep_id)) -end - local device_init = function(driver, device) device:set_component_to_endpoint_fn(component_to_endpoint) device:set_endpoint_to_component_fn(endpoint_to_component) @@ -87,52 +72,11 @@ local device_init = function(driver, device) end local device_lib = require "st.device" if device.network_type == device_lib.NETWORK_TYPE_ZIGBEE then + local find_child = require "lifecycle_handlers.find_child" device:set_find_child(find_child) end end -local function is_mcd_device(device) - local components = device.profile.components - if type(components) == "table" then - local component_count = 0 - for _, component in pairs(components) do - component_count = component_count + 1 - end - return component_count >= 2 - end -end - -local function device_added(driver, device, event) - local clusters = require "st.zigbee.zcl.clusters" - local device_lib = require "st.device" - - local main_endpoint = device:get_endpoint(clusters.OnOff.ID) - if is_mcd_device(device) == false and device.network_type == device_lib.NETWORK_TYPE_ZIGBEE then - for _, ep in ipairs(device.zigbee_endpoints) do - if ep.id ~= main_endpoint then - if device:supports_server_cluster(clusters.OnOff.ID, ep.id) then - device:set_find_child(find_child) - if find_child(device, ep.id) == nil then - local name = string.format("%s %d", device.label, ep.id) - local child_profile = "basic-switch" - driver:try_create_device( - { - type = "EDGE_CHILD", - label = name, - profile = child_profile, - parent_device_id = device.id, - parent_assigned_child_key = string.format("%02X", ep.id), - vendor_provided_label = name - } - ) - end - end - end - end - end -end - - local zigbee_switch_driver_template = { supported_capabilities = { capabilities.switch, @@ -186,9 +130,9 @@ local zigbee_switch_driver_template = { current_config_version = 1, lifecycle_handlers = { init = configurationMap.power_reconfig_wrapper(device_init), - added = device_added, - infoChanged = info_changed, - doConfigure = do_configure + added = lazy_handler("lifecycle_handlers.device_added"), + infoChanged = lazy_handler("lifecycle_handlers.info_changed"), + doConfigure = lazy_handler("lifecycle_handlers.do_configure"), }, health_check = false, } diff --git a/drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/device_added.lua b/drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/device_added.lua new file mode 100644 index 0000000000..44b2979c33 --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/device_added.lua @@ -0,0 +1,56 @@ +-- Copyright 2025 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +local find_child = require "lifecycle_handlers.find_child" + +local function is_mcd_device(device) + local components = device.profile.components + if type(components) == "table" then + local component_count = 0 + for _, component in pairs(components) do + component_count = component_count + 1 + end + return component_count >= 2 + end +end + +return function(driver, device, event) + local clusters = require "st.zigbee.zcl.clusters" + local device_lib = require "st.device" + + local main_endpoint = device:get_endpoint(clusters.OnOff.ID) + if is_mcd_device(device) == false and device.network_type == device_lib.NETWORK_TYPE_ZIGBEE then + for _, ep in ipairs(device.zigbee_endpoints) do + if ep.id ~= main_endpoint then + if device:supports_server_cluster(clusters.OnOff.ID, ep.id) then + device:set_find_child(find_child) + if find_child(device, ep.id) == nil then + local name = string.format("%s %d", device.label, ep.id) + local child_profile = "basic-switch" + driver:try_create_device( + { + type = "EDGE_CHILD", + label = name, + profile = child_profile, + parent_device_id = device.id, + parent_assigned_child_key = string.format("%02X", ep.id), + vendor_provided_label = name + } + ) + end + end + end + end + end +end diff --git a/drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/do_configure.lua b/drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/do_configure.lua new file mode 100644 index 0000000000..5de558aedc --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/do_configure.lua @@ -0,0 +1,27 @@ +-- Copyright 2025 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +local capabilities = require "st.capabilities" +return function(self, device) + device:refresh() + device:configure() + + -- Additional one time configuration + if device:supports_capability(capabilities.energyMeter) or device:supports_capability(capabilities.powerMeter) then + local clusters = require "st.zigbee.zcl.clusters" + -- Divisor and multipler for EnergyMeter + device:send(clusters.SimpleMetering.attributes.Divisor:read(device)) + device:send(clusters.SimpleMetering.attributes.Multiplier:read(device)) + end +end diff --git a/drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/find_child.lua b/drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/find_child.lua new file mode 100644 index 0000000000..e33df67817 --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/find_child.lua @@ -0,0 +1,17 @@ +-- Copyright 2025 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +return function(parent, ep_id) + return parent:get_child_by_parent_assigned_key(string.format("%02X", ep_id)) +end diff --git a/drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/info_changed.lua b/drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/info_changed.lua new file mode 100644 index 0000000000..9699760a92 --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/src/lifecycle_handlers/info_changed.lua @@ -0,0 +1,18 @@ +-- Copyright 2025 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +return function(self, device, event, args) + local preferences = require "preferences" + preferences.update_preferences(self, device, args) +end