1313from bleak import BleakClient
1414from bleak .backends .device import BLEDevice
1515from packaging .version import Version
16+ from reactivex import Observable
1617from reactivex .subject import BehaviorSubject , Subject
1718from tqdm .auto import tqdm
1819from 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