diff --git a/snap7/asio/__init__.py b/snap7/asio/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/snap7/asio/client.py b/snap7/asio/client.py new file mode 100644 index 00000000..a47415df --- /dev/null +++ b/snap7/asio/client.py @@ -0,0 +1,30 @@ +from functools import partial +from snap7.client import Client +from asyncio import get_running_loop +from concurrent.futures import ThreadPoolExecutor + + +class AsyncClient: + def __await__(self) -> "AsyncClient": + return self + + def __init__(self) -> None: + self.client = Client() + self.loop = get_running_loop() + self.pool = ThreadPoolExecutor() + + async def disconnect(self) -> None: + await self.loop.run_in_executor(self.pool, lambda: self.client.disconnect) + + async def destroy(self) -> None: + await self.loop.run_in_executor(self.pool, lambda: self.client.destroy) + + async def db_write(self, db_number: int, start: int, data: bytearray) -> int: + # func: Callable[[], int] = lambda: self.client.db_write(db_number, start, data) + func = partial(self.client.db_write, db_number, start, data) + result: int = await self.loop.run_in_executor(self.pool, func) # type: ignore + return result + + async def db_get(self, db_number: int) -> bytearray: + result: bytearray = await self.loop.run_in_executor(self.pool, lambda: self.client.db_get(db_number)) + return result diff --git a/tests/test_async_client.py b/tests/test_async_client.py new file mode 100644 index 00000000..cc87c0c6 --- /dev/null +++ b/tests/test_async_client.py @@ -0,0 +1,42 @@ +from snap7.asio.client import AsyncClient +from snap7.server import mainloop +from unittest import IsolatedAsyncioTestCase, main +from multiprocessing import Process +from time import sleep + + +class AsyncClientTest(IsolatedAsyncioTestCase): + process = None + + @classmethod + def setUpClass(cls) -> None: + cls.process = Process(target=mainloop) + cls.process.start() + sleep(2) # wait for server to start + + @classmethod + def tearDownClass(cls) -> None: + if cls.process: + cls.process.terminate() + cls.process.join(1) + if cls.process.is_alive(): + cls.process.kill() + + async def asyncSetUp(self) -> None: + self.client = AsyncClient() + + async def asyncTearDown(self) -> None: + await self.client.disconnect() + await self.client.destroy() + + async def test_db_write(self) -> None: + size = 40 + data = bytearray(size) + await self.client.db_write(db_number=1, start=0, data=data) + + async def test_db_get(self) -> None: + await self.client.db_get(db_number=1) + + +if __name__ == "__main__": + main() diff --git a/tests/test_client.py b/tests/test_client.py index 4a96cf31..996f4738 100755 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -96,18 +96,6 @@ def tearDown(self) -> None: self.client.disconnect() self.client.destroy() - def _as_check_loop(self, check_times: int = 20) -> int: - check_status = c_int(-1) - # preparing Server values - for i in range(check_times): - self.client.check_as_completion(check_status) - if check_status.value == 0: - break - time.sleep(0.5) - else: - raise TimeoutError(f"Async Request not finished after {check_times} times - Fail") - return check_status.value - def test_db_read(self) -> None: size = 40 start = 0