1
0
forked from M-Labs/kirdy

driver: Add lock for tcp writer & reader stream

This commit is contained in:
linuswck 2024-04-02 13:19:40 +08:00
parent 6d107d55cf
commit 09863353cd

View File

@ -87,10 +87,11 @@ Filter_Config = {
} }
class Device: 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_cmd = send_cmd_handler
self._send_raw_cmd = send_raw_cmd_handler self._send_raw_cmd = send_raw_cmd_handler
self._read_response = read_response 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]): 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:
} }
} }
""" """
retry = 0
response = await self._send_cmd(TARGET_DEVICE, "GetStatusReport") while(retry < 3):
if response["msg_type"] != "Acknowledge": response = await self._send_cmd(TARGET_DEVICE, "GetStatusReport")
return response if response["msg_type"] != "Acknowledge":
return await self._read_response() 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): async def get_settings_summary(self):
""" """
@ -263,8 +270,9 @@ class Device:
return await self._send_cmd(TARGET_DEVICE, "HardReset") return await self._send_cmd(TARGET_DEVICE, "HardReset")
class Laser: class Laser:
def __init__(self, send_cmd_handler): def __init__(self, send_cmd_handler, cmd_lock):
self._send_cmd = send_cmd_handler self._send_cmd = send_cmd_handler
self._cmd_lock = cmd_lock
async def set_power_on(self, on): async def set_power_on(self, on):
""" """
@ -313,10 +321,12 @@ class Laser:
- responsitivity: A/W - responsitivity: A/W
- dark current: A - dark current: A
""" """
response = await self._send_cmd(TARGET_LD, "SetPdResponsitivity", responsitivity) async with self._cmd_lock:
if response["msg_type"] != "Acknowledge": response = await self._send_cmd(TARGET_LD, "SetPdResponsitivity", responsitivity, lock=False)
return response print(response)
return await self._send_cmd(TARGET_LD, "SetPdDarkCurrent", dark_current) 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): async def set_ld_pwr_limit(self, pwr_limit):
""" """
@ -334,10 +344,10 @@ class Laser:
return await self._send_cmd(TARGET_LD, "ClearAlarm") return await self._send_cmd(TARGET_LD, "ClearAlarm")
class Thermostat: 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_cmd = send_cmd_handler
self._send_raw_cmd = send_raw_cmd_handler self._send_raw_cmd = send_raw_cmd_handler
self._cmd_lock = cmd_lock
async def set_power_on(self, on): async def set_power_on(self, on):
""" """
Power up or power down thermostat Power up or power down thermostat
@ -522,9 +532,9 @@ class Kirdy:
self._cmd_lock = asyncio.Lock() self._cmd_lock = asyncio.Lock()
self._report_mode_on = False self._report_mode_on = False
self.timeout = None self.timeout = None
self.device = Device(self._send_cmd_handler, self._send_raw_cmd_handler, self._read_response) 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.laser = Laser(self._send_cmd_handler, self._cmd_lock)
self.thermostat = Thermostat(self._send_cmd_handler, self._send_raw_cmd_handler) self.thermostat = Thermostat(self._send_cmd_handler, self._send_raw_cmd_handler, self._cmd_lock)
self._cmd_list = { self._cmd_list = {
TARGET_DEVICE: { TARGET_DEVICE: {
@ -646,21 +656,37 @@ class Kirdy:
pass pass
return { "msg_type": "Internal No json object found in response" } 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, # If the cmd involves a cmd specific data type,
# checking is done separately within the functions being called # 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 retry = 0
while retry < 10: while retry < 10:
self._writer.write(bytes(json.dumps(cmd), "UTF-8")) self._writer.write(bytes(json.dumps(cmd), "UTF-8"))
await self._writer.drain() await self._writer.drain()
response = await self._read_response() response = await self._read_response()
if response["msg_type"] == "Acknowledge": try:
return response if response["msg_type"] == "Acknowledge":
retry += 1 return response
await asyncio.sleep(0.1) except:
retry += 1
await asyncio.sleep(0.1)
raise NoAckRecv 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 = {} cmd_dict = {}
if not(target in self._cmd_list.keys()) or not(cmd in self._cmd_list[target].keys()): 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")) self._writer.write(bytes(json.dumps(cmd_dict), "UTF-8"))
await self._writer.drain() await self._writer.drain()
response = await self._read_response() response = await self._read_response()
if response["msg_type"] == "Acknowledge": try:
return response if response["msg_type"] == "Acknowledge":
retry += 1 return response
await asyncio.sleep(0.1) except:
retry += 1
await asyncio.sleep(0.1)
raise NoAckRecv raise NoAckRecv
async def report_mode(self, report_interval = 0.0, buffer_size = 16384): async def report_mode(self, report_interval = 0.0, buffer_size = 16384):