Skip to content

Commit deae046

Browse files
committed
Update for pymodbus 3.6.x
1 parent 7d9a4fe commit deae046

File tree

3 files changed

+36
-13
lines changed

3 files changed

+36
-13
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,27 @@ peripherals = [
9797
...
9898
```
9999

100+
### Passive Tcpdump Client
101+
102+
##### `qtoggleserver.conf:`
103+
``` ini
104+
...
105+
peripherals = [
106+
...
107+
{
108+
driver = "qtoggleserver.modbus.ModbusTcpDumpClient"
109+
port = 5020 # TCP port to sniff
110+
iface = "eth0" # network interface to sniff (defaults to `any`)
111+
master_ip = "192.168.1.122" # IP address of the master Modbus machine (optional)
112+
slave_ip = "192.168.1.123" # IP address of the slave Modbus machine (optional)
113+
tcpdumo = "/usr/bin/tcpdump" # full path to the `tcpdump` binary (optional)
114+
# see below for common parameters
115+
}
116+
...
117+
]
118+
...
119+
```
120+
100121
### Common Parameters
101122

102123
The following parameters are common to all types of Modbus clients and servers:

qtoggleserver/modbus/client.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
from pymodbus.client import (
88
AsyncModbusSerialClient as InternalAsyncModbusSerialClient,
99
AsyncModbusTcpClient as InternalAsyncModbusTcpClient,
10-
ModbusBaseClient as InternalModbusBaseClient,
1110
)
11+
from pymodbus.client.base import ModbusBaseClient as InternalModbusBaseClient
1212
from pymodbus.pdu import ExceptionResponse
1313

1414
from qtoggleserver.core import ports as core_ports
@@ -101,22 +101,25 @@ async def ensure_client(self) -> bool:
101101
self.debug('waiting %d seconds for initial delay', self.initial_delay)
102102
await asyncio.sleep(self.initial_delay)
103103

104+
while not self._pymodbus_client.connected:
105+
await asyncio.sleep(0.1)
106+
104107
if not self._pymodbus_client.connected:
105108
self.warning('could not connect to unit')
106109
# Don't leave the client (partially) connected
107110
try:
108-
await self._pymodbus_client.close()
111+
self._pymodbus_client.close()
109112
except Exception:
110113
# We don't care if connection closing fails - we're going to recreate the client from scratch anyway
111114
pass
112115
return False
113116

114117
return True
115118

116-
async def close_client(self) -> None:
119+
def close_client(self) -> None:
117120
self.info('disconnecting from unit')
118121
try:
119-
await self._pymodbus_client.close()
122+
self._pymodbus_client.close()
120123
except Exception:
121124
# We don't care if connection closing fails - we're going to recreate the client from scratch anyway
122125
pass
@@ -142,7 +145,7 @@ async def handle_enable(self) -> None:
142145

143146
async def handle_disable(self) -> None:
144147
await super().handle_disable()
145-
await self.close_client()
148+
self.close_client()
146149

147150
async def poll(self) -> None:
148151
if not await self.ensure_client():
@@ -271,14 +274,14 @@ def __init__(
271274
serial_baud: int = DEFAULT_SERIAL_BAUD,
272275
serial_stopbits: int = DEFAULT_SERIAL_STOPBITS,
273276
serial_bytesize: int = DEFAULT_SERIAL_BYTESIZE,
274-
serial_parity: int = DEFAULT_SERIAL_PARITY,
277+
serial_parity: str = DEFAULT_SERIAL_PARITY,
275278
**kwargs
276279
) -> None:
277280
self.serial_port: str = serial_port
278281
self.serial_baud: int = serial_baud
279282
self.serial_stopbits: int = serial_stopbits
280283
self.serial_bytesize: int = serial_bytesize
281-
self.serial_parity: int = serial_parity
284+
self.serial_parity: str = serial_parity
282285

283286
kwargs.setdefault('method', self.DEFAULT_METHOD)
284287

@@ -329,7 +332,7 @@ async def make_internal_client(self) -> InternalModbusBaseClient:
329332
def handle_offline(self) -> None:
330333
# Automatically close and cleanup any existing client if peripheral goes offline. We want to start from scratch
331334
# with a brand-new client.
332-
asyncio.create_task(self.close_client())
335+
self.close_client()
333336

334337

335338
class BasePassiveModbusClient(BaseModbusClient, metaclass=abc.ABCMeta):

qtoggleserver/modbus/passive/base.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
from typing import List, Optional, Union
55

6-
from pymodbus import bit_read_message, bit_write_message, register_read_message, register_write_message
7-
from pymodbus.client import ModbusBaseClient as InternalModbusBaseClient
6+
from pymodbus import Framer, bit_read_message, bit_write_message, register_read_message, register_write_message
7+
from pymodbus.client.base import ModbusBaseClient as InternalModbusBaseClient
88

99

1010
class InternalPassiveException(Exception):
@@ -19,7 +19,7 @@ def __init__(self) -> None:
1919
self._input_register_values: dict[int, int] = {}
2020
self._run_task: Optional[asyncio.Task] = None
2121

22-
super().__init__(xframer='ignored')
22+
super().__init__(framer=Framer.RTU)
2323

2424
@abc.abstractmethod
2525
async def run(self) -> None:
@@ -35,10 +35,9 @@ async def connect(self) -> None:
3535
if not self._run_task:
3636
self._run_task = asyncio.create_task(self._run())
3737

38-
async def close(self) -> None:
38+
def close(self, reconnect: bool = False) -> None:
3939
if self._run_task:
4040
self._run_task.cancel()
41-
await self._run_task
4241
self._run_task = None
4342

4443
@property

0 commit comments

Comments
 (0)