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
11 changes: 11 additions & 0 deletions drivers/SmartThings/matter-lock/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,17 @@ matterManufacturer:
vendorId: 0x101D
productId: 0x8110
deviceProfileName: lock-user-pin-schedule-battery
#Dreame
- id: "5420/38144"
deviceLabel: Dreame NAVO Smart Lock A10
vendorId: 0x152C
productId: 0x9500
deviceProfileName: lock
- id: "5420/38145"
deviceLabel: Dreame NAVO Smart Lock E10
vendorId: 0x152C
productId: 0x9501
deviceProfileName: lock
matterGeneric:
- id: "matter/door-lock"
deviceLabel: Matter Door Lock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ local NEW_MATTER_LOCK_PRODUCTS = {
{0x1421, 0x0081}, -- Kwikset Aura Reach
{0x1236, 0xa538}, -- Schlage Sense Pro
{0x1236, 0x3800}, -- Schlage
{0x1236, 0xA738} -- Schlage
{0x1236, 0xA738}, -- Schlage
{0x152C, 0x9500}, -- Dreame NAVO Smart Lock A10
{0x152C, 0x9501} -- Dreame NAVO Smart Lock E10
}

return NEW_MATTER_LOCK_PRODUCTS
31 changes: 31 additions & 0 deletions drivers/SmartThings/matter-switch/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,26 @@ matterManufacturer:
vendorId: 0x1396
productId: 0x1045
deviceProfileName: light-color-level
- id: "5014/4578"
deviceLabel: Linkind Light Stick T19
vendorId: 0x1396
productId: 0x11E2
deviceProfileName: light-color-level
- id: "5014/4274"
deviceLabel: Linkind Smart Ceiling Light
vendorId: 0x1396
productId: 0x10B2
deviceProfileName: light-color-level
- id: "5014/4642"
deviceLabel: Linkind Smart Permanent Outdoor Lights
vendorId: 0x1396
productId: 0x1222
deviceProfileName: light-color-level
- id: "5014/4629"
deviceLabel: Smart Outdoor String Lights
vendorId: 0x1396
productId: 0x1215
deviceProfileName: light-color-level
#Bosch Smart Home
- id: "4617/12310"
deviceLabel: Plug Compact [M]
Expand Down Expand Up @@ -848,6 +868,11 @@ matterManufacturer:
vendorId: 0x1387
productId: 0x1270
deviceProfileName: light-color-level
- id: "4999/24755"
deviceLabel: Govee Uplighter Floor Lamp with Nebula Effect
vendorId: 0x1387
productId: 0x60B3
deviceProfileName: light-color-level
# Hager
- id: "4741/8"
deviceLabel: Hager matter 2 buttons (battery)
Expand Down Expand Up @@ -4113,6 +4138,12 @@ matterManufacturer:
vendorId: 0x1344
productId: 0x041E
deviceProfileName: matter-bridge
#Tapo
- id: "5010/269"
deviceLabel: Tapo Smart Power Strip
vendorId: 0x1392
productId: 0x010D
deviceProfileName: plug-binary


matterGeneric:
Expand Down
6 changes: 6 additions & 0 deletions drivers/SmartThings/zigbee-button/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ zigbeeManufacturer:
manufacturer: WALL HERO
model: ACL-401SCA4
deviceProfileName: thirty-buttons
# SONOFF
- id: "SONOFF/SNZB-01M"
deviceLabel: SNZB-01M
manufacturer: SONOFF
model: SNZB-01M
deviceProfileName: four-buttons-battery
- id: "MultIR/MIR-SO100"
deviceLabel: MultiIR Smart button MIR-SO100
manufacturer: MultIR
Expand Down
279 changes: 279 additions & 0 deletions drivers/SmartThings/zigbee-button/src/test/test_sonoff_button.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
-- Copyright 2026 SmartThings, Inc.
-- Licensed under the Apache License, Version 2.0

local test = require "integration_test"
local clusters = require "st.zigbee.zcl.clusters"
local capabilities = require "st.capabilities"
local t_utils = require "integration_test.utils"
local zigbee_test_utils = require "integration_test.zigbee_test_utils"
local zb_const = require "st.zigbee.constants"
local messages = require "st.zigbee.messages"
local data_types = require "st.zigbee.data_types"
local zcl_messages = require "st.zigbee.zcl"
local report_attr = require "st.zigbee.zcl.global_commands.report_attribute"

