Skip to content

Commit d4cd82c

Browse files
Use single component rather than MCD
This commit changes the fan/light configuration to be a single component rather than MCD, for reasons layed out in the review discussion.
1 parent 578944f commit d4cd82c

File tree

3 files changed

+63
-73
lines changed

3 files changed

+63
-73
lines changed

drivers/SmartThings/matter-switch/profiles/light-color-level-fan.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,13 @@ components:
1818
range: [ 2200, 6500 ]
1919
- id: colorControl
2020
version: 1
21+
- id: fanMode
22+
version: 1
23+
- id: fanSpeedPercent
24+
version: 1
2125
- id: firmwareUpdate
2226
version: 1
2327
- id: refresh
2428
version: 1
2529
categories:
2630
- name: Light
27-
- id: fan
28-
capabilities:
29-
- id: fanMode
30-
version: 1
31-
- id: fanSpeedPercent
32-
version: 1
33-
categories:
34-
- name: Fan

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

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,12 @@ local SWITCH_INITIALIZED = "__switch_intialized"
5151
-- in the device table for devices that joined prior to this transition, and it
5252
-- will not be set for new devices.
5353
local COMPONENT_TO_ENDPOINT_MAP = "__component_to_endpoint_map"
54-
-- COMPONENT_TO_ENDPOINT_MAP_NEW_DEVICES is for new devices that can be supported
55-
-- by a MCD configuration.
56-
local COMPONENT_TO_ENDPOINT_MAP_NEW_DEVICES = "__component_to_endpoint_map_button"
54+
-- COMPONENT_TO_ENDPOINT_MAP_BUTTON is for devices with button endpoints, to
55+
-- preserve the MCD functionality for button devices from the matter-button
56+
-- driver after it was merged into the matter-switch driver. Note that devices
57+
-- containing both button endpoints and switch endpoints will use this field
58+
-- rather than COMPONENT_TO_ENDPOINT_MAP.
59+
local COMPONENT_TO_ENDPOINT_MAP_BUTTON = "__component_to_endpoint_map_button"
5760
local ENERGY_MANAGEMENT_ENDPOINT = "__energy_management_endpoint"
5861
local IS_PARENT_CHILD_DEVICE = "__is_parent_child_device"
5962
local COLOR_TEMP_BOUND_RECEIVED_KELVIN = "__colorTemp_bound_received_kelvin"
@@ -453,15 +456,15 @@ local function find_default_endpoint(device)
453456
end
454457

455458
local function component_to_endpoint(device, component)
456-
local map = device:get_field(COMPONENT_TO_ENDPOINT_MAP_NEW_DEVICES) or device:get_field(COMPONENT_TO_ENDPOINT_MAP) or {}
459+
local map = device:get_field(COMPONENT_TO_ENDPOINT_MAP_BUTTON) or device:get_field(COMPONENT_TO_ENDPOINT_MAP) or {}
457460
if map[component] then
458461
return map[component]
459462
end
460463
return find_default_endpoint(device)
461464
end
462465

463466
local function endpoint_to_component(device, ep)
464-
local map = device:get_field(COMPONENT_TO_ENDPOINT_MAP_NEW_DEVICES) or device:get_field(COMPONENT_TO_ENDPOINT_MAP) or {}
467+
local map = device:get_field(COMPONENT_TO_ENDPOINT_MAP_BUTTON) or device:get_field(COMPONENT_TO_ENDPOINT_MAP) or {}
465468
for component, endpoint in pairs(map) do
466469
if endpoint == ep then
467470
return component
@@ -584,43 +587,32 @@ local function find_child(parent, ep_id)
584587
end
585588

