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
6 changes: 6 additions & 0 deletions drivers/SmartThings/zigbee-switch/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2451,6 +2451,12 @@ zigbeeManufacturer:
manufacturer: JNL
model: Y-K002-001
deviceProfileName: basic-switch
#FIRSTLED
- id: "ManDai Technology/DC2DC12MiV1"
deviceLabel: Easy-Fit Driver
manufacturer: ManDai Technology
model: DC2DC12MiV1
deviceProfileName: light-color-temp-time-restore
zigbeeGeneric:
- id: "genericSwitch"
deviceLabel: Zigbee Switch
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: light-color-temp-time-restore
components:
- id: main
capabilities:
- id: switch
version: 1
- id: switchLevel
version: 1
config:
values:
- key: "level.value"
range: [1, 100]
- id: colorTemperature
version: 1
- id: firmwareUpdate
version: 1
- id: refresh
version: 1
categories:
- name: Light
preferences:
- title: "上电状态(power-on state/파워온 상태)"
name: powerOnMode
description: "上电状态(power-on state/파워온 상태)"
required: false
preferenceType: enumeration
definition:
options:
0: "关闭(off/닫다)"
1: "打开(on/열다)"
2: "恢复记忆状态(restore/복원)"
default: 0
- title: "驱动电流(drive current/구동 전류)"
name: ledDriveCurrent
description: "驱动电流(drive current/구동 전류)/50~333mA"
required: false
preferenceType: integer
definition:
minimum: 50
maximum: 333
default: 270
- title: "亮度时间(dimmingTransitionTime/밝기 전환 시간)"
name: dimTransitionTime
description: "亮度过渡时间(dimming transition time/밝기 전환 시간)1000~10000ms"
required: false
preferenceType: integer
definition:
minimum: 1000
maximum: 10000
default: 1000
- title: "色温时间(CCTTransitionTime/색온 전환 시간)"
name: colorTempTransitionTime
description: "色温过渡时间(CCT transition time/색온 전환 시간)1000~10000ms"
required: false
preferenceType: integer
definition:
minimum: 1000
maximum: 10000
default: 1000
- title: "输出模式(output mode/출력 모드)"
name: outputMode
description: "输出模式(output mode/출력 모드)"
required: false
preferenceType: enumeration
definition:
options:
0: "双路CW(dual CW/듀얼 CW)"
1: "双路WC(dual WC/듀얼 WC)"
2: "单路(single channel/단일 채널)"
default: 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- Copyright 2026 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

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

return {
{ mfr = "ManDai Technology", model = "DC2DC12MiV1" }
}
63 changes: 63 additions & 0 deletions drivers/SmartThings/zigbee-switch/src/firstled-light/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
-- Copyright 2026 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

local cluster_base = require "st.zigbee.cluster_base"
local data_types = require "st.zigbee.data_types"

local PRIVATE_CLUSTER_ID = 0xFC00

local preference_map = {
["outputMode"] = {
cluster_id = PRIVATE_CLUSTER_ID,
attribute_id = 0x0000,
data_type = data_types.Uint8
},
["powerOnMode"] = {
cluster_id = PRIVATE_CLUSTER_ID,
attribute_id = 0x0001,
data_type = data_types.Uint8
},
["ledDriveCurrent"] = {
cluster_id = PRIVATE_CLUSTER_ID,
attribute_id = 0x0002,
data_type = data_types.Uint16
},
["dimTransitionTime"] = {
cluster_id = PRIVATE_CLUSTER_ID,
attribute_id = 0x0003,
data_type = data_types.Uint16
},
["colorTempTransitionTime"] = {
cluster_id = PRIVATE_CLUSTER_ID,
attribute_id = 0x0004,
data_type = data_types.Uint16
}
}

local function device_info_changed(driver, device, event, args)
local preferences = device.preferences
local old_preferences = args.old_st_store.preferences
if preferences ~= nil then
for id, attr in pairs(preference_map) do
local old_value = old_preferences[id]
local value = preferences[id]
if value ~= nil and value ~= old_value then
value = tonumber(value)
device:send(cluster_base.write_attribute(device,
data_types.ClusterId(attr.cluster_id),
data_types.AttributeId(attr.attribute_id),
data_types.validate_or_build_type(value, attr.data_type, "payload")))
end
end
end
end

local firstled_light_handlers = {
NAME = "firstled-light handlers",
lifecycle_handlers = {
infoChanged = device_info_changed
},
can_handle = require("firstled-light.can_handle")
}

