1
+ -- Copyright 2023 philh30
2
+ --
3
+ -- Licensed under the Apache License, Version 2.0 (the "License");
4
+ -- you may not use this file except in compliance with the License.
5
+ -- You may obtain a copy of the License at
6
+ --
7
+ -- http://www.apache.org/licenses/LICENSE-2.0
8
+ --
9
+ -- Unless required by applicable law or agreed to in writing, software
10
+ -- distributed under the License is distributed on an "AS IS" BASIS,
11
+ -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ -- See the License for the specific language governing permissions and
13
+ -- limitations under the License.
14
+
15
+ local st_device = require " st.device"
16
+ local clusters = require " st.zigbee.zcl.clusters"
17
+ local capabilities = require " st.capabilities"
18
+ local FanControl = clusters .FanControl
19
+ local Level = clusters .Level
20
+ local OnOff = clusters .OnOff
21
+
22
+ local IFL_FINGERPRINTS = {
23
+ { mfr = " Samsung Electronics" , model = " SAMSUNG-ITM-Z-003" },
24
+ }
25
+
26
+ local is_ifl = function (opts , driver , device )
27
+ for _ , fingerprint in ipairs (IFL_FINGERPRINTS ) do
28
+ if device :get_manufacturer () == fingerprint .mfr and device :get_model () == fingerprint .model then
29
+ return true
30
+ end
31
+ end
32
+ return false
33
+ end
34
+
35
+ -- Create child device
36
+
37
+ local function add_child (driver ,parent ,profile ,child_type )
38
+ local child_metadata = {
39
+ type = " EDGE_CHILD" ,
40
+ label = string.format (" %s %s" , parent .label , child_type ),
41
+ profile = profile ,
42
+ parent_device_id = parent .id ,
43
+ parent_assigned_child_key = child_type ,
44
+ vendor_provided_label = string.format (" %s %s" , parent .label , child_type )
45
+ }
46
+ driver :try_create_device (child_metadata )
47
+ end
48
+
49
+ local function info_changed (driver , device , event , args )
50
+ if (device .preferences or {}).childLight2 then
51
+ if not device :get_child_by_parent_assigned_key (' light' ) then
52
+ add_child (driver ,device ,' switch-level' ,' light' )
53
+ end
54
+ end
55
+ end
56
+
57
+ -- CAPABILITY HANDLERS
58
+
59
+ local function on_handler (driver , device , command )
60
+ local dev = device
61
+ if device .network_type == st_device .NETWORK_TYPE_CHILD then
62
+ command .component = ' light'
63
+ dev = device :get_parent_device ()
64
+ end
65
+ if command .component == ' light' then
66
+ dev :send (OnOff .server .commands .On (dev ))
67
+ else
68
+ local speed = dev :get_field (' LAST_FAN_SPD' ) or 1
69
+ dev :send (FanControl .attributes .FanMode :write (dev ,speed ))
70
+ dev :send (FanControl .attributes .FanMode :read (dev ,speed ))
71
+ end
72
+ end
73
+
74
+ local function off_handler (driver , device , command )
75
+ local dev = device
76
+ if device .network_type == st_device .NETWORK_TYPE_CHILD then
77
+ command .component = ' light'
78
+ dev = device :get_parent_device ()
79
+ end
80
+ if command .component == ' light' then
81
+ dev :send (OnOff .server .commands .Off (dev ))
82
+ else
83
+ dev :send (FanControl .attributes .FanMode :write (dev ,FanControl .attributes .FanMode .OFF ))
84
+ end
85
+ dev :send (FanControl .attributes .FanMode :read (dev ,FanControl .attributes .FanMode .OFF ))
86
+ end
87
+
88
+ local function switch_level_handler (driver , device , command )
89
+ local dev = device
90
+ if device .network_type == st_device .NETWORK_TYPE_CHILD then
91
+ command .component = ' light'
92
+ dev = device :get_parent_device ()
93
+ end
94
+ if command .component == ' light' then
95
+ local level = math.floor (command .args .level / 100.0 * 254 )
96
+ dev :send (Level .server .commands .MoveToLevelWithOnOff (dev , level , command .args .rate or 0xFFFF ))
97
+ end
98
+ end
99
+
100
+ local function fan_speed_handler (driver , device , command )
101
+ device :send (FanControl .attributes .FanMode :write (device ,command .args .speed ))
102
+ device :send (FanControl .attributes .FanMode :read (device ,command .args .speed ))
103
+ end
104
+
105
+ -- ZIGBEE HANDLERS
106
+
107
+ local function zb_fan_control_handler (driver , device , value , zb_rx )
108
+ device :emit_event (capabilities .fanSpeed .fanSpeed (value .value ))
109
+ local evt = capabilities .switch .switch (value .value > 0 and ' on' or ' off' , { visibility = { displayed = false } })
110
+ device :emit_component_event (device .profile .components .main ,evt )
111
+ if value .value > 0 then
112
+ device :set_field (' LAST_FAN_SPD' , value .value , {persist = true })
113
+ end
114
+ end
115
+
116
+ local function zb_level_handler (driver , device , value , zb_rx )
117
+ local evt = capabilities .switchLevel .level (math.floor ((value .value / 254.0 * 100 ) + 0.5 ))
118
+ device :emit_component_event (device .profile .components .light ,evt )
119
+ local child = device :get_child_by_parent_assigned_key (' light' )
120
+ if child ~= nil then
121
+ child :emit_event (evt )
122
+ end
123
+ end
124
+
125
+ local function zb_onoff_handler (driver , device , value , zb_rx )
126
+ local attr = capabilities .switch .switch
127
+ local evt = value .value and attr .on () or attr .off ()
128
+ device :emit_component_event (device .profile .components .light ,evt )
129
+ local child = device :get_child_by_parent_assigned_key (' light' )
130
+ if child ~= nil then
131
+ child :emit_event (evt )
132
+ end
133
+ end
134
+
135
+ local itm_fan_light = {
136
+ NAME = " ITM Fan Light" ,
137
+ zigbee_handlers = {
138
+ attr = {
139
+ [FanControl .ID ] = {
140
+ [FanControl .attributes .FanMode .ID ] = zb_fan_control_handler
141
+ },
142
+ [Level .ID ] = {
143
+ [Level .attributes .CurrentLevel .ID ] = zb_level_handler
144
+ },
145
+ [OnOff .ID ] = {
146
+ [OnOff .attributes .OnOff .ID ] = zb_onoff_handler
147
+ }
148
+ }
149
+ },
150
+ capability_handlers = {
151
+ [capabilities .switch .ID ] = {
152
+ [capabilities .switch .commands .on .NAME ] = on_handler ,
153
+ [capabilities .switch .commands .off .NAME ] = off_handler ,
154
+ },
155
+ [capabilities .switchLevel .ID ] = {
156
+ [capabilities .switchLevel .commands .setLevel .NAME ] = switch_level_handler
157
+ },
158
+ [capabilities .fanSpeed .ID ] = {
159
+ [capabilities .fanSpeed .commands .setFanSpeed .NAME ] = fan_speed_handler
160
+ }
161
+ },
162
+ lifecycle_handlers = {
163
+ infoChanged = info_changed ,
164
+ },
165
+ can_handle = is_ifl
166
+ }
167
+
168
+ return itm_fan_light
0 commit comments