Skip to content

Commit 03dc986

Browse files
committed
add MultiIR Smoke Detector MIR-SM200
1 parent 98114d8 commit 03dc986

File tree

8 files changed

+288
-0
lines changed

8 files changed

+288
-0
lines changed

drivers/SmartThings/zigbee-smoke-detector/fingerprints.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,8 @@ zigbeeManufacturer:
5454
manufacturer: HEIMAN
5555
model: GASSensor-N
5656
deviceProfileName: smoke-detector
57+
- id: "MultIR/MIR-SM200"
58+
deviceLabel: MultiIR Smoke Detector MIR-SM200
59+
manufacturer: MultIR
60+
model: MIR-SM200
61+
deviceProfileName: smoke-battery-tamper-no-fw-update
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: smoke-battery-tamper-no-fw-update
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: smokeDetector
6+
version: 1
7+
- id: tamperAlert
8+
version: 1
9+
- id: battery
10+
version: 1
11+
- id: refresh
12+
version: 1
13+
categories:
14+
- name: SmokeDetector
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-SM200" }
6+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
-- Copyright 2026 SmartThings, Inc.
2+
-- Licensed under the Apache License, Version 2.0
3+
4+
local zcl_clusters = require "st.zigbee.zcl.clusters"
5+
local capabilities = require "st.capabilities"
6+
7+
local IASZone = zcl_clusters.IASZone
8+
9+
local function generate_event_from_zone_status(driver, device, zone_status, zb_rx)
10+
if zone_status:is_alarm1_set() then
11+
device:emit_event(capabilities.smokeDetector.smoke.detected())
12+
elseif zone_status:is_alarm2_set() then
13+
device:emit_event(capabilities.smokeDetector.smoke.tested())
14+
else
15+
device:emit_event(capabilities.smokeDetector.smoke.clear())
16+
end
17+
if device:supports_capability(capabilities.tamperAlert) then
18+
device:emit_event(zone_status:is_tamper_set() and capabilities.tamperAlert.tamper.detected() or capabilities.tamperAlert.tamper.clear())
19+
end
20+
end
21+
22+
local function ias_zone_status_change_handler(driver, device, zb_rx)
23+
local zone_status = zb_rx.body.zcl_body.zone_status
24+
generate_event_from_zone_status(driver, device, zone_status, zb_rx)
25+
end
26+
27+
local function added_handler(self, device)
28+
device:emit_event(capabilities.battery.battery(100))
29+
device:emit_event(capabilities.smokeDetector.smoke.clear())
30+
device:emit_event(capabilities.tamperAlert.tamper.clear())
31+
end
32+
33+
local MultiIR_smoke_detector_handler = {
34+
NAME = "MultiIR Smoke Detector Handler",
35+
lifecycle_handlers = {
36+
added = added_handler
37+
},
38+
zigbee_handlers = {
39+
cluster = {
40+
[IASZone.ID] = {
41+
[IASZone.client.commands.ZoneStatusChangeNotification.ID] = ias_zone_status_change_handler
42+
}
43+
},
44+
attr = {
45+
[IASZone.ID] = {
46+
[IASZone.attributes.ZoneStatus.ID] = generate_event_from_zone_status
47+
}
48+
}
49+
},
50+
can_handle = require("MultiIR.can_handle")
51+
}
52+
53+
return MultiIR_smoke_detector_handler

drivers/SmartThings/zigbee-smoke-detector/src/sub_drivers.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ local sub_drivers = {
66
lazy_load_if_possible("frient"),
77
lazy_load_if_possible("aqara-gas"),
88
lazy_load_if_possible("aqara"),
9+
lazy_load_if_possible("MultiIR"),
910
}
1011
return sub_drivers
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
-- Copyright 2026 SmartThings, Inc.
2+
-- Licensed under the Apache License, Version 2.0
3+
4+
local test = require "integration_test"
5+
local clusters = require "st.zigbee.zcl.clusters"
6+
local capabilities = require "st.capabilities"
7+
local t_utils = require "integration_test.utils"
8+
local zigbee_test_utils = require "integration_test.zigbee_test_utils"
9+
10+
local IASZone = clusters.IASZone
11+
12+
local mock_device = test.mock_device.build_test_zigbee_device(
13+
{ profile = t_utils.get_profile_definition("smoke-battery-tamper-no-fw-update.yml"),
14+
zigbee_endpoints = {
15+
[0x01] = {
16+
id = 0x01,
17+
manufacturer = "MultIR",
18+
model = "MIR-SM200",
19+
server_clusters = { 0x0001,0x0020, 0x0500, 0x0502 }
20+
}
21+
}
22+
}
23+
)
24+
25+
zigbee_test_utils.prepare_zigbee_env_info()
26+
27+
local function test_init()
28+
test.mock_device.add_test_device(mock_device)
29+
end
30+
31+
test.set_test_init_function(test_init)
32+
33+
test.register_coroutine_test(
34+
"Handle added lifecycle",
35+
function()
36+
test.socket.zigbee:__set_channel_ordering("relaxed")
37+
test.socket.capability:__set_channel_ordering("relaxed")
38+
test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" })
39+
test.socket.capability:__expect_send(mock_device:generate_test_message("main",
40+
capabilities.battery.battery(100)))
41+
test.socket.capability:__expect_send(mock_device:generate_test_message("main",
42+
capabilities.smokeDetector.smoke.clear()))
43+
test.socket.capability:__expect_send(mock_device:generate_test_message("main",
44+
capabilities.tamperAlert.tamper.clear()))
45+
end,
46+
{
47+
min_api_version = 19
48+
}
49+
)
50+
51+
test.register_message_test(
52+
"Reported ZoneStatus should be handled: smoke/clear tamper/clear",
53+
{
54+
{
55+
channel = "zigbee",
56+
direction = "receive",
57+
message = { mock_device.id, IASZone.attributes.ZoneStatus:build_test_attr_report(mock_device, 0x0000) }
58+
},
59+
{
60+
channel = "capability",
61+
direction = "send",
62+
message = mock_device:generate_test_message("main", capabilities.smokeDetector.smoke.clear())
63+
},
64+
{
65+
channel = "capability",
66+
direction = "send",
67+
message = mock_device:generate_test_message("main", capabilities.tamperAlert.tamper.clear())
68+
}
69+
},
70+
{
71+
min_api_version = 19
72+
}
73+
)
74+
75+
test.register_message_test(
76+
"Reported ZoneStatus should be handled: smoke/detected tamper/detected",
77+
{
78+
{
79+
channel = "zigbee",
80+
direction = "receive",
81+
message = { mock_device.id, IASZone.attributes.ZoneStatus:build_test_attr_report(mock_device, 0x0005) }
82+
},
83+
{
84+
channel = "capability",
85+
direction = "send",
86+
message = mock_device:generate_test_message("main", capabilities.smokeDetector.smoke.detected())
87+
},
88+
{
89+
channel = "capability",
90+
direction = "send",
91+
message = mock_device:generate_test_message("main", capabilities.tamperAlert.tamper.detected())
92+
}
93+
},
94+
{
95+
min_api_version = 19
96+
}
97+
)
98+
99+
test.register_message_test(
100+
"Reported ZoneStatus should be handled: smoke/tested tamper/detected",
101+
{
102+
{
103+
channel = "zigbee",
104+
direction = "receive",
105+
message = { mock_device.id, IASZone.attributes.ZoneStatus:build_test_attr_report(mock_device, 0x0006) }
106+
},
107+
{
108+
channel = "capability",
109+
direction = "send",
110+
message = mock_device:generate_test_message("main", capabilities.smokeDetector.smoke.tested())
111+
},
112+
{
113+
channel = "capability",
114+
direction = "send",
115+
message = mock_device:generate_test_message("main", capabilities.tamperAlert.tamper.detected())
116+
}
117+
},
118+
{
119+
min_api_version = 19
120+
}
121+
)
122+
123+
test.register_message_test(
124+
"ZoneStatusChangeNotification should be handled: smoke/detected tamper/detected",
125+
{
126+
{
127+
channel = "zigbee",
128+
direction = "receive",
129+
message = { mock_device.id, IASZone.client.commands.ZoneStatusChangeNotification.build_test_rx(mock_device, 0x0005, 0x00) }
130+
},
131+
{
132+
channel = "capability",
133+
direction = "send",
134+
message = mock_device:generate_test_message("main", capabilities.smokeDetector.smoke.detected())
135+
},
136+
{
137+
channel = "capability",
138+
direction = "send",
139+
message = mock_device:generate_test_message("main", capabilities.tamperAlert.tamper.detected())
140+
}
141+
},
142+
{
143+
min_api_version = 19
144+
}
145+
)
146+
147+
test.register_message_test(
148+
"ZoneStatusChangeNotification should be handled: smoke/tested tamper/detected",
149+
{
150+
{
151+
channel = "zigbee",
152+
direction = "receive",
153+
message = { mock_device.id, IASZone.client.commands.ZoneStatusChangeNotification.build_test_rx(mock_device, 0x0006, 0x00) }
154+
},
155+
{
156+
channel = "capability",
157+
direction = "send",
158+
message = mock_device:generate_test_message("main", capabilities.smokeDetector.smoke.tested())
159+
},
160+
{
161+
channel = "capability",
162+
direction = "send",
163+
message = mock_device:generate_test_message("main", capabilities.tamperAlert.tamper.detected())
164+
}
165+
},
166+
{
167+
min_api_version = 19
168+
}
169+
)
170+
171+
test.register_message_test(
172+
"ZoneStatusChangeNotification should be handled: smoke/clear tamper/clear",
173+
{
174+
{
175+
channel = "zigbee",
176+
direction = "receive",
177+
message = { mock_device.id, IASZone.client.commands.ZoneStatusChangeNotification.build_test_rx(mock_device, 0x0000, 0x00) }
178+
},
179+
{
180+
channel = "capability",
181+
direction = "send",
182+
message = mock_device:generate_test_message("main", capabilities.smokeDetector.smoke.clear())
183+
},
184+
{
185+
channel = "capability",
186+
direction = "send",
187+
message = mock_device:generate_test_message("main", capabilities.tamperAlert.tamper.clear())
188+
}
189+
},
190+
{
191+
min_api_version = 19
192+
}
193+
)
194+
195+
test.run_registered_tests()

tools/localizations/cn.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,4 @@ Aqara Wireless Mini Switch T1,Aqara 无线开关 T1
134134
"WISTAR WSCMXJ Smart Curtain Motor",威仕达智能开合帘电机 WSCMXJ
135135
"HAOJAI Smart Switch 3-key",好家智能三键开关
136136
"HAOJAI Smart Switch 6-key",好家智能六键开关
137+
"MultiIR Smoke Detector MIR-SM200",麦乐克烟雾报警器MIR-SM200

0 commit comments

Comments
 (0)