Skip to content

Commit 7d38852

Browse files
authored
Merge pull request #2989 from SmartThingsCommunity/prod-release-5-20
Prod release 5/20
2 parents 8cec702 + 95b5138 commit 7d38852

12 files changed

Lines changed: 645 additions & 2 deletions

File tree

drivers/SmartThings/matter-lock/fingerprints.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ matterManufacturer:
2020
vendorId: 0x115F
2121
productId: 0x286A
2222
deviceProfileName: lock-user-pin
23+
- id: "4447/10244"
24+
deviceLabel: Aqara Smart Lock U400
25+
vendorId: 0x115F
26+
productId: 0x2804
27+
deviceProfileName: lock
2328
#Eufy
2429
- id: "5427/1"
2530
deviceLabel: eufy Smart Lock E31

drivers/SmartThings/matter-lock/src/new-matter-lock/fingerprints.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ local NEW_MATTER_LOCK_PRODUCTS = {
3434
{0x1421, 0x0042}, -- Kwikset Halo Select Plus
3535
{0x1421, 0x0081}, -- Kwikset Aura Reach
3636
{0x1236, 0xa538}, -- Schlage Sense Pro
37+
{0x1236, 0x3800}, -- Schlage
38+
{0x1236, 0xA738} -- Schlage
3739
}
3840

3941
return NEW_MATTER_LOCK_PRODUCTS

drivers/SmartThings/matter-lock/src/test/test_new_matter_lock.lua

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2100,7 +2100,6 @@ test.register_coroutine_test(
21002100
}
21012101
)
21022102

2103-
-- mock_device:set_field(lock_utils.COTA_CRED, "654123", {persist = true}) --overwrite random cred for test expectation
21042103
test.register_coroutine_test(
21052104
"Add Guest User and failure response ",
21062105
function()
@@ -2232,4 +2231,113 @@ test.register_coroutine_test(
22322231
}
22332232
)
22342233

2234+
test.register_coroutine_test(
2235+
"Add Guest User and failure response, and ClearUser command fails as well",
2236+
function()
2237+
test.socket.capability:__queue_receive(
2238+
{
2239+
mock_device.id,
2240+
{
2241+
capability = capabilities.lockCredentials.ID,
2242+
command = "addCredential",
2243+
args = {0, "guest", "pin", "654123"}
2244+
},
2245+
}
2246+
)
2247+
test.socket.matter:__expect_send(
2248+
{
2249+
mock_device.id,
2250+
DoorLock.server.commands.SetCredential(
2251+
mock_device, 1, -- endpoint
2252+
DoorLock.types.DataOperationTypeEnum.ADD, -- operation_type
2253+
DoorLock.types.CredentialStruct(
2254+
{credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1}
2255+
), -- credential
2256+
"654123", -- credential_data
2257+
nil, -- user_index
2258+
nil, -- user_status
2259+
DoorLock.types.UserTypeEnum.SCHEDULE_RESTRICTED_USER -- user_type
2260+
),
2261+
}
2262+
)
2263+
test.wait_for_events()
2264+
test.socket.matter:__queue_receive(
2265+
{
2266+
mock_device.id,
2267+
DoorLock.client.commands.SetCredentialResponse:build_test_command_response(
2268+
mock_device, 1,
2269+
DoorLock.types.DlStatus.SUCCESS, -- status
2270+
1, -- user_index
2271+
2 -- next_credential_index
2272+
),
2273+
}
2274+
)
2275+
test.socket.capability:__expect_send(
2276+
mock_device:generate_test_message(
2277+
"main",
2278+
capabilities.lockUsers.users({{userIndex = 1, userType = "guest"}}, {visibility={displayed=false}})
2279+
)
2280+
)
2281+
test.socket.capability:__expect_send(
2282+
mock_device:generate_test_message(
2283+
"main",
2284+
capabilities.lockCredentials.credentials(
2285+
{{credentialIndex=1, credentialType="pin", userIndex=1}}, {visibility={displayed=false}}
2286+
)
2287+
)
2288+
)
2289+
test.socket.matter:__expect_send(
2290+
{
2291+
mock_device.id,
2292+
DoorLock.server.commands.SetYearDaySchedule(
2293+
mock_device, 1, -- endpoint
2294+
1, -- year_day_index
2295+
1, -- user_index
2296+
0, -- local_start_time
2297+
0xffffffff -- local_end_time
2298+
),
2299+
}
2300+
)
2301+
test.wait_for_events()
2302+
test.socket.matter:__queue_receive(
2303+
{
2304+
mock_device.id,
2305+
DoorLock.server.commands.SetYearDaySchedule:build_test_command_response(
2306+
mock_device, 1,
2307+
DoorLock.types.DlStatus.FAILURE -- status
2308+
),
2309+
}
2310+
)
2311+
test.socket.matter:__expect_send({
2312+
mock_device.id,
2313+
DoorLock.server.commands.ClearUser(
2314+
mock_device, 1,
2315+
1
2316+
)
2317+
})
2318+
test.wait_for_events()
2319+
test.socket.matter:__queue_receive(
2320+
{
2321+
mock_device.id,
2322+
DoorLock.server.commands.ClearUser:build_test_command_response(
2323+
mock_device, 1,
2324+
DoorLock.types.DlStatus.FAILURE -- status
2325+
),
2326+
}
2327+
)
2328+
test.socket.capability:__expect_send(
2329+
mock_device:generate_test_message(
2330+
"main",
2331+
capabilities.lockCredentials.commandResult(
2332+
{commandName="addCredential", statusCode="success", userIndex=1}, {state_change=true, visibility={displayed=false}}
2333+
)
2334+
)
2335+
)
2336+
end,
2337+
{
2338+
min_api_version = 17
2339+
}
2340+
)
2341+
2342+
22352343
test.run_registered_tests()

