diff --git a/drivers/SmartThings/zigbee-switch/src/inovelli-vzm31-sn/init.lua b/drivers/SmartThings/zigbee-switch/src/inovelli-vzm31-sn/init.lua index 4176e30113..a0dae6db3f 100644 --- a/drivers/SmartThings/zigbee-switch/src/inovelli-vzm31-sn/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/inovelli-vzm31-sn/init.lua @@ -150,7 +150,7 @@ local function info_changed(driver, device, event, args) local preferences = preference_map if args.old_st_store.preferences["notificationChild"] ~= device.preferences.notificationChild and args.old_st_store.preferences["notificationChild"] == false and device.preferences.notificationChild == true then if not device:get_child_by_parent_assigned_key('notification') then - add_child(driver,device,'rgbw-bulb-2700K-6500K','notificaiton') + add_child(driver,device,'rgbw-bulb-2700K-6500K','notification') end end for id, value in pairs(device.preferences) do @@ -229,10 +229,10 @@ local device_init = function(self, device) end device:send(cluster_base.read_attribute(device, data_types.ClusterId(0x0000), 0x4000)) else - switch_utils.emit_event_if_latest_state_missing(device, "main", capabilities.colorControl.NAME, capabilities.colorControl.hue.NAME, capabilities.colorControl.hue(1)) - switch_utils.emit_event_if_latest_state_missing(device, "main", capabilities.colorControl.NAME, capabilities.colorControl.saturation.NAME, capabilities.colorControl.saturation(1)) - switch_utils.emit_event_if_latest_state_missing(device, "main", capabilities.colorTemperature.NAME, capabilities.colorTemperature.colorTemperature.NAME, capabilities.colorTemperature.colorTemperature(6500)) - switch_utils.emit_event_if_latest_state_missing(device, "main", capabilities.switchLevel.NAME, capabilities.switchLevel.level.NAME, capabilities.switchLevel.level(100)) + switch_utils.emit_event_if_latest_state_missing(device, "main", capabilities.colorControl, capabilities.colorControl.hue.NAME, capabilities.colorControl.hue(1)) + switch_utils.emit_event_if_latest_state_missing(device, "main", capabilities.colorControl, capabilities.colorControl.saturation.NAME, capabilities.colorControl.saturation(1)) + switch_utils.emit_event_if_latest_state_missing(device, "main", capabilities.colorTemperature, capabilities.colorTemperature.colorTemperature.NAME, capabilities.colorTemperature.colorTemperature(6500)) + switch_utils.emit_event_if_latest_state_missing(device, "main", capabilities.switchLevel, capabilities.switchLevel.level.NAME, capabilities.switchLevel.level(100)) switch_utils.emit_event_if_latest_state_missing(device, "main", capabilities.switch, capabilities.switch.switch.NAME, capabilities.switch.switch("off")) end end diff --git a/drivers/SmartThings/zigbee-switch/src/test/test_aqara_switch_no_power.lua b/drivers/SmartThings/zigbee-switch/src/test/test_aqara_switch_no_power.lua index 91683622d1..e35a1c25e5 100644 --- a/drivers/SmartThings/zigbee-switch/src/test/test_aqara_switch_no_power.lua +++ b/drivers/SmartThings/zigbee-switch/src/test/test_aqara_switch_no_power.lua @@ -37,6 +37,23 @@ local PRIVATE_MODE = "PRIVATE_MODE" local mock_device = test.mock_device.build_test_zigbee_device( { + label = "Aqara Smart Wall Switch H1 EU (No Neutral, Double Rocker) 1", + profile = t_utils.get_profile_definition("aqara-switch-no-power.yml"), + fingerprinted_endpoint_id = 0x01, + zigbee_endpoints = { + [1] = { + id = 1, + manufacturer = "LUMI", + model = "lumi.switch.l2aeu1", + server_clusters = { 0x0006 } + } + } + } +) + +local mock_base_device = test.mock_device.build_test_zigbee_device( + { + label = "Aqara Smart Wall Switch H1 EU (No Neutral, Double Rocker) 1", profile = t_utils.get_profile_definition("aqara-switch-no-power.yml"), fingerprinted_endpoint_id = 0x01, zigbee_endpoints = { @@ -62,6 +79,7 @@ zigbee_test_utils.prepare_zigbee_env_info() local function test_init() test.mock_device.add_test_device(mock_device) + test.mock_device.add_test_device(mock_base_device) test.mock_device.add_test_device(mock_child) end @@ -114,6 +132,30 @@ test.register_coroutine_test( end ) +test.register_coroutine_test( + "Lifecycle - added test", + function() + -- The initial switch event should be send during the device's first time onboarding + test.socket.zigbee:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({ mock_base_device.id, "added" }) + mock_base_device:expect_device_create({ + type = "EDGE_CHILD", + label = "Aqara Smart Wall Switch H1 EU (No Neutral, Double Rocker) 2", + profile = "aqara-switch-child", + parent_device_id = mock_base_device.id, + parent_assigned_child_key = "02" + }) + test.socket.capability:__expect_send(mock_base_device:generate_test_message("main", capabilities.button.numberOfButtons({ value = 2 }, + { visibility = { displayed = false } }))) + test.socket.zigbee:__expect_send({ mock_base_device.id, + cluster_base.write_manufacturer_specific_attribute(mock_base_device, PRIVATE_CLUSTER_ID, PRIVATE_ATTRIBUTE_ID, MFG_CODE, + data_types.Uint8, 1) }) + test.socket.capability:__expect_send(mock_base_device:generate_test_message("main", capabilities.button.supportedButtonValues({ "pushed" }, + { visibility = { displayed = false } }))) + test.socket.capability:__expect_send(mock_base_device:generate_test_message("main", capabilities.button.button.pushed({ state_change = false }))) + end +) + test.register_coroutine_test( "Refresh device", function() diff --git a/drivers/SmartThings/zigbee-switch/src/test/test_enbrighten_metering_dimmer.lua b/drivers/SmartThings/zigbee-switch/src/test/test_enbrighten_metering_dimmer.lua index b7b4f67b7a..3b8c7187b4 100644 --- a/drivers/SmartThings/zigbee-switch/src/test/test_enbrighten_metering_dimmer.lua +++ b/drivers/SmartThings/zigbee-switch/src/test/test_enbrighten_metering_dimmer.lua @@ -14,11 +14,13 @@ local test = require "integration_test" local clusters = require "st.zigbee.zcl.clusters" +local ElectricalMeasurementCluster = clusters.ElectricalMeasurement local OnOffCluster = clusters.OnOff local LevelCluster = clusters.Level local SimpleMeteringCluster = clusters.SimpleMetering local capabilities = require "st.capabilities" local t_utils = require "integration_test.utils" +local zigbee_test_utils = require "integration_test.zigbee_test_utils" local mock_device = test.mock_device.build_test_zigbee_device({ profile = t_utils.get_profile_definition("switch-dimmer-power-energy.yml"), @@ -27,12 +29,14 @@ local mock_device = test.mock_device.build_test_zigbee_device({ id = 1, manufacturer = "Jasco Products", model = "43082", - server_clusters = { 0x0000, 0x0003, 0x0004, 0x0005, 0x0006, 0x0008, 0x0702, 0x0B05 }, + server_clusters = { 0x0000, 0x0003, 0x0004, 0x0005, 0x0006, 0x0008, 0x0702, 0x0B04 }, client_clusters = { 0x000A, 0x0019 } } } }) +zigbee_test_utils.prepare_zigbee_env_info() + local function test_init() mock_device:set_field("_configuration_version", 1, {persist = true}) test.mock_device.add_test_device(mock_device) @@ -40,6 +44,104 @@ end test.set_test_init_function(test_init) +test.register_coroutine_test( + "lifecycle configure event should configure device", + function () + test.socket.zigbee:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({mock_device.id, "doConfigure"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + ElectricalMeasurementCluster.ID) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + OnOffCluster.ID) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + LevelCluster.ID) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + SimpleMeteringCluster.ID) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ActivePower:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ACPowerMultiplier:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ACPowerDivisor:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + LevelCluster.attributes.CurrentLevel:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + SimpleMeteringCluster.attributes.InstantaneousDemand:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + SimpleMeteringCluster.attributes.CurrentSummationDelivered:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + SimpleMeteringCluster.attributes.Multiplier:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + SimpleMeteringCluster.attributes.Divisor:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ACPowerMultiplier:configure_reporting(mock_device, 1, 43200, 1) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ACPowerDivisor:configure_reporting(mock_device, 1, 43200, 1) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ActivePower:configure_reporting(mock_device, 5, 3600, 5) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:configure_reporting(mock_device, 0, 300) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + LevelCluster.attributes.CurrentLevel:configure_reporting(mock_device, 1, 3600, 1) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + SimpleMeteringCluster.attributes.InstantaneousDemand:configure_reporting(mock_device, 5, 3600, 5) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + SimpleMeteringCluster.attributes.CurrentSummationDelivered:configure_reporting(mock_device, 5, 3600, 1) + }) + + mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + end +) + test.register_message_test( "Capability command On should be handled", { diff --git a/drivers/SmartThings/zigbee-switch/src/test/test_inovelli-vzm31-sn.lua b/drivers/SmartThings/zigbee-switch/src/test/test_inovelli-vzm31-sn.lua new file mode 100755 index 0000000000..41ae8a049b --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/src/test/test_inovelli-vzm31-sn.lua @@ -0,0 +1,484 @@ +-- 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 test = require "integration_test" +local clusters = require "st.zigbee.zcl.clusters" +local cluster_base = require "st.zigbee.cluster_base" +local BasicCluster = clusters.Basic +local OnOffCluster = clusters.OnOff +local LevelCluster = clusters.Level +local SimpleMeteringCluster = clusters.SimpleMetering +local ElectricalMeasurementCluster = clusters.ElectricalMeasurement +local capabilities = require "st.capabilities" +local t_utils = require "integration_test.utils" +local zigbee_test_utils = require "integration_test.zigbee_test_utils" +local data_types = require "st.zigbee.data_types" +local utils = require "st.utils" + +local PRIVATE_CLUSTER_ID = 0xFC31 +local PRIVATE_CMD_NOTIF_ID = 0x01 +local PRIVATE_CMD_SCENE_ID =0x00 +local MFG_CODE = 0x122F + +local parent_profile = t_utils.get_profile_definition("inovelli-vzm31-sn.yml") +local child_profile = t_utils.get_profile_definition("rgbw-bulb-2700K-6500K.yml") + +local mock_device = test.mock_device.build_test_zigbee_device({ + label = "Inovelli 2-in-1 Blue Series", + profile = parent_profile, + zigbee_endpoints = { + [1] = { + id = 1, + manufacturer = "Inovelli", + model = "VZM31-SN", + server_clusters = { 0x0000, 0x0006, 0x0008, 0x0702, 0x0B04 }, + }, + [2] = { + id = 2, + manufacturer = "Inovelli", + model = "VZM31-SN", + server_clusters = { 0x0006 }, + }, + [3] = { + id = 3, + manufacturer = "Inovelli", + model = "VZM31-SN", + server_clusters = { 0x0006 }, + }, + [4] = { + id = 4, + manufacturer = "Inovelli", + model = "VZM31-SN", + server_clusters = { 0x0006 }, + }, + }, + fingerprinted_endpoint_id = 0x01 +}) + +local mock_first_child = test.mock_device.build_test_child_device({ + profile = child_profile, + device_network_id = string.format("%04X:%02X", mock_device:get_short_address(), 2), + parent_device_id = mock_device.id, + parent_assigned_child_key = string.format("%02X", 2) +}) + +zigbee_test_utils.prepare_zigbee_env_info() + +local function test_init() + mock_device:set_field("_configuration_version", 1, {persist = true}) + test.mock_device.add_test_device(mock_device) + test.socket.capability:__set_channel_ordering("relaxed") + test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.switchLevel.level(0))) + test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.powerMeter.power(0))) + test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.energyMeter.energy(0))) + test.socket.capability:__expect_send(mock_device:generate_test_message("button1", capabilities.button.supportedButtonValues({"pushed","held","down_hold","pushed_2x","pushed_3x","pushed_4x","pushed_5x"}, { visibility = { displayed = false } }))) + test.socket.capability:__expect_send(mock_device:generate_test_message("button2", capabilities.button.supportedButtonValues({"pushed","held","down_hold","pushed_2x","pushed_3x","pushed_4x","pushed_5x"}, { visibility = { displayed = false } }))) + test.socket.capability:__expect_send(mock_device:generate_test_message("button3", capabilities.button.supportedButtonValues({"pushed","held","down_hold","pushed_2x","pushed_3x","pushed_4x","pushed_5x"}, { visibility = { displayed = false } }))) + test.socket.capability:__expect_send(mock_device:generate_test_message("button1", capabilities.button.numberOfButtons({ value = 1 }, { visibility = { displayed = false } }))) + test.socket.capability:__expect_send(mock_device:generate_test_message("button2", capabilities.button.numberOfButtons({ value = 1 }, { visibility = { displayed = false } }))) + test.socket.capability:__expect_send(mock_device:generate_test_message("button3", capabilities.button.numberOfButtons({ value = 1 }, { visibility = { displayed = false } }))) + + test.socket.zigbee:__expect_send({mock_device.id, BasicCluster.attributes.SWBuildID:read(mock_device)}) + + test.mock_device.add_test_device(mock_first_child) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.colorControl.hue(1))) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.colorControl.saturation(1))) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.colorTemperature.colorTemperature(6500))) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.switchLevel.level(100))) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.switch.switch.off())) + +end + +test.set_test_init_function(test_init) + +test.register_coroutine_test( + "lifecycle configure event should configure device", + function () + test.socket.zigbee:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({mock_device.id, "doConfigure"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + LevelCluster.attributes.CurrentLevel:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + SimpleMeteringCluster.attributes.InstantaneousDemand:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + SimpleMeteringCluster.attributes.CurrentSummationDelivered:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + SimpleMeteringCluster.attributes.Multiplier:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + SimpleMeteringCluster.attributes.Divisor:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ActivePower:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ACPowerMultiplier:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ACPowerDivisor:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:read(mock_device):to_endpoint(0x02) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:read(mock_device):to_endpoint(0x03) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:read(mock_device):to_endpoint(0x04) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:configure_reporting(mock_device, 0, 300):to_endpoint(1) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:configure_reporting(mock_device, 0, 300):to_endpoint(2) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:configure_reporting(mock_device, 0, 300):to_endpoint(3) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:configure_reporting(mock_device, 0, 300):to_endpoint(4) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + LevelCluster.attributes.CurrentLevel:configure_reporting(mock_device, 1, 3600, 1) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + SimpleMeteringCluster.attributes.InstantaneousDemand:configure_reporting(mock_device, 5, 3600, 5) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + SimpleMeteringCluster.attributes.CurrentSummationDelivered:configure_reporting(mock_device, 5, 3600, 1) + }) + + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ACPowerMultiplier:configure_reporting(mock_device, 1, 43200, 1) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ACPowerDivisor:configure_reporting(mock_device, 1, 43200, 1) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ActivePower:configure_reporting(mock_device, 5, 3600, 5) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + BasicCluster.attributes.SWBuildID:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + ElectricalMeasurementCluster.ID) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + SimpleMeteringCluster.ID) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + LevelCluster.ID) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + OnOffCluster.ID, 1):to_endpoint(1) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + OnOffCluster.ID, 2):to_endpoint(2) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + OnOffCluster.ID, 3):to_endpoint(3) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + OnOffCluster.ID, 4):to_endpoint(4) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + PRIVATE_CLUSTER_ID, 2) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + cluster_base.read_manufacturer_specific_attribute(mock_device, PRIVATE_CLUSTER_ID, 21, MFG_CODE) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ACPowerDivisor:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ACPowerMultiplier:read(mock_device) + }) + + mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + end +) + +test.register_coroutine_test( + "parameter258 in infochanged", + function() + test.socket.device_lifecycle:__queue_receive(mock_device:generate_info_changed({ + preferences = { ["parameter258"] = "0" } + })) + test.mock_time.advance_time(3) + test.socket.zigbee:__expect_send({ mock_device.id, + cluster_base.write_manufacturer_specific_attribute(mock_device, PRIVATE_CLUSTER_ID, 258, + MFG_CODE, data_types.Boolean, false) }) + test.socket.zigbee:__expect_send({ mock_device.id, + BasicCluster.attributes.SWBuildID:read(mock_device) }) + end +) + +test.register_coroutine_test( + "parameter22 in infochanged", + function() + test.socket.device_lifecycle:__queue_receive(mock_device:generate_info_changed({ + preferences = { ["parameter22"] = "0" } + })) + test.mock_time.advance_time(3) + test.socket.zigbee:__expect_send({ mock_device.id, + cluster_base.write_manufacturer_specific_attribute(mock_device, PRIVATE_CLUSTER_ID, 22, + MFG_CODE, data_types.Uint8, 0) }) + test.socket.zigbee:__expect_send({ mock_device.id, + BasicCluster.attributes.SWBuildID:read(mock_device) }) + end +) + + +test.register_message_test( + "Capability on command switch on should be handled : parent device", + { + { + channel = "capability", + direction = "receive", + message = { mock_device.id, { capability = "switch", component = "main", command = "on", args = { } } } + }, + { + channel = "zigbee", + direction = "send", + message = { mock_device.id, OnOffCluster.server.commands.On(mock_device) } + } + } +) + +test.register_coroutine_test( + "Capability on command switch on should be handled : child device", + function() + test.socket.capability:__queue_receive({mock_first_child.id, { capability = "switch", component = "main", command = "on", args = {}}}) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.switch.switch.on())) + test.timer.__create_and_queue_test_time_advance_timer(2, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(60 * 1) + test.socket.zigbee:__expect_send({ mock_device.id, + cluster_base.build_manufacturer_specific_command(mock_device, PRIVATE_CLUSTER_ID, PRIVATE_CMD_NOTIF_ID, MFG_CODE, utils.serialize_int(16803071,4,false,false)) }) + end +) + +test.register_message_test( + "Capability off command switch on should be handled : parent device", + { + { + channel = "capability", + direction = "receive", + message = { mock_device.id, { capability = "switch", component = "main", command = "off", args = { } } } + }, + { + channel = "zigbee", + direction = "send", + message = { mock_device.id, OnOffCluster.server.commands.Off(mock_device) } + } + } +) + +test.register_coroutine_test( + "Capability on command switch on should be handled : child device", + function() + test.socket.capability:__queue_receive({mock_first_child.id, { capability = "switch", component = "main", command = "off", args = {}}}) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.switch.switch.off())) + test.timer.__create_and_queue_test_time_advance_timer(2, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(60 * 1) + test.socket.zigbee:__expect_send({ mock_device.id, + cluster_base.build_manufacturer_specific_command(mock_device, PRIVATE_CLUSTER_ID, PRIVATE_CMD_NOTIF_ID, MFG_CODE, utils.serialize_int(0,4,false,false)) }) + end +) + + +test.register_message_test( + "Capability setLevel command switch on should be handled : parent device", + { + { + channel = "capability", + direction = "receive", + message = { mock_device.id, { capability = "switchLevel", component = "main", command = "setLevel", args = { 57, 0 } } } + }, + { + channel = "zigbee", + direction = "send", + message = { mock_device.id, LevelCluster.server.commands.MoveToLevelWithOnOff(mock_device, + math.floor(57 * 0xFE / 100), + 0) } + } + } +) + +test.register_coroutine_test( + "Capability setLevel command switch on should be handled : child device", + function() + test.socket.capability:__queue_receive({mock_first_child.id, { capability = "switchLevel", component = "main", command = "setLevel", args = { 57, 0 }}}) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.switchLevel.level(57))) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.switch.switch.on())) + test.timer.__create_and_queue_test_time_advance_timer(2, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(60 * 1) + test.socket.zigbee:__expect_send({ mock_device.id, + cluster_base.build_manufacturer_specific_command(mock_device, PRIVATE_CLUSTER_ID, PRIVATE_CMD_NOTIF_ID, MFG_CODE, utils.serialize_int(16792063,4,false,false)) }) + end +) + + +test.register_coroutine_test( + "Capability setColorTemperature command switch on should be handled : child device", + function() + test.socket.capability:__queue_receive({mock_first_child.id, { capability = "colorTemperature", component = "main", command = "setColorTemperature", args = { 1800 }}}) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.colorControl.hue(100))) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.colorTemperature.colorTemperature(1800))) + test.timer.__create_and_queue_test_time_advance_timer(2, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(60 * 1) + test.socket.zigbee:__expect_send({ mock_device.id, + cluster_base.build_manufacturer_specific_command(mock_device, PRIVATE_CLUSTER_ID, PRIVATE_CMD_NOTIF_ID, MFG_CODE, utils.serialize_int(33514751,4,false,false)) }) + end +) + +test.register_coroutine_test( + "Capability setColor command switch on should be handled : child device", + function() + test.socket.capability:__queue_receive({mock_first_child.id, { capability = "colorControl", component = "main", command = "setColor", args = { { hue = 50, saturation = 50 } }}}) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.colorControl.hue(50))) + test.socket.capability:__expect_send(mock_first_child:generate_test_message("main", capabilities.colorControl.saturation(50))) + test.timer.__create_and_queue_test_time_advance_timer(2, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(60 * 1) + test.socket.zigbee:__expect_send({ mock_device.id, + cluster_base.build_manufacturer_specific_command(mock_device, PRIVATE_CLUSTER_ID, PRIVATE_CMD_NOTIF_ID, MFG_CODE, utils.serialize_int(25191679,4,false,false)) }) + end +) + +local ENDPOINT = 0x01 +local FRAME_CTRL = 0x1D +local PROFILE_ID = 0x0104 + +local build_scene_message = function(device, payload) + local message = zigbee_test_utils.build_custom_command_id( + device, + PRIVATE_CLUSTER_ID, + PRIVATE_CMD_SCENE_ID, + MFG_CODE, + payload, + ENDPOINT + ) + + message.body.zcl_header.frame_ctrl.value = FRAME_CTRL + message.address_header.profile.value = PROFILE_ID + + return message +end + +test.register_coroutine_test( + "Reported private cluster should be handled", + function() + test.socket.zigbee:__queue_receive({ + mock_device.id, + build_scene_message(mock_device, "\x01\x01") + }) + test.socket.capability:__expect_send(mock_device:generate_test_message("button1", capabilities.button.button.held({state_change = true}))) + end +) + +test.register_coroutine_test( + "Handle Power meter", + function() + test.socket.zigbee:__queue_receive({ + mock_device.id, + SimpleMeteringCluster.attributes.InstantaneousDemand:build_test_attr_report(mock_device, 60) + }) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.powerMeter.power({ value = 6.0, unit = "W" })) + ) + + test.socket.zigbee:__queue_receive({ + mock_device.id, + ElectricalMeasurementCluster.attributes.ActivePower:build_test_attr_report(mock_device, 100) + }) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.powerMeter.power({ value = 10.0, unit = "W" })) + ) + end +) + +test.register_coroutine_test( + "Handle Energy meter", + function() + test.socket.zigbee:__queue_receive({ + mock_device.id, + SimpleMeteringCluster.attributes.CurrentSummationDelivered:build_test_attr_report(mock_device, 600) + }) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.energyMeter.energy({ value = 6.0, unit = "kWh" })) + ) + end +) + +test.run_registered_tests() diff --git a/drivers/SmartThings/zigbee-switch/src/test/test_jasco_switch.lua b/drivers/SmartThings/zigbee-switch/src/test/test_jasco_switch.lua index 6b07420b87..750ef895f2 100644 --- a/drivers/SmartThings/zigbee-switch/src/test/test_jasco_switch.lua +++ b/drivers/SmartThings/zigbee-switch/src/test/test_jasco_switch.lua @@ -26,7 +26,7 @@ local mock_device = test.mock_device.build_test_zigbee_device({ id = 1, manufacturer = "Jasco Products", model = "43078", - server_clusters = { 0x0000, 0x0003, 0x0004, 0x0005, 0x0006, 0x0702, 0x0B05 }, + server_clusters = { 0x0000, 0x0003, 0x0004, 0x0005, 0x0006, 0x0702, 0x0B04 }, client_clusters = { 0x000A, 0x0019 } } } diff --git a/drivers/SmartThings/zigbee-switch/src/test/test_robb_smarrt_2-wire_dimmer.lua b/drivers/SmartThings/zigbee-switch/src/test/test_robb_smarrt_2-wire_dimmer.lua index c1be129215..d533d69489 100644 --- a/drivers/SmartThings/zigbee-switch/src/test/test_robb_smarrt_2-wire_dimmer.lua +++ b/drivers/SmartThings/zigbee-switch/src/test/test_robb_smarrt_2-wire_dimmer.lua @@ -30,7 +30,7 @@ local mock_device = test.mock_device.build_test_zigbee_device( id = 1, manufacturer = "ROBB smarrt", model = "ROB_200-011-0", - server_clusters = { 0x0000, 0x0003, 0x0004, 0x0005, 0x0006, 0x0008, 0x0702, 0x0B04, 0x0B05 }, + server_clusters = { 0x0000, 0x0003, 0x0004, 0x0005, 0x0006, 0x0008, 0x0702, 0x0B04 }, client_clusters = { 0x0019 } } } diff --git a/drivers/SmartThings/zigbee-switch/src/test/test_robb_smarrt_knob_dimmer.lua b/drivers/SmartThings/zigbee-switch/src/test/test_robb_smarrt_knob_dimmer.lua index 0c66abd359..d7e4db0f09 100644 --- a/drivers/SmartThings/zigbee-switch/src/test/test_robb_smarrt_knob_dimmer.lua +++ b/drivers/SmartThings/zigbee-switch/src/test/test_robb_smarrt_knob_dimmer.lua @@ -30,7 +30,7 @@ local mock_device = test.mock_device.build_test_zigbee_device( id = 1, manufacturer = "ROBB smarrt", model = "ROB_200-014-0", - server_clusters = { 0x0000, 0x0003, 0x0004, 0x0005, 0x0006, 0x0008, 0x0702, 0x0B04, 0x0B05 }, + server_clusters = { 0x0000, 0x0003, 0x0004, 0x0005, 0x0006, 0x0008, 0x0702, 0x0B04 }, client_clusters = { 0x0019 } } } diff --git a/drivers/SmartThings/zigbee-switch/src/test/test_switch_power.lua b/drivers/SmartThings/zigbee-switch/src/test/test_switch_power.lua index 74598ef3a5..d4d427bc58 100644 --- a/drivers/SmartThings/zigbee-switch/src/test/test_switch_power.lua +++ b/drivers/SmartThings/zigbee-switch/src/test/test_switch_power.lua @@ -35,11 +35,43 @@ local mock_device = test.mock_device.build_test_zigbee_device( } ) + +local mock_aurora_relay_device = test.mock_device.build_test_zigbee_device( + { profile = t_utils.get_profile_definition("switch-power.yml"), + fingerprinted_endpoint_id = 0x01, + zigbee_endpoints = { + [1] = { + id = 1, + manufacturer = "Aurora", + model = "Smart16ARelay51AU", + server_clusters = {0x0006, 0x0B04, 0x0702} + } + } + } +) + +local mock_vimar_device = test.mock_device.build_test_zigbee_device( + { profile = t_utils.get_profile_definition("switch-power.yml"), + fingerprinted_endpoint_id = 0x01, + zigbee_endpoints = { + [1] = { + id = 1, + manufacturer = "Vimar", + model = "Mains_Power_Outlet_v1.0", + server_clusters = {0x0006, 0x0B04, 0x0702} + } + } + } +) + + zigbee_test_utils.prepare_zigbee_env_info() local function test_init() mock_device:set_field("_configuration_version", 1, {persist = true}) test.mock_device.add_test_device(mock_device) + test.mock_device.add_test_device(mock_aurora_relay_device) + test.mock_device.add_test_device(mock_vimar_device) end test.set_test_init_function(test_init) @@ -159,4 +191,131 @@ test.register_message_test( } ) +test.register_coroutine_test( + "Configure should configure all necessary attributes and refresh device :aurora relay", + function() + test.socket.device_lifecycle:__queue_receive({ mock_aurora_relay_device.id, "doConfigure" }) + test.socket.zigbee:__set_channel_ordering("relaxed") + + test.socket.zigbee:__expect_send({ + mock_aurora_relay_device.id, + zigbee_test_utils.build_bind_request(mock_aurora_relay_device, zigbee_test_utils.mock_hub_eui, OnOff.ID) + }) + test.socket.zigbee:__expect_send({ + mock_aurora_relay_device.id, + zigbee_test_utils.build_bind_request(mock_aurora_relay_device, zigbee_test_utils.mock_hub_eui, ElectricalMeasurement.ID) + }) + test.socket.zigbee:__expect_send({ + mock_aurora_relay_device.id, + zigbee_test_utils.build_bind_request(mock_aurora_relay_device, zigbee_test_utils.mock_hub_eui, SimpleMetering.ID) + }) + + test.socket.zigbee:__expect_send( + { + mock_aurora_relay_device.id, + OnOff.attributes.OnOff:configure_reporting(mock_aurora_relay_device, 0, 300, 1) + } + ) + test.socket.zigbee:__expect_send( + { + mock_aurora_relay_device.id, + ElectricalMeasurement.attributes.ActivePower:configure_reporting(mock_aurora_relay_device, 5, 3600, 5) + } + ) + test.socket.zigbee:__expect_send( + { + mock_aurora_relay_device.id, + ElectricalMeasurement.attributes.ACPowerMultiplier:configure_reporting(mock_aurora_relay_device, 1, 43200, 1) + } + ) + test.socket.zigbee:__expect_send( + { + mock_aurora_relay_device.id, + ElectricalMeasurement.attributes.ACPowerDivisor:configure_reporting(mock_aurora_relay_device, 1, 43200, 1) + } + ) + test.socket.zigbee:__expect_send( + { + mock_aurora_relay_device.id, + SimpleMetering.attributes.InstantaneousDemand:configure_reporting(mock_aurora_relay_device, 5, 3600, 5) + } + ) + + test.socket.zigbee:__expect_send({ mock_aurora_relay_device.id, OnOff.attributes.OnOff:read(mock_aurora_relay_device) }) + test.socket.zigbee:__expect_send({ mock_aurora_relay_device.id, ElectricalMeasurement.attributes.ActivePower:read(mock_aurora_relay_device) }) + test.socket.zigbee:__expect_send({ mock_aurora_relay_device.id, ElectricalMeasurement.attributes.ACPowerDivisor:read(mock_aurora_relay_device) }) + test.socket.zigbee:__expect_send({ mock_aurora_relay_device.id, ElectricalMeasurement.attributes.ACPowerMultiplier:read(mock_aurora_relay_device) }) + test.socket.zigbee:__expect_send({ mock_aurora_relay_device.id, SimpleMetering.attributes.InstantaneousDemand:read(mock_aurora_relay_device) }) + mock_aurora_relay_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + end +) + +test.register_coroutine_test( + "Configure should configure all necessary attributes and refresh device : vimar", + function() + test.socket.device_lifecycle:__queue_receive({ mock_vimar_device.id, "doConfigure" }) + test.socket.zigbee:__set_channel_ordering("relaxed") + + test.socket.zigbee:__expect_send({ + mock_vimar_device.id, + zigbee_test_utils.build_bind_request(mock_vimar_device, zigbee_test_utils.mock_hub_eui, OnOff.ID) + }) + test.socket.zigbee:__expect_send({ + mock_vimar_device.id, + zigbee_test_utils.build_bind_request(mock_vimar_device, zigbee_test_utils.mock_hub_eui, ElectricalMeasurement.ID) + }) + test.socket.zigbee:__expect_send({ + mock_vimar_device.id, + zigbee_test_utils.build_bind_request(mock_vimar_device, zigbee_test_utils.mock_hub_eui, SimpleMetering.ID) + }) + test.socket.zigbee:__expect_send( + { + mock_vimar_device.id, + OnOff.attributes.OnOff:configure_reporting(mock_vimar_device, 0, 300, 1) + } + ) + test.socket.zigbee:__expect_send( + { + mock_vimar_device.id, + ElectricalMeasurement.attributes.ActivePower:configure_reporting(mock_vimar_device, 1, 15, 1) + } + ) + test.socket.zigbee:__expect_send( + { + mock_vimar_device.id, + ElectricalMeasurement.attributes.ActivePower:configure_reporting(mock_vimar_device, 5, 3600, 5) + } + ) + test.socket.zigbee:__expect_send( + { + mock_vimar_device.id, + ElectricalMeasurement.attributes.ACPowerMultiplier:configure_reporting(mock_vimar_device, 1, 43200, 1) + } + ) + test.socket.zigbee:__expect_send( + { + mock_vimar_device.id, + ElectricalMeasurement.attributes.ACPowerDivisor:configure_reporting(mock_vimar_device, 1, 43200, 1) + } + ) + test.socket.zigbee:__expect_send( + { + mock_vimar_device.id, + SimpleMetering.attributes.InstantaneousDemand:configure_reporting(mock_vimar_device, 5, 3600, 5) + } + ) + test.socket.zigbee:__expect_send({ + mock_vimar_device.id, + zigbee_test_utils.build_bind_request(mock_vimar_device, zigbee_test_utils.mock_hub_eui, ElectricalMeasurement.ID) + }) + test.socket.zigbee:__expect_send({ mock_vimar_device.id, OnOff.attributes.OnOff:read(mock_vimar_device) }) + test.socket.zigbee:__expect_send({ mock_vimar_device.id, ElectricalMeasurement.attributes.ActivePower:read(mock_vimar_device) }) + test.socket.zigbee:__expect_send({ mock_vimar_device.id, ElectricalMeasurement.attributes.ACPowerDivisor:read(mock_vimar_device) }) + test.socket.zigbee:__expect_send({ mock_vimar_device.id, ElectricalMeasurement.attributes.ACPowerMultiplier:read(mock_vimar_device) }) + test.socket.zigbee:__expect_send({ mock_vimar_device.id, SimpleMetering.attributes.InstantaneousDemand:read(mock_vimar_device) }) + mock_vimar_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + end +) + + test.run_registered_tests() diff --git a/drivers/SmartThings/zigbee-switch/src/test/test_tuya_multi.lua b/drivers/SmartThings/zigbee-switch/src/test/test_tuya_multi.lua new file mode 100755 index 0000000000..45f3d4e2b3 --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/src/test/test_tuya_multi.lua @@ -0,0 +1,93 @@ +-- 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 test = require "integration_test" +local clusters = require "st.zigbee.zcl.clusters" +local BasicCluster = clusters.Basic +local OnOffCluster = clusters.OnOff +local t_utils = require "integration_test.utils" +local zigbee_test_utils = require "integration_test.zigbee_test_utils" + +local profile = t_utils.get_profile_definition("basic-switch.yml") + +local mock_device = test.mock_device.build_test_zigbee_device({ + label = "Zigbee Switch", + profile = profile, + zigbee_endpoints = { + [1] = { + id = 1, + manufacturer = "_TZ123fas", + server_clusters = { 0x0006 }, + }, + [2] = { + id = 2, + manufacturer = "_TZ123fas", + server_clusters = { 0x0006 }, + }, + }, + fingerprinted_endpoint_id = 0x01 +}) + +zigbee_test_utils.prepare_zigbee_env_info() + +local function test_init() + mock_device:set_field("_configuration_version", 1, {persist = true}) + test.mock_device.add_test_device(mock_device) +end + +test.set_test_init_function(test_init) + +test.register_coroutine_test( + "lifecycle configure event should configure device", + function () + test.socket.zigbee:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({mock_device.id, "doConfigure"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:read(mock_device):to_endpoint(0x02) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:configure_reporting(mock_device, 0, 300):to_endpoint(1) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + OnOffCluster.attributes.OnOff:configure_reporting(mock_device, 0, 300):to_endpoint(2) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + OnOffCluster.ID, 1):to_endpoint(1) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + OnOffCluster.ID, 2):to_endpoint(2) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_attribute_read(mock_device, BasicCluster.ID, {0x0004, 0x0000, 0x0001, 0x0005, 0x0007, 0xfffe}) + }) + + mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + end +) + +test.run_registered_tests() diff --git a/drivers/SmartThings/zigbee-switch/src/test/test_zigbee_dimmer_power_energy.lua b/drivers/SmartThings/zigbee-switch/src/test/test_zigbee_dimmer_power_energy.lua deleted file mode 100644 index 9b62d57546..0000000000 --- a/drivers/SmartThings/zigbee-switch/src/test/test_zigbee_dimmer_power_energy.lua +++ /dev/null @@ -1,190 +0,0 @@ --- Copyright 2022 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 test = require "integration_test" -local clusters = require "st.zigbee.zcl.clusters" -local OnOffCluster = clusters.OnOff -local LevelCluster = clusters.Level -local SimpleMeteringCluster = clusters.SimpleMetering -local capabilities = require "st.capabilities" -local t_utils = require "integration_test.utils" - -local mock_device = test.mock_device.build_test_zigbee_device({ - profile = t_utils.get_profile_definition("switch-dimmer-power-energy.yml"), - zigbee_endpoints = { - [1] = { - id = 1, - server_clusters = { 0x0000, 0x0003, 0x0004, 0x0005, 0x0006, 0x0008, 0x0702, 0x0B05 }, - client_clusters = { 0x000A, 0x0019 } - } - } -}) - -local function test_init() - mock_device:set_field("_configuration_version", 1, {persist = true}) - test.mock_device.add_test_device(mock_device) -end - -test.set_test_init_function(test_init) - -test.register_message_test( - "Capability command On should be handled", - { - { - channel = "capability", - direction = "receive", - message = { mock_device.id, { capability = "switch", component = "main", command = "on", args = { } } } - }, - { - channel = "devices", - direction = "send", - message = { - "register_native_capability_cmd_handler", - { device_uuid = mock_device.id, capability_id = "switch", capability_cmd_id = "on" } - } - }, - { - channel = "zigbee", - direction = "send", - message = { mock_device.id, OnOffCluster.server.commands.On(mock_device) } - } - } -) - -test.register_message_test( - "Capability command Off should be handled", - { - { - channel = "capability", - direction = "receive", - message = { mock_device.id, { capability = "switch", component = "main", command = "off", args = { } } } - }, - { - channel = "devices", - direction = "send", - message = { - "register_native_capability_cmd_handler", - { device_uuid = mock_device.id, capability_id = "switch", capability_cmd_id = "off" } - } - }, - { - channel = "zigbee", - direction = "send", - message = { mock_device.id, OnOffCluster.server.commands.Off(mock_device) } - } - } -) - -test.register_message_test( - "Capability command setLevel should be handled", - { - { - channel = "capability", - direction = "receive", - message = { mock_device.id, { capability = "switchLevel", component = "main", command = "setLevel", args = { 57, 0 } } } - }, - { - channel = "devices", - direction = "send", - message = { - "register_native_capability_cmd_handler", - { device_uuid = mock_device.id, capability_id = "switchLevel", capability_cmd_id = "setLevel" } - } - }, - { - channel = "zigbee", - direction = "send", - message = { - mock_device.id, - LevelCluster.server.commands.MoveToLevelWithOnOff(mock_device, math.floor(57 * 254 / 100)) - } - } - } -) - -test.register_message_test( - "Handle Switch Level", - { - { - channel = "zigbee", - direction = "receive", - message = { - mock_device.id, - LevelCluster.attributes.CurrentLevel:build_test_attr_report(mock_device, math.floor(57 / 100 * 254)) - } - }, - { - channel = "capability", - direction = "send", - message = mock_device:generate_test_message("main", capabilities.switchLevel.level(57)) - }, - { - channel = "devices", - direction = "send", - message = { - "register_native_capability_attr_handler", - { device_uuid = mock_device.id, capability_id = "switchLevel", capability_attr_id = "level" } - } - }, - } -) - -test.register_message_test( - "Handle Power meter, Sensor value is in kW, capability attribute value is in W", - { - { - channel = "zigbee", - direction = "receive", - message = { mock_device.id, SimpleMeteringCluster.attributes.Divisor:build_test_attr_report(mock_device, 0x0A) } - }, - { - channel = "zigbee", - direction = "receive", - message = { mock_device.id, SimpleMeteringCluster.attributes.InstantaneousDemand:build_test_attr_report(mock_device, 0x14D) } - }, - { - channel = "capability", - direction = "send", - message = mock_device:generate_test_message("main", capabilities.powerMeter.power({ value = 33300.0, unit = "W" })) - } - } -) - -test.register_message_test( - "Handle Energy meter", - { - { - channel = "zigbee", - direction = "receive", - message = { mock_device.id, SimpleMeteringCluster.attributes.Multiplier:build_test_attr_report(mock_device, 1) } - }, - { - channel = "zigbee", - direction = "receive", - message = { mock_device.id, SimpleMeteringCluster.attributes.Divisor:build_test_attr_report(mock_device, 0x2710) } - }, - { - channel = "zigbee", - direction = "receive", - message = { mock_device.id, SimpleMeteringCluster.attributes.CurrentSummationDelivered:build_test_attr_report(mock_device, 0x15B3) } - }, - { - channel = "capability", - direction = "send", - message = mock_device:generate_test_message("main", capabilities.energyMeter.energy({ value = 0.5555, unit = "kWh" })) - } - } -) - -test.run_registered_tests() diff --git a/drivers/SmartThings/zigbee-switch/src/zigbee-dimmer-power-energy/enbrighten-metering-dimmer/init.lua b/drivers/SmartThings/zigbee-switch/src/zigbee-dimmer-power-energy/enbrighten-metering-dimmer/init.lua deleted file mode 100644 index d4fcdb3990..0000000000 --- a/drivers/SmartThings/zigbee-switch/src/zigbee-dimmer-power-energy/enbrighten-metering-dimmer/init.lua +++ /dev/null @@ -1,67 +0,0 @@ --- Copyright 2022 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 capabilities = require "st.capabilities" -local constants = require "st.zigbee.constants" -local SimpleMetering = clusters.SimpleMetering -local configurations = require "configurations" - -local ENBRIGHTEN_METERING_DIMMER_FINGERPRINTS = { - { mfr = "Jasco Products", model = "43082" } -} - -local is_enbrighten_metering_dimmer = function(opts, driver, device) - for _, fingerprint in ipairs(ENBRIGHTEN_METERING_DIMMER_FINGERPRINTS) do - if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then - return true - end - end - return false -end - -local device_init = function(self, device) - local customEnergyDivisor = 10000 - device:set_field(constants.SIMPLE_METERING_DIVISOR_KEY, customEnergyDivisor, {persist = true}) -end - -local do_configure = function(self, device) - device:refresh() - device:configure() -end - -local instantaneous_demand_handler = function(driver, device, value, zb_rx) - local raw_value = value.value - local divisor = 10 - raw_value = raw_value / divisor - device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.powerMeter.power({value = raw_value, unit = "W" })) -end - -local enbrighten_metering_dimmer = { - NAME = "enbrighten metering dimmer", - zigbee_handlers = { - attr = { - [SimpleMetering.ID] = { - [SimpleMetering.attributes.InstantaneousDemand.ID] = instantaneous_demand_handler - } - } - }, - lifecycle_handlers = { - init = configurations.power_reconfig_wrapper(device_init), - doConfigure = do_configure - }, - can_handle = is_enbrighten_metering_dimmer -} - -return enbrighten_metering_dimmer diff --git a/drivers/SmartThings/zigbee-switch/src/zigbee-dimmer-power-energy/init.lua b/drivers/SmartThings/zigbee-switch/src/zigbee-dimmer-power-energy/init.lua index f799a165aa..75f2af82c1 100644 --- a/drivers/SmartThings/zigbee-switch/src/zigbee-dimmer-power-energy/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/zigbee-dimmer-power-energy/init.lua @@ -15,7 +15,8 @@ local clusters = require "st.zigbee.zcl.clusters" local capabilities = require "st.capabilities" local SimpleMetering = clusters.SimpleMetering -local ElectricalMeasurement = clusters.ElectricalMeasurement +local constants = require "st.zigbee.constants" +local configurations = require "configurations" local ZIGBEE_DIMMER_POWER_ENERGY_FINGERPRINTS = { { mfr = "Jasco Products", model = "43082" } @@ -31,6 +32,11 @@ local is_zigbee_dimmer_power_energy = function(opts, driver, device) return false end +local device_init = function(self, device) + local customEnergyDivisor = 10000 + device:set_field(constants.SIMPLE_METERING_DIVISOR_KEY, customEnergyDivisor, {persist = true}) +end + local do_configure = function(self, device) device:refresh() device:configure() @@ -41,24 +47,29 @@ local do_configure = function(self, device) device:send(SimpleMetering.attributes.Divisor:read(device)) device:send(SimpleMetering.attributes.Multiplier:read(device)) end +end - if device:supports_capability(capabilities.energyMeter) then - -- Divisor and multipler for EnergyMeter - device:send(ElectricalMeasurement.attributes.ACPowerDivisor:read(device)) - device:send(ElectricalMeasurement.attributes.ACPowerMultiplier:read(device)) - end +local instantaneous_demand_handler = function(driver, device, value, zb_rx) + local raw_value = value.value + local divisor = 10 + raw_value = raw_value / divisor + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.powerMeter.power({value = raw_value, unit = "W" })) end local zigbee_dimmer_power_energy_handler = { NAME = "zigbee dimmer power energy handler", + zigbee_handlers = { + attr = { + [SimpleMetering.ID] = { + [SimpleMetering.attributes.InstantaneousDemand.ID] = instantaneous_demand_handler + } + } + }, lifecycle_handlers = { + init = configurations.power_reconfig_wrapper(device_init), doConfigure = do_configure, }, - sub_drivers = { - require("zigbee-dimmer-power-energy/enbrighten-metering-dimmer") - }, can_handle = is_zigbee_dimmer_power_energy - } return zigbee_dimmer_power_energy_handler diff --git a/drivers/SmartThings/zigbee-switch/src/zll-polling/init.lua b/drivers/SmartThings/zigbee-switch/src/zll-polling/init.lua index 59424dd784..d3ce34c2fd 100644 --- a/drivers/SmartThings/zigbee-switch/src/zll-polling/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/zll-polling/init.lua @@ -18,7 +18,7 @@ local clusters = require "st.zigbee.zcl.clusters" local function zll_profile(opts, driver, device, zb_rx, ...) local endpoint = device.zigbee_endpoints[device.fingerprinted_endpoint_id] or device.zigbee_endpoints[tostring(device.fingerprinted_endpoint_id)] - if (endpoint.profile_id == constants.ZLL_PROFILE_ID) then + if (endpoint ~= nil and endpoint.profile_id == constants.ZLL_PROFILE_ID) then local subdriver = require("zll-polling") return true, subdriver else