Skip to content

Commit 6844613

Browse files
authored
WWSTCERT-7844 Feature/matter britzyhub (#2189)
1 parent dba5fc6 commit 6844613

File tree

10 files changed

+432
-0
lines changed

10 files changed

+432
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# BritzyHub Matter Edge Driver
2+
3+
Edge driver for registering BritzyHub Matter dedicated Matter devices.
4+
5+
---
6+
7+
## Reference
8+
9+
- Use CLI.md for detailed SmartThings CLI command summaries
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name: 'BritzyHub Matter'
2+
packageKey: 'britzyhub-matter'
3+
permissions:
4+
matter: {}
5+
description: "SmartThings Edge driver for BritzyHub Matter devices."
6+
vendorSupportInformation: "https://sinux.kr"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
matterGeneric:
2+
- id: "elevator"
3+
deviceLabel: Elevator
4+
deviceTypes:
5+
- id: 0xFF02
6+
deviceProfileName: elevator
7+
- id: "gas-valve"
8+
deviceLabel: Gas Valve
9+
deviceTypes:
10+
- id: 0xFF01
11+
deviceProfileName: gas-valve
12+
- id: "vent"
13+
deviceLabel: Vent
14+
deviceTypes:
15+
- id: 0xFF03
16+
deviceProfileName: vent
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name: elevator
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: elevatorCall
6+
version: 1
7+
- id: refresh
8+
version: 1
9+
categories:
10+
- name: Elevator
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name: gas-valve
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: safetyValve
6+
version: 1
7+
- id: refresh
8+
version: 1
9+
categories:
10+
- name: GasValve
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: vent
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: switch
6+
version: 1
7+
- id: fanMode
8+
version: 1
9+
config:
10+
values:
11+
- key: "fanMode.value"
12+
enabledValues:
13+
- low
14+
- medium
15+
- high
16+
- id: refresh
17+
version: 1
18+
categories:
19+
- name: Vent
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
-- SinuxSoft (c) 2025
2+
-- Licensed under the Apache License, Version 2.0
3+
4+
local capabilities = require "st.capabilities"
5+
local clusters = require "st.matter.clusters"
6+
local log = require "log"
7+
8+
local elevator_cap = capabilities.elevatorCall
9+
local onoff_cluster = clusters.OnOff
10+
11+
local ELEVATOR_DEVICE_TYPE_ID = 0xFF02
12+
13+
local function on_off_attr_handler(driver, device, ib, response)
14+
if ib.data.value then
15+
device:emit_event_for_endpoint(ib.endpoint_id, elevator_cap.callStatus.called())
16+
else
17+
device:emit_event_for_endpoint(ib.endpoint_id, elevator_cap.callStatus.standby())
18+
end
19+
end
20+
21+
local function handle_elevator_call(driver, device, cmd)
22+
local endpoint_id = device:component_to_endpoint(cmd.component)
23+
local req = onoff_cluster.server.commands.On(device, endpoint_id)
24+
device:send(req)
25+
end
26+
27+
local function find_default_endpoint(device, cluster)
28+
local eps = device:get_endpoints(cluster)
29+
table.sort(eps)
30+
for _, ep in ipairs(eps) do
31+
if ep ~= 0 then return ep end
32+
end
33+
log.warn(string.format("No endpoint found, using default %d", device.MATTER_DEFAULT_ENDPOINT))
34+
return device.MATTER_DEFAULT_ENDPOINT
35+
end
36+
37+
local function component_to_endpoint(device, component_name, cluster_id)
38+
return find_default_endpoint(device, clusters.OnOff.ID)
39+
end
40+
41+
local function device_init(driver, device)
42+
device:subscribe()
43+
device:set_component_to_endpoint_fn(component_to_endpoint)
44+
end
45+
46+
local function info_changed(driver, device, event, args)
47+
device:add_subscribed_attribute(onoff_cluster.attributes.OnOff)
48+
device:subscribe()
49+
end
50+
51+
local function is_matter_elevator(opts, driver, device)
52+
for _, ep in ipairs(device.endpoints) do
53+
for _, dt in ipairs(ep.device_types) do
54+
if dt.device_type_id == ELEVATOR_DEVICE_TYPE_ID then
55+
return true
56+
end
57+
end
58+
end
59+
return false
60+
end
61+
62+
local elevator_handler = {
63+
NAME = "Elevator Handler",
64+
can_handle = is_matter_elevator,
65+
lifecycle_handlers = {
66+
init = device_init,
67+
infoChanged = info_changed,
68+
},
69+
matter_handlers = {
70+
attr = {
71+
[onoff_cluster.ID] = {
72+
[onoff_cluster.attributes.OnOff.ID] = on_off_attr_handler,
73+
}
74+
}
75+
},
76+
capability_handlers = {
77+
[elevator_cap.ID] = {
78+
[elevator_cap.commands.call.NAME] = handle_elevator_call,
79+
}
80+
},
81+
supported_capabilities = {
82+
elevator_cap,
83+
},
84+
subscribed_attributes = {
85+
[elevator_cap.ID] = {
86+
onoff_cluster.attributes.OnOff
87+
}
88+
},
89+
}
90+
91+
return elevator_handler
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
-- SinuxSoft (c) 2025
2+
-- Licensed under the Apache License, Version 2.0
3+
4+
local capabilities = require "st.capabilities"
5+
local clusters = require "st.matter.clusters"
6+
local log = require "log"
7+
8+
local valve_cap = capabilities.safetyValve
9+
local onoff_cluster = clusters.OnOff
10+
11+
local GAS_VALVE_DEVICE_TYPE_ID = 0xFF01
12+
13+
local function on_off_attr_handler(driver, device, ib, response)
14+
if ib.data.value then
15+
device:emit_event_for_endpoint(ib.endpoint_id, valve_cap.valve.open())
16+
else
17+
device:emit_event_for_endpoint(ib.endpoint_id, valve_cap.valve.closed())
18+
end
19+
end
20+
21+
local function handle_valve_close(driver, device, cmd)
22+
local endpoint_id = device:component_to_endpoint(cmd.component)
23+
local req = onoff_cluster.server.commands.Off(device, endpoint_id)
24+
device:send(req)
25+
end
26+
27+
local function find_default_endpoint(device, cluster)
28+
local eps = device:get_endpoints(cluster)
29+
table.sort(eps)
30+
for _, ep in ipairs(eps) do
31+
if ep ~= 0 then return ep end
32+
end
33+
log.warn(string.format("No endpoint found, using default %d", device.MATTER_DEFAULT_ENDPOINT))
34+
return device.MATTER_DEFAULT_ENDPOINT
35+
end
36+
37+
local function component_to_endpoint(device, component_name, cluster_id)
38+
return find_default_endpoint(device, onoff_cluster.ID)
39+
end
40+
41+
local function device_init(driver, device)
42+
device:subscribe()
43+
device:set_component_to_endpoint_fn(component_to_endpoint)
44+
end
45+
46+
local function info_changed(driver, device, event, args)
47+
device:add_subscribed_attribute(onoff_cluster.attributes.OnOff)
48+
device:subscribe()
49+
end
50+
51+
local function is_matter_gas_valve(opts, driver, device)
52+
for _, ep in ipairs(device.endpoints) do
53+
for _, dt in ipairs(ep.device_types) do
54+
if dt.device_type_id == GAS_VALVE_DEVICE_TYPE_ID then
55+
return true
56+
end
57+
end
58+
end
59+
return false
60+
end
61+
62+
local gas_valve_handler = {
63+
NAME = "Gas Valve Handler",
64+
can_handle = is_matter_gas_valve,
65+
lifecycle_handlers = {
66+
init = device_init,
67+
infoChanged = info_changed,
68+
},
69+
matter_handlers = {
70+
attr = {
71+
[onoff_cluster.ID] = {
72+
[onoff_cluster.attributes.OnOff.ID] = on_off_attr_handler,
73+
}
74+
}
75+
},
76+
capability_handlers = {
77+
[valve_cap.ID] = {
78+
[valve_cap.commands.close.NAME] = handle_valve_close,
79+
}
80+
},
81+
supported_capabilities = {
82+
valve_cap,
83+
},
84+
subscribed_attributes = {
85+
[valve_cap.ID] = {
86+
onoff_cluster.attributes.OnOff
87+
}
88+
},
89+
}
90+
91+
return gas_valve_handler
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
-- SinuxSoft (c) 2025
2+
-- Licensed under the Apache License, Version 2.0
3+
4+
local MatterDriver = require "st.matter.driver"
5+
local log = require "log"
6+
7+
local matter_driver = MatterDriver("britzyhub-matter", {
8+
sub_drivers = {
9+
require ("elevator"),
10+
require ("gas-valve"),
11+
require ("vent"),
12+
}
13+
})
14+
15+
log.info_with({hub_logs=true}, string.format("Starting %s driver, with dispatcher: %s", matter_driver.NAME, matter_driver.matter_dispatcher))
16+
matter_driver:run()

0 commit comments

Comments
 (0)