How to avoid multiple simultaneous connection attempts? #1469
-
Hi everyone, In a small program using pymodbus 3.2.2 and python 3.9.16 in a dedicated pyenv under debian11, the logs show that there are multiple connection attempts while already communicating:
The logging format is the one of the program, sorry for that... I use the async version of the clients. In this case it was a TCP client. The pymodbus client is saved in In the program (running as a daemon), there is a loop over the read requests like: async def run_loop(self):
connected = False
# Polling loop
while not self.should_stop.is_set():
# for time measuring
t_begin = time.time()
if self.new_config is not None:
self.apply_new_config()
# Connect
if not connected or not self.client.connected:
connected = await self.connect()
exception = None
read_results = {}
self.cycle += 1
for cmd_id, request in self.requests.items():
# some code to filter the needed requests
request_ok = True
value = None
# Read coils (code 0x01) || Read discrete inputs (code 0x02)
if request['fct_modbus'] in ('1', '2'):
count = 1
if request['data_type'] == 'blob':
count = int(request['count'])
try:
if request['fct_modbus'] == '1':
response = await self.client.read_coils(address=request['addr'], count=count, slave=request['slave'])
elif request['fct_modbus'] == '2':
response = await self.client.read_discrete_inputs(address=request['addr'], count=count, slave=request['slave'])
request_ok = PyModbusClient.check_response(response)
except Exception as e:
request_ok = False
exception = e
connected = False
if request_ok:
value = response.bits[0]
# some code
else:
# some code
# Read holding registers (code 0x03) || Read input registers (code 0x04)
elif request['fct_modbus'] in ('3', '4'):
normal_number, count, sp_sf = PyModbusClient.request_info(request)
try:
if request['fct_modbus'] == '3':
response = await self.client.read_holding_registers(address=request['addr'], count=count, slave=request['slave'])
elif request['fct_modbus'] == '4':
response = await self.client.read_input_registers(address=request['addr'], count=count, slave=request['slave'])
request_ok = PyModbusClient.check_response(response)
except Exception as e:
request_ok = False
exception = e
connected = False
if request_ok:
decoder = BinaryPayloadDecoder.fromRegisters(response.registers, request['byteorder'], request['wordorder'])
# some code to decode the response and storing the desired value in
value = 'the received value with the right coding here'
# Save the result of this request
if request_ok:
read_results[cmd_id] = value
if request['data_type'] == 'string':
try:
read_results[cmd_id] = value.decode()
except:
read_results[cmd_id] = '<*ERROR*>'[:request['strlen']]
logging.debug('PyModbusClient: read value for ' + request['name'] + ' (command id ' + cmd_id + '): ' + str(value))
else:
error_log = 'PyModbusClient: Something went wrong while reading ' + request['name'] + ' (command id ' + cmd_id + ')'
if exception:
if isinstance(exception, ModbusException):
logging.error(error_log + ': ' + repr(exception) + ' - ' + exception.string)
else:
logging.error(error_log + ': ' + repr(exception) + ' - ' + str(exception))
else:
logging.error(error_log)
# Small pause if serial
if self.eqConfig['eqProtocol'] == 'serial' and request['fct_modbus'] != 'fromBlob':
await asyncio.sleep(0.05)
# After all the info requests
# Send results to jeedom
self.send_results_to_jeedom(read_results)
# Keep the connection open or not...
if self.eqConfig['eqKeepopen'] == '0' or not connected:
connected = await self.disconnect()
# Polling time
elapsed_time = time.time() - t_begin
if elapsed_time >= self.polling:
self.polling = (elapsed_time // self.polling_config + 1) * self.polling_config
logging.warning('PyModbusClient: the polling time is too short, setting it to ' + str(self.polling) + ' s.')
while self.polling - elapsed_time > 0 and not self.should_stop.is_set():
self.check_queue(self.polling - elapsed_time)
await self.execute_write_requests(True, connected)
elapsed_time = time.time() - t_begin
# The loop has exited
connected = await self.disconnect()
self.shutdown()
The connect and disconnect functions: async def connect(self):
logging.debug('PyModbusClient: connect called')
try:
if not self.client.connected:
logging.debug('PyModbusClient: connecting...')
await self.client.connect()
ret = True
except Exception as e:
logging.error('PyModbusClient: Something went wrong while connecting to equipment id ' + self.eqConfig['id'] + ': ' + repr(e) + ' - ' + e.string)
ret = False
delay = float(self.eqConfig['eqFirstDelay'])
await asyncio.sleep(delay)
return ret
async def disconnect(self):
logging.debug('PyModbusClient: disconnect called')
try:
await self.client.close()
except Exception as e:
logging.error('PyModbusClient: Something went wrong while closing connection to equipment id ' + self.eqConfig['id'] + ': ' + repr(e) + ' - ' + e.string)
return False How to avoid the multiple connection attempts? Could the pymodbus connection attempt be cancelled if the connection is established? Thank you. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
How about reading the documentation https://pymodbus.readthedocs.io/en/latest/source/library/client.html |
Beta Was this translation helpful? Give feedback.
-
you cannot, but there is a callback which you can use to stop the client. |
Beta Was this translation helpful? Give feedback.
How about reading the documentation https://pymodbus.readthedocs.io/en/latest/source/library/client.html
it explains how to avoid reconnect.