Skip to content

Make the run command wait for Hub to get ready #30

Open
@lobodpav

Description

@lobodpav

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 --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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions