Skip to content

Commit 496f328

Browse files
committed
Change get/set_field to get/set_field_for_endpoint
Signed-off-by: Hunsup Jung <hunsup.jung@samsung.com>
1 parent c3849ad commit 496f328

2 files changed

Lines changed: 49 additions & 76 deletions

File tree

‎drivers/SmartThings/matter-window-covering/src/init.lua‎

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,22 @@ local TARGET_TILT_PERCENT = {
4141

4242
local 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+
4460
local 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)
112128
end
113129

114130
--- Tries to emit the idle window shade status if no target percentages are set.
115131
--- @param device any a Matter device object
116132
local 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
123139
end
@@ -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)
141157
end
142158

143159
local function is_target_value_reached(current_value, target_value)
@@ -266,15 +282,15 @@ end
266282

267283
-- capability handlers
268284
local 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
288304
local 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
302318
local 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
322338
local 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
))
329345
end
330346

331347
local 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,
@@ -351,7 +368,7 @@ end
351368
local 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
370386
end
@@ -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
381396
end
@@ -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
398413
end
@@ -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
415430
end

‎drivers/SmartThings/matter-window-covering/src/test/test_matter_multi_window_covering.lua‎

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -568,48 +568,6 @@ test.register_coroutine_test(
568568
}
569569
)
570570

571-
test.register_coroutine_test(
572-
"WindowCovering TargetPositionLiftPercent100ths sets field appropriately",
573-
function()
574-
for i = 1, #mock_child_device do
575-
test.socket.matter:__queue_receive(
576-
{
577-
mock_child_device[i].id,
578-
WindowCovering.attributes.TargetPositionLiftPercent100ths:build_test_report_data(
579-
mock_child_device[i], CHILD_DEVICE_MAP[i].ep, 5000
580-
),
581-
}
582-
)
583-
test.wait_for_events()
584-
assert(mock_child_device[i]:get_field("__target_lift_percent") == 50)
585-
end
586-
end,
587-
{
588-
min_api_version = 17
589-
}
590-
)
591-
592-
test.register_coroutine_test(
593-
"WindowCovering TargetPositionTiltPercent100ths sets field appropriately",
594-
function()
595-
for i = 1, #mock_child_device do
596-
test.socket.matter:__queue_receive(
597-
{
598-
mock_child_device[i].id,
599-
WindowCovering.attributes.TargetPositionTiltPercent100ths:build_test_report_data(
600-
mock_child_device[i], CHILD_DEVICE_MAP[i].ep, 5000
601-
),
602-
}
603-
)
604-
test.wait_for_events()
605-
assert(mock_child_device[i]:get_field("__target_tilt_percent") == 50)
606-
end
607-
end,
608-
{
609-
min_api_version = 17
610-
}
611-
)
612-
613571
test.register_coroutine_test(
614572
"WindowCovering TargetPositionLiftPercent100ths triggers operational status update when appropriate",
615573
function()

0 commit comments

Comments
 (0)