Fix modbus transaction response (#33824)

Sometimes a modbus server do not respond to a transaction,
this is a contradiction to the modbus protocol specification,
but merely a matter of fact.

Use asynio.await_for() to provoke a timeout, and close the
transaction.
This commit is contained in:
jan iversen 2020-04-08 22:04:47 +02:00 committed by Paulus Schoutsen
parent 7eba08f385
commit 663c994dfb

View File

@ -2,6 +2,7 @@
import asyncio import asyncio
import logging import logging
from async_timeout import timeout
from pymodbus.client.asynchronous import schedulers from pymodbus.client.asynchronous import schedulers
from pymodbus.client.asynchronous.serial import AsyncModbusSerialClient as ClientSerial from pymodbus.client.asynchronous.serial import AsyncModbusSerialClient as ClientSerial
from pymodbus.client.asynchronous.tcp import AsyncModbusTCPClient as ClientTCP from pymodbus.client.asynchronous.tcp import AsyncModbusTCPClient as ClientTCP
@ -246,7 +247,12 @@ class ModbusHub:
await self._connect_delay() await self._connect_delay()
async with self._lock: async with self._lock:
kwargs = {"unit": unit} if unit else {} kwargs = {"unit": unit} if unit else {}
result = await func(address, count, **kwargs) try:
async with timeout(self._config_timeout):
result = await func(address, count, **kwargs)
except asyncio.TimeoutError:
result = None
if isinstance(result, (ModbusException, ExceptionResponse)): if isinstance(result, (ModbusException, ExceptionResponse)):
_LOGGER.error("Hub %s Exception (%s)", self._config_name, result) _LOGGER.error("Hub %s Exception (%s)", self._config_name, result)
return result return result
@ -256,7 +262,11 @@ class ModbusHub:
await self._connect_delay() await self._connect_delay()
async with self._lock: async with self._lock:
kwargs = {"unit": unit} if unit else {} kwargs = {"unit": unit} if unit else {}
await func(address, value, **kwargs) try:
async with timeout(self._config_timeout):
func(address, value, **kwargs)
except asyncio.TimeoutError:
return
async def read_coils(self, unit, address, count): async def read_coils(self, unit, address, count):
"""Read coils.""" """Read coils."""