jmri_dccex.transport
Byte-stream transport for DCC-EX — same shape as the other drivers.
1"""Byte-stream transport for DCC-EX — same shape as the other drivers.""" 2from jmri_dccex.transport.loopback import LoopbackPort, loopback_pair 3from jmri_dccex.transport.port import BytePort 4from jmri_dccex.transport.serial_port import SerialPort 5from jmri_dccex.transport.tcp_port import TcpPort 6 7__all__ = ["BytePort", "LoopbackPort", "SerialPort", "TcpPort", "loopback_pair"]
class
BytePort(abc.ABC):
8class BytePort(ABC): 9 @abstractmethod 10 async def write(self, data: bytes) -> None: ... 11 @abstractmethod 12 async def read_byte(self) -> int: ... 13 @abstractmethod 14 async def aclose(self) -> None: ... 15 @property 16 @abstractmethod 17 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.
17class SerialPort(BytePort): 18 def __init__(self, reader: StreamReader, writer: StreamWriter) -> None: 19 self._reader = reader 20 self._writer = writer 21 self._open = True 22 23 @classmethod 24 async def open(cls, port: str, baud: int = DEFAULT_BAUD) -> SerialPort: 25 import serial_asyncio # noqa: PLC0415 26 reader, writer = await serial_asyncio.open_serial_connection(url=port, baudrate=baud) 27 return cls(reader=reader, writer=writer) 28 29 async def write(self, data: bytes) -> None: 30 if not self._open: 31 raise RuntimeError("port is closed") 32 self._writer.write(data) 33 await self._writer.drain() 34 35 async def read_byte(self) -> int: 36 data = await self._reader.readexactly(1) 37 return data[0] 38 39 async def aclose(self) -> None: 40 if not self._open: 41 return 42 self._open = False 43 self._writer.close() 44 with contextlib.suppress(Exception): 45 await self._writer.wait_closed() 46 47 @property 48 def is_open(self) -> bool: 49 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.