Skip to content

Commit f088c1a

Browse files
committed
minor stability changes to the behavior when using the stay-connected arg
1 parent 3bec955 commit f088c1a

File tree

2 files changed

+42
-12
lines changed

2 files changed

+42
-12
lines changed

pybricksdev/cli/__init__.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -303,22 +303,12 @@ async def reconnect_hub():
303303
# current program, so the menu was canceled and we are now printing
304304
# the hub stdout until the user program ends on the hub.
305305
try:
306-
await hub._wait_for_user_program_stop(
307-
2.25, raise_error_on_timeout=True
308-
)
306+
await hub._wait_for_power_button_release()
307+
await hub._wait_for_user_program_stop()
309308

310309
except HubDisconnectError:
311310
hub = await reconnect_hub()
312311

313-
except asyncio.TimeoutError:
314-
# On windows, it can take significantly longer
315-
# for the device to register that the hub was
316-
# disconnected. If _wait_for_user_program_stop
317-
# throws a timeout error, we can assume that the
318-
# hub was disconnected.
319-
await hub.disconnect()
320-
hub = await reconnect_hub()
321-
322312
except HubDisconnectError:
323313
# let terminal cool off before making a new prompt
324314
await asyncio.sleep(0.3)

pybricksdev/connections/pybricks.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,46 @@ def handle_power_button_press(status: StatusFlag):
741741
)
742742
return awaitable_task.result()
743743

744+
async def _wait_for_power_button_release(
745+
self, program_start_timeout=1, raise_error_on_timeout=False
746+
):
747+
power_button_pressed: asyncio.Queue[bool] = asyncio.Queue()
748+
749+
with self.status_observable.pipe(
750+
op.map(lambda s: bool(s & StatusFlag.POWER_BUTTON_PRESSED)),
751+
op.distinct_until_changed(),
752+
).subscribe(lambda s: power_button_pressed.put_nowait(s)):
753+
# The first item in the queue is the current status. The status
754+
# could change before or after the last checksum is received,
755+
# so this could be either true or false.
756+
is_pressed = await self.race_disconnect(power_button_pressed.get())
757+
758+
if not is_pressed:
759+
# If the button isn't already pressed,
760+
# wait a short time for it to become pressed
761+
try:
762+
await asyncio.wait_for(
763+
self.race_disconnect(power_button_pressed.get()),
764+
program_start_timeout,
765+
)
766+
except asyncio.TimeoutError:
767+
if raise_error_on_timeout:
768+
raise
769+
# If the button never shows as pressed,
770+
# assume that we just missed the status flag
771+
logger.debug(
772+
"timed out waiting for power button press, assuming is was a short press"
773+
)
774+
return
775+
776+
# At this point, we know the button is pressed, so the
777+
# next item in the queue must indicate the button has
778+
# been released.
779+
is_pressed = await self.race_disconnect(power_button_pressed.get())
780+
781+
# maybe catch mistake if the code is changed
782+
assert not is_pressed
783+
744784
async def _wait_for_user_program_stop(
745785
self, program_start_timeout=1, raise_error_on_timeout=False
746786
):

0 commit comments

Comments
 (0)