Skip to content

Commit 2a28cff

Browse files
committed
add MultiIR Smart button MIR-SO100
1 parent 98114d8 commit 2a28cff

File tree

8 files changed

+206
-0
lines changed

8 files changed

+206
-0
lines changed

drivers/SmartThings/zigbee-button/fingerprints.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,11 @@ zigbeeManufacturer:
267267
manufacturer: WALL HERO
268268
model: ACL-401SCA4
269269
deviceProfileName: thirty-buttons
270+
- id: "MultIR/MIR-SO100"
271+
deviceLabel: MultiIR Smart button MIR-SO100
272+
manufacturer: MultIR
273+
model: MIR-SO100
274+
deviceProfileName: one-button-battery-no-fw-update
270275
zigbeeGeneric:
271276
- id: "generic-button-sensor"
272277
deviceLabel: "Zigbee Generic Button"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: one-button-battery-no-fw-update
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: button
6+
version: 1
7+
- id: battery
8+
version: 1
9+
- id: refresh
10+
version: 1
11+
categories:
12+
- name: Button
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-SO100" }
6+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
-- Copyright 2026 SmartThings, Inc.
2+
-- Licensed under the Apache License, Version 2.0
3+
4+
5+
local zcl_clusters = require "st.zigbee.zcl.clusters"
6+
local capabilities = require "st.capabilities"
7+
local log = require "log"
8+
9+
local IASZone = zcl_clusters.IASZone
10+
local PRIVATE_CMD_ID = 0xF1
11+
12+
local function ias_zone_private_cmd_handler(self, device, zb_rx)
13+
local cmd_data = zb_rx.body.zcl_body.body_bytes:byte(1)
14+
if cmd_data == 0 then
15+
device:emit_event(capabilities.button.button.pushed({state_change = true}))
16+
elseif cmd_data == 1 then
17+
device:emit_event(capabilities.button.button.double({state_change = true}))
18+
elseif cmd_data == 0x80 then
19+
device:emit_event(capabilities.button.button.held({state_change = true}))
20+
else
21+
log.info("ias_zone_private_cmd Unknown value",zb_rx.body.zcl_body.body_bytes:byte(1))
22+
end
23+
end
24+
25+
local MultiIR_Emergency_Button = {
26+
NAME = "MultiIR Emergency Button",
27+
zigbee_handlers = {
28+
cluster = {
29+
[IASZone.ID] = {
30+
[PRIVATE_CMD_ID] = ias_zone_private_cmd_handler
31+
}
32+
}
33+
},
34+
can_handle = require("MultiIR.can_handle")
35+
}
36+
37+
return MultiIR_Emergency_Button

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ local sub_drivers = {
1414
lazy_load_if_possible("ewelink"),
1515
lazy_load_if_possible("thirdreality"),
1616
lazy_load_if_possible("ezviz"),
17+
lazy_load_if_possible("MultiIR"),
1718
}
1819
return sub_drivers
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
-- Copyright 2026 SmartThings, Inc.
2+
-- Licensed under the Apache License, Version 2.0
3+
4+
-- Mock out globals
5+
local capabilities = require "st.capabilities"
6+
local clusters = require "st.zigbee.zcl.clusters"
7+
local t_utils = require "integration_test.utils"
8+
local test = require "integration_test"
9+
local zigbee_test_utils = require "integration_test.zigbee_test_utils"
10+
11+
local IASZone = clusters.IASZone
12+
local PRIVATE_CMD_ID = 0xF1
13+
14+
local mock_device = test.mock_device.build_test_zigbee_device(
15+
{
16+
profile = t_utils.get_profile_definition("one-button-battery-no-fw-update.yml"),
17+
zigbee_endpoints = {
18+
[1] = {
19+
id = 1,
20+
manufacturer = "MultIR",
21+
model = "MIR-SO100",
22+
server_clusters = {0x0000, 0x0001, 0x0003, 0x0020, 0x0500, 0x0B05}
23+
}
24+
}
25+
}
26+
)
27+
28+
zigbee_test_utils.prepare_zigbee_env_info()
29+
local function test_init()
30+
test.mock_device.add_test_device(mock_device)
31+
end
32+
33+
test.set_test_init_function(test_init)
34+
35+
36+
37+
test.register_coroutine_test(
38+
"added lifecycle event",
39+
function()
40+
-- The initial button pushed event should be send during the device's first time onboarding
41+
test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" })
42+
test.socket.capability:__set_channel_ordering("relaxed")
43+
test.socket.capability:__expect_send(
44+
mock_device:generate_test_message(
45+
"main",
46+
capabilities.button.supportedButtonValues({ "pushed","held","double" }, { visibility = { displayed = false } })
47+
)
48+
)
49+
test.socket.capability:__expect_send(
50+
mock_device:generate_test_message(
51+
"main",
52+
capabilities.button.numberOfButtons({ value = 1 }, { visibility = { displayed = false } })
53+
)
54+
)
55+
test.socket.capability:__expect_send({
56+
mock_device.id,
57+
{
58+
capability_id = "button", component_id = "main",
59+
attribute_id = "button", state = { value = "pushed" }
60+
}
61+
})
62+
-- Avoid sending the initial button pushed event after driver switch-over, as the switch-over event itself re-triggers the added lifecycle.
63+
test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" })
64+
test.socket.capability:__set_channel_ordering("relaxed")
65+
test.socket.capability:__expect_send(
66+
mock_device:generate_test_message(
67+
"main",
68+
capabilities.button.supportedButtonValues({ "pushed","held","double" }, { visibility = { displayed = false } })
69+
)
70+
)
71+
test.socket.capability:__expect_send(
72+
mock_device:generate_test_message(
73+
"main",
74+
capabilities.button.numberOfButtons({ value = 1 }, { visibility = { displayed = false } })
75+
)
76+
)
77+
end,
78+
{
79+
min_api_version = 19
80+
}
81+
)
82+
83+
test.register_message_test(
84+
"IASZone cmd 0xF1 0x00 are handled",
85+
{
86+
{
87+
channel = "zigbee",
88+
direction = "receive",
89+
message = { mock_device.id, zigbee_test_utils.build_custom_command_id(mock_device, IASZone.ID, PRIVATE_CMD_ID, 0x0000, "\x00", 0x01) }
90+
},
91+
{
92+
channel = "capability",
93+
direction = "send",
94+
message = mock_device:generate_test_message("main", capabilities.button.button.pushed({state_change = true}))
95+
}
96+
}
97+
)
98+
99+
test.register_message_test(
100+
"IASZone cmd 0xF1 0x01 are handled",
101+
{
102+
{
103+
channel = "zigbee",
104+
direction = "receive",
105+
message = { mock_device.id, zigbee_test_utils.build_custom_command_id(mock_device, IASZone.ID, PRIVATE_CMD_ID, 0x0000, "\x01", 0x01) }
106+
},
107+
{
108+
channel = "capability",
109+
direction = "send",
110+
message = mock_device:generate_test_message("main", capabilities.button.button.double({state_change = true}))
111+
}
112+
}
113+
)
114+
115+
test.register_message_test(
116+
"IASZone cmd 0xF1 0x80 are handled",
117+
{
118+
{
119+
channel = "zigbee",
120+
direction = "receive",
121+
message = { mock_device.id, zigbee_test_utils.build_custom_command_id(mock_device, IASZone.ID, PRIVATE_CMD_ID, 0x0000, "\x80", 0x01) }
122+
},
123+
{
124+
channel = "capability",
125+
direction = "send",
126+
message = mock_device:generate_test_message("main", capabilities.button.button.held({state_change = true}))
127+
}
128+
}
129+
)
130+
131+
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 Smart button MIR-SO100",麦乐克智能按钮MIR-SO100

0 commit comments

Comments
 (0)