jmri_openlcb.transport
OpenLCB byte-stream transport.
1"""OpenLCB byte-stream transport.""" 2from jmri_openlcb.transport.loopback import LoopbackPort, loopback_pair 3from jmri_openlcb.transport.port import BytePort 4from jmri_openlcb.transport.serial_port import SerialPort 5from jmri_openlcb.transport.tcp_port import TcpPort 6 7__all__ = ["BytePort", "LoopbackPort", "SerialPort", "TcpPort", "loopback_pair"]
class
BytePort(abc.ABC):
7class BytePort(ABC): 8 @abstractmethod 9 async def write(self, data: bytes) -> None: ... 10 @abstractmethod 11 async def read_byte(self) -> int: ... 12 @abstractmethod 13 async def aclose(self) -> None: ... 14 @property 15 @abstractmethod 16 def is_open(self) -> bool: ...
Helper class that provides a standard way to create an ABC using inheritance.
9class LoopbackPort(BytePort): 10 def __init__(self, read_q: asyncio.Queue[int], write_q: asyncio.Queue[int]) -> None: 11 self._r = read_q 12 self._w = write_q 13 self._open = True 14 15 async def write(self, data: bytes) -> None: 16 if not self._open: 17 raise RuntimeError("port is closed") 18 for b in data: 19 await self._w.put(b) 20 21 async def read_byte(self) -> int: 22 return await self._r.get() 23 24 async def aclose(self) -> None: 25 self._open = False 26 27 @property 28 def is_open(self) -> bool: 29 return self._open
Helper class that provides a standard way to create an ABC using inheritance.
18class SerialPort(BytePort): 19 def __init__(self, reader: StreamReader, writer: StreamWriter) -> None: 20 self._reader = reader 21 self._writer = writer 22 self._open = True 23 24 @classmethod 25 async def open(cls, port: str, baud: int = DEFAULT_BAUD) -> SerialPort: 26 import serial_asyncio # noqa: PLC0415 27 reader, writer = await serial_asyncio.open_serial_connection(url=port, baudrate=baud) 28 return cls(reader=reader, writer=writer) 29 30 async def write(self, data: bytes) -> None: 31 if not self._open: 32 raise RuntimeError("port is closed") 33 self._writer.write(data) 34 await self._writer.drain() 35 36 async def read_byte(self) -> int: 37 data = await self._reader.readexactly(1) 38 return data[0] 39 40 async def aclose(self) -> None: 41 if not self._open: 42 return 43 self._open = False 44 self._writer.close() 45 with contextlib.suppress(Exception): 46 await self._writer.wait_closed() 47 48 @property 49 def is_open(self) -> bool: 50 return self._open
Helper class that provides a standard way to create an ABC using inheritance.
15class TcpPort(BytePort): 16 def __init__(self, reader: StreamReader, writer: StreamWriter) -> None: 17 self._reader = reader 18 self._writer = writer 19 self._open = True 20 21 @classmethod 22 async def open(cls, host: str, port: int) -> TcpPort: 23 reader, writer = await asyncio.open_connection(host, port) 24 return cls(reader=reader, writer=writer) 25 26 async def write(self, data: bytes) -> None: 27 if not self._open: 28 raise RuntimeError("port is closed") 29 self._writer.write(data) 30 await self._writer.drain() 31 32 async def read_byte(self) -> int: 33 data = await self._reader.readexactly(1) 34 return data[0] 35 36 async def aclose(self) -> None: 37 if not self._open: 38 return 39 self._open = False 40 self._writer.close() 41 with contextlib.suppress(Exception): 42 await self._writer.wait_closed() 43 44 @property 45 def is_open(self) -> bool: 46 return self._open
Helper class that provides a standard way to create an ABC using inheritance.