From bdf405dfcf7349943cd0d5b6c80430317efb2f15 Mon Sep 17 00:00:00 2001 From: Marcell Nagy Date: Mon, 13 May 2024 11:08:46 +0100 Subject: [PATCH] Add serial connection --- pyproject.toml | 7 +-- src/fastcs/connections/serial_connection.py | 54 +++++++++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 src/fastcs/connections/serial_connection.py diff --git a/pyproject.toml b/pyproject.toml index 4ab1226c..012c367c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,12 +10,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", ] description = "Control system agnostic framework for building Device support in Python that will work for both EPICS and Tango" -dependencies = [ - "numpy", - "pydantic", - "pvi~=0.8.1", - "softioc", -] +dependencies = ["aioserial", "numpy", "pydantic", "pvi~=0.8.1", "softioc"] dynamic = ["version"] license.file = "LICENSE" readme = "README.md" diff --git a/src/fastcs/connections/serial_connection.py b/src/fastcs/connections/serial_connection.py new file mode 100644 index 00000000..f62b15d8 --- /dev/null +++ b/src/fastcs/connections/serial_connection.py @@ -0,0 +1,54 @@ +import asyncio +from dataclasses import dataclass + +import aioserial + + +class NotOpenedError(Exception): + pass + + +@dataclass +class SerialConnectionSettings: + port: str + baud: int = 115200 + + +class SerialConnection: + def __init__(self): + self.aioserial_instance = None + self._lock = asyncio.Lock() + + async def connect(self, settings: SerialConnectionSettings) -> None: + self.aioserial_instance = aioserial.AioSerial( + port=settings.port, baudrate=settings.baud + ) + + def ensure_open(self): + if self.aioserial_instance is None: + raise NotOpenedError( + "Need to call connect() before using SerialConnection." + ) + + async def send_command(self, message: bytes) -> None: + async with self._lock: + self.ensure_open() + await self._send_message(message) + + async def send_query(self, message: bytes, response_size: int) -> bytes: + async with self._lock: + self.ensure_open() + await self._send_message(message) + return await self._receive_response(response_size) + + async def close(self) -> None: + async with self._lock: + self.ensure_open() + self.aioserial_instance.close() + self.aioserial_instance = None + + async def _send_message(self, message): + await self.aioserial_instance.write_async(message) + + async def _receive_response(self, size): + return await self.aioserial_instance.read_async(size)