Skip to content

Commit 6337ece

Browse files
committed
pybricksdev.connections.pybricks: add stdout_observable property
This adds a new property for subscribing to each received stdout notification. Fixes: https://github.com/orgs/pybricks/discussions/1038
1 parent a08db5f commit 6337ece

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
### Added
10+
- Added `PybricksHub.stdout_observable` property ([support#1038]).
11+
912
### Fixed
1013
- Fixed endline in `PybricksHub.write_line()`.
1114

15+
[support#1038]: https://github.com/orgs/pybricks/discussions/1038
16+
1217
## [1.0.0-alpha.44] - 2023-04-20
1318

1419
### Fixed

pybricksdev/connections/pybricks.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from bleak import BleakClient
1414
from bleak.backends.device import BLEDevice
1515
from packaging.version import Version
16+
from reactivex import Observable
1617
from reactivex.subject import BehaviorSubject, Subject
1718
from tqdm.auto import tqdm
1819
from tqdm.contrib.logging import logging_redirect_tqdm
@@ -80,6 +81,7 @@ class PybricksHub:
8081
def __init__(self):
8182
self.connection_state_observable = BehaviorSubject(ConnectionState.DISCONNECTED)
8283
self.status_observable = BehaviorSubject(StatusFlag(0))
84+
self._stdout_subject = Subject()
8385
self.nus_observable = Subject()
8486
self.print_output = True
8587
self.fw_version = None
@@ -118,6 +120,13 @@ def __init__(self):
118120
# File handle for logging
119121
self.log_file = None
120122

123+
@property
124+
def stdout_observable(self) -> Observable[bytes]:
125+
"""
126+
Observable used to subscribe to stdout of the hub.
127+
"""
128+
return self._stdout_subject
129+
121130
def _line_handler(self, line: bytes) -> None:
122131
"""
123132
Handles new incoming lines. Handle special actions if needed,
@@ -201,6 +210,8 @@ def _nus_handler(self, sender, data: bytearray) -> None:
201210
# support legacy firmware where the Nordic UART service
202211
# was used for stdio
203212
if self._legacy_stdio:
213+
self._stdout_subject.on_next(data)
214+
204215
if self._enable_line_handler:
205216
self._handle_line_data(data)
206217

@@ -211,6 +222,7 @@ def _pybricks_service_handler(self, _: int, data: bytes) -> None:
211222
self.status_observable.on_next(StatusFlag(flags))
212223
elif data[0] == Event.WRITE_STDOUT:
213224
payload = data[1:]
225+
self._stdout_subject.on_next(payload)
214226

215227
if self._enable_line_handler:
216228
self._handle_line_data(payload)
@@ -403,7 +415,17 @@ async def read_line(self) -> str:
403415
404416
Returns:
405417
The next line read from stdout (without the newline).
418+
419+
Raises:
420+
RuntimeError:
421+
if line handler is disabled (e.g. :meth:`run` is
422+
called with ``line_handler=False``)
423+
RuntimeError:
424+
if hub becomes disconnected
406425
"""
426+
if not self._enable_line_handler:
427+
raise RuntimeError("line handler is disabled, method would block forever")
428+
407429
return await self.race_disconnect(self._stdout_line_queue.get())
408430

409431
async def start_user_program(self) -> None:

0 commit comments

Comments
 (0)