### Introduction When fine-tuning programs and running them via `pybricksdev`, I often run the program several times per minute. However, what happens to me frequently is that 1. the Hub is off (turns off itself after a certain inactivity period) 2. the Hub is running the old program when I forget to stop it by pressing the Hub's button In both cases, the execution fails and I have to either turn the Hub on or stop the program, and then re-run `pybricksdev run` command. It would be much more user firiendly if `pybricksdev` would handle these scenarios: 1. If the Hub is turned off while `pybricksdev run` is waiting for connection, the program should be loaded and executed once the Hub is turned on 2. If the Hub runs a program while `pybricksdev run` is executed, `pybricksdev` should 1. either wait a moment till the user stops the old running program and then load and run the new one 2. or even better, stop the old program and run the new one ### Environment macOS 12 Python 3.10.1 pybricksdev v1.0.0-alpha.24 Inventor Hub ### Replication steps 1. Switch off the Hub 2. Execute `pybricksdev run ble program.py` 3. Switch on the Hub 4. **Actual behaviour:** `asyncio.exceptions.TimeoutError` 5. **Expected behaviour:** The program should be uploaded and executed ### Stack trace ``` Traceback (most recent call last): File "/Users/pavel/.pyenv/versions/3.8.12/lib/python3.8/runpy.py", line 194, in _run_module_as_main return _run_code(code, main_globals, None, File "/Users/pavel/.pyenv/versions/3.8.12/lib/python3.8/runpy.py", line 87, in _run_code exec(code, run_globals) File "/Users/pavel/Git/Other/pybricksdev/pybricksdev/__main__.py", line 9, in <module> main() File "/Users/pavel/Git/Other/pybricksdev/pybricksdev/cli/__init__.py", line 374, in main asyncio.run(subparsers.choices[args.tool].tool.run(args)) File "/Users/pavel/.pyenv/versions/3.8.12/lib/python3.8/asyncio/runners.py", line 44, in run return loop.run_until_complete(main) File "/Users/pavel/.pyenv/versions/3.8.12/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete return future.result() File "/Users/pavel/Git/Other/pybricksdev/pybricksdev/cli/__init__.py", line 198, in run await hub.run(script_path, args.wait) File "/Users/pavel/Git/Other/pybricksdev/pybricksdev/connections.py", line 367, in run await self.send_block(length) File "/Users/pavel/Git/Other/pybricksdev/pybricksdev/connections.py", line 340, in send_block await asyncio.wait_for(self.checksum_ready.wait(), timeout=0.5) File "/Users/pavel/.pyenv/versions/3.8.12/lib/python3.8/asyncio/tasks.py", line 501, in wait_for raise exceptions.TimeoutError() asyncio.exceptions.TimeoutError ``` ### Analysis (`cli/__init__.py` and `connections.py`) 1. The `device_or_address = await find_device(args.name)` works with a default `10s` timeout 2. Increasing the `await asyncio.wait_for(self.checksum_ready.wait(), timeout=0.5)` timeout does not help 3. The `nus_handler` isn't caled at all for some reason, once the Hub is turned on 4. If I do sleep before a connection is made, everything works. ```diff diff --git a/pybricksdev/connections.py b/pybricksdev/connections.py index c56d1f4..520e8b3 100644 --- a/pybricksdev/connections.py +++ b/pybricksdev/connections.py @@ -291,6 +291,7 @@ class PybricksHub: logger.info("Disconnected!") self.connected = False + await asyncio.sleep(5) await self.client.connect(disconnected_callback=disconnected_handler) try: logger.info("Connected successfully!") ``` I've tried to fix the problem myself but failed. Would you guide me on how could I achieve the behaviour described in the `Introduction` section? Happy to code the stuff myself if that's possible.