From 9f4541b20bf787060b60bce92c2d723de03bebb4 Mon Sep 17 00:00:00 2001 From: Hunsup Jung Date: Tue, 1 Sep 2026 13:57:40 +0900 Subject: [PATCH 1/2] Add debounce delay to coalesce both subscription updates Signed-off-by: Hunsup Jung --- drivers/SmartThings/matter-rvc/src/init.lua | 32 ++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/SmartThings/matter-rvc/src/init.lua b/drivers/SmartThings/matter-rvc/src/init.lua index 2badac1413..1a833a6512 100644 --- a/drivers/SmartThings/matter-rvc/src/init.lua +++ b/drivers/SmartThings/matter-rvc/src/init.lua @@ -50,6 +50,8 @@ local OPERATING_STATE_MAP = { [clus_rvc_op_enum.DOCKED] = cap_op_enum.docked } +local DEBOUNCE_DELAY_S = 1 -- wait for both sources(OperationalState and RvcRunMode) to settle + local subscribed_attributes = { [capabilities.mode.ID] = { clusters.RvcRunMode.attributes.SupportedModes, @@ -292,12 +294,14 @@ local function run_mode_current_mode_handler(driver, device, ib, response) device:set_field(CURRENT_RUN_MODE, current_run_mode, { persist = true }) -- Update supported mode - local current_state = device:get_latest_state( - "main", - capabilities.robotCleanerOperatingState.ID, - capabilities.robotCleanerOperatingState.operatingState.NAME - ) - update_supported_arguments(device, ib.endpoint_id, current_run_mode, current_state) + device.thread:call_with_delay(DEBOUNCE_DELAY_S, function() + local current_state = device:get_latest_state( + "main", + capabilities.robotCleanerOperatingState.ID, + capabilities.robotCleanerOperatingState.operatingState.NAME + ) + update_supported_arguments(device, ib.endpoint_id, current_run_mode, current_state) + end) end local function clean_mode_supported_mode_handler(driver, device, ib, response) @@ -336,13 +340,15 @@ local function rvc_operational_state_attr_handler(driver, device, ib, response) device:emit_event_for_endpoint(ib.endpoint_id, OPERATING_STATE_MAP[ib.data.value]()) end - -- Supported Mode update - local current_run_mode = device:get_field(CURRENT_RUN_MODE) - if ib.data.value ~= clus_op_enum.ERROR then - update_supported_arguments(device, ib.endpoint_id, current_run_mode, OPERATING_STATE_MAP[ib.data.value].NAME) - else - update_supported_arguments(device, ib.endpoint_id, current_run_mode, "Error") - end + -- Update supported mode + device.thread:call_with_delay(DEBOUNCE_DELAY_S, function() + local current_run_mode = device:get_field(CURRENT_RUN_MODE) + if ib.data.value ~= clus_op_enum.ERROR then + update_supported_arguments(device, ib.endpoint_id, current_run_mode, OPERATING_STATE_MAP[ib.data.value].NAME) + else + update_supported_arguments(device, ib.endpoint_id, current_run_mode, "Error") + end + end) end local function rvc_operational_error_attr_handler(driver, device, ib, response) From 2985cc634a40e27494950295ce861a4b77d826d6 Mon Sep 17 00:00:00 2001 From: Hunsup Jung Date: Wed, 2 Sep 2026 14:33:46 +0900 Subject: [PATCH 2/2] Modify test case to add debounce delay Signed-off-by: Hunsup Jung --- .../matter-rvc/src/test/test_matter_rvc.lua | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/drivers/SmartThings/matter-rvc/src/test/test_matter_rvc.lua b/drivers/SmartThings/matter-rvc/src/test/test_matter_rvc.lua index e1c95249a8..f26a3c5083 100644 --- a/drivers/SmartThings/matter-rvc/src/test/test_matter_rvc.lua +++ b/drivers/SmartThings/matter-rvc/src/test/test_matter_rvc.lua @@ -260,6 +260,9 @@ test.register_coroutine_test( IDLE_MODE.mode ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -291,6 +294,9 @@ test.register_coroutine_test( CLEANING_MODE.mode ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -319,6 +325,9 @@ test.register_coroutine_test( MAPPING_MODE.mode ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -396,6 +405,9 @@ test.register_coroutine_test( IDLE_MODE.mode ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -437,6 +449,9 @@ test.register_coroutine_test( CLEANING_MODE.mode ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -475,6 +490,9 @@ test.register_coroutine_test( CLEANING_MODE.mode ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -484,6 +502,7 @@ test.register_coroutine_test( ) ) ) + test.wait_for_events() test.socket.matter:__queue_receive({ mock_device.id, clusters.RvcOperationalState.server.attributes.OperationalState:build_test_report_data( @@ -498,6 +517,9 @@ test.register_coroutine_test( capabilities.robotCleanerOperatingState.operatingState.running() ) ) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -538,6 +560,9 @@ test.register_coroutine_test( IDLE_MODE.mode ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -550,6 +575,7 @@ test.register_coroutine_test( ) ) ) + test.wait_for_events() test.socket.matter:__queue_receive({ mock_device.id, clusters.RvcOperationalState.server.attributes.OperationalState:build_test_report_data( @@ -564,6 +590,9 @@ test.register_coroutine_test( capabilities.robotCleanerOperatingState.operatingState.running() ) ) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -592,6 +621,9 @@ test.register_coroutine_test( IDLE_MODE.mode ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -604,6 +636,7 @@ test.register_coroutine_test( ) ) ) + test.wait_for_events() test.socket.matter:__queue_receive({ mock_device.id, clusters.RvcOperationalState.server.attributes.OperationalState:build_test_report_data( @@ -618,6 +651,9 @@ test.register_coroutine_test( capabilities.robotCleanerOperatingState.operatingState.paused() ) ) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -649,6 +685,9 @@ test.register_coroutine_test( IDLE_MODE.mode ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -661,6 +700,7 @@ test.register_coroutine_test( ) ) ) + test.wait_for_events() test.socket.matter:__queue_receive({ mock_device.id, clusters.RvcOperationalState.server.attributes.OperationalState:build_test_report_data( @@ -675,6 +715,9 @@ test.register_coroutine_test( capabilities.robotCleanerOperatingState.operatingState.seekingCharger() ) ) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -706,6 +749,9 @@ test.register_coroutine_test( IDLE_MODE.mode ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -718,6 +764,7 @@ test.register_coroutine_test( ) ) ) + test.wait_for_events() test.socket.matter:__queue_receive({ mock_device.id, clusters.RvcOperationalState.server.attributes.OperationalState:build_test_report_data( @@ -732,6 +779,9 @@ test.register_coroutine_test( capabilities.robotCleanerOperatingState.operatingState.charging() ) ) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -760,6 +810,9 @@ test.register_coroutine_test( IDLE_MODE.mode ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -772,6 +825,7 @@ test.register_coroutine_test( ) ) ) + test.wait_for_events() test.socket.matter:__queue_receive({ mock_device.id, clusters.RvcOperationalState.server.attributes.OperationalState:build_test_report_data( @@ -786,6 +840,9 @@ test.register_coroutine_test( capabilities.robotCleanerOperatingState.operatingState.docked() ) ) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -814,6 +871,9 @@ test.register_coroutine_test( IDLE_MODE.mode ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -826,6 +886,7 @@ test.register_coroutine_test( ) ) ) + test.wait_for_events() test.socket.matter:__queue_receive({ mock_device.id, clusters.RvcOperationalState.server.attributes.OperationalState:build_test_report_data( @@ -834,6 +895,9 @@ test.register_coroutine_test( clusters.OperationalState.types.OperationalStateEnum.ERROR ) }) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.wait_for_events() + test.mock_time.advance_time(1) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", @@ -843,6 +907,7 @@ test.register_coroutine_test( ) ) ) + test.wait_for_events() test.socket.matter:__queue_receive({ mock_device.id, clusters.RvcOperationalState.server.attributes.OperationalError:build_test_report_data(