586589
local function build_component_map(device, main_endpoint)
587-
local component_name, endpoints
590+
-- create component mapping on the main profile button endpoints
588591
local button_eps = device:get_endpoints(clusters.Switch.ID, {feature_bitmap=clusters.Switch.types.SwitchFeature.MOMENTARY_SWITCH})
589-
local fan_eps = device:get_endpoints(clusters.FanControl.ID)
590-
table.sort(button_eps)
591-
table.sort(fan_eps)
592-
593-
if #button_eps > 0 and STATIC_BUTTON_PROFILE_SUPPORTED[#button_eps] then
594-
component_name = "button"
595-
endpoints = button_eps
596-
elseif #fan_eps > 0 then
597-
component_name = "fan"
598-
endpoints = fan_eps
599-
else
600-
return
601-
end
602-
603-
local component_map = {}
604-
component_map["main"] = main_endpoint
605-
for component_num, ep in ipairs(endpoints) do
606-
if ep ~= main_endpoint then
607-
local component = component_name
608-
if #endpoints > 1 then
609-
component = component .. component_num
592+
if tbl_contains(STATIC_BUTTON_PROFILE_SUPPORTED, #button_eps) then
593+
table.sort(button_eps)
594+
local component_map = {}
595+
component_map["main"] = main_endpoint
596+
for component_num, ep in ipairs(button_eps) do
597+
if ep ~= main_endpoint then
598+
local button_component = "button"
599+
if #button_eps > 1 then
600+
button_component = button_component .. component_num
601+
end
602+
component_map[button_component] = ep
610603
end
611-
component_map[component] = ep
612604
end
605+
device:set_field(COMPONENT_TO_ENDPOINT_MAP_BUTTON, component_map, {persist = true})
613606
end
614-
device:set_field(COMPONENT_TO_ENDPOINT_MAP_NEW_DEVICES, component_map, {persist = true})
615607
end
616608

617-
local function build_mcd_profile(device, main_endpoint)
609+
local function build_profile(device, main_endpoint)
618610
local button_eps = device:get_endpoints(clusters.Switch.ID, {feature_bitmap=clusters.Switch.types.SwitchFeature.MOMENTARY_SWITCH})
619611
local fan_eps = device:get_endpoints(clusters.FanControl.ID)
620612
local profile_name
621613
local battery_supported
622614

623-
if #button_eps > 0 and STATIC_BUTTON_PROFILE_SUPPORTED[#button_eps] then
615+
if tbl_contains(STATIC_BUTTON_PROFILE_SUPPORTED, #button_eps) then
624616
profile_name = string.gsub(#button_eps .. "-button", "1%-", "") -- remove the "1-" in a device with 1 button ep
625617
if device_type_supports_button_switch_combination(device, main_endpoint) then
626618
profile_name = "light-level-" .. profile_name
@@ -632,7 +624,7 @@ local function build_mcd_profile(device, main_endpoint)
632624
device:send(attribute_list_read)
633625
end
634626
elseif #fan_eps > 0 then
635-
profile_name = "light-color-level-fan"
627+
profile_name = "light-color-level-fan" -- currently the only supported fan+light configuration
636628
else
637629
return
638630
end
@@ -704,7 +696,7 @@ local function handle_light_switch_with_onOff_server_clusters(device, main_endpo
704696
end
705697

706698
local function initialize_switch(driver, device, main_endpoint)
707-
build_mcd_profile(device, main_endpoint)
699+
build_profile(device, main_endpoint)
708700
build_component_map(device, main_endpoint)
709701
configure_buttons(device)
710702

drivers/SmartThings/matter-switch/src/test/test_matter_light_fan.lua

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ local capabilities = require "st.capabilities"
1616
local clusters = require "st.matter.generated.zap_clusters"
1717
local t_utils = require "integration_test.utils"
1818
local test = require "integration_test"
19+
local version = require "version"
1920

2021
local TRANSITION_TIME = 0
2122
local OPTIONS_MASK = 0x01
@@ -94,43 +95,44 @@ end
9495

9596
test.set_test_init_function(test_init)
9697

97-
test.register_message_test(
98-
"Main switch component: switch capability should send the appropriate commands",
99-
{
100-
{
101-
channel = "capability",
102-
direction = "receive",
103-
message = {
98+
test.register_coroutine_test(
99+
"Switch capability should send the appropriate commands", function()
100+
test.socket.capability:__queue_receive(
101+
{
104102
mock_device.id,
105103
{ capability = "switch", component = "main", command = "on", args = { } }
106104
}
107-
},
108-
{
109-
channel = "matter",
110-
direction = "send",
111-
message = {
105+
)
106+
if version.api >= 11 then
107+
test.socket.devices:__expect_send(
108+
{
109+
"register_native_capability_cmd_handler",
110+
{ device_uuid = mock_device.id, capability_id = "switch", capability_cmd_id = "on" }
111+
}
112+
)
113+
end
114+
test.socket.matter:__expect_send(
115+
{
112116
mock_device.id,
113-
clusters.OnOff.server.commands.On(mock_device, mock_device_ep1)
114-
},
115-
},
116-
{
117-
channel = "matter",
118-
direction = "receive",
119-
message = {
117+
clusters.OnOff.server.commands.On(mock_device, 1)
118+
}
119+
)
120+
test.socket.matter:__queue_receive(
121+
{
120122
mock_device.id,
121123
clusters.OnOff.attributes.OnOff:build_test_report_data(mock_device, mock_device_ep1, true)
122124
}
123-
},
124-
{
125-
channel = "capability",
126-
direction = "send",
127-
message = mock_device:generate_test_message("main", capabilities.switch.switch.on())
128-
}
129-
}
125+
)
126+
test.socket.capability:__expect_send(
127+
mock_device:generate_test_message(
128+
"main", capabilities.switch.switch.on()
129+
)
130+
)
131+
end
130132
)
131133

132134
test.register_message_test(
133-
"Main switch component: Set color temperature should send the appropriate commands",
135+
"Set color temperature should send the appropriate commands",
134136
{
135137
{
136138
channel = "capability",
@@ -187,7 +189,7 @@ test.register_message_test(
187189
{
188190
channel = "capability",
189191
direction = "send",
190-
message = mock_device:generate_test_message("fan", capabilities.fanMode.fanMode.auto())
192+
message = mock_device:generate_test_message("main", capabilities.fanMode.fanMode.auto())
191193
},
192194
{
193195
channel = "matter",
@@ -200,7 +202,7 @@ test.register_message_test(
200202
{
201203
channel = "capability",
202204
direction = "send",
203-
message = mock_device:generate_test_message("fan", capabilities.fanMode.fanMode.auto())
205+
message = mock_device:generate_test_message("main", capabilities.fanMode.fanMode.auto())
204206
},
205207
{
206208
channel = "matter",
@@ -213,7 +215,7 @@ test.register_message_test(
213215
{
214216
channel = "capability",
215217
direction = "send",
216-
message = mock_device:generate_test_message("fan", capabilities.fanMode.fanMode("medium"))
218+
message = mock_device:generate_test_message("main", capabilities.fanMode.fanMode("medium"))
217219
}
218220
}
219221
)
@@ -233,7 +235,7 @@ test.register_message_test(
233235
{
234236
channel = "capability",
235237
direction = "send",
236-
message = mock_device:generate_test_message("fan", capabilities.fanMode.supportedFanModes({"off", "high"}, {visibility={displayed=false}}))
238+
message = mock_device:generate_test_message("main", capabilities.fanMode.supportedFanModes({"off", "high"}, {visibility={displayed=false}}))
237239
},
238240
{
239241
channel = "matter",
@@ -246,7 +248,7 @@ test.register_message_test(
246248
{
247249
channel = "capability",
248250
direction = "send",
249-
message = mock_device:generate_test_message("fan", capabilities.fanMode.supportedFanModes({"off", "low", "medium", "high", "auto"}, {visibility={displayed=false}}))
251+
message = mock_device:generate_test_message("main", capabilities.fanMode.supportedFanModes({"off", "low", "medium", "high", "auto"}, {visibility={displayed=false}}))
250252
},
251253
}
252254
)

0 commit comments

Comments
 (0)