local SONOFF_PRIVATE_BUTTON_CLUSTER = 0xFC12
local SONOFF_PRIVATE_ATTR = 0x0000

local mock_device = test.mock_device.build_test_zigbee_device(
{
profile = t_utils.get_profile_definition("four-buttons-battery.yml"),
zigbee_endpoints = {
[1] = {
id = 1,
manufacturer = "SONOFF",
model = "SNZB-01M",
server_clusters = { 0x0001, 0xFC12 }
},
[2] = {
id = 2,
manufacturer = "SONOFF",
model = "SNZB-01M",
server_clusters = { 0x0001, 0xFC12 }
},
[3] = {
id = 3,
manufacturer = "SONOFF",
model = "SNZB-01M",
server_clusters = { 0x0001, 0xFC12 }
},
[4] = {
id = 4,
manufacturer = "SONOFF",
model = "SNZB-01M",
server_clusters = { 0x0001, 0xFC12 }
}
}
}
)

zigbee_test_utils.prepare_zigbee_env_info()

local function build_test_attr_report(device, endpoint, value)
local report_body = report_attr.ReportAttribute({
report_attr.ReportAttributeAttributeRecord(SONOFF_PRIVATE_ATTR, data_types.Uint8.ID, value)
})
local zclh = zcl_messages.ZclHeader({
cmd = data_types.ZCLCommandId(report_body.ID)
})
local addrh = messages.AddressHeader(
device:get_short_address(),
endpoint,
zb_const.HUB.ADDR,
zb_const.HUB.ENDPOINT,
zb_const.HA_PROFILE_ID,
SONOFF_PRIVATE_BUTTON_CLUSTER
)
local message_body = zcl_messages.ZclMessageBody({
zcl_header = zclh,
zcl_body = report_body
})

return messages.ZigbeeMessageRx({
address_header = addrh,
body = message_body
})
end

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

test.set_test_init_function(test_init)

test.register_coroutine_test(
"added lifecycle event",
function()
test.socket.capability:__set_channel_ordering("relaxed")
test.socket.capability:__expect_send(
mock_device:generate_test_message(
"main",
capabilities.button.supportedButtonValues({ "pushed", "double", "held", "pushed_3x" }, { visibility = { displayed = false } })
)
)
test.socket.capability:__expect_send(
mock_device:generate_test_message(
"main",
capabilities.button.numberOfButtons({ value = 4 }, { visibility = { displayed = false } })
)
)

-- Check initial events for button 1
test.socket.capability:__expect_send(
mock_device:generate_test_message(
"button1",
capabilities.button.supportedButtonValues({ "pushed", "double", "held", "pushed_3x" }, { visibility = { displayed = false } })
)
)
test.socket.capability:__expect_send(
mock_device:generate_test_message(
"button1",
capabilities.button.numberOfButtons({ value = 1 }, { visibility = { displayed = false } })
)
)

-- Check initial events for button 2
test.socket.capability:__expect_send(
mock_device:generate_test_message(
"button2",
capabilities.button.supportedButtonValues({ "pushed", "double", "held", "pushed_3x" }, { visibility = { displayed = false } })
)
)
test.socket.capability:__expect_send(
mock_device:generate_test_message(
"button2",
capabilities.button.numberOfButtons({ value = 1 }, { visibility = { displayed = false } })
)
)

-- Check initial events for button 3
test.socket.capability:__expect_send(
mock_device:generate_test_message(
"button3",
capabilities.button.supportedButtonValues({ "pushed", "double", "held", "pushed_3x" }, { visibility = { displayed = false } })
)
)
test.socket.capability:__expect_send(
mock_device:generate_test_message(
"button3",
capabilities.button.numberOfButtons({ value = 1 }, { visibility = { displayed = false } })
)
)

-- Check initial events for button 4
test.socket.capability:__expect_send(
mock_device:generate_test_message(
"button4",
capabilities.button.supportedButtonValues({ "pushed", "double", "held", "pushed_3x" }, { visibility = { displayed = false } })
)
)
test.socket.capability:__expect_send(
mock_device:generate_test_message(
"button4",
capabilities.button.numberOfButtons({ value = 1 }, { visibility = { displayed = false } })
)
)
test.socket.capability:__expect_send(
mock_device:generate_test_message("main", capabilities.button.button.pushed({ state_change = false }))
)

test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" })
test.wait_for_events()
end,
{
min_api_version = 17
}
)

