Use multiple QModbusServer on the same Modbus backend
-
Hi.
I'm writing a server application who act as modbus server where multiple modbus clients( currently Siemens LOGO! PLC's) write their inputs status to the app. These inputs are connected to industrial machines and the the goal is to obtain the status of these machines in order to perform some checks( like running status or alarms etc..).
Basing on the modbus slave example found in QtCreator i can succesfully manage one plc at time, by setting the correct server address, listening port and bind address.
with
server->setConnectionParameter(QModbusDevice::NetworkPortParameter, 502); server->setConnectionParameter(QModbusDevice::NetworkAddressParameter, "192.168.0.162"); server->setServerAddress(1); server->connectDevice();
i can successfully manage a single plc configured to connect to my computer, using the server '1'.
However, i have no clue on how to expand it to accept connections from others plc, by setting their server address to 2, 3 etc...
If i try to create another QModbusServer with the same configuration but different server address, as expected it cannot bind to the port '502' because it's already used by the previous QModbusServer.If i change the port to '503' for the second QModbusServer i can manage another PLC but i don't want to use one port for one device when they can be addressed by their server address (also, don't want to open multiple ports on my server)
By reading the description of QModbusServer
Modbus networks can have multiple Modbus servers. Modbus Servers are read/written by a Modbus client represented by QModbusClient. QModbusServer communicates with a Modbus backend, providing users with a convenient API.
i'm asking myself if the tcp socket is managed by the modbus backend and then multiple QModbusServer's can be attached to it where each one filter out their data.
Question: can i use multiple QModbusServer's (obviously with different setServerAddress(X) ) communicating on the same port? If so, how can i reach it?
Using Qt 5.8 (mingw32) on windows 10.
Thanks.
Ivan. -
Hi @IvanVa
Question: can i use multiple QModbusServer's (obviously with different setServerAddress(X) ) communicating on the same port? If so, how can i reach it?
I must admit that my Modbus knowledge is limited; however: Isn't the pure base of a server to handle multiple clients? Why does your server need multiple addresses? As all clients only see "their" server, this should not be a problem.
What might be a problem is to differentiate the clients from this single server, but in principle each client should have a separate connection, so even this should be manageable.
Am I overlooking something?
-
Yes, the pure base of the server is to accept multiple clients. But the concept of client and server in the modbus is a bit different from the classical concept everybody knows.
However, the real problem , as you mentioned, is to differentiate the client.
If multiple clients connect to the same server with address '1' (this addres is like an id), when they send (or to be more technical, write) data to the server, a signal is emitted but it does not contain any reference of the client who sent it.From this, my idea was to create different QModbusServer with different addresses (again , address is like an id) to force one client per server and thus be able to distinguish them.
But being forced to potentially open 1000 ports for 1000 clients is not a big deal.
EDIT:
but in principle each client should have a separate connection, so even this should be manageable.
Yes, but the QModbusServer mask out everything about the phisicals tcp sockets so i'm not able to know where, frompotentially multiple tcp connections, the data comes from.
-
Hi,
I think that "serverAddress" is only used when the communication stack is Serial. Think on a RS485 network that a lot of devices are connected, the only way to identify a device is this address as there is not IP or Port.
Why don't you change the way the connection is done? Use a Client instead of a Server in your application and a Server in your Devices(PLC, ...). Then, you need N modbus clients that will poll the servers. Every modbus client will represent a Device.
In this case you will have N modbus clients. Using the other approach you have N modus servers.
-
Hi @IvanVa,
However, the real problem , as you mentioned, is to differentiate the client.
Yes, in classical TCP/IP the remote port is used for that. As Modbus/TCP is based on TCP, this information should still be available.
If multiple clients connect to the same server with address '1' (this addres is like an id), when they send (or to be more technical, write) data to the server, a signal is emitted but it does not contain any reference of the client who sent it.
But then you would have to give the client another address, not the server. Am I right?
But being forced to potentially open 1000 ports for 1000 clients is not a big deal.
You want to manage 1000 slaves? :)
I slightly remember, that Linux
systemd
is able to listen to one port, and if a connection arrives, it starts a new instance of the server process and then connects the server to the existing connection.Wouldn't that be what you need?
-
@ollarch
serverAddress still do something event with tcp. With the qtcreator examples, if serverAddress don't match an error is lauched.i was temporary excluding to invert the server/client because i'm potentially bouncing into a nat problem, but it's still an idea.
But then you would have to give the client another address, not the server. Am I right?
there's no 'clientAddress' in the modbus. And if i tell the client to send data to the server '2' the only server, with address=1 will not receive the data.
You want to manage 1000 slaves? :)
Nope. it was just an exageration to tell i don't want to open one port per device.
Maximum expected is no more than 5 devices (currently, in future, who knows .. :) ) -
@IvanVa
Sorry, I have developed my own modbus classes and I use to ignore this value.So, there is no other way that have a Server per Client.
You have to think that every Server will be a "map" of the Client.
You cannot have only one Server with multiple Clients because you will mix data. Read the modbus documentation, one Server, one Client connection.
1000 Servers with 1000 Clients connected is not a problem. The problem could be on thefrecuency of the received data. If the Clients send data every second is not a problem but 1000 clients sending data every 1ms could be. -
Sorry, I have developed my own modbus classes and I use to ignore this value.
There is even a bugreport that proves your statement: https://bugreports.qt.io/browse/QTBUG-65201
I really feel that ModbusTcpServer should provide a means to distinguish between multiple clients.
The socket is still available in
QModbusTcpServerPrivate::setupTcpServer
and also in thereadyRead()
lambda slot, but from there it is not forwarded to the higher layers. -
Hi,
have a look here http://www.modbus.org/docs/Modbus_Messaging_Implementation_Guide_V1_0b.pdf. It says on page 23:On TCP/IP, the MODBUS server is addressed using its IP address; therefore, the MODBUS Unit Identifier is useless. The value 0xFF has to be used.
So i think you need to use multiple ports.
Or use one server where all PLCs write their data into a specific range of registers, eg
PLC Registers 1 0 - 9 2 10 - 19 3 20 - 29 ... ... -
@beecksche
Good to know. I think i will use the multiple ports solution. Sounds like less subject to accidental mistakes on the indexes as your other idea.Plus i just found that playing with the children() function of all QObjects i can reach the child (or childs) QTcpSocket objects managing the connection between the plc and the server app.
This don't avoid using multiple QModbusServer objects but at least i can check if the connected client have the expected source ip, and even emit an alarm in case multiple plc's are connected to one server.Thanks for now.
-
Hi,
I realize that this thread is over 2 years old, but I hope that someone could clarify how it would be possible to use children() function (or maybe findChild?) to locate the QTcpSocket or QTcpServer instance inside the QModbusTcpServer / QModbusTcpPrivate objects.
I am also faced with the need to identify the client for every read and write operations, so that I could correctly substitute Modbus holding registers with a client-specific version.Short of modifying and re-building the Qt sources to add my own implementation inheriting from the ModbusTcpServer class, I cannot come up with any ideas how to get access to that underlying socket for a client connection.
Any suggestion would be greatly appreciated!
Thank you,
Alex -
@Alex-O use ip aliases (Windows or Linux worked for me), then for each server (slave device) create a thread. For example I created a class where I can manipulate one modbus device (as a slave device), then attach each object (containing a modbus device) to a thread, in the main ui class.
You can do the same thing if your application acts as a client, put each client in a thread.