return firstled_light_handlers
3 changes: 2 additions & 1 deletion drivers/SmartThings/zigbee-switch/src/sub_drivers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ return {
lazy_load_if_possible("frient"),
lazy_load_if_possible("frient-IO"),
lazy_load_if_possible("color_temp_range_handlers"),
lazy_load_if_possible("stateless_handlers")
lazy_load_if_possible("stateless_handlers"),
lazy_load_if_possible("firstled-light")
}
106 changes: 106 additions & 0 deletions drivers/SmartThings/zigbee-switch/src/test/test_firstled_light.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
-- Copyright 2026 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

local test = require "integration_test"
local t_utils = require "integration_test.utils"
local cluster_base = require "st.zigbee.cluster_base"
local data_types = require "st.zigbee.data_types"
local zigbee_test_utils = require "integration_test.zigbee_test_utils"

local PRIVATE_CLUSTER_ID = 0xFC00

local mock_device = test.mock_device.build_test_zigbee_device(
{
profile = t_utils.get_profile_definition("light-color-temp-time-restore.yml"),
fingerprinted_endpoint_id = 0x01,
zigbee_endpoints = {
[1] = {
id = 1,
manufacturer = "ManDai Technology",
model = "DC2DC12MiV1",
server_clusters = { 0x0006, 0x0008, 0x0300 }
}
}
}
)

zigbee_test_utils.prepare_zigbee_env_info()

local function test_init()
test.mock_device.add_test_device(mock_device)
end

test.set_test_init_function(test_init)

-- ====================== Preferences ======================
test.register_coroutine_test("infoChanged - outputMode 0", function()
test.socket.device_lifecycle:__queue_receive(mock_device:generate_info_changed({ preferences = { outputMode = "0" }}))
test.socket.zigbee:__expect_send({ mock_device.id,
cluster_base.write_attribute(mock_device,
data_types.ClusterId(PRIVATE_CLUSTER_ID),
data_types.AttributeId(0x0000),
data_types.validate_or_build_type(0, data_types.Uint8, "payload"))
})
end,
{
min_api_version = 19
}
)

test.register_coroutine_test("infoChanged - powerOnMode 0", function()
test.socket.device_lifecycle:__queue_receive(mock_device:generate_info_changed({ preferences = { powerOnMode = "0" }}))
test.socket.zigbee:__expect_send({ mock_device.id,
cluster_base.write_attribute(mock_device,
data_types.ClusterId(PRIVATE_CLUSTER_ID),
data_types.AttributeId(0x0001),
data_types.validate_or_build_type(0, data_types.Uint8, "payload"))
})
end,
{
min_api_version = 19
}
)

test.register_coroutine_test("infoChanged - ledDriveCurrent 100", function()
test.socket.device_lifecycle:__queue_receive(mock_device:generate_info_changed({ preferences = { ledDriveCurrent = "100" }}))
test.socket.zigbee:__expect_send({ mock_device.id,
cluster_base.write_attribute(mock_device,
data_types.ClusterId(PRIVATE_CLUSTER_ID),
data_types.AttributeId(0x0002),
data_types.validate_or_build_type(100, data_types.Uint16, "payload"))
})
end,
{
min_api_version = 19
}
)

test.register_coroutine_test("infoChanged - dimTransitionTime 2000", function()
test.socket.device_lifecycle:__queue_receive(mock_device:generate_info_changed({ preferences = { dimTransitionTime = "2000" }}))
test.socket.zigbee:__expect_send({ mock_device.id,
cluster_base.write_attribute(mock_device,
data_types.ClusterId(PRIVATE_CLUSTER_ID),
data_types.AttributeId(0x0003),
data_types.validate_or_build_type(2000, data_types.Uint16, "payload"))
})
end,
{
min_api_version = 19
}
)

test.register_coroutine_test("infoChanged - colorTempTransitionTime 2000", function()
test.socket.device_lifecycle:__queue_receive(mock_device:generate_info_changed({ preferences = { colorTempTransitionTime = "2000" }}))
test.socket.zigbee:__expect_send({ mock_device.id,
cluster_base.write_attribute(mock_device,
data_types.ClusterId(PRIVATE_CLUSTER_ID),
data_types.AttributeId(0x0004),
data_types.validate_or_build_type(2000, data_types.Uint16, "payload"))
})
end,
{
min_api_version = 19
}
)

test.run_registered_tests()
Loading