test.register_coroutine_test(
"Button pushed message should generate event",
function()
-- 0xFC12, 0x0000, 0x01 = pushed
local attr_report = build_test_attr_report(mock_device, 1, data_types.Uint8(0x01))

test.socket.zigbee:__queue_receive({ mock_device.id, attr_report })
test.socket.capability:__expect_send(
mock_device:generate_test_message("button1", capabilities.button.button.pushed({ state_change = true }))
)
test.socket.capability:__expect_send(
mock_device:generate_test_message("main", capabilities.button.button.pushed({ state_change = true }))
)
end,
{
min_api_version = 17
}
)

test.register_coroutine_test(
"Button double message should generate event",
function()
-- 0xFC12, 0x0000, 0x02 = double
local attr_report = build_test_attr_report(mock_device, 1, data_types.Uint8(0x02))

test.socket.zigbee:__queue_receive({ mock_device.id, attr_report })
test.socket.capability:__expect_send(
mock_device:generate_test_message("button1", capabilities.button.button.double({ state_change = true }))
)
test.socket.capability:__expect_send(
mock_device:generate_test_message("main", capabilities.button.button.double({ state_change = true }))
)
end,
{
min_api_version = 17
}
)

test.register_coroutine_test(
"Button held message should generate event",
function()
-- 0xFC12, 0x0000, 0x03 = held
local attr_report = build_test_attr_report(mock_device, 1, data_types.Uint8(0x03))

test.socket.zigbee:__queue_receive({ mock_device.id, attr_report })
test.socket.capability:__expect_send(
mock_device:generate_test_message("button1", capabilities.button.button.held({ state_change = true }))
)
test.socket.capability:__expect_send(
mock_device:generate_test_message("main", capabilities.button.button.held({ state_change = true }))
)
end,
{
min_api_version = 17
}
)

test.register_coroutine_test(
"Button pushed_3x message should generate event",
function()
-- 0xFC12, 0x0000, 0x04 = pushed_3x
local attr_report = build_test_attr_report(mock_device, 1, data_types.Uint8(0x04))

test.socket.zigbee:__queue_receive({ mock_device.id, attr_report })
test.socket.capability:__expect_send(
mock_device:generate_test_message("button1", capabilities.button.button.pushed_3x({ state_change = true }))
)
test.socket.capability:__expect_send(
mock_device:generate_test_message("main", capabilities.button.button.pushed_3x({ state_change = true }))
)
end,
{
min_api_version = 17
}
)

test.register_coroutine_test(
"Button 2 pushed message should generate event on button2 component",
function()
-- Endpoint 2 test
local attr_report = build_test_attr_report(mock_device, 2, data_types.Uint8(0x01))

test.socket.zigbee:__queue_receive({ mock_device.id, attr_report })
test.socket.capability:__expect_send(
mock_device:generate_test_message("button2", capabilities.button.button.pushed({ state_change = true }))
)
test.socket.capability:__expect_send(
mock_device:generate_test_message("main", capabilities.button.button.pushed({ state_change = true }))
)
end,
{
min_api_version = 17
}
)

test.register_coroutine_test(
"Battery percentage report should generate event",
function()
local battery_report = clusters.PowerConfiguration.attributes.BatteryPercentageRemaining:build_test_attr_report(mock_device, 180)

test.socket.zigbee:__queue_receive({ mock_device.id, battery_report })
test.socket.capability:__expect_send(
mock_device:generate_test_message("main", capabilities.battery.battery(90))
)
end,
{
min_api_version = 17
}
)

test.run_registered_tests()

Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ local ZIGBEE_MULTI_BUTTON_FINGERPRINTS = {
{ mfr = "Vimar", model = "RemoteControl_v1.0" },
{ mfr = "Linxura", model = "Smart Controller" },
{ mfr = "Linxura", model = "Aura Smart Button" },
{ mfr = "SONOFF", model = "SNZB-01M" },
{ mfr = "zunzunbee", model = "SSWZ8T" }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ local supported_values = require "zigbee-multi-button.supported_values"
local button_utils = require "button_utils"



local function added_handler(self, device)
local config = supported_values.get_device_parameters(device)
for _, component in pairs(device.profile.components) do
Expand Down
Loading
Loading