Skip to content

Commit 035ffc2

Browse files
Fix reconnectDelay to be within (100ms, 5min) (#1244)
* Fix broadCastEnable docstring * Reduce min reconnect delay to 100ms, and cap max at 5 min. Co-authored-by: jan Iversen <jancasacondor@gmail.com>
1 parent 6224f71 commit 035ffc2

File tree

5 files changed

+91
-66
lines changed

5 files changed

+91
-66
lines changed

pymodbus/client/base.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,17 @@ class ModbusBaseClient(ModbusClientMixin):
3131
:param close_comm_on_error: (optional) Close connection on error.
3232
:param strict: (optional) Strict timing, 1.5 character between requests.
3333
:param broadcast_enable: (optional) True to treat id 0 as broadcast address.
34-
:param reconnect_delay: (optional) Delay in milliseconds before reconnecting.
34+
:param reconnect_delay: (optional) Minimum delay in milliseconds before reconnecting.
35+
:param reconnect_delay_max: (optional) Maximum delay in milliseconds before reconnecting.
3536
:param kwargs: (optional) Experimental parameters.
3637
3738
.. tip::
3839
Common parameters and all external methods for all clients are documented here,
3940
and not repeated with each client.
4041
4142
.. tip::
42-
**reconnect_delay** doubles automatically with each unsuccessful connect.
43+
**delay_ms** doubles automatically with each unsuccessful connect, from
44+
**reconnect_delay** to **reconnect_delay_max**.
4345
Set `reconnect_delay=0` to avoid automatic reconnection.
4446
4547
:mod:`ModbusBaseClient` is normally not referenced outside :mod:`pymodbus`,
@@ -82,6 +84,7 @@ class _params: # pylint: disable=too-many-instance-attributes
8284
broadcast_enable: bool = None
8385
kwargs: dict = None
8486
reconnect_delay: int = None
87+
reconnect_delay_max: int = None
8588

8689
baudrate: int = None
8790
bytesize: int = None
@@ -107,6 +110,7 @@ def __init__(
107110
strict: bool = Defaults.Strict,
108111
broadcast_enable: bool = Defaults.BroadcastEnable,
109112
reconnect_delay: int = Defaults.ReconnectDelay,
113+
reconnect_delay_max: int = Defaults.ReconnectDelayMax,
110114
**kwargs: any,
111115
) -> None:
112116
"""Initialize a client instance."""
@@ -118,7 +122,8 @@ def __init__(
118122
self.params.close_comm_on_error = bool(close_comm_on_error)
119123
self.params.strict = bool(strict)
120124
self.params.broadcast_enable = bool(broadcast_enable)
121-
self.params.reconnect_delay = reconnect_delay
125+
self.params.reconnect_delay = int(reconnect_delay)
126+
self.params.reconnect_delay_max = int(reconnect_delay_max)
122127
self.params.kwargs = kwargs
123128

124129
# Common variables.

pymodbus/client/tcp.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ def _create_protocol(self):
8989
strict=self.params.strict,
9090
broadcast_enable=self.params.broadcast_enable,
9191
reconnect_delay=self.params.reconnect_delay,
92+
reconnect_delay_max=self.params.reconnect_delay_max,
9293
**self.params.kwargs,
9394
)
9495
protocol.factory = self
@@ -144,7 +145,7 @@ async def _reconnect(self):
144145
txt = f"Waiting {self.delay_ms} ms before next connection attempt."
145146
_logger.debug(txt)
146147
await asyncio.sleep(self.delay_ms / 1000)
147-
self.delay_ms = 2 * self.delay_ms
148+
self.delay_ms = min(2 * self.delay_ms, self.params.reconnect_delay_max)
148149

149150
return await self._connect()
150151

pymodbus/client/udp.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ def _create_protocol(self, host=None, port=0):
109109
strict=self.params.strict,
110110
broadcast_enable=self.params.broadcast_enable,
111111
reconnect_delay=self.params.reconnect_delay,
112+
reconnect_delay_max=self.params.reconnect_delay_max,
112113
**self.params.kwargs,
113114
)
114115
protocol.params.host = host

pymodbus/constants.py

