@@ -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 Initial_Status_Display = " __initial_status_display"
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 (Initial_Status_Display , true )
7265end
7366
7467local function info_changed (driver , device , event , args )
@@ -135,6 +128,19 @@ local function handle_shade_level(driver, device, cmd)
135128 device :send (req )
136129end
137130
131+ -- to decide the status of window covering
132+ local function decide_status (device , ib , position )
133+ if position == 0 then
134+ device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .closed ())
135+ elseif position == 100 then
136+ device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .open ())
137+ elseif position > 0 and position < 100 then
138+ device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .partially_open ())
139+ else
140+ device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShade .windowShade .unknown ())
141+ end
142+ end
143+
138144-- current lift percentage, changed to 100ths percent
139145local function current_pos_handler (driver , device , ib , response )
140146 local position = 0
@@ -144,69 +150,30 @@ local function current_pos_handler(driver, device, ib, response)
144150 ib .endpoint_id , capabilities .windowShadeLevel .shadeLevel (position )
145151 )
146152 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 )
153+ device :set_field (CURRENT_POSITION , position )
154+ if device :get_field (Initial_Status_Display ) == true then
155+ -- Emiting window status during initialization
156+ decide_status (device , ib , position )
157+ device :set_field (Initial_Status_Display , false )
158+ elseif device :get_field (TARGET_POSITION ) == position and device :get_field (Initial_Status_Display ) == false then
159+ -- Emiting window status after arriving to the target position
160+ decide_status (device , ib , position )
162161 end
163162end
164163
165164-- checks the current position of the shade
166- local function current_status_handler (driver , device , ib , response )
165+ local function target_pos_handler (driver , device , ib , response )
167166 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
167+ local target_position
168+ if ib .data .value ~= nil then
169+ target_position = 100 - math.floor ((ib .data .value / 100 ))
209170 end
171+ device :set_field (TARGET_POSITION , target_position )
172+ if device :get_field (CURRENT_POSITION ) > target_position then
173+ device :emit_event_for_endpoint (ib .endpoint_id , attr .closing ())
174+ elseif device :get_field (CURRENT_POSITION ) < target_position then
175+ device :emit_event_for_endpoint (ib .endpoint_id , attr .opening ())
176+ end
210177end
211178
212179local function level_attr_handler (driver , device , ib , response )
@@ -235,7 +202,8 @@ local matter_driver_template = {
235202 [clusters .WindowCovering .ID ] = {
236203 -- uses percent100ths more often
237204 [clusters .WindowCovering .attributes .CurrentPositionLiftPercent100ths .ID ] = current_pos_handler ,
238- [clusters .WindowCovering .attributes .OperationalStatus .ID ] = current_status_handler ,
205+ [clusters .WindowCovering .attributes .TargetPositionLiftPercent100ths .ID ] = target_pos_handler ,
206+ -- [clusters.WindowCovering.attributes.OperationalStatus.ID] = current_status_handler,
239207 },
240208 [clusters .PowerSource .ID ] = {
241209 [clusters .PowerSource .attributes .BatPercentRemaining .ID ] = battery_percent_remaining_attr_handler ,
@@ -249,6 +217,7 @@ local matter_driver_template = {
249217 [capabilities .windowShadeLevel .ID ] = {
250218 clusters .LevelControl .attributes .CurrentLevel ,
251219 clusters .WindowCovering .attributes .CurrentPositionLiftPercent100ths ,
220+ clusters .WindowCovering .attributes .TargetPositionLiftPercent100ths ,
252221 },
253222 [capabilities .battery .ID ] = {
254223 clusters .PowerSource .attributes .BatPercentRemaining
0 commit comments