Unsolved QtModbus doesn't reconnect programmatically
-
In my application I have two
QAction
for connecting and disconnecting:QModbusClient *_modbus; void modbusConnect(QString host, int port) { if (_modbus) { _modbus->disconnectDevice(); delete _modbus; } _modbus = new QModbusTcpClient(this); _modbus->setConnectionParameter(QModbusDevice::NetworkPortParameter, port); _modbus->setConnectionParameter(QModbusDevice::NetworkAddressParameter, host); _modbus->setTimeout(250); _modbus->setNumberOfRetries(1); qDebug() << _modbus->connectDevice(); _timerConnectionTimeout.start(); } void modbusDisconnect() { if (_modbus) _modbus->disconnectDevice(); } void timerConnection_timeout() { _modbus->disconnectDevice(); emit timeoutConnection(); }
First question: even if the remote device is not available the
connectDevice()
function returns always true. But the documentation says:Connects the device to the Modbus network. Returns true on success; otherwise false.
Hence if it cannot connect the device to the Modbus network it should return false. Am I wrong?
Now I have to handle an automatic re-connection. That means if the device is connected and then it's not reachable anymore (i.e. I turn it off) when it will be available again I want to reconnect to it. Hence I did something very simple: when a reading timeouts I do the following:
ui->actionDisconnect->trigger(); QTimer::singleShot(1000, ui->actionConnect, &QAction::trigger);
Those
QAction
will call the two functions above. Well, something weird happens: with this code the_modbus->state()
will remainConnectingState
forever. Even when the device is available - I mean it does not connect at all.Instead if I click those actions with the mouse, it will connect immediately!
The code executed is the very same... why it doesn't work programmatically? Is there a better way to reconnect? -
-
@AndyS Here the issue: https://bugreports.qt.io/browse/QTBUG-71282. It's the first time I created one - I hope I did it well!
-
Hi @Mark81,
You did it right thanks!
-
@AndyS if your issue is solved, please don't forget to mark your post as such! Thanks.
-
@Pablo-J.-Rogina It's not my issue :)
-
Neither is mine :)
Anyway, closing this as there is nothing we can do here anymore.
-
Sorry guys, but the issue is not solved at all! We've just discovered a documentation bug - but that wasn't the main issue.
The big problem, still there, is the second part of the question. Why does reconnection work only if triggered by a user click and it doesn't executing the same code using a
QTimer
? -
@Mark81 don't connect the timer to the action, connect it to the corresponding slot instead.
-
The QtModubus module has an asynchronous API. So by calling
connectDevice()
ordisconnectDevice()
your client is not connected/disconnected to the device immediately, but rather inConnectingState/ClosingState
. You have to receive the signalstateChanged()
to ensure the connection state of your client. Only when the state of the client isConnectedState
your client is connected.Also when you want to reconnect, I would ensure that you the state of the client is
UnconnectedState
.Or just do a QHostInfo::lookupHost . Once the lookup was successfull you can connect again.
-
@aha_1980 said in QtModbus doesn't reconnect programmatically:
@Mark81 don't connect the timer to the action, connect it to the corresponding slot instead.
Tried: nothing change.
-
@beecksche said in QtModbus doesn't reconnect programmatically:
The QtModubus module has an asynchronous API. So by calling
connectDevice()
ordisconnectDevice()
your client is not connected/disconnected to the device immediately, but rather inConnectingState/ClosingState
. You have to receive the signalstateChanged()
to ensure the connection state of your client. Only when the state of the client isConnectedState
your client is connected.Also when you want to reconnect, I would ensure that you the state of the client is
UnconnectedState
.I'm aware of this, but I have some thoughts about:
-
I cannot wait such a long time: the built-in timeout is too long for my needs. Hence when I want to disconnect and reconnect I must use my own timeout timer
-
I understand it might not be the best approach, but after calling
disconnectDevice()
I actually delete the object. It's not enough to force a disconnection? -
Anyway, I don't understand why it works clicking the action on the UI, even one right the other, and it doesn't by code, even waiting few seconds
-
-
Then either debug it yourself, or provide more code.
Are you sure
ui->actionDisconnect->trigger();
does what you expect?It should work the same way with a timer as it would work with a button.