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
0 commit comments