Skip to content

Commit 853b02b

Browse files
authored
add MultiIR Siren MIR-SR100 (#2873)
1 parent e645be8 commit 853b02b

8 files changed

Lines changed: 493 additions & 0 deletions

File tree

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)