Lines changed: 78 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -11,105 +11,120 @@
1111
class Defaults(Singleton): # pylint: disable=too-few-public-methods
1212
"""A collection of modbus default values.
1313
14-
.. attribute:: Port
14+
.. attribute:: Port
1515
16-
The default modbus tcp server port (502)
16+
The default modbus tcp server port (502)
1717
18-
.. attribute:: TLSPort
18+
.. attribute:: TLSPort
1919
20-
The default modbus tcp over tls server port (802)
20+
The default modbus tcp over tls server port (802)
2121
2222
23-
.. attribute:: Backoff
23+
.. attribute:: Backoff
2424
25-
The default exponential backoff delay (0.3 seconds)
25+
The default exponential backoff delay (0.3 seconds) for a request
2626
27-
.. attribute:: Retries
27+
.. attribute:: Retries
2828
29-
The default number of times a client should retry the given
30-
request before failing (3)
29+
The default number of times a client should retry the given
30+
request before failing (3)
3131
32-
.. attribute:: RetryOnEmpty
32+
.. attribute:: RetryOnEmpty
3333
34-
A flag indicating if a transaction should be retried in the
35-
case that an empty response is received. This is useful for
36-
slow clients that may need more time to process a request.
34+
A flag indicating if a transaction should be retried in the
35+
case that an empty response is received. This is useful for
36+
slow clients that may need more time to process a request.
3737
38-
.. attribute:: RetryOnInvalid
38+
.. attribute:: RetryOnInvalid
3939
40-
A flag indicating if a transaction should be retried in the
41-
case that an invalid response is received.
40+
A flag indicating if a transaction should be retried in the
41+
case that an invalid response is received.
4242
43-
.. attribute:: Timeout
43+
.. attribute:: Timeout
4444
45-
The default amount of time a client should wait for a request
46-
to be processed (3 seconds)
45+
The default amount of time a client should wait for a request
46+
to be processed (3 seconds)
4747
48-
.. attribute:: Reconnects
48+
.. attribute:: Reconnects
4949
50-
The default number of times a client should attempt to reconnect
51-
before deciding the server is down (0)
50+
The default number of times a client should attempt to reconnect
51+
before deciding the server is down (0)
5252
53-
.. attribute:: TransactionId
53+
.. attribute:: TransactionId
5454
55-
The starting transaction identifier number (0)
55+
The starting transaction identifier number (0)
5656
57-
.. attribute:: ProtocolId
57+
.. attribute:: ProtocolId
5858
59-
The modbus protocol id. Currently, this is set to 0 in all
60-
but proprietary implementations.
59+
The modbus protocol id. Currently, this is set to 0 in all
60+
but proprietary implementations.
6161
62-
.. attribute:: Slave
62+
.. attribute:: Slave
6363
64-
The modbus slave address. Currently, this is set to 0x00 which
65-
means this request should be broadcast to all the slave devices
66-
(really means that all the devices should respond).
64+
The modbus slave address. Currently, this is set to 0x00 which
65+
means this request should be broadcast to all the slave devices
66+
(really means that all the devices should respond).
6767
68-
.. attribute:: Baudrate
68+
.. attribute:: Baudrate
6969
70-
The speed at which the data is transmitted over the serial line.
71-
This defaults to 19200.
70+
The speed at which the data is transmitted over the serial line.
71+
This defaults to 19200.
7272
73-
.. attribute:: Parity
73+
.. attribute:: Parity
7474
75-
The type of checksum to use to verify data integrity. This can be
76-
on of the following::
75+
The type of checksum to use to verify data integrity. This can be
76+
on of the following::
7777
78-
- (E)ven - 1 0 1 0 | P(0)
79-
- (O)dd - 1 0 1 0 | P(1)
80-
- (N)one - 1 0 1 0 | no parity
78+
- (E)ven - 1 0 1 0 | P(0)
79+
- (O)dd - 1 0 1 0 | P(1)
80+
- (N)one - 1 0 1 0 | no parity
8181
82-
This defaults to (N)one.
82+
This defaults to (N)one.
8383
84-
.. attribute:: Bytesize
84+
.. attribute:: Bytesize
8585
86-
The number of bits in a byte of serial data. This can be one of
87-
5, 6, 7, or 8. This defaults to 8.
86+
The number of bits in a byte of serial data. This can be one of
87+
5, 6, 7, or 8. This defaults to 8.
8888
89-
.. attribute:: Stopbits
89+
.. attribute:: Stopbits
9090
91-
The number of bits sent after each character in a message to
92-
indicate the end of the byte. This defaults to 1.
91+
The number of bits sent after each character in a message to
92+
indicate the end of the byte. This defaults to 1.
9393
94-
.. attribute:: ZeroMode
94+
.. attribute:: ZeroMode
9595
96-
Indicates if the slave datastore should use indexing at 0 or 1.
97-
More about this can be read in section 4.4 of the modbus specification.
96+
Indicates if the slave datastore should use indexing at 0 or 1.
97+
More about this can be read in section 4.4 of the modbus specification.
9898
99-
.. attribute:: IgnoreMissingSlaves
99+
.. attribute:: IgnoreMissingSlaves
100100
101-
In case a request is made to a missing slave, this defines if an error
102-
should be returned or simply ignored. This is useful for the case of a
103-
serial server emulater where a request to a non-existent slave on a bus
104-
will never respond. The client in this case will simply timeout.
101+
In case a request is made to a missing slave, this defines if an error
102+
should be returned or simply ignored. This is useful for the case of a
103+
serial server emulater where a request to a non-existent slave on a bus
104+
will never respond. The client in this case will simply timeout.
105105
106-
.. attribute:: broadcast_enable
106+
.. attribute:: broadcastEnable
107+
108+
When False unit_id 0 will be treated as any other unit_id. When True and
109+
the unit_id is 0 the server will execute all requests on all server
110+
contexts and not respond and the client will skip trying to receive a
111+
response. Default value False does not conform to Modbus spec but maintains
112+
legacy behavior for existing pymodbus users.
113+
114+
.. attribute: reconnectDelayMin
115+
116+
When a connection has been dropped, the client will initially wait
117+
reconnectDelayMin milliseconds before attempting a reconnect. If the
118+
attempt fails, it will double the delay before attempting again, up to a
119+
a maximum of ReconnectDelayMax. (binary exponential backoff).
120+
121+
.. attribute: reconnectDelayMax
122+
123+
When a connection has been dropped, the client will initially wait
124+
reconnectDelayMin milliseconds before attempting a reconnect. If the
125+
attempt fails, it will double the delay before attempting again, up to a
126+
a maximum of ReconnectDelayMax. (binary exponential backoff)
107127
108-
When False unit_id 0 will be treated as any other unit_id. When True and
109-
the unit_id is 0 the server will execute all requests on all server
110-
contexts and not respond and the client will skip trying to receive a
111-
response. Default value False does not conform to Modbus spec but maintains
112-
legacy behavior for existing pymodbus users.
113128
114129
"""
115130

@@ -136,7 +151,8 @@ class Defaults(Singleton): # pylint: disable=too-few-public-methods
136151
IgnoreMissingSlaves = False
137152
ReadSize = 1024
138153
BroadcastEnable = False
139-
ReconnectDelay = 1000 * 60 * 5
154+
ReconnectDelay = 100
155+
ReconnectDelayMax = 1000 * 60 * 5
140156
Count = 1
141157

142158

test/test_client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ def test_client_mixin(arglist, method, arg, response):
110110
"strict": not Defaults.Strict,
111111
"broadcast_enable": not Defaults.BroadcastEnable,
112112
"reconnect_delay": 117,
113+
"reconnect_delay_max": 250,
113114
},
114115
"defaults": {
115116
"timeout": Defaults.Timeout,
@@ -119,6 +120,7 @@ def test_client_mixin(arglist, method, arg, response):
119120
"strict": Defaults.Strict,
120121
"broadcast_enable": Defaults.BroadcastEnable,
121122
"reconnect_delay": Defaults.ReconnectDelay,
123+
"reconnect_delay_max": Defaults.ReconnectDelayMax,
122124
},
123125
},
124126
"serial": {

0 commit comments

Comments
 (0)