@@ -41,6 +41,22 @@ local TARGET_TILT_PERCENT = {
4141
4242local TARGET_REACH_TOLERANCE = 0.5
4343
44+ local function get_field_for_endpoint (device , field , endpoint )
45+ local field_device = device
46+ if device :get_field (IS_PARENT_CHILD_DEVICE ) ~= true then
47+ field_device = device :get_parent_device ()
48+ end
49+ return field_device :get_field (string.format (" %s_%d" , field , endpoint ))
50+ end
51+
52+ local function set_field_for_endpoint (device , field , endpoint , value , additional_params )
53+ local field_device = device
54+ if device :get_field (IS_PARENT_CHILD_DEVICE ) ~= true then
55+ field_device = device :get_parent_device ()
56+ end
57+ field_device :set_field (string.format (" %s_%d" , field , endpoint ), value , additional_params )
58+ end
59+
4460local function find_child (parent_device , ep_id )
4561 local assigned_key = parent_device :get_field (string.format (" %s_%d" , ASSIGNED_CHILD_KEY , ep_id )) or ep_id
4662 return parent_device :get_child_by_parent_assigned_key (string.format (" %d" , assigned_key ))
@@ -102,22 +118,22 @@ end
102118--- Clears the cached target percentage and cancels any associated timeout.
103119--- @param device any a Matter device object
104120--- @param op_fields table a table containing operational field constants used for caching target percentages and timeouts.
105- local function clear_cached_data (device , op_fields )
106- local current_timer = device : get_field ( op_fields .TIMEOUT )
121+ local function clear_cached_data (device , op_fields , ep )
122+ local current_timer = get_field_for_endpoint ( device , op_fields .TIMEOUT , ep )
107123 if current_timer then
108124 device .thread :cancel_timer (current_timer )
109125 end
110- device : set_field ( op_fields .STATE , nil )
111- device : set_field ( op_fields .TIMEOUT , nil )
126+ set_field_for_endpoint ( device , op_fields .STATE , ep , nil )
127+ set_field_for_endpoint ( device , op_fields .TIMEOUT , ep , nil )
112128end
113129
114130--- Tries to emit the idle window shade status if no target percentages are set.
115131--- @param device any a Matter device object
116132local function try_emit_idle_window_shade_status (device , ep )
117- if not device : get_field ( TARGET_LIFT_PERCENT .STATE ) and
118- not device : get_field ( TARGET_TILT_PERCENT .STATE ) then
133+ if not get_field_for_endpoint ( device , TARGET_LIFT_PERCENT .STATE , ep ) and
134+ not get_field_for_endpoint ( device , TARGET_TILT_PERCENT .STATE , ep ) then
119135 --- gets child device if one exists for this endpoint
120- local status_device = ep and find_child (device , ep ) or device
136+ local status_device = find_child (device , ep ) or device
121137 status_device :emit_event (get_idle_window_shade_status (status_device ))
122138 end
123139end
@@ -126,18 +142,18 @@ end
126142--- @param device any a Matter device object
127143--- @param data number the target percentage to cache
128144--- @param op_fields table a table containing operational field constants used for caching target percentages and timeouts.
129- local function cache_data_with_timeout (device , data , op_fields )
130- device : set_field ( op_fields .STATE , data )
131- local previous_timer = device : get_field ( op_fields .TIMEOUT )
145+ local function cache_data_with_timeout (device , data , op_fields , ep )
146+ set_field_for_endpoint ( device , op_fields .STATE , ep , data )
147+ local previous_timer = get_field_for_endpoint ( device , op_fields .TIMEOUT , ep )
132148 if previous_timer then
133149 device .thread :cancel_timer (previous_timer )
134150 end
135151 local new_timer = device .thread :call_with_delay (op_fields .TIMEOUT_DELAY_S , function ()
136- device : set_field ( op_fields .STATE , nil )
137- device : set_field ( op_fields .TIMEOUT , nil )
138- try_emit_idle_window_shade_status (device , nil )
152+ set_field_for_endpoint ( device , op_fields .STATE , ep , nil )
153+ set_field_for_endpoint ( device , op_fields .TIMEOUT , ep , nil )
154+ try_emit_idle_window_shade_status (device , ep )
139155 end )
140- device : set_field ( op_fields .TIMEOUT , new_timer )
156+ set_field_for_endpoint ( device , op_fields .TIMEOUT , ep , new_timer )
141157end
142158
143159local function is_target_value_reached (current_value , target_value )
@@ -266,15 +282,15 @@ end
266282
267283-- capability handlers
268284local function handle_preset (driver , device , cmd )
285+ local endpoint_id = device :component_to_endpoint (cmd .component )
269286 local preset_target_percent = device :get_latest_state (
270287 " main" ,
271288 capabilities .windowShadePreset .ID ,
272289 capabilities .windowShadePreset .position .NAME ,
273290 DEFAULT_PRESET_LEVEL
274291 )
275- cache_data_with_timeout (device , preset_target_percent , TARGET_LIFT_PERCENT )
292+ cache_data_with_timeout (device , preset_target_percent , TARGET_LIFT_PERCENT , endpoint_id )
276293 local hundredths_lift_percent = (100 - preset_target_percent ) * 100
277- local endpoint_id = device :component_to_endpoint (cmd .component )
278294 device :send (clusters .WindowCovering .server .commands .GoToLiftPercentage (
279295 device , endpoint_id , hundredths_lift_percent
280296 ))
@@ -288,10 +304,10 @@ end
288304local function handle_close (driver , device , cmd )
289305 local endpoint_id = device :component_to_endpoint (cmd .component )
290306 if # device :get_endpoints (clusters .WindowCovering .ID , {feature_bitmap = clusters .WindowCovering .types .Feature .LIFT }) > 0 then
291- cache_data_with_timeout (device , device .preferences .reverse and 100 or 0 , TARGET_LIFT_PERCENT )
307+ cache_data_with_timeout (device , device .preferences .reverse and 100 or 0 , TARGET_LIFT_PERCENT , endpoint_id )
292308 end
293309 if # device :get_endpoints (clusters .WindowCovering .ID , {feature_bitmap = clusters .WindowCovering .types .Feature .TILT }) > 0 then
294- cache_data_with_timeout (device , device .preferences .reverse and 100 or 0 , TARGET_TILT_PERCENT )
310+ cache_data_with_timeout (device , device .preferences .reverse and 100 or 0 , TARGET_TILT_PERCENT , endpoint_id )
295311 end
296312 device :send (device .preferences .reverse and
297313 clusters .WindowCovering .server .commands .UpOrOpen (device , endpoint_id ) or
@@ -302,10 +318,10 @@ end
302318local function handle_open (driver , device , cmd )
303319 local endpoint_id = device :component_to_endpoint (cmd .component )
304320 if # device :get_endpoints (clusters .WindowCovering .ID , {feature_bitmap = clusters .WindowCovering .types .Feature .LIFT }) > 0 then
305- cache_data_with_timeout (device , device .preferences .reverse and 0 or 100 , TARGET_LIFT_PERCENT )
321+ cache_data_with_timeout (device , device .preferences .reverse and 0 or 100 , TARGET_LIFT_PERCENT , endpoint_id )
306322 end
307323 if # device :get_endpoints (clusters .WindowCovering .ID , {feature_bitmap = clusters .WindowCovering .types .Feature .TILT }) > 0 then
308- cache_data_with_timeout (device , device .preferences .reverse and 0 or 100 , TARGET_TILT_PERCENT )
324+ cache_data_with_timeout (device , device .preferences .reverse and 0 or 100 , TARGET_TILT_PERCENT , endpoint_id )
309325 end
310326 device :send (device .preferences .reverse and
311327 clusters .WindowCovering .server .commands .DownOrClose (device , endpoint_id ) or
@@ -322,23 +338,24 @@ end
322338local function handle_shade_level (driver , device , cmd )
323339 local endpoint_id = device :component_to_endpoint (cmd .component )
324340 local hundredths_lift_percentage = (100 - cmd .args .shadeLevel ) * 100
325- cache_data_with_timeout (device , cmd .args .shadeLevel , TARGET_LIFT_PERCENT )
341+ cache_data_with_timeout (device , cmd .args .shadeLevel , TARGET_LIFT_PERCENT , endpoint_id )
326342 device :send (clusters .WindowCovering .server .commands .GoToLiftPercentage (
327343 device , endpoint_id , hundredths_lift_percentage
328344 ))
329345end
330346
331347local function handle_step_shade_level (driver , device , cmd )
348+ local endpoint_id = device :component_to_endpoint (cmd .component )
332349 local step = cmd .args .stepSize
333350 local latest_lift_percentage = device :get_latest_state (
334351 " main" ,
335352 capabilities .windowShadeLevel .ID ,
336353 capabilities .windowShadeLevel .shadeLevel .NAME ,
337354 0
338355 )
339- local target_lift_percent = device : get_field ( TARGET_LIFT_PERCENT .STATE ) or latest_lift_percentage
356+ local target_lift_percent = get_field_for_endpoint ( device , TARGET_LIFT_PERCENT .STATE , endpoint_id ) or latest_lift_percentage
340357 local updated_target_lift = utils .clamp_value (target_lift_percent + step , 0 , 100 )
341- cache_data_with_timeout (device , updated_target_lift , TARGET_LIFT_PERCENT )
358+ cache_data_with_timeout (device , updated_target_lift , TARGET_LIFT_PERCENT , endpoint_id )
342359 driver :inject_capability_command (device , {
343360 capability = capabilities .windowShadeLevel .ID ,
344361 component = cmd .component ,
351368local function handle_shade_tilt_level (driver , device , cmd )
352369 local endpoint_id = device :component_to_endpoint (cmd .component )
353370 local hundredths_tilt_percentage = (100 - cmd .args .level ) * 100
354- cache_data_with_timeout (device , cmd .args .level , TARGET_TILT_PERCENT )
371+ cache_data_with_timeout (device , cmd .args .level , TARGET_TILT_PERCENT , endpoint_id )
355372 device :send (clusters .WindowCovering .server .commands .GoToTiltPercentage (
356373 device , endpoint_id , hundredths_tilt_percentage
357374 ))
@@ -362,9 +379,8 @@ local function current_position_lift_percent_100ths_handler(driver, device, ib,
362379 if not ib .data .value then return end
363380 local lift_percent = 100 - math.floor (ib .data .value / 100 )
364381 device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShadeLevel .shadeLevel (lift_percent ))
365-
366- if is_target_value_reached (lift_percent , device :get_field (TARGET_LIFT_PERCENT .STATE )) then
367- clear_cached_data (device , TARGET_LIFT_PERCENT )
382+ if is_target_value_reached (lift_percent , get_field_for_endpoint (device , TARGET_LIFT_PERCENT .STATE , ib .endpoint_id )) then
383+ clear_cached_data (device , TARGET_LIFT_PERCENT , ib .endpoint_id )
368384 try_emit_idle_window_shade_status (device , ib .endpoint_id )
369385 end
370386end
@@ -373,9 +389,8 @@ local function current_position_tilt_percent_100ths_handler(driver, device, ib,
373389 if not ib .data .value then return end
374390 local tilt_percent = 100 - math.floor (ib .data .value / 100 )
375391 device :emit_event_for_endpoint (ib .endpoint_id , capabilities .windowShadeTiltLevel .shadeTiltLevel (tilt_percent ))
376-
377- if is_target_value_reached (tilt_percent , device :get_field (TARGET_TILT_PERCENT .STATE )) then
378- clear_cached_data (device , TARGET_TILT_PERCENT )
392+ if is_target_value_reached (tilt_percent , get_field_for_endpoint (device , TARGET_TILT_PERCENT .STATE , ib .endpoint_id )) then
393+ clear_cached_data (device , TARGET_TILT_PERCENT , ib .endpoint_id )
379394 try_emit_idle_window_shade_status (device , ib .endpoint_id )
380395 end
381396end
@@ -389,10 +404,10 @@ local function target_position_lift_percent_100ths_handler(driver, device, ib, r
389404 capabilities .windowShadeLevel .shadeLevel .NAME
390405 )
391406 if latest_lift_percentage and is_target_value_reached (latest_lift_percentage , target_lift_percent ) then
392- clear_cached_data (device , TARGET_LIFT_PERCENT )
407+ clear_cached_data (device , TARGET_LIFT_PERCENT , ib . endpoint_id )
393408 try_emit_idle_window_shade_status (device , ib .endpoint_id )
394409 else
395- cache_data_with_timeout (device , target_lift_percent , TARGET_LIFT_PERCENT )
410+ cache_data_with_timeout (device , target_lift_percent , TARGET_LIFT_PERCENT , ib . endpoint_id )
396411 end
397412 end
398413end
@@ -406,10 +421,10 @@ local function target_position_tilt_percent_100ths_handler(driver, device, ib, r
406421 capabilities .windowShadeTiltLevel .shadeTiltLevel .NAME
407422 )
408423 if latest_tilt_percent and is_target_value_reached (latest_tilt_percent , target_tilt_percent ) then
409- clear_cached_data (device , TARGET_TILT_PERCENT )
424+ clear_cached_data (device , TARGET_TILT_PERCENT , ib . endpoint_id )
410425 try_emit_idle_window_shade_status (device , ib .endpoint_id )
411426 else
412- cache_data_with_timeout (device , target_tilt_percent , TARGET_TILT_PERCENT )
427+ cache_data_with_timeout (device , target_tilt_percent , TARGET_TILT_PERCENT , ib . endpoint_id )
413428 end
414429 end
415430end
0 commit comments