Skip to content
Open
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
17 changes: 17 additions & 0 deletions drivers/SmartThings/zigbee-switch/src/aqara-light/can_handle.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

return function(opts, driver, device)
local FINGERPRINTS = {
{ mfr = "LUMI", model = "lumi.light.acn004" },
{ mfr = "Aqara", model = "lumi.light.acn014" }
}

for _, fingerprint in ipairs(FINGERPRINTS) do
if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then
local subdriver = require("aqara-light")
return true, subdriver
end
end
return false
end
20 changes: 4 additions & 16 deletions drivers/SmartThings/zigbee-switch/src/aqara-light/init.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

local clusters = require "st.zigbee.zcl.clusters"
local cluster_base = require "st.zigbee.cluster_base"
local data_types = require "st.zigbee.data_types"
Expand All @@ -12,21 +15,6 @@ local PRIVATE_CLUSTER_ID = 0xFCC0
local PRIVATE_ATTRIBUTE_ID = 0x0009
local MFG_CODE = 0x115F

local FINGERPRINTS = {
{ mfr = "LUMI", model = "lumi.light.acn004" },
{ mfr = "Aqara", model = "lumi.light.acn014" }
}

local function is_aqara_products(opts, driver, device)
for _, fingerprint in ipairs(FINGERPRINTS) do
if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then
local subdriver = require("aqara-light")
return true, subdriver
end
end
return false
end

local function do_refresh(self, device)
device:send(OnOff.attributes.OnOff:read(device))
device:send(Level.attributes.CurrentLevel:read(device))
Expand Down Expand Up @@ -65,7 +53,7 @@ local aqara_light_handler = {
[capabilities.switchLevel.commands.setLevel.NAME] = set_level_handler
}
},
can_handle = is_aqara_products
can_handle = require("aqara-light.can_handle"),
}

return aqara_light_handler
13 changes: 13 additions & 0 deletions drivers/SmartThings/zigbee-switch/src/aqara/can_handle.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

return function(opts, driver, device)
local FINGERPRINTS = require("aqara.fingerprints")
for _, fingerprint in ipairs(FINGERPRINTS) do
if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then
local subdriver = require("aqara")
return true, subdriver
end
end
return false
end
22 changes: 22 additions & 0 deletions drivers/SmartThings/zigbee-switch/src/aqara/fingerprints.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

return {
{ mfr = "LUMI", model = "lumi.plug.maeu01" },
{ mfr = "LUMI", model = "lumi.plug.macn01" },
{ mfr = "LUMI", model = "lumi.switch.n0agl1" },
{ mfr = "LUMI", model = "lumi.switch.l0agl1" },
{ mfr = "LUMI", model = "lumi.switch.n0acn2" },
{ mfr = "LUMI", model = "lumi.switch.n1acn1" },
{ mfr = "LUMI", model = "lumi.switch.n2acn1" },
{ mfr = "LUMI", model = "lumi.switch.n3acn1" },
{ mfr = "LUMI", model = "lumi.switch.b1laus01" },
{ mfr = "LUMI", model = "lumi.switch.b2laus01" },
{ mfr = "LUMI", model = "lumi.switch.n1aeu1" },
{ mfr = "LUMI", model = "lumi.switch.n2aeu1" },
{ mfr = "LUMI", model = "lumi.switch.l1aeu1" },
{ mfr = "LUMI", model = "lumi.switch.l2aeu1" },
{ mfr = "LUMI", model = "lumi.switch.b1nacn01" },
{ mfr = "LUMI", model = "lumi.switch.b2nacn01" },
{ mfr = "LUMI", model = "lumi.switch.b3n01" }
}
34 changes: 4 additions & 30 deletions drivers/SmartThings/zigbee-switch/src/aqara/init.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

local capabilities = require "st.capabilities"
local clusters = require "st.zigbee.zcl.clusters"
local cluster_base = require "st.zigbee.cluster_base"
Expand All @@ -24,26 +27,6 @@ local ELECTRIC_SWITCH_TYPE_ATTRIBUTE_ID = 0x000A
local LAST_REPORT_TIME = "LAST_REPORT_TIME"
local PRIVATE_MODE = "PRIVATE_MODE"

