Skip to content

Commit

Permalink
Fix handling of lock in TCP connect and retry
Browse files Browse the repository at this point in the history
  • Loading branch information
mletenay committed May 3, 2024
1 parent 143ec25 commit 3041de9
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 25 deletions.
53 changes: 32 additions & 21 deletions goodwe/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,28 +239,36 @@ def error_received(self, exc: Exception) -> None:

async def send_request(self, command: ProtocolCommand) -> Future:
"""Send message via transport"""
async with self._ensure_lock():
try:
await self._connect()
response_future = asyncio.get_running_loop().create_future()
self._send_request(command, response_future)
await response_future
return response_future
except asyncio.CancelledError:
if self._retry < self.retries:
await self._ensure_lock().acquire()
try:
await self._connect()
response_future = asyncio.get_running_loop().create_future()
self._send_request(command, response_future)
await response_future
return response_future
except asyncio.CancelledError:
if self._retry < self.retries:
if self._timer:
logger.debug("Connection broken error")
self._retry += 1
self._close_transport()
return await self.send_request(command)
else:
return self._max_retries_reached()
except ConnectionRefusedError as exc:
if self._retry < self.retries:
logger.debug("Connection refused error: %s", exc)
self._retry += 1
return await self.send_request(command)
else:
return self._max_retries_reached()
self._retry += 1
if self._lock and self._lock.locked():
self._lock.release()
self._close_transport()
return await self.send_request(command)
else:
return self._max_retries_reached()
except ConnectionRefusedError as exc:
if self._retry < self.retries:
logger.debug("Connection refused error: %s", exc)
self._retry += 1
if self._lock and self._lock.locked():
self._lock.release()
return await self.send_request(command)
else:
return self._max_retries_reached()
finally:
if self._lock and self._lock.locked():
self._lock.release()

def _send_request(self, command: ProtocolCommand, response_future: Future) -> None:
"""Send message via transport"""
Expand All @@ -276,6 +284,9 @@ def _timeout_mechanism(self) -> None:
if self.response_future.done():
self._retry = 0
else:
if self._timer:
logger.debug("Failed to receive response to %s in time (%ds).", self.command, self.timeout)
self._timer = None
self._close_transport()

def _max_retries_reached(self) -> Future:
Expand Down
16 changes: 12 additions & 4 deletions tests/inverter_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,26 @@
# print(asyncio.run(inverter.read_setting('grid_export_limit')))

# -------------------------------
# Execute modbus protocol command
# Execute modbus RTU protocol command
# -------------------------------
# response = asyncio.run(goodwe.protocol.ModbusReadCommand(COMM_ADDR, 0x88b8, 0x21).execute(IP_ADDRESS, TIMEOUT, RETRIES))
# response = asyncio.run(goodwe.protocol.ModbusRtuReadCommand(COMM_ADDR, 0x88b8, 0x21).execute(
# goodwe.protocol.UdpInverterProtocol(IP_ADDRESS, PORT, TIMEOUT, RETRIES)))
# print(response)

# -------------------------------
# Execute modbus TCP protocol command
# -------------------------------
# response = asyncio.run(goodwe.protocol.ModbusTcpReadCommand(180, 301, 3).execute(
# goodwe.protocol.TcpInverterProtocol('192.168.1.13', 502, TIMEOUT, RETRIES)))
# print(response.response_data().hex())

# -------------------------------
# Execute AA55 protocol command
# -------------------------------
# response = asyncio.run(goodwe.protocol.Aa55ProtocolCommand("010200", "0182").execute(IP_ADDRESS, TIMEOUT, RETRIES))
# response = asyncio.run(goodwe.protocol.Aa55ProtocolCommand("010200", "0182").execute(
# goodwe.protocol.UdpInverterProtocol(IP_ADDRESS, PORT, TIMEOUT, RETRIES)))
# print(response)


# -----------------
# Test parallel requests
#
Expand Down

0 comments on commit 3041de9

Please sign in to comment.