Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rolling the Beta changes to Production #1351

Merged
merged 11 commits into from
Apr 30, 2024
36 changes: 16 additions & 20 deletions drivers/SmartThings/matter-switch/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
-- limitations under the License.

local capabilities = require "st.capabilities"
local im = require "st.matter.interaction_model"
local log = require "log"
local clusters = require "st.matter.clusters"
local MatterDriver = require "st.matter.driver"
Expand All @@ -39,7 +38,7 @@ local SWITCH_INITIALIZED = "__switch_intialized"
-- in the device table for devices that joined prior to this transition, and it
-- will not be set for new devices.
local COMPONENT_TO_ENDPOINT_MAP = "__component_to_endpoint_map"
local BOUNDS_CHECKED = "__bounds_checked"
local IS_PARENT_CHILD_DEVICE = "__is_parent_child_device"
local COLOR_TEMP_BOUND_RECEIVED = "__colorTemp_bound_received"
local COLOR_TEMP_MIN = "__color_temp_min"
local COLOR_TEMP_MAX = "__color_temp_max"
Expand Down Expand Up @@ -151,6 +150,13 @@ local function initialize_switch(driver, device)
end
end

if num_server_eps > 1 then
-- If the device is a parent child device, then set the find_child function on init.
-- This is persisted because initialize switch is only run once, but find_child function should be set
-- on each driver init.
device:set_field(IS_PARENT_CHILD_DEVICE, true, {persist = true})
end

