Skip to content

Commit

Permalink
feat: send_and_receive is atomic
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuafishman committed Sep 12, 2023
1 parent 2e49daa commit 39e2fa3
Showing 1 changed file with 23 additions and 16 deletions.
39 changes: 23 additions & 16 deletions adam_modbus/interface.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import asyncio
import socket
from collections import defaultdict
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from dataclasses import dataclass
from typing import Literal
from typing import ClassVar, Literal


class AdamConnectionError(RuntimeError):
Expand All @@ -22,22 +23,28 @@ class AdamConnection:
timeout: float = ADAM_CONNECTION_TIMEOUT
model: str | None = None

async def _send_and_receive(self, message: str) -> str:
loop = asyncio.get_running_loop()
# ClassVar so it's shared among all AdamConnections
ADAM_CONNECTION_LOCKS: ClassVar = defaultdict[tuple[str, int], asyncio.Lock](
lambda: asyncio.Lock()
)

try:
await asyncio.wait_for(
loop.sock_sendall(self.socket, message.encode("ascii")),
self.timeout,
)
adam_out = await asyncio.wait_for(
loop.sock_recv(self.socket, 100), self.timeout
)
except asyncio.TimeoutError:
raise AdamConnectionError("ADAM connection timed out")

response = adam_out.decode().strip()
return response
async def _send_and_receive(self, message: str) -> str:
async with self.ADAM_CONNECTION_LOCKS[(self.ip, self.port)]:
loop = asyncio.get_running_loop()

try:
await asyncio.wait_for(
loop.sock_sendall(self.socket, message.encode("ascii")),
self.timeout,
)
adam_out = await asyncio.wait_for(
loop.sock_recv(self.socket, 100), self.timeout
)
except asyncio.TimeoutError:
raise AdamConnectionError("ADAM connection timed out")

response = adam_out.decode().strip()
return response

async def set_digital_out(
self,
Expand Down

0 comments on commit 39e2fa3

Please sign in to comment.