Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 remain ConnectingState 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?


  • Moderators

    Hi @Mark81,

    If the device is not there and it is returning true when calling connectToDevice(), then this sounds like a bug. Can you report this on JIRA with an example there to reproduce it? Thanks.



  • @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!


  • Moderators

    Hi @Mark81,

    You did it right thanks!



  • @AndyS if your issue is solved, please don't forget to mark your post as such! Thanks.


  • Moderators

    @Pablo-J.-Rogina It's not my issue :)


  • Lifetime Qt Champion

    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?


  • Lifetime Qt Champion

    @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() or disconnectDevice() your client is not connected/disconnected to the device immediately, but rather in ConnectingState/ClosingState. You have to receive the signal stateChanged() to ensure the connection state of your client. Only when the state of the client is ConnectedState 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() or disconnectDevice() your client is not connected/disconnected to the device immediately, but rather in ConnectingState/ClosingState. You have to receive the signal stateChanged() to ensure the connection state of your client. Only when the state of the client is ConnectedState 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


  • Lifetime Qt Champion

    @Mark81

    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.


Log in to reply