device:set_field(SWITCH_INITIALIZED, true)
-- The case where num_server_eps > 0 is a workaround for devices that have the On/Off
-- Light Switch device type but implement the On Off cluster as server (which is against the spec
Expand Down Expand Up @@ -211,24 +217,10 @@ local function device_init(driver, device)
end
device:set_component_to_endpoint_fn(component_to_endpoint)
device:set_endpoint_to_component_fn(endpoint_to_component)
device:set_find_child(find_child)
device:subscribe()

if not device:get_field(BOUNDS_CHECKED) then
local limit_read = im.InteractionRequest(im.InteractionRequest.RequestType.READ, {})
if device:supports_capability(capabilities.colorTemperature) then
limit_read:merge(clusters.ColorControl.attributes.ColorTempPhysicalMinMireds:read())
limit_read:merge(clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds:read())
end
if device:supports_capability(capabilities.switchLevel) then
limit_read:merge(clusters.LevelControl.attributes.MinLevel:read())
limit_read:merge(clusters.LevelControl.attributes.MaxLevel:read())
end
if #limit_read.info_blocks ~= 0 then
device:send(limit_read)
end
device:set_field(BOUNDS_CHECKED, true)
if device:get_field(IS_PARENT_CHILD_DEVICE) == true then
device:set_find_child(find_child)
end
device:subscribe()
end
end

Expand Down Expand Up @@ -540,7 +532,9 @@ local matter_driver_template = {
clusters.OnOff.attributes.OnOff
},
[capabilities.switchLevel.ID] = {
clusters.LevelControl.attributes.CurrentLevel
clusters.LevelControl.attributes.CurrentLevel,
clusters.LevelControl.attributes.MaxLevel,
clusters.LevelControl.attributes.MinLevel,
},
[capabilities.colorControl.ID] = {
clusters.ColorControl.attributes.CurrentHue,
Expand All @@ -550,6 +544,8 @@ local matter_driver_template = {
},
[capabilities.colorTemperature.ID] = {
clusters.ColorControl.attributes.ColorTemperatureMireds,
clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds,
clusters.ColorControl.attributes.ColorTempPhysicalMinMireds,
},
[capabilities.illuminanceMeasurement.ID] = {
clusters.IlluminanceMeasurement.attributes.MeasuredValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,18 @@ local function test_init()
local cluster_subscribe_list = {
clusters.OnOff.attributes.OnOff,
clusters.LevelControl.attributes.CurrentLevel,
clusters.LevelControl.attributes.MaxLevel,
clusters.LevelControl.attributes.MinLevel,
clusters.ColorControl.attributes.CurrentHue,
clusters.ColorControl.attributes.CurrentSaturation,
clusters.ColorControl.attributes.CurrentX,
clusters.ColorControl.attributes.CurrentY,
clusters.ColorControl.attributes.ColorTemperatureMireds,
clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds,
clusters.ColorControl.attributes.ColorTempPhysicalMinMireds,
clusters.IlluminanceMeasurement.attributes.MeasuredValue,
clusters.OccupancySensing.attributes.Occupancy
}
-- Set __bounds_checked to bypass the setpoint limit reads so they do not need
-- to be checked in the init function.
mock_device:set_field("__bounds_checked", true, {persist = true})
test.socket.matter:__set_channel_ordering("relaxed")
local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device)
for i, cluster in ipairs(cluster_subscribe_list) do
Expand Down
18 changes: 4 additions & 14 deletions drivers/SmartThings/matter-switch/src/test/test_matter_switch.lua
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,15 @@ local mock_device_no_hue_sat = test.mock_device.build_test_matter_device({
local cluster_subscribe_list = {
clusters.OnOff.attributes.OnOff,
clusters.LevelControl.attributes.CurrentLevel,
clusters.LevelControl.attributes.MaxLevel,
clusters.LevelControl.attributes.MinLevel,
clusters.ColorControl.attributes.CurrentHue,
clusters.ColorControl.attributes.CurrentSaturation,
clusters.ColorControl.attributes.CurrentX,
clusters.ColorControl.attributes.CurrentY,
clusters.ColorControl.attributes.ColorTemperatureMireds,
clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds,
clusters.ColorControl.attributes.ColorTempPhysicalMinMireds,
}

local function test_init()
Expand All @@ -96,13 +100,6 @@ local function test_init()
end
end
test.socket.matter:__expect_send({mock_device.id, subscribe_request})

local limit_read = clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds:read()
limit_read:merge(clusters.ColorControl.attributes.ColorTempPhysicalMinMireds:read())
limit_read:merge(clusters.LevelControl.attributes.MaxLevel:read())
limit_read:merge(clusters.LevelControl.attributes.MinLevel:read())
test.socket.matter:__expect_send({mock_device.id, limit_read})

test.mock_device.add_test_device(mock_device)

subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device_no_hue_sat)
Expand All @@ -112,13 +109,6 @@ local function test_init()
end
end
test.socket.matter:__expect_send({mock_device_no_hue_sat.id, subscribe_request})

limit_read = clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds:read()
limit_read:merge(clusters.ColorControl.attributes.ColorTempPhysicalMinMireds:read())
limit_read:merge(clusters.LevelControl.attributes.MaxLevel:read())
limit_read:merge(clusters.LevelControl.attributes.MinLevel:read())
test.socket.matter:__expect_send({mock_device_no_hue_sat.id, limit_read})

test.mock_device.add_test_device(mock_device_no_hue_sat)
end
test.set_test_init_function(test_init)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,12 @@ local function test_init()
local cluster_subscribe_list = {
clusters.OnOff.attributes.OnOff,
clusters.LevelControl.attributes.CurrentLevel,
clusters.LevelControl.attributes.MaxLevel,
clusters.LevelControl.attributes.MinLevel,
clusters.ColorControl.attributes.ColorTemperatureMireds,
clusters.ColorControl.attributes.ColorTempPhysicalMaxMireds,
clusters.ColorControl.attributes.ColorTempPhysicalMinMireds,
}
-- Set __bounds_checked to bypass the setpoint limit reads so they do not need
-- to be checked in the init function.
mock_device:set_field("__bounds_checked", true, {persist = true})
local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device)
for i, cluster in ipairs(cluster_subscribe_list) do
if i > 1 then
Expand Down
31 changes: 18 additions & 13 deletions drivers/SmartThings/zigbee-button/src/aqara/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -82,29 +82,34 @@ local function device_init(driver, device)
end

local function added_handler(self, device)
if device:get_model() == "lumi.remote.b1acn02" then
device:send(cluster_base.write_manufacturer_specific_attribute(device,
PRIVATE_CLUSTER_ID, PRIVATE_ATTRIBUTE_ID_T1, MFG_CODE, data_types.Uint8, 1))
elseif device:get_model() == "lumi.remote.acn003" then
device:send(cluster_base.write_manufacturer_specific_attribute(device,
PRIVATE_CLUSTER_ID, PRIVATE_ATTRIBUTE_ID_E1, MFG_CODE, data_types.Uint8, 2))
end
-- when the wireless switch T1 accesses the network, the gateway sends
-- private attribute 0009 to make the device no longer distinguish
-- between the standard gateway and the aqara gateway.
-- When wireless switch E1 is connected to the network, the gateway sends
-- private attribute 0125 to enable the device to send double-click and long-press packets.
device:emit_event(capabilities.button.supportedButtonValues({"pushed","held","double"}, {visibility = { displayed = false }}))
device:emit_event(capabilities.button.numberOfButtons({value = 1}))
device:emit_event(capabilities.button.button.pushed({state_change = false}))
device:emit_event(capabilities.battery.battery(100))
end

local function do_configure(driver, device)
device:configure()
if device:get_model() == "lumi.remote.b1acn02" then
device:send(cluster_base.write_manufacturer_specific_attribute(device,
PRIVATE_CLUSTER_ID, PRIVATE_ATTRIBUTE_ID_T1, MFG_CODE, data_types.Uint8, 1))
elseif device:get_model() == "lumi.remote.acn003" then
device:send(cluster_base.write_manufacturer_specific_attribute(device,
PRIVATE_CLUSTER_ID, PRIVATE_ATTRIBUTE_ID_E1, MFG_CODE, data_types.Uint8, 2))
end
-- when the wireless switch T1 accesses the network, the gateway sends
-- private attribute 0009 to make the device no longer distinguish
-- between the standard gateway and the aqara gateway.
-- When wireless switch E1 is connected to the network, the gateway sends
-- private attribute 0125 to enable the device to send double-click and long-press packets.
end

local aqara_wireless_switch_handler = {
NAME = "Aqara Wireless Switch Handler",
lifecycle_handlers = {
init = device_init,
added = added_handler
added = added_handler,
doConfigure = do_configure
},
zigbee_handlers = {
attr = {
Expand Down
100 changes: 100 additions & 0 deletions drivers/SmartThings/zigbee-button/src/test/test_SLED_button.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
-- Copyright 2024 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 t_utils = require "integration_test.utils"
local zigbee_test_utils = require "integration_test.zigbee_test_utils"
local capabilities = require "st.capabilities"

local Level = clusters.Level
local OnOff = clusters.OnOff
local ColorControl = clusters.ColorControl
local button_attr = capabilities.button.button

local mock_device = test.mock_device.build_test_zigbee_device(
{
profile = t_utils.get_profile_definition("SLED-three-buttons.yml"),
zigbee_endpoints = {
[1] = {
id = 1,
manufacturer = "Samsung Electronics",
model = "SAMSUNG-ITM-Z-005",
server_clusters = {0x0001, 0x0006, 0x0008, 0x0300}
}
}
}
)

zigbee_test_utils.prepare_zigbee_env_info()
local function test_init()
test.mock_device.add_test_device(mock_device)
zigbee_test_utils.init_noop_health_check_timer()
end

test.set_test_init_function(test_init)

test.register_coroutine_test(
"Reported button should be handled: pushed true",
function()
test.socket.zigbee:__queue_receive({ mock_device.id, OnOff.server.commands.On.build_test_rx(mock_device) })
test.socket.capability:__expect_send(
mock_device:generate_test_message("button1", button_attr.pushed({ state_change = true }))
)
test.wait_for_events()
test.socket.zigbee:__queue_receive({ mock_device.id, OnOff.server.commands.Off.build_test_rx(mock_device) })
test.socket.capability:__expect_send(
mock_device:generate_test_message("button2", button_attr.pushed({ state_change = true }))
)
test.wait_for_events()
test.socket.zigbee:__queue_receive({ mock_device.id, OnOff.server.commands.Toggle.build_test_rx(mock_device) })
test.socket.capability:__expect_send(
mock_device:generate_test_message("button3", button_attr.pushed({ state_change = true }))
)
end
)

test.register_coroutine_test(
"Reported button should be handled: held true",
function()
test.wait_for_events()
test.socket.zigbee:__queue_receive({ mock_device.id, Level.server.commands.MoveWithOnOff.build_test_rx(mock_device, 0x00, 0x00) })
test.socket.capability:__expect_send(
mock_device:generate_test_message("button1", button_attr.held({ state_change = true }))
)
test.socket.zigbee:__queue_receive({ mock_device.id, Level.server.commands.Move.build_test_rx(mock_device, 0x00, 0x00) })
test.socket.capability:__expect_send(
mock_device:generate_test_message("button2", button_attr.held({ state_change = true }))
)
test.wait_for_events()
test.socket.zigbee:__queue_receive({ mock_device.id, ColorControl.server.commands.MoveToColorTemperature.build_test_rx(mock_device, 0x00, 0x00) })
test.socket.capability:__expect_send(
mock_device:generate_test_message("button3", button_attr.held({ state_change = true }))
)
test.wait_for_events()
end
)

test.register_coroutine_test(
"Handle doConfigure lifecycle",
function()
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, OnOff.ID)
})
mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" })
end
)

test.run_registered_tests()
Loading
Loading