I've got this python program that handles communication between a PLC using OPCUA, some mass flow controllers using Modbus TCP and an Arduino using Serial. The program is supposed to run continuously and it does so for 3 hours with no trouble as my PLC is controlling another system but after this I get this error:
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\ua_client.py", line 230, in open_secure_channel
raise RuntimeError('Two Open Secure Channel requests can not happen too close to each other. ' 'The response must be processed and returned before the next request can be sent.')
RuntimeError: Two Open Secure Channel requests can not happen too close to each other. The response must be processed and returned before the next request can be sent.
ERROR:asyncua.client.client:Error in watchdog loop
Traceback (most recent call last):
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\client.py", line 551, in _monitor_server_loop
_ = await self.nodes.server_state.read_value()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\common\node.py", line 207, in read_value
result = await self.read_data_value()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\common\node.py", line 220, in read_data_value
return await self.read_attribute(ua.AttributeIds.Value, None, raise_on_bad_status)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\common\node.py", line 342, in read_attribute
result = await self.session.read(params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\ua_client.py", line 404, in read
data = await self.protocol.send_request(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\ua_client.py", line 165, in send_request
await self.pre_request_hook()
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\client.py", line 534, in check_connection
await self._renew_channel_task
RuntimeError: Two Open Secure Channel requests can not happen too close to each other. The response must be processed and returned before the next request can be sent.
ERROR:asyncua.client.client:Error in watchdog loop
Traceback (most recent call last):
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\client.py", line 551, in _monitor_server_loop
_ = await self.nodes.server_state.read_value()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\common\node.py", line 207, in read_value
result = await self.read_data_value()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\common\node.py", line 220, in read_data_value
return await self.read_attribute(ua.AttributeIds.Value, None, raise_on_bad_status)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\common\node.py", line 342, in read_attribute
result = await self.session.read(params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\ua_client.py", line 404, in read
data = await self.protocol.send_request(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\ua_client.py", line 165, in send_request
await self.pre_request_hook()
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\client.py", line 534, in check_connection
await self._renew_channel_task
RuntimeError: Two Open Secure Channel requests can not happen too close to each other. The response must be processed and returned before the next request can be sent.
ERROR:asyncio:Task exception was never retrieved
future: <Task finished name='Task-3' coro=<Client._monitor_server_loop() done, defined at C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\client.py:542> exception=RuntimeError('Two Open Secure Channel requests can not happen too close to each other. The response must be processed and returned before the next request can be sent.')>
Traceback (most recent call last):
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\client.py", line 551, in _monitor_server_loop
_ = await self.nodes.server_state.read_value()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\common\node.py", line 207, in read_value
result = await self.read_data_value()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\common\node.py", line 220, in read_data_value
return await self.read_attribute(ua.AttributeIds.Value, None, raise_on_bad_status)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\common\node.py", line 342, in read_attribute
result = await self.session.read(params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\ua_client.py", line 404, in read
data = await self.protocol.send_request(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\ua_client.py", line 165, in send_request
await self.pre_request_hook()
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\client.py", line 534, in check_connection
await self._renew_channel_task
RuntimeError: Two Open Secure Channel requests can not happen too close to each other. The response must be processed and returned before the next request can be sent.
INFO:asyncua.client.client:disconnect
INFO:asyncua.client.ua_client.UaClient:close_session
INFO:asyncua.client.ua_client.UASocketProtocol:close_secure_channel
INFO:asyncua.client.ua_client.UASocketProtocol:Request to close socket received
INFO:asyncua.client.ua_client.UASocketProtocol:Socket has closed connection
Traceback (most recent call last):
File "c:\Users\labuser\Documents\Automation\Automation_test.py", line 339, in <module>
asyncio.run(main())
File "C:\Users\labuser\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 194, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "C:\Users\labuser\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\labuser\AppData\Local\Programs\Python\Python312\Lib\asyncio\base_events.py", line 685, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "C:\Users\labuser\Documents\Automation\Lib\site-packages\asyncua\client\client.py", line 700, in close_session
await self._renew_channel_task
RuntimeError: Two Open Secure Channel requests can not happen too close to each other. The response must be processed and returned before the next request can be sent.
Here is the code:
import asyncio
import logging
import serial
from asyncua import Client, ua
from pymodbus.client import AsyncModbusTcpClient
from struct import pack, unpack
import pandas as pd
# Initialize DataFrame to store recorded variables
df = pd.DataFrame(columns=['Timestamp', 'Variable', 'Value'])
# Configure logging
logging.basicConfig(level=logging.INFO)
# Define the serial port and baud rate
arduino = serial.Serial('COM8', 9600)
asyncio.sleep(2)
async def record_variables(variable, value):
dosing_time = pd.Timestamp.now()
global df
new_row = {'Timestamp': dosing_time, 'Variable': variable, 'Value': value}
print("New Row:", new_row) # Check the new row before appending
df = pd.concat([df, pd.DataFrame([new_row])], ignore_index=True)
df.to_csv(r"C:/Users/labuser/df.csv", index=False)
def set_valve_position(channel, position):
if position == 0:
#arduino.write(bytes(str(channel) + '0', 'utf-8')) # Send 'channel1' to Arduino to activate solenoid valve
#print(f"Solenoid valve on channel {channel} activated")
arduino.write(f"{channel} {position}\n".encode())
elif position == 1:
arduino.write(f"{channel} {position}\n".encode()) # Send 'channel0' to Arduino to deactivate solenoid valve
#print(f"Solenoid valve on channel {channel} deactivated")
else:
print("invalid input")
# Function to read data from input registers (Function Code 4)
async def read_input_registers(modbusclient, start_address, num_elements, slave, datatype):
response = await modbusclient.read_input_registers(start_address, num_elements, unit=slave)
if response.isError():
logging.error(f"Read Input Registers Error for {datatype}: {response}")
else:
if datatype == 'B':
data = response.registers[0] # Assuming you expect only one register for Unsigned8 datatype
else:
data_bytes = b''.join(pack('>H', register) for register in response.registers)
data = unpack(datatype, data_bytes)
print(f"{datatype} Data:", data)
return data
# Function to read holding registers (Function Code 3)
async def read_holding_registers(modbusclient, start_address, num_registers, slave, datatype):
response = await modbusclient.read_holding_registers(start_address, num_registers, unit=slave)
if response.isError():
print("Read Holding Registers Error:", response)
else:
if datatype == 'B':
data = response.registers[0] # Assuming you expect only one register for Unsigned8 datatype
else:
data_bytes = b''.join(pack('>H', register) for register in response.registers)
data = unpack(datatype, data_bytes)
print(f"{datatype} Data:", data)
return data
# Function to write data to holding registers
async def write_holding_registers(modbusclient, start_address, data, slave):
response = await modbusclient.write_holding_registers(start_address, data, unit=slave)
if response.isError():
print("Write Holding Registers Error:", response)
else:
print("Write Successful")
# Function to write register
async def write_register(modbusclient, address, value, slave):
await modbusclient.connect()
response = await modbusclient.write_register(address, value, unit=slave)
if response.isError():
print("Write Single Register Error:", response)
else:
print("Write Successful")
# Function to write single holding register (Function Code 6)
async def write_single_register(modbusclient, address, value, slave):
# Convert the float value to bytes
byte_value = pack('!f', value)
# Write the bytes to the specified address
response = await modbusclient.write_registers(address, [int.from_bytes(byte_value[i:i+2], byteorder='big') for i in range(0, len(byte_value), 2)], unit=slave)
if response.isError():
print("Write Single Register Error:", response)
else:
print("Write Successful")
async def write_value_bool(client, node_id, value):
client_node = client.get_node(node_id)
await client_node.set_data_value(value=value, varianttype=ua.VariantType.Boolean) # Pass value directly
#await client_node.set_value(client_node_dv)
print("Value of : " + str(client_node) + ' : ' + str(value))
async def read_input_value(client, node_id):
client_node = client.get_node(node_id)
client_node_value = await client_node.read_value()
logging.info(f"Value of {client_node}: {client_node_value}")
return client_node_value
async def write_value_float(client, node_id, value):
client_node = client.get_node(node_id)
client_node_dv = await client_node.write_value(ua.Variant(float(value), ua.VariantType.Float)) # Pass value directly
await client_node.set_value(client_node_dv)
print("Value of : " + str(client_node) + ' : ' + str(value))
async def keep_connection_alive(modbusclient, client, stop_event):
"""
Periodically read a register to keep the Modbus connection alive.
"""
loop = asyncio.get_running_loop()
while not stop_event.is_set():
try:
# Perform a non-blocking read operation to keep the connection alive
await read_input_registers(modbusclient, 0, 1, 1, 'B')
await asyncio.sleep(30) # Send a ping every minute or as needed
await read_input_value (client, "ns=4;s=|var|C6 S14 PRO.Application.GVL.PBPumpOnOff")
await asyncio.sleep(30)
except Exception as e:
# Handle exceptions if the connection is lost or any other errors occur
print(f"Error during connection keep-alive: {e}")
# async def record_dosing_quantity(client, MFC_01DosedQuantity_g, MFC_02DosedQuantity_g):
# while True:
# try:
# await write_value_float(client,"ns=4;s=|var|C6 S14 PRO.Application.GVL.MFC01_DosedQuantity", MFC_01DosedQuantity_g)
# except Exception as e:
# print(f"Error during write dosed quantity: {e}")
# try:
# await write_value_float(client,"ns=4;s=|var|C6 S14 PRO.Application.GVL.MFC02_DosedQuantity", MFC_01DosedQuantity_g)
# except Exception as e:
# print(f"Error during write dosed quantity: {e}")
#Setup one for coupling ()
async def PhosDCI_operations(modbusclient, MFC01_PhosphoramiditeQuantity_g,
MFC02_DCIQuantity_g,
Phosphoramiditie_VP,
DCI_VP,
MFC02_CyanethanolQuantity_g,
Cyanethanol_VP,
MFC02_POSCSOQuantity_g,
POSCSO_VP,
client
):
await modbusclient.connect()
stop_event = asyncio.Event()
try:
# Since the Modbus operations are synchronous, run them in executor to avoid blocking the event loop
loop = asyncio.get_running_loop()
keep_alive_task = asyncio.create_task(keep_connection_alive(modbusclient, client, stop_event))
## Phosphoramidite + DCI premixing
# write the code to take Phosphoramidite_VP abd DCI_VP
await loop.run_in_executor(None, set_valve_position, Phosphoramiditie_VP, 1)
#await loop.run_in_executor(None, set_valve_position, Phosphoramiditie_VP, 1) #DCI is without manifold for now
await asyncio.sleep(2)
# Write dosing setpoint to MFC_01&02
await loop.run_in_executor(None, write_single_register, modbusclient, 1711, MFC01_PhosphoramiditeQuantity_g/1000, 1) #MFC01_SetpointDosingQuantity
await asyncio.sleep(0.1)
await write_single_register(modbusclient, 2711, MFC02_DCIQuantity_g/1000, 1) #MFC02_SetpointDosingQuantity
await asyncio.sleep(0.1)
# Write MFC01&02_StartBatch
await write_register(modbusclient, 0, 256, 1) #Write MFC01_StartBatch - 256is dose and 0is stop
await asyncio.sleep(0.1)
await write_register(modbusclient, 1, 256, 1) #Write MFC02_StartBatch - 256is dose and 0is stop
await asyncio.sleep(0.1)
# Read MFC01&02_StartBatch
await write_register(modbusclient, 0, 0, 1) #Write MFC01_StartBatch - 256is dose and 0is stop
await asyncio.sleep(0.1)
await write_register(modbusclient, 1, 0, 1) #Write MFC02_StartBatch - 256is dose and 0is stop
#Finishing the phosphoramidite + DCI premixing
await asyncio.sleep(12) #20s as test.
await loop.run_in_executor(None, set_valve_position, Phosphoramiditie_VP, 0)
MFC_01DosedQuantity_g = await read_input_registers(modbusclient, 8, 2, 1, '>f' ) #Float datatype (big-endian)
await record_variables('MFC01_DosedQuantity_g', MFC_01DosedQuantity_g)
MFC_02DosedQuantity_g = await read_input_registers(modbusclient, 18, 2, 1, '>f') #Float datatype (big-endian)
await record_variables('MFC02_DosedQuantity_g', MFC_02DosedQuantity_g)
#await record_variables()
#await asyncio.sleep(2)
#await record_dosing_quantity(client, MFC_01DosedQuantity_g, MFC_02DosedQuantity_g )
await asyncio.sleep(3600)
## Cyanethanol
# write the code to take Cyanethanol_VP
await loop.run_in_executor(None, set_valve_position, Cyanethanol_VP, 1)
await asyncio.sleep(2)
# Write dosing setpoint to MFC_02
await write_single_register(modbusclient, 1711, MFC02_CyanethanolQuantity_g/1000, 1) #MFC01_SetpointDosingQuantity
await asyncio.sleep(0.1)
# Write MFC01&02_StartBatch
await write_register(modbusclient, 0, 256, 1) #Write MFC01_StartBatch - 256is dose and 0is stop
await asyncio.sleep(0.1)
await write_register(modbusclient, 0, 0, 1) #Write MFC01_StartBatch - 256is dose and 0is stop
#Finishing the phosphoramidite + DCI premixing
await asyncio.sleep(12) #20s as test. Change this to 2mins for actual coupling reaction
await loop.run_in_executor(None, set_valve_position, Cyanethanol_VP, 0)
MFC_02DosedCyethanolQuantity_g = await read_input_registers(modbusclient, 8, 2, 1, '>f') #Float datatype (big-endian)
await record_variables('MFC02_CyanethanolQuantity_g', MFC_02DosedCyethanolQuantity_g)
#await record_variables()
await asyncio.sleep(60)
## POS_CSO
# write the code to take PSOCSO_VP
await loop.run_in_executor(None, set_valve_position, POSCSO_VP, 1)
await asyncio.sleep(2)
# Write dosing setpoint to MFC_02
await write_single_register( modbusclient, 1711, MFC02_POSCSOQuantity_g/1000, 1) #MFC02_SetpointDosingQuantity
await asyncio.sleep(0.1)
# Write MFC01&02_StartBatch
await write_register( modbusclient, 0, 256, 1) #Write MFC01_StartBatch - 256is dose and 0is stop
await asyncio.sleep(0.1)
await write_register( modbusclient, 0, 0, 1) #Write MFC01_StartBatch - 256is dose and 0is stop
#Finishing the phosphoramidite + DCI premixing
await asyncio.sleep(12) #20s as test. Change this to 2mins for actual coupling reaction
await loop.run_in_executor(None, set_valve_position, POSCSO_VP, 0)
MFC_02DosedCSOQuantity_g = await read_input_registers( modbusclient, 8, 2, 1, '>f') #Float datatype (big-endian)
await record_variables('MFC02_POSCSOQuantity_g', MFC_02DosedCSOQuantity_g)
#await record_variables()
await asyncio.sleep(3600)
finally:
stop_event.set()
await asyncio.sleep(15) #Disconnect - estimate how long the dosing will take
await keep_alive_task
await modbusclient.close()
#Setup one for detrit()
async def Detrit_operations(modbusclient, MFC02_TFAQuantity_g,
MFC02_TEMESQuantity_g,
TFA_VP,
TEMES_VP,
client
):
await modbusclient.connect()
stop_event = asyncio.Event()
try:
# Since the Modbus operations are synchronous, run them in executor to avoid blocking the event loop
loop = asyncio.get_running_loop()
keep_alive_task = asyncio.create_task(keep_connection_alive(modbusclient,client, stop_event))
## Acid detrit
# write the code to take Phosphoramidite_VP abd DCI_VP
await loop.run_in_executor(None, set_valve_position, TEMES_VP, 1)
await asyncio.sleep(2)
# Write dosing setpoint to MFC_02
await write_single_register(modbusclient, 1711, MFC02_TEMESQuantity_g/1000, 1) #MFC01_SetpointDosingQuantity
await asyncio.sleep(0.1)
# Write MFC02_StartBatch
await write_register(modbusclient, 0, 256, 1) #Write MFC01_StartBatch - 256is dose and 0is stop
await asyncio.sleep(0.1)
# Read MFC02_StartBatch
await write_register(modbusclient, 0, 0, 1) #Write MFC01_StartBatch - 256is dose and 0is stop
#Finishing the phosphoramidite + DCI premixing
await asyncio.sleep(120) #20s as test. Change this to 10mins for actual coupling reaction
loop.run_in_executor(None, set_valve_position, TEMES_VP, 0)
MFC_02DosedTEMESQuantity_g = await read_input_registers(modbusclient, 8, 2, 1, '>f') #Float datatype (big-endian)
await record_variables('MFC02_TEMESQuantity_g', MFC_02DosedTEMESQuantity_g)
await asyncio.sleep(1200)
## TEMES
# write the code to take Cyanethanol_VP
await loop.run_in_executor(None, set_valve_position, TFA_VP, 1)
await asyncio.sleep(2)
# Write dosing setpoint to MFC_02
await write_single_register(modbusclient, 1711, MFC02_TFAQuantity_g/1000, 1) #MFC02_SetpointDosingQuantity
await asyncio.sleep(0.1)
# Write MFC01&02_StartBatch
await write_register(modbusclient, 0, 256, 1) #Write MFC02_StartBatch - 256is dose and 0is stop
#
await asyncio.sleep(0.1)
await write_register(modbusclient, 0, 0, 1) #Write MFC02_StartBatch - 256is dose and 0is stop
# Read MFC01&02_StartBatch
#Finishing the phosphoramidite + DCI premixing
await asyncio.sleep(12) #20s as test. Change this to 2mins for actual coupling reaction
await loop.run_in_executor(None, set_valve_position, TFA_VP, 0)
MFC_02DosedTFAQuantity_g = read_input_registers(modbusclient, 8, 2, 1, '>f') #Float datatype (big-endian)
await record_variables('MFC02_TFAQuantity_g', MFC_02DosedTFAQuantity_g)
await asyncio.sleep(120)
finally:
stop_event.set()
await asyncio.sleep(15) #Disconnect - estimate how long the dosing will take
await keep_alive_task
await modbusclient.close()
#Running the dosing sequence
async def main():
url = "address"
logging.info(f"Connecting to {url} ...")
# Modbus TCP client initialization
modbusclient = AsyncModbusTcpClient('modbusaddress')
async with Client(url=url) as client:
await client.connect()
root = client.get_root_node()
logging.info(f"Objects root node is: {root}")
coupling_param = {
1.5: (5, 5, 1, 5, 5, 2, 5, 3),
2.5: (5, 5, 5, 5, 5, 5, 5, 5),
3.5: (5, 5, 1, 5, 5, 2, 5, 3)} #PhosDCI_operations(MFC01_PhosphoramiditeQuantity_g, MFC02_DCIQuantity_g, Phosphoramiditie_VP, DCI_VP, MFC02_CyanethanolQuantity_g, Cyanethanol_VP, MFC02_POSCSOQuantity_g, POSCSO_VP)
detrit_param = {
1: (5, 5, 5, 5),
2: (5, 5, 5, 5),
3: (5, 5, 5, 5),
4: (5, 5, 5, 5)}#Detrit_operations(MFC02_TFAQuantity_g, MFC02_TEMESQuantity_g, TFA_VP, TEMES_VP, client):
#5: (27.5, 10, 1, 3)}
while True:
## Should replace the node_value woth a 'handshake' value from PLC
## One node_value for coupling (potentially sub divided into phos-DCI, quench, PO/PS0)
## Onde node_value for detrit (potentially sub divided into traps and then acid)
node_value = await read_input_value(client, "ns=4;s=|var|C6 S14 PRO.Application.GVL.Dosing")
process_stage = await read_input_value(client, "ns=4;s=|var|C6 S14 PRO.Application.GVL.ProcessStage") ## Assign Process_stage to GVL.ProcessStage
if node_value:
logging.info(f"Node value: {node_value}")
if process_stage == int(process_stage):
#await write_value_bool(client, "ns=4;s=|var|C6 S14 PRO.Application.GVL.Dosing", True)
try:
await write_value_bool(client, "ns=4;s=|var|C6 S14 PRO.Application.GVL.Detritylation", True) # Writing an integer value
except Exception as e:
logging.error("error")
try:
await Detrit_operations(modbusclient, *detrit_param[process_stage], client)
except Exception as e:
logging.error(f"Error during modbus operations: {e}")
try:
await write_value_bool(client, "ns=4;s=|var|C6 S14 PRO.Application.GVL.Dosing", False) # Writing an integer value
except Exception as e:
logging.error(f"Error during write_value_bool dosing 309 operations: {e}")
try:
await write_value_bool(client, "ns=4;s=|var|C6 S14 PRO.Application.GVL.PBDFMode", True) # Writing an integer value
except Exception as e:
logging.error(f"Error during write_value_bool PBDFMode 313 operations: {e}")
else:
try:
await write_value_bool(client, "ns=4;s=|var|C6 S14 PRO.Application.GVL.Coupling", True) # Writing an integer value
except Exception as e:
logging.error("error")
try:
await PhosDCI_operations(modbusclient, *coupling_param[process_stage], client)
except Exception as e:
logging.error(f"Error during modbus operations: {e}")
try:
await write_value_bool(client, "ns=4;s=|var|C6 S14 PRO.Application.GVL.Dosing", False) # Writing an integer value
except Exception as e:
logging.error(f"Error during write_value_bool Dosing 236 operations: {e}")
try:
await write_value_bool(client, "ns=4;s=|var|C6 S14 PRO.Application.GVL.PBDFMode", True) # Writing an integer value
except Exception as e:
logging.error(f"Error during write_value_bool PBDFMode 330 operations: {e}")
await asyncio.sleep(5)
else:
logging.info("Node value is not True, skipping Modbus operations")
await asyncio.sleep(5) # Adjust sleep duration as needed
if __name__ == "__main__":
asyncio.run(main())
Previously the code ran modbus I/O synchronously, had the same issue after 3 hours of operation where I would get a RuntimeError. I changed the modbus I/O to be async but same issue. I'm not super sure what to try next.
You connect multiple times, remove the client.connect
line.
Because with async with Client(url=url) as client
you already connect to the server.
async with Client(url=url) as client:
await client.connect() <--- remove this line