local FINGERPRINTS = {
{ mfr = "LUMI", model = "lumi.plug.maeu01" },
{ mfr = "LUMI", model = "lumi.plug.macn01" },
{ mfr = "LUMI", model = "lumi.switch.n0agl1" },
{ mfr = "LUMI", model = "lumi.switch.l0agl1" },
{ mfr = "LUMI", model = "lumi.switch.n0acn2" },
{ mfr = "LUMI", model = "lumi.switch.n1acn1" },
{ mfr = "LUMI", model = "lumi.switch.n2acn1" },
{ mfr = "LUMI", model = "lumi.switch.n3acn1" },
{ mfr = "LUMI", model = "lumi.switch.b1laus01" },
{ mfr = "LUMI", model = "lumi.switch.b2laus01" },
{ mfr = "LUMI", model = "lumi.switch.n1aeu1" },
{ mfr = "LUMI", model = "lumi.switch.n2aeu1" },
{ mfr = "LUMI", model = "lumi.switch.l1aeu1" },
{ mfr = "LUMI", model = "lumi.switch.l2aeu1" },
{ mfr = "LUMI", model = "lumi.switch.b1nacn01" },
{ mfr = "LUMI", model = "lumi.switch.b2nacn01" },
{ mfr = "LUMI", model = "lumi.switch.b3n01" }
}

local preference_map = {
["stse.restorePowerState"] = {
cluster_id = PRIVATE_CLUSTER_ID,
Expand Down Expand Up @@ -137,15 +120,6 @@ local preference_map = {
},
}

local function is_aqara_products(opts, driver, device)
for _, fingerprint in ipairs(FINGERPRINTS) do
if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then
local subdriver = require("aqara")
return true, subdriver
end
end
return false
end

local function private_mode_handler(driver, device, value, zb_rx)
device:set_field(PRIVATE_MODE, value.value, { persist = true })
Expand Down Expand Up @@ -286,7 +260,7 @@ local aqara_switch_handler = {
require("aqara.version"),
require("aqara.multi-switch")
},
can_handle = is_aqara_products
can_handle = require("aqara.can_handle"),
}

return aqara_switch_handler
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

return function(opts, driver, device)
local FINGERPRINTS = require("aqara.multi-switch.fingerprints")
for _, fingerprint in ipairs(FINGERPRINTS) do
if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then
return true, require("aqara.multi-switch")
end
end
return false
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

return {
{ mfr = "LUMI", model = "lumi.switch.n1acn1", children = 1, child_profile = "" },
{ mfr = "LUMI", model = "lumi.switch.n2acn1", children = 2, child_profile = "aqara-switch-child" },
{ mfr = "LUMI", model = "lumi.switch.n3acn1", children = 3, child_profile = "aqara-switch-child" },
{ mfr = "LUMI", model = "lumi.switch.b1laus01", children = 1, child_profile = "" },
{ mfr = "LUMI", model = "lumi.switch.b2laus01", children = 2, child_profile = "aqara-switch-child" },
{ mfr = "LUMI", model = "lumi.switch.l2aeu1", children = 2, child_profile = "aqara-switch-child" },
{ mfr = "LUMI", model = "lumi.switch.n2aeu1", children = 2, child_profile = "aqara-switch-child" },
{ mfr = "LUMI", model = "lumi.switch.b2nacn01", children = 2, child_profile = "aqara-switch-child" },
{ mfr = "LUMI", model = "lumi.switch.b3n01", children = 3, child_profile = "aqara-switch-child" }
}
27 changes: 5 additions & 22 deletions drivers/SmartThings/zigbee-switch/src/aqara/multi-switch/init.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

local device_lib = require "st.device"
local capabilities = require "st.capabilities"
local cluster_base = require "st.zigbee.cluster_base"
Expand All @@ -8,27 +11,7 @@ local switch_utils = require "switch_utils"
local PRIVATE_CLUSTER_ID = 0xFCC0
local PRIVATE_ATTRIBUTE_ID = 0x0009
local MFG_CODE = 0x115F

local FINGERPRINTS = {
{ mfr = "LUMI", model = "lumi.switch.n1acn1", children = 1, child_profile = "" },
{ mfr = "LUMI", model = "lumi.switch.n2acn1", children = 2, child_profile = "aqara-switch-child" },
{ mfr = "LUMI", model = "lumi.switch.n3acn1", children = 3, child_profile = "aqara-switch-child" },
{ mfr = "LUMI", model = "lumi.switch.b1laus01", children = 1, child_profile = "" },
{ mfr = "LUMI", model = "lumi.switch.b2laus01", children = 2, child_profile = "aqara-switch-child" },
{ mfr = "LUMI", model = "lumi.switch.l2aeu1", children = 2, child_profile = "aqara-switch-child" },
{ mfr = "LUMI", model = "lumi.switch.n2aeu1", children = 2, child_profile = "aqara-switch-child" },
{ mfr = "LUMI", model = "lumi.switch.b2nacn01", children = 2, child_profile = "aqara-switch-child" },
{ mfr = "LUMI", model = "lumi.switch.b3n01", children = 3, child_profile = "aqara-switch-child" }
}

local function is_aqara_products(opts, driver, device)
for _, fingerprint in ipairs(FINGERPRINTS) do
if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then
return true
end
end
return false
end
local FINGERPRINTS = require("aqara.multi-switch.fingerprints")

