Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,7 @@ function AttributeHandlers.power_source_attribute_list_handler(driver, device, i
profile_name = string.format("%d-", #button_eps) .. profile_name
end

if device.manufacturer_info.vendor_id == fields.AQARA_MANUFACTURER_ID and
device.manufacturer_info.product_id == fields.AQARA_CLIMATE_SENSOR_W100_ID then
if switch_utils.get_product_override_field(device, "is_climate_sensor_w100") then
profile_name = profile_name .. "-temperature-humidity"
end
device:try_update_metadata({ profile = profile_name })
Expand Down
12 changes: 12 additions & 0 deletions drivers/SmartThings/matter-switch/src/test/test_matter_bridge.lua
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ end
test.register_coroutine_test(
"Profile should not change for devices with aggregator device type (bridges)",
function()
local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_bridge)
for i, cluster in ipairs(cluster_subscribe_list) do
if i > 1 then
subscribe_request:merge(cluster:subscribe(mock_bridge))
end
end
test.socket.device_lifecycle:__queue_receive({ mock_bridge.id, "added" })
test.socket.matter:__expect_send({mock_bridge.id, subscribe_request})
test.socket.device_lifecycle:__queue_receive({ mock_bridge.id, "init" })
test.socket.matter:__expect_send({mock_bridge.id, subscribe_request})
test.socket.device_lifecycle:__queue_receive({ mock_bridge.id, "doConfigure" })
mock_bridge:expect_metadata_update({ provisioning_state = "PROVISIONED" })
end,
{ test_init = test_init_mock_bridge }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,9 @@ function SwitchDeviceConfiguration.assign_child_profile(device, child_ep)
end
end

-- Check if device has an overridden child profile that differs from the profile that would match
-- the child's device type for the following two cases:
-- 1. To add Electrical Sensor only to the first EDGE_CHILD (light-power-energy-powerConsumption)
-- for the Aqara Light Switch H2. The profile of the second EDGE_CHILD for this device is
-- determined in the "for" loop above (e.g., light-binary)
-- 2. The selected profile for the child device matches the initial profile defined in
-- child_device_profile_overrides
for id, vendor in pairs(fields.child_device_profile_overrides_per_vendor_id) do
for _, fingerprint in ipairs(vendor) do
if device.manufacturer_info.product_id == fingerprint.product_id and
((device.manufacturer_info.vendor_id == fields.AQARA_MANUFACTURER_ID and child_ep == 1) or profile == fingerprint.initial_profile) then
return fingerprint.target_profile
end
end
-- vendor override checks
if child_ep == switch_utils.get_product_override_field(device, "ep_id") or profile == switch_utils.get_product_override_field(device, "initial_profile") then
profile = switch_utils.get_product_override_field(device, "target_profile") or profile
end

-- default to "switch-binary" if no profile is found
Expand Down
26 changes: 12 additions & 14 deletions drivers/SmartThings/matter-switch/src/utils/switch_fields.lua
Original file line number Diff line number Diff line change
Expand Up @@ -106,19 +106,20 @@ SwitchFields.HUE_SAT_COLOR_MODE = clusters.ColorControl.types.ColorMode.CURRENT_
SwitchFields.X_Y_COLOR_MODE = clusters.ColorControl.types.ColorMode.CURRENTX_AND_CURRENTY


SwitchFields.child_device_profile_overrides_per_vendor_id = {
SwitchFields.vendor_overrides = {
[0x1321] = {
{ product_id = 0x000C, target_profile = "switch-binary", initial_profile = "plug-binary" },
{ product_id = 0x000D, target_profile = "switch-binary", initial_profile = "plug-binary" },
[0x000C] = { target_profile = "switch-binary", initial_profile = "plug-binary" },
[0x000D] = { target_profile = "switch-binary", initial_profile = "plug-binary" },
},
[0x115F] = {
{ product_id = 0x1003, target_profile = "light-power-energy-powerConsumption" }, -- 2 Buttons(Generic Switch), 1 Channel(On/Off Light)
{ product_id = 0x1004, target_profile = "light-power-energy-powerConsumption" }, -- 2 Buttons(Generic Switch), 2 Channels(On/Off Light)
{ product_id = 0x1005, target_profile = "light-power-energy-powerConsumption" }, -- 4 Buttons(Generic Switch), 3 Channels(On/Off Light)
{ product_id = 0x1006, target_profile = "light-level-power-energy-powerConsumption" }, -- 3 Buttons(Generic Switch), 1 Channels(Dimmable Light)
{ product_id = 0x1008, target_profile = "light-power-energy-powerConsumption" }, -- 2 Buttons(Generic Switch), 1 Channel(On/Off Light)
{ product_id = 0x1009, target_profile = "light-power-energy-powerConsumption" }, -- 4 Buttons(Generic Switch), 2 Channels(On/Off Light)
{ product_id = 0x100A, target_profile = "light-level-power-energy-powerConsumption" }, -- 1 Buttons(Generic Switch), 1 Channels(Dimmable Light)
[0x115F] = { -- AQARA_MANUFACTURER_ID
[0x1003] = { target_profile = "light-power-energy-powerConsumption", ep_id = 1 }, -- 2 Buttons(Generic Switch), 1 Channel(On/Off Light)
[0x1004] = { target_profile = "light-power-energy-powerConsumption", ep_id = 1 }, -- 2 Buttons(Generic Switch), 2 Channels(On/Off Light)
[0x1005] = { target_profile = "light-power-energy-powerConsumption", ep_id = 1 }, -- 4 Buttons(Generic Switch), 3 Channels(On/Off Light)
[0x1008] = { target_profile = "light-power-energy-powerConsumption", ep_id = 1 }, -- 2 Buttons(Generic Switch), 1 Channel(On/Off Light)
[0x1009] = { target_profile = "light-power-energy-powerConsumption", ep_id = 1 }, -- 4 Buttons(Generic Switch), 2 Channels(On/Off Light)
[0x1006] = { ignore_combo_switch_button = true, target_profile = "light-level-power-energy-powerConsumption", ep_id = 1 }, -- 3 Buttons(Generic Switch), 1 Channels(Dimmable Light)
[0x100A] = { ignore_combo_switch_button = true, target_profile = "light-level-power-energy-powerConsumption", ep_id = 1 }, -- 1 Buttons(Generic Switch), 1 Channels(Dimmable Light)
[0x2004] = { is_climate_sensor_w100 = true }, -- Climate Sensor W100, requires unique profile
}
}

Expand Down Expand Up @@ -150,9 +151,6 @@ SwitchFields.TEMP_BOUND_RECEIVED = "__temp_bound_received"
SwitchFields.TEMP_MIN = "__temp_min"
SwitchFields.TEMP_MAX = "__temp_max"

SwitchFields.AQARA_MANUFACTURER_ID = 0x115F
SwitchFields.AQARA_CLIMATE_SENSOR_W100_ID = 0x2004

SwitchFields.TRANSITION_TIME = 0 --1/10ths of a second
-- When sent with a command, these options mask and override bitmaps cause the command
-- to take effect when the switch/light is off.
Expand Down
53 changes: 28 additions & 25 deletions drivers/SmartThings/matter-switch/src/utils/switch_utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ function utils.mired_to_kelvin(value, minOrMax)
end
end

function utils.get_product_override_field(device, override_key)
if fields.vendor_overrides[device.manufacturer_info.vendor_id]
and fields.vendor_overrides[device.manufacturer_info.vendor_id][device.manufacturer_info.product_id]
then
return fields.vendor_overrides[device.manufacturer_info.vendor_id][device.manufacturer_info.product_id][override_key]
end
end

function utils.check_field_name_updates(device)
for _, field in ipairs(fields.updated_fields) do
if device:get_field(field.current_field_name) then
Expand All @@ -78,29 +86,18 @@ end
--- whether the device type for an endpoint is currently supported by a profile for
--- combination button/switch devices.
function utils.device_type_supports_button_switch_combination(device, endpoint_id)
for _, ep in ipairs(device.endpoints) do
if ep.endpoint_id == endpoint_id then
for _, dt in ipairs(ep.device_types) do
if dt.device_type_id == fields.DIMMABLE_LIGHT_DEVICE_TYPE_ID then
for _, fingerprint in ipairs(fields.child_device_profile_overrides_per_vendor_id[0x115F]) do
if device.manufacturer_info.product_id == fingerprint.product_id then
return false -- For Aqara Dimmer Switch with Button.
end
end
return true
end
end
end
if utils.get_product_override_field(device, "ignore_combo_switch_button") then
return false
end
return false
local dimmable_eps = utils.get_endpoints_by_device_type(device, fields.DIMMABLE_LIGHT_DEVICE_TYPE_ID)
return utils.tbl_contains(dimmable_eps, endpoint_id)
end

--- find_default_endpoint is a helper function to handle situations where
--- device does not have endpoint ids in sequential order from 1
function utils.find_default_endpoint(device)
if device.manufacturer_info.vendor_id == fields.AQARA_MANUFACTURER_ID and
device.manufacturer_info.product_id == fields.AQARA_CLIMATE_SENSOR_W100_ID then
-- In case of Aqara Climate Sensor W100, in order to sequentially set the button name to button 1, 2, 3
-- Buttons should not be set on the main component for the Aqara Climate Sensor W100,
if utils.get_product_override_field(device, "is_climate_sensor_w100") then
return device.MATTER_DEFAULT_ENDPOINT
end

Expand Down Expand Up @@ -171,6 +168,19 @@ function utils.matter_handler(driver, device, response_block)
device.log.info(string.format("Fallback handler for %s", response_block))
end

-- get a list of endpoints for a specified device type.
function utils.get_endpoints_by_device_type(device, device_type_id)
local dt_eps = {}
for _, ep in ipairs(device.endpoints) do
for _, dt in ipairs(ep.device_types) do
if dt.device_type_id == device_type_id then
table.insert(dt_eps, ep.endpoint_id)
end
end
end
return dt_eps
end

--helper function to create list of multi press values
function utils.create_multi_press_values_list(size, supportsHeld)
local list = {"pushed", "double"}
Expand All @@ -183,14 +193,7 @@ function utils.create_multi_press_values_list(size, supportsHeld)
end

function utils.detect_bridge(device)
for _, ep in ipairs(device.endpoints) do
for _, dt in ipairs(ep.device_types) do
if dt.device_type_id == fields.AGGREGATOR_DEVICE_TYPE_ID then
return true
end
end
end
return false
return #utils.get_endpoints_by_device_type(device, fields.AGGREGATOR_DEVICE_TYPE_ID) > 0
end

function utils.detect_matter_thing(device)
Expand Down
Loading