diff --git a/examples/chip-tool/commands/interactive/InteractiveCommands.cpp b/examples/chip-tool/commands/interactive/InteractiveCommands.cpp index 41fcf731ebc7a3..6dae09ce392206 100644 --- a/examples/chip-tool/commands/interactive/InteractiveCommands.cpp +++ b/examples/chip-tool/commands/interactive/InteractiveCommands.cpp @@ -65,6 +65,7 @@ struct InteractiveServerResult { bool mEnabled = false; bool mIsAsyncReport = false; + uint16_t mTimeout = 0; int mStatus = EXIT_SUCCESS; std::vector mResults; std::vector mLogs; @@ -92,18 +93,31 @@ struct InteractiveServerResult // protected by a mutex. std::mutex mMutex; - void Setup(bool isAsyncReport) + void Setup(bool isAsyncReport, uint16_t timeout) { auto lock = ScopedLock(mMutex); mEnabled = true; mIsAsyncReport = isAsyncReport; + mTimeout = timeout; + + if (mIsAsyncReport && mTimeout) + { + chip::DeviceLayer::PlatformMgr().ScheduleWork(StartAsyncTimeout, reinterpret_cast(this)); + } } void Reset() { - auto lock = ScopedLock(mMutex); + auto lock = ScopedLock(mMutex); + + if (mIsAsyncReport && mTimeout) + { + chip::DeviceLayer::PlatformMgr().ScheduleWork(StopAsyncTimeout, reinterpret_cast(this)); + } + mEnabled = false; mIsAsyncReport = false; + mTimeout = 0; mStatus = EXIT_SUCCESS; mResults.clear(); mLogs.clear(); @@ -204,6 +218,24 @@ struct InteractiveServerResult content << "}"; return content.str(); } + + static void StartAsyncTimeout(intptr_t arg) + { + auto self = reinterpret_cast(arg); + auto timeout = chip::System::Clock::Seconds16(self->mTimeout); + chip::DeviceLayer::SystemLayer().StartTimer(timeout, OnAsyncTimeout, self); + } + + static void StopAsyncTimeout(intptr_t arg) + { + auto self = reinterpret_cast(arg); + chip::DeviceLayer::SystemLayer().CancelTimer(OnAsyncTimeout, self); + } + + static void OnAsyncTimeout(chip::System::Layer *, void * appState) + { + RemoteDataModelLogger::LogErrorAsJSON(CHIP_ERROR_TIMEOUT); + } }; InteractiveServerResult gInteractiveServerResult; @@ -263,7 +295,19 @@ CHIP_ERROR InteractiveServerCommand::RunCommand() bool InteractiveServerCommand::OnWebSocketMessageReceived(char * msg) { bool isAsyncReport = strlen(msg) == 0; - gInteractiveServerResult.Setup(isAsyncReport); + uint16_t timeout = 0; + if (!isAsyncReport && strlen(msg) <= 5 /* Only look for numeric values <= 65535 */) + { + std::stringstream ss; + ss << msg; + ss >> timeout; + if (!ss.fail()) + { + isAsyncReport = true; + } + } + + gInteractiveServerResult.Setup(isAsyncReport, timeout); VerifyOrReturnValue(!isAsyncReport, true); auto shouldStop = ParseCommand(msg, &gInteractiveServerResult.mStatus); diff --git a/examples/chip-tool/py_matter_chip_tool_adapter/matter_chip_tool_adapter/encoder.py b/examples/chip-tool/py_matter_chip_tool_adapter/matter_chip_tool_adapter/encoder.py index 7371fb6b0fa3bb..8340289c0e2852 100644 --- a/examples/chip-tool/py_matter_chip_tool_adapter/matter_chip_tool_adapter/encoder.py +++ b/examples/chip-tool/py_matter_chip_tool_adapter/matter_chip_tool_adapter/encoder.py @@ -197,7 +197,7 @@ def encode(self, request): command, command_specifier = self.__get_command_name(request) if command == 'wait-for-report': - return '' + return str(request.timeout) if request.timeout is not None else '' arguments = self.__get_arguments(request) base64_arguments = base64.b64encode( @@ -270,6 +270,8 @@ def __get_arguments(self, request): arguments, request.max_interval, "max-interval") arguments = self.__maybe_add(arguments, request.timed_interaction_timeout_ms, "timedInteractionTimeoutMs") + arguments = self.__maybe_add( + arguments, request.timeout, "timeout") arguments = self.__maybe_add( arguments, request.event_number, "event-min") arguments = self.__maybe_add( diff --git a/scripts/py_matter_yamltests/matter_yamltests/parser.py b/scripts/py_matter_yamltests/matter_yamltests/parser.py index ed99851b735e34..82b798a85156a4 100644 --- a/scripts/py_matter_yamltests/matter_yamltests/parser.py +++ b/scripts/py_matter_yamltests/matter_yamltests/parser.py @@ -201,6 +201,7 @@ def __init__(self, test: dict, config: dict, definitions: SpecDefinitions, pics_ self.max_interval = _value_or_none(test, 'maxInterval') self.timed_interaction_timeout_ms = _value_or_none( test, 'timedInteractionTimeoutMs') + self.timeout = _value_or_none(test, 'timeout') self.data_version = _value_or_none( test, 'dataVersion') self.busy_wait_ms = _value_or_none(test, 'busyWaitMs') @@ -661,6 +662,10 @@ def max_interval(self): def timed_interaction_timeout_ms(self): return self._test.timed_interaction_timeout_ms + @property + def timeout(self): + return self._test.timeout + @property def data_version(self): return self._test.data_version diff --git a/scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py b/scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py index ae434e68b08fda..77bb6d78eff190 100644 --- a/scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py +++ b/scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py @@ -105,6 +105,7 @@ def __check_test_step(self, config: dict, content): 'response': (dict, list, str), # Can be a variable 'minInterval': int, 'maxInterval': int, + 'timeout': int, 'timedInteractionTimeoutMs': int, 'dataVersion': (list, int, str), # Can be a variable 'busyWaitMs': int,