Description and code:
I'm using the Synchronous ModbusTcpServer with pymodbus
library to create a Modbus Slave/Server, that here's the code:
from pymodbus.server.sync import StartTcpServer, ModbusTcpServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from twisted.internet.task import LoopingCall
from twisted.internet import reactor
import threading
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)
def run_server():
block1 = ModbusSequentialDataBlock(0x00, [717] * 0x0F)
block2 = ModbusSequentialDataBlock(0x10, [323] * 0x1F)
store2 = ModbusSlaveContext(hr=block1, ir=block2)
slaves = {
0x01: store2,
}
context = ModbusServerContext(slaves=slaves, single=False)
identity = ModbusDeviceIdentification()
identity.VendorName = 'Pymodbus'
identity.ProductCode = 'PM'
identity.VendorUrl = 'http://github.com/riptideio/pymodbus/'
identity.ProductName = 'Pymodbus Server'
identity.ModelName = 'Pymodbus Server'
identity.MajorMinorRevision = '1.0'
interval = 2
server = ModbusTcpServer(context,
identity=identity,
address=('0.0.0.0', 5021)) # Problem cause.
thread_ = threading.Thread(target=server.serve_forever, daemon=True)
thread_.start()
loop = LoopingCall(f=update_values, a=server)
loop.start(interval, now=True)
reactor.run()
def update_values(a):
print("-----------START-----------")
rfuncode = 3
wfuncode = 16
slave_id = 0x01
address = 0x00
context_ = a.context[slave_id]
values = context_.getValues(rfuncode, address, count=32)
print(values)
values = [val+1 for val in values]
context_.setValues(wfuncode, address, values)
print("------------END------------")
if __name__ == "__main__":
run_server()
When a client app connects to this server and when I close this code (with Ctrl+C) and run again encountered with this error:
OSError: [Errno 98] Address already in use
I know that in socket creation we can use socket.SO_REUSEADDR
for overcome on this issue.
Also, I can .close()
connection in client side to resolve this issue but I want have a stable server.
Question:
Is there a built-in way to overcome this? I find out this argument (socket.SO_REUSEADDR
) in Asynchronous ModbusTcpServer (in async.py
) but there isn't in Synchronous ModbusTcpServer (sync.py
).
[NOTE]:
Versions
- Python: 3.6.5
- OS: Ubuntu 16.04
- Pymodbus: 1.5.2
- Modbus Hardware (if used): No
Pymodbus Specific
- Server: tcp - sync
- Client: tcp - sync