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 GitHub
parent 7dd42bc32d
commit 2d1002d40d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

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
@ -242,7 +243,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
@ -252,7 +258,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."""