drivers/SmartThings/matter-switch/fingerprints.yml

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,26 @@ matterManufacturer:
186186
vendorId: 0x1396
187187
productId: 0x10B1
188188
deviceProfileName: light-level-colorTemperature
189+
- id: "5014/4164"
190+
deviceLabel: Linkind Smart Light Bulb
191+
vendorId: 0x1396
192+
productId: 0x1044
193+
deviceProfileName: light-color-level
194+
- id: "5014/4118"
195+
deviceLabel: Linkind Smart Filament Bulb
196+
vendorId: 0x1396
197+
productId: 0x1016
198+
deviceProfileName: light-color-level
199+
- id: "5014/4116"
200+
deviceLabel: Linkind Smart Light Bulb
201+
vendorId: 0x1396
202+
productId: 0x1014
203+
deviceProfileName: light-color-level
204+
- id: "5014/4165"
205+
deviceLabel: Linkind Smart Downlight
206+
vendorId: 0x1396
207+
productId: 0x1045
208+
deviceProfileName: light-color-level
189209
#Bosch Smart Home
190210
- id: "4617/12310"
191211
deviceLabel: Plug Compact [M]
@@ -674,7 +694,7 @@ matterManufacturer:
674694
productId: 0x61B9
675695
deviceProfileName: light-color-level
676696
- id: "4999/24742"
677-
deviceLabel: Govee Ceiling Light Pro (15 inch)
697+
deviceLabel: Govee Ceiling Light Pro
678698
vendorId: 0x1387
679699
productId: 0x60A6
680700
deviceProfileName: light-color-level
@@ -813,6 +833,21 @@ matterManufacturer:
813833
vendorId: 0x1387
814834
productId: 0x1741
815835
deviceProfileName: light-color-level
836+
- id: "4999/5808"
837+
deviceLabel: Govee Floor Lamp 3
838+
vendorId: 0x1387
839+
productId: 0x16B0
840+
deviceProfileName: light-color-level
841+
- id: "4999/5824"
842+
deviceLabel: Govee Floor Lamp 3 Lite
843+
vendorId: 0x1387
844+
productId: 0x16C0
845+
deviceProfileName: light-color-level
846+
- id: "4999/4720"
847+
deviceLabel: Govee Ceiling Light Ultra (21inch)
848+
vendorId: 0x1387
849+
productId: 0x1270
850+
deviceProfileName: light-color-level
816851
# Hager
817852
- id: "4741/8"
818853
deviceLabel: Hager matter 2 buttons (battery)

