@@ -19,16 +19,10 @@ local log = require "log"
1919local clusters = require " st.matter.clusters"
2020local MatterDriver = require " st.matter.driver"
2121
22- local DEFAULT_LEVEL = 0
2322local PROFILE_MATCHED = " __profile_matched"
24- local IS_MOVING = " __is_moving"
25- local EVENT_STATE = " __event_state"
26-
27- local WindowCoveringEventEnum = {
28- NO_EVENT = 0x00 ,
29- CURRENT_POSITION_EVENT = 0x01 ,
30- OPERATIONAL_STATE_EVENT = 0x02
31- }
23+ local CURRENT_POSITION = " __current_position"
24+ local TARGET_POSITION = " __target_position"
25+ local First_Time_Onboarding = " __first_time_onboarding"
3226
3327local function find_default_endpoint (device , cluster )
3428 local res = device .MATTER_DEFAULT_ENDPOINT
@@ -62,13 +56,12 @@ local function match_profile(device)
6256end
6357
6458local function device_init (driver , device )
65- device :set_field (EVENT_STATE , WindowCoveringEventEnum .NO_EVENT )
66- device :set_field (IS_MOVING , false )
6759 if not device :get_field (PROFILE_MATCHED ) then
6860 match_profile (device )
6961 end
7062 device :set_component_to_endpoint_fn (component_to_endpoint )
7163 device :subscribe ()
64+ device :set_field (First_Time_Onboarding , true )
7265end
7366
7467local function info_changed (driver , device , event , args )
@@ -144,69 +137,45 @@ local function current_pos_handler(driver, device, ib, response)
144137 ib .endpoint_id , capabilities .windowShadeLevel .shadeLevel (position )
145138 )
146139 end
147- if device :get_field (EVENT_STATE ) == WindowCoveringEventEnum .OPERATIONAL_STATE_EVENT then
148- if not device :get_field (IS_MOVING ) then
149- if position == 0 then
150- device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .closed ())
151- elseif position == 100 then
152- device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .open ())
153- elseif position > 0 and position < 100 then
154- device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .partially_open ())
155- else
156- device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .unknown ())
157- end
158- device :set_field (EVENT_STATE , WindowCoveringEventEnum .NO_EVENT )
159- end
160- else
161- device :set_field (EVENT_STATE , WindowCoveringEventEnum .CURRENT_POSITION_EVENT )
140+ device :set_field (CURRENT_POSITION , position )
141+ if device :get_field (TARGET_POSITION ) == position then
142+ if position == 0 then
143+ device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .closed ())
144+ elseif position == 100 then
145+ device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .open ())
146+ elseif position > 0 and position < 100 then
147+ device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .partially_open ())
148+ else
149+ device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .unknown ())
150+ end
151+ end
152+ if device :get_field (First_Time_Onboarding ) == true then
153+ if position == 0 then
154+ device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .closed ())
155+ elseif position == 100 then
156+ device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .open ())
157+ elseif position > 0 and position < 100 then
158+ device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .partially_open ())
159+ else
160+ device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .unknown ())
161+ end
162+ device :set_field (First_Time_Onboarding , false )
162163 end
163164end
164165
165166-- checks the current position of the shade
166- local function current_status_handler (driver , device , ib , response )
167+ local function target_pos_handler (driver , device , ib , response )
167168 local attr = capabilities .windowShade .windowShade
168- local position = device :get_latest_state (
169- " main" , capabilities .windowShadeLevel .ID ,
170- capabilities .windowShadeLevel .shadeLevel .NAME
171- ) or DEFAULT_LEVEL
172- for _ , rb in ipairs (response .info_blocks ) do
173- if rb .info_block .attribute_id == clusters .WindowCovering .attributes .CurrentPositionLiftPercent100ths .ID and
174- rb .info_block .cluster_id == clusters .WindowCovering .ID and
175- rb .info_block .data .value ~= nil then
176- position = 100 - math.floor ((rb .info_block .data .value / 100 ))
177- end
178- end
179- local state = ib .data .value & clusters .WindowCovering .types .OperationalStatus .GLOBAL -- Could use LIFT instead
180- if device :get_field (EVENT_STATE ) == WindowCoveringEventEnum .CURRENT_POSITION_EVENT then
181- if state == 0 then -- not moving
182- if position == 100 then -- open
183- device :emit_event_for_endpoint (ib .endpoint_id , attr .open ())
184- elseif position == 0 then -- closed
185- device :emit_event_for_endpoint (ib .endpoint_id , attr .closed ())
186- else
187- device :emit_event_for_endpoint (ib .endpoint_id , attr .partially_open ())
188- end
189- device :set_field (IS_MOVING , false )
190- elseif state == 1 then -- opening
191- device :emit_event_for_endpoint (ib .endpoint_id , attr .opening ())
192- elseif state == 2 then -- closing
193- device :emit_event_for_endpoint (ib .endpoint_id , attr .closing ())
194- else
195- device :emit_event_for_endpoint (ib .endpoint_id , attr .unknown ())
196- end
197- device :set_field (EVENT_STATE , WindowCoveringEventEnum .NO_EVENT )
198- else
199- if state == 1 then -- opening
200- device :emit_event_for_endpoint (ib .endpoint_id , attr .opening ())
201- device :set_field (IS_MOVING , true )
202- elseif state == 2 then -- closing
203- device :emit_event_for_endpoint (ib .endpoint_id , attr .closing ())
204- device :set_field (IS_MOVING , true )
205- else
206- device :set_field (IS_MOVING , false )
207- device :set_field (EVENT_STATE , WindowCoveringEventEnum .OPERATIONAL_STATE_EVENT )
208- end
169+ local target_position
170+ if ib .data .value ~= nil then
171+ target_position = 100 - math.floor ((ib .data .value / 100 ))
209172 end
173+ device :set_field (TARGET_POSITION , target_position )
174+ if device :get_field (CURRENT_POSITION ) > target_position then
175+ device :emit_event_for_endpoint (ib .endpoint_id , attr .closing ())
176+ elseif device :get_field (CURRENT_POSITION ) < target_position then
177+ device :emit_event_for_endpoint (ib .endpoint_id , attr .opening ())
178+ end
210179end
211180
212181local function level_attr_handler (driver , device , ib , response )
@@ -235,7 +204,8 @@ local matter_driver_template = {
235204 [clusters .WindowCovering .ID ] = {
236205 -- uses percent100ths more often
237206 [clusters .WindowCovering .attributes .CurrentPositionLiftPercent100ths .ID ] = current_pos_handler ,
238- [clusters .WindowCovering .attributes .OperationalStatus .ID ] = current_status_handler ,
207+ [clusters .WindowCovering .attributes .TargetPositionLiftPercent100ths .ID ] = target_pos_handler ,
208+ -- [clusters.WindowCovering.attributes.OperationalStatus.ID] = current_status_handler,
239209 },
240210 [clusters .PowerSource .ID ] = {
241211 [clusters .PowerSource .attributes .BatPercentRemaining .ID ] = battery_percent_remaining_attr_handler ,
@@ -249,6 +219,7 @@ local matter_driver_template = {
249219 [capabilities .windowShadeLevel .ID ] = {
250220 clusters .LevelControl .attributes .CurrentLevel ,
251221 clusters .WindowCovering .attributes .CurrentPositionLiftPercent100ths ,
222+ clusters .WindowCovering .attributes .TargetPositionLiftPercent100ths ,
252223 },
253224 [capabilities .battery .ID ] = {
254225 clusters .PowerSource .attributes .BatPercentRemaining
0 commit comments