From 09863353cd5683b6e8b9802663e83af43c9a736c Mon Sep 17 00:00:00 2001 From: linuswck Date: Tue, 2 Apr 2024 13:19:40 +0800 Subject: [PATCH] driver: Add lock for tcp writer & reader stream --- pykirdy/driver/kirdy_async.py | 80 +++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 26 deletions(-) diff --git a/pykirdy/driver/kirdy_async.py b/pykirdy/driver/kirdy_async.py index f0f0a7e..2c78cdf 100644 --- a/pykirdy/driver/kirdy_async.py +++ b/pykirdy/driver/kirdy_async.py @@ -87,10 +87,11 @@ Filter_Config = { } class Device: - def __init__(self, send_cmd_handler, send_raw_cmd_handler, read_response): + def __init__(self, send_cmd_handler, send_raw_cmd_handler, read_response, cmd_lock): self._send_cmd = send_cmd_handler self._send_raw_cmd = send_raw_cmd_handler self._read_response = read_response + self._cmd_lock = cmd_lock async def set_ip_settings(self, addr=[192, 168, 1, 128], port=1337, prefix_len=24, gateway=[192, 168, 1, 1]): """ @@ -154,11 +155,17 @@ class Device: } } """ - - response = await self._send_cmd(TARGET_DEVICE, "GetStatusReport") - if response["msg_type"] != "Acknowledge": - return response - return await self._read_response() + retry = 0 + while(retry < 3): + response = await self._send_cmd(TARGET_DEVICE, "GetStatusReport") + if response["msg_type"] != "Acknowledge": + return response + status_report = await self._read_response() + if "ts" in status_report: + return status_report + else: + retry += 1 + return None async def get_settings_summary(self): """ @@ -263,8 +270,9 @@ class Device: return await self._send_cmd(TARGET_DEVICE, "HardReset") class Laser: - def __init__(self, send_cmd_handler): + def __init__(self, send_cmd_handler, cmd_lock): self._send_cmd = send_cmd_handler + self._cmd_lock = cmd_lock async def set_power_on(self, on): """ @@ -313,10 +321,12 @@ class Laser: - responsitivity: A/W - dark current: A """ - response = await self._send_cmd(TARGET_LD, "SetPdResponsitivity", responsitivity) - if response["msg_type"] != "Acknowledge": - return response - return await self._send_cmd(TARGET_LD, "SetPdDarkCurrent", dark_current) + async with self._cmd_lock: + response = await self._send_cmd(TARGET_LD, "SetPdResponsitivity", responsitivity, lock=False) + print(response) + if response["msg_type"] != "Acknowledge": + return response + return await self._send_cmd(TARGET_LD, "SetPdDarkCurrent", dark_current, lock=False) async def set_ld_pwr_limit(self, pwr_limit): """ @@ -334,10 +344,10 @@ class Laser: return await self._send_cmd(TARGET_LD, "ClearAlarm") class Thermostat: - def __init__(self, send_cmd_handler, send_raw_cmd_handler): + def __init__(self, send_cmd_handler, send_raw_cmd_handler, cmd_lock): self._send_cmd = send_cmd_handler self._send_raw_cmd = send_raw_cmd_handler - + self._cmd_lock = cmd_lock async def set_power_on(self, on): """ Power up or power down thermostat @@ -522,9 +532,9 @@ class Kirdy: self._cmd_lock = asyncio.Lock() self._report_mode_on = False self.timeout = None - self.device = Device(self._send_cmd_handler, self._send_raw_cmd_handler, self._read_response) - self.laser = Laser(self._send_cmd_handler) - self.thermostat = Thermostat(self._send_cmd_handler, self._send_raw_cmd_handler) + self.device = Device(self._send_cmd_handler, self._send_raw_cmd_handler, self._read_response, self._cmd_lock) + self.laser = Laser(self._send_cmd_handler, self._cmd_lock) + self.thermostat = Thermostat(self._send_cmd_handler, self._send_raw_cmd_handler, self._cmd_lock) self._cmd_list = { TARGET_DEVICE: { @@ -646,21 +656,37 @@ class Kirdy: pass return { "msg_type": "Internal No json object found in response" } + async def _send_raw_cmd_handler(self, cmd, lock=True): + if lock: + async with self._cmd_lock: + return await asyncio.shield(self._send_raw_cmd(cmd)) + else: + return await asyncio.shield(self._send_raw_cmd(cmd)) + # If the cmd involves a cmd specific data type, # checking is done separately within the functions being called - async def _send_raw_cmd_handler(self, cmd): + async def _send_raw_cmd(self, cmd): retry = 0 while retry < 10: self._writer.write(bytes(json.dumps(cmd), "UTF-8")) await self._writer.drain() response = await self._read_response() - if response["msg_type"] == "Acknowledge": - return response - retry += 1 - await asyncio.sleep(0.1) + try: + if response["msg_type"] == "Acknowledge": + return response + except: + retry += 1 + await asyncio.sleep(0.1) raise NoAckRecv - async def _send_cmd_handler(self, target, cmd, data=None): + async def _send_cmd_handler(self, target, cmd, data=None, lock=True): + if lock: + async with self._cmd_lock: + return await asyncio.shield(self._send_cmd(target, cmd, data)) + else: + return await asyncio.shield(self._send_cmd(target, cmd, data)) + + async def _send_cmd(self, target, cmd, data): cmd_dict = {} if not(target in self._cmd_list.keys()) or not(cmd in self._cmd_list[target].keys()): @@ -688,10 +714,12 @@ class Kirdy: self._writer.write(bytes(json.dumps(cmd_dict), "UTF-8")) await self._writer.drain() response = await self._read_response() - if response["msg_type"] == "Acknowledge": - return response - retry += 1 - await asyncio.sleep(0.1) + try: + if response["msg_type"] == "Acknowledge": + return response + except: + retry += 1 + await asyncio.sleep(0.1) raise NoAckRecv async def report_mode(self, report_interval = 0.0, buffer_size = 16384):