local function get_children_amount(device)
for _, fingerprint in ipairs(FINGERPRINTS) do
Expand Down Expand Up @@ -106,7 +89,7 @@ local aqara_multi_switch_handler = {
init = configurations.power_reconfig_wrapper(device_init),
added = device_added
},
can_handle = is_aqara_products
can_handle = require("aqara.multi-switch.can_handle"),
}

return aqara_multi_switch_handler
9 changes: 9 additions & 0 deletions drivers/SmartThings/zigbee-switch/src/aqara/sub_drivers.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

local lazy_load = require "lazy_load_subdriver"

return {
lazy_load("aqara.multi-switch"),
lazy_load("aqara.version"),
}
13 changes: 13 additions & 0 deletions drivers/SmartThings/zigbee-switch/src/aqara/version/can_handle.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

return function (opts, driver, device)
local PRIVATE_MODE = "PRIVATE_MODE"
local private_mode = device:get_field(PRIVATE_MODE) or 0
local res = private_mode == 1
if res then
return res, require("aqara.version")
else
return res
end
end
8 changes: 4 additions & 4 deletions drivers/SmartThings/zigbee-switch/src/aqara/version/init.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

local capabilities = require "st.capabilities"
local clusters = require "st.zigbee.zcl.clusters"
local constants = require "st.zigbee.constants"
Expand Down Expand Up @@ -102,10 +105,7 @@ local aqara_switch_version_handler = {
}
}
},
can_handle = function (opts, driver, device)
local private_mode = device:get_field(PRIVATE_MODE) or 0
return private_mode == 1
end
can_handle = require("aqara.version.can_handle")
}

return aqara_switch_version_handler
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0


-- There are reports of at least one device (SONOFF 01MINIZB) which occasionally
-- reports this value as an Int8, rather than a Boolean, as per the spec
return function(opts, driver, device, zb_rx, ...)
local zcl_clusters = require "st.zigbee.zcl.clusters"
local data_types = require "st.zigbee.data_types"
local can_handle = opts.dispatcher_class == "ZigbeeMessageDispatcher" and
device:get_manufacturer() == "SONOFF" and
zb_rx.body and
zb_rx.body.zcl_body and
zb_rx.body.zcl_body.attr_records and
zb_rx.address_header.cluster.value == zcl_clusters.OnOff.ID and
zb_rx.body.zcl_body.attr_records[1].attr_id.value == zcl_clusters.OnOff.attributes.OnOff.ID and
zb_rx.body.zcl_body.attr_records[1].data_type.value ~= data_types.Boolean.ID
if can_handle then
local subdriver = require("bad_on_off_data_type")
return true, subdriver
else
return false
end
end
Original file line number Diff line number Diff line change
@@ -1,40 +1,9 @@
-- Copyright 2023 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.
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

local zcl_clusters = require "st.zigbee.zcl.clusters"
local data_types = require "st.zigbee.data_types"
local capabilities = require "st.capabilities"

-- There are reports of at least one device (SONOFF 01MINIZB) which occasionally
-- reports this value as an Int8, rather than a Boolean, as per the spec
local function incorrect_data_type_detected(opts, driver, device, zb_rx, ...)
local can_handle = opts.dispatcher_class == "ZigbeeMessageDispatcher" and
device:get_manufacturer() == "SONOFF" and
zb_rx.body and
zb_rx.body.zcl_body and
zb_rx.body.zcl_body.attr_records and
zb_rx.address_header.cluster.value == zcl_clusters.OnOff.ID and
zb_rx.body.zcl_body.attr_records[1].attr_id.value == zcl_clusters.OnOff.attributes.OnOff.ID and
zb_rx.body.zcl_body.attr_records[1].data_type.value ~= data_types.Boolean.ID
if can_handle then
local subdriver = require("bad_on_off_data_type")
return true, subdriver
else
return false
end
end

local function on_off_attr_handler(driver, device, value, zb_rx)
local attr = capabilities.switch.switch
device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, value.value == 0 and attr.off() or attr.on())
Expand All @@ -49,7 +18,7 @@ local bad_on_off_data_type = {
}
}
},
can_handle = incorrect_data_type_detected
can_handle = require("bad_on_off_data_type.can_handle"),
}

return bad_on_off_data_type
return bad_on_off_data_type
15 changes: 2 additions & 13 deletions drivers/SmartThings/zigbee-switch/src/configurations/devices.lua
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
-- 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.
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

local clusters = require "st.zigbee.zcl.clusters"
local ColorControl = clusters.ColorControl
Expand Down
15 changes: 2 additions & 13 deletions drivers/SmartThings/zigbee-switch/src/configurations/init.lua
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
-- 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.
-- Copyright 2025 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0


local CONFIGURATION_VERSION_KEY = "_configuration_version"
Expand Down
Loading
Loading