drivers/SmartThings/zigbee-siren/fingerprints.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,8 @@ zigbeeManufacturer :
2929
manufacturer: Sercomm Corp.
3030
model: SZ-SRN12N
3131
deviceProfileName: basic-alarm
32+
- id: "MultIR/MIR-SR100"
33+
deviceLabel: MultiIR Siren MIR-SR100
34+
manufacturer: MultIR
35+
model: MIR-SR100
36+
deviceProfileName: switch-alarm-tamper-warningduration-volume-no-fw-update
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: switch-alarm-tamper-warningduration-volume-no-fw-update
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: switch
6+
version: 1
7+
- id: alarm
8+
version: 1
9+
- id: tamperAlert
10+
version: 1
11+
- id: refresh
12+
version: 1
13+
categories:
14+
- name: Siren
15+
preferences:
16+
- title: "警报时长/秒(warning duration/sec)"
17+
name: warningDuration
18+
description: "警报持续时间 单位:秒(warning duration unit:seconds)"
19+
required: false
20+
preferenceType: integer
21+
definition:
22+
minimum: 30
23+
maximum: 1800
24+
default: 1800
25+
- title: "警报音量(siren volume)"
26+
name: sirenVolume
27+
description: "警报音量大小(siren volume)"
28+
required: false
29+
preferenceType: enumeration
30+
definition:
31+
options:
32+
0: "低(low)"
33+
1: "中(medium)"
34+
2: "高(high)"
35+
3: "最大(max)"
36+
default: 3
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- Copyright 2026 SmartThings, Inc.
2+
-- Licensed under the Apache License, Version 2.0
3+
4+
return function(opts, driver, device, ...)
5+
local FINGERPRINTS = require "MultiIR.fingerprints"
6+
for _, fingerprint in ipairs(FINGERPRINTS) do
7+
if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then
8+
local subdriver = require("MultiIR")
9+
return true, subdriver
10+
end
11+
end
12+
return false
13+
end
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-- Copyright 2026 SmartThings, Inc.
2+
-- Licensed under the Apache License, Version 2.0
3+
4+
return {
5+
{ mfr = "MultIR", model = "MIR-SR100" }
6+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
-- Copyright 2026 SmartThings, Inc.
2+
-- Licensed under the Apache License, Version 2.0
3+
4+
5+
local data_types = require "st.zigbee.data_types"
6+
local zcl_clusters = require "st.zigbee.zcl.clusters"
7+
8+
local IASWD = zcl_clusters.IASWD
9+
local IASZone = zcl_clusters.IASZone
10+
local IaswdLevel = IASWD.types.IaswdLevel
11+
local SirenConfiguration = IASWD.types.SirenConfiguration
12+
local WarningMode = IASWD.types.WarningMode
13+
local Strobe = IASWD.types.Strobe
14+
local capabilities = require "st.capabilities"
15+
local ALARM_COMMAND = "alarmCommand"
16+
local DEFAULT_MAX_WARNING_DURATION = 1800
17+
local ALARM_STROBE_DUTY_CYCLE = 40
18+
19+
local alarm_command = {
20+
OFF = 0,
21+
SIREN = 1,
22+
STROBE = 2,
23+
BOTH = 3
24+
}
25+
26+
local function device_added (driver, device)
27+
device:emit_event(capabilities.switch.switch.off())
28+
device:emit_event(capabilities.alarm.alarm.off())
29+
if(device:supports_capability(capabilities.tamperAlert)) then
30+
device:emit_event(capabilities.tamperAlert.tamper.clear())
31+
end
32+
device:send(IASWD.attributes.MaxDuration:read(device))
33+
end
34+
35+
local function generate_event_from_zone_status(driver, device, zone_status, zb_rx)
36+
if device:supports_capability(capabilities.tamperAlert) then
37+
device:emit_event(zone_status:is_tamper_set() and capabilities.tamperAlert.tamper.detected() or capabilities.tamperAlert.tamper.clear())
38+
end
39+
end
40+
41+
local function ias_zone_status_change_handler(driver, device, zb_rx)
42+
local zone_status = zb_rx.body.zcl_body.zone_status
43+
generate_event_from_zone_status(driver, device, zone_status, zb_rx)
44+
end
45+
46+
local function send_siren_command(device, warning_mode, warning_siren_level, warning_duration, strobe_active, strobe_level)
47+
local siren_configuration
48+
49+
siren_configuration = SirenConfiguration(0x00)
50+
siren_configuration:set_warning_mode(warning_mode)
51+
siren_configuration:set_siren_level(warning_siren_level)
52+
siren_configuration:set_strobe(strobe_active)
53+
54+
device:send(
55+
IASWD.server.commands.StartWarning(
56+
device,
57+
siren_configuration,
58+
data_types.Uint16(warning_duration),
59+
data_types.Uint8(ALARM_STROBE_DUTY_CYCLE),
60+
data_types.Enum8(strobe_level)
61+
)
62+
)
63+
end
64+
65+
local function siren_switch_off_handler(driver, device, command)
66+
device:set_field(ALARM_COMMAND, alarm_command.OFF, {persist = true})
67+
send_siren_command(device, WarningMode.STOP, IaswdLevel.LOW_LEVEL, DEFAULT_MAX_WARNING_DURATION, Strobe.NO_STROBE, IaswdLevel.LOW_LEVEL)
68+
end
69+
70+
local function siren_alarm_siren_handler(alarm_cmd, WarningMode, Strobe, strobe_level)
71+
return function(driver, device, command)
72+
device:set_field(ALARM_COMMAND, alarm_cmd, {persist = true})
73+
74+
local sirenVolume_msg = tonumber(device.preferences.sirenVolume) or IaswdLevel.VERY_HIGH_LEVEL
75+
local warning_duration = tonumber(device.preferences.warningDuration) or DEFAULT_MAX_WARNING_DURATION
76+
77+
send_siren_command(device, WarningMode, sirenVolume_msg, warning_duration, Strobe, strobe_level)
78+
79+
device.thread:call_with_delay(warning_duration, function() -- Send command to switch from siren to off in the app when the siren is done
80+
if(device:get_field(ALARM_COMMAND) ~= alarm_command.OFF) then
81+
siren_switch_off_handler(driver, device, alarm_cmd)
82+
end
83+
end)
84+
end
85+
end
86+
87+
local MultiIR_siren_driver = {
88+
NAME = "MultiIR Zigbee siren",
89+
lifecycle_handlers = {
90+
added = device_added,
91+
},
92+
capability_handlers = {
93+
[capabilities.alarm.ID] = {
94+
[capabilities.alarm.commands.off.NAME] = siren_switch_off_handler,
95+
[capabilities.alarm.commands.siren.NAME] = siren_alarm_siren_handler(alarm_command.SIREN, WarningMode.BURGLAR, Strobe.NO_STROBE, IaswdLevel.LOW_LEVEL),
96+
[capabilities.alarm.commands.both.NAME] = siren_alarm_siren_handler(alarm_command.BOTH, WarningMode.BURGLAR, Strobe.USE_STROBE , IaswdLevel.VERY_HIGH_LEVEL),
97+
[capabilities.alarm.commands.strobe.NAME] = siren_alarm_siren_handler(alarm_command.STROBE, WarningMode.STOP, Strobe.USE_STROBE, IaswdLevel.VERY_HIGH_LEVEL)
98+
},
99+
[capabilities.switch.ID] = {
100+
[capabilities.switch.commands.on.NAME] = siren_alarm_siren_handler(alarm_command.BOTH, WarningMode.BURGLAR, Strobe.USE_STROBE , IaswdLevel.VERY_HIGH_LEVEL),
101+
[capabilities.switch.commands.off.NAME] = siren_switch_off_handler
102+
}
103+
},
104+
zigbee_handlers = {
105+
cluster = {
106+
[IASZone.ID] = {
107+
[IASZone.client.commands.ZoneStatusChangeNotification.ID] = ias_zone_status_change_handler
108+
}
109+
},
110+
attr = {
111+
[IASZone.ID] = {
112+
[IASZone.attributes.ZoneStatus.ID] = generate_event_from_zone_status
113+
}
114+
}
115+
},
116+
can_handle = require("MultiIR.can_handle"),
117+
}
118+
119+
return MultiIR_siren_driver

drivers/SmartThings/zigbee-siren/src/sub_drivers.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ local lazy_load_if_possible = require "lazy_load_subdriver"
66
return {
77
lazy_load_if_possible("frient"),
88
lazy_load_if_possible("ozom"),
9+
lazy_load_if_possible("MultiIR"),
910
}

0 commit comments

Comments
 (0)