Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Slot called twice by QModbusReply, why?
Forum Updated to NodeBB v4.3 + New Features

Slot called twice by QModbusReply, why?

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 3 Posters 593 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    robro
    wrote on last edited by
    #1

    Hello,

    I am making my first steps with Modbus and it basically works.
    However, somehow the QModbusReply reply seems to emit the finished signal twice instead of once after calling readInputRegister(). Therfore the finishedReply() slot is invoked twice too.

    Has anyone a clue why this is happening?

    Thank you very much! :-)

    class.h:

    #ifndef MODBUS_CLIENT_H
    #define MODBUS_CLIENT_H
    
    #include "modbus_lib_global.h"
    #include <QObject>
    #include <QModbusTcpClient>
    #include <QDebug>
    
    class MODBUS_LIBSHARED_EXPORT Modbus_client : public QObject
    {
        Q_OBJECT
    
    public:
        explicit Modbus_client(QObject *parent = nullptr);
    
        void setConnectionParms(QString Ip, QString Port);
        void readInputRegister(int Registeraddress);
    
    signals:
        void queryResult(int);
    
    private slots:
        void onStateChanged();
        void onErrorOccurred();
        void finishedReply();
    
    private:
        bool debug = false;
        QModbusTcpClient *device;
        QModbusReply *reply;
        int registeraddress;
    
    };
    
    #endif // MODBUS_CLIENT_H
    

    class.cpp

    #include "modbus_client.h"
    
    Modbus_client::Modbus_client(QObject *parent) : QObject(parent)
    {
        device = new QModbusTcpClient();
        if(device != nullptr) {
            if(debug) qDebug() << "Created modbus device, state is:" << device->state();
            connect(device, &QModbusTcpClient::stateChanged, this, &Modbus_client::onStateChanged);
            connect(device, &QModbusTcpClient::errorOccurred, this, &Modbus_client::onErrorOccurred);
        } else qFatal("Unable to create Modbus TCP client device!");
    
    }
    
    void Modbus_client::setConnectionParms(QString Ip, QString Port)
    {
        device->setConnectionParameter(QModbusDevice::NetworkPortParameter, Port);
        device->setConnectionParameter(QModbusDevice::NetworkAddressParameter, Ip);
    }
    
    void Modbus_client::readInputRegister(int Registeraddress)
    {
        registeraddress = Registeraddress;
        // Connect modbus device
        if(!device->connectDevice()) {
            qDebug() << "Connect failed! Error is: " << device->errorString();
        }
    }
    
    void Modbus_client::onStateChanged()
    {
        if(device->state() == QModbusDevice::ConnectedState) {
            QVector<quint16> data(1); // One Byte
            QModbusDataUnit adu(QModbusDataUnit::InputRegisters, registeraddress, data); 
            reply = device->sendReadRequest(adu, 255);
            if(!reply->isFinished()) {
                connect(reply, &QModbusReply::finished, this, &Modbus_client::finishedReply, Qt::UniqueConnection); //Invoked only once (tested)
                qDebug() << "Invoked";
            } else finishedReply();
    
        }
        else if(device->state() == QModbusDevice::ClosingState) {
            if(debug) qDebug() << "Disconnected, state is: " << device->state();
        }
    }
    
    void Modbus_client::onErrorOccurred()
    {
        qDebug() << "Error occured!" << device->errorString();
    
    }
    
    void Modbus_client::finishedReply()
    {
        //This slot is called twice, after calling "readInputRegister()" once, but should be invoked once!
        qDebug() << "Called finishedReply()";
    
        if(reply != nullptr) {
            qDebug() << "triggered by: " <<sender();
    
            //emit queryResult(reply->result().value(0));
            reply->deleteLater();
    
        } else qDebug() << "Send of ready request failed! Error is: " << device->state();
    
    
        device->disconnectDevice();
    }
    

    Output:

    Invoked
    Called finishedReply()
    triggered by:  QModbusReply(0x27e13578770)
    Called finishedReply()
    triggered by:  QModbusReply(0x27e13578770)
    
    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Check the number of times onStateChanged is called and whether you're passing twice in the part that connects that slot.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • R Offline
        R Offline
        robro
        wrote on last edited by
        #3

        Thanks for the hint.

        I checked it.
        The condition if(device->state() == QModbusDevice::ConnectedState) is true only once.
        Still the reply slot is triggered twice.

        I do not find any mistake but I noticed that the second triggering comes late, after the device is disconnected:

        State changed QModbusDevice::ConnectingState
        State changed QModbusDevice::ConnectedState
        Invoked
        Called finishedReply()
        triggered by:  QModbusReply(0x20a102d9790)
        State changed QModbusDevice::ClosingState
        State changed QModbusDevice::UnconnectedState
        Called finishedReply()
        triggered by:  QModbusReply(0x20a102d9790)
        

        One solution to elliminate the second call of finishedReply() is to disconnect the signal in the finishedReply() function:

        disconnect(reply, &QModbusReply::finished, this, &Modbus_client::finishedReply);
        

        I know that this is dirty and therefore I still would like to figure out what happens.

        Do you have any other ideas?

        Thanks

        Pablo J. RoginaP 1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          I'd say it's likely not the expected behaviour. What version of Qt are you using ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • R robro

            Thanks for the hint.

            I checked it.
            The condition if(device->state() == QModbusDevice::ConnectedState) is true only once.
            Still the reply slot is triggered twice.

            I do not find any mistake but I noticed that the second triggering comes late, after the device is disconnected:

            State changed QModbusDevice::ConnectingState
            State changed QModbusDevice::ConnectedState
            Invoked
            Called finishedReply()
            triggered by:  QModbusReply(0x20a102d9790)
            State changed QModbusDevice::ClosingState
            State changed QModbusDevice::UnconnectedState
            Called finishedReply()
            triggered by:  QModbusReply(0x20a102d9790)
            

            One solution to elliminate the second call of finishedReply() is to disconnect the signal in the finishedReply() function:

            disconnect(reply, &QModbusReply::finished, this, &Modbus_client::finishedReply);
            

            I know that this is dirty and therefore I still would like to figure out what happens.

            Do you have any other ideas?

            Thanks

            Pablo J. RoginaP Offline
            Pablo J. RoginaP Offline
            Pablo J. Rogina
            wrote on last edited by
            #5

            @robro have you already run this client example? just to check if the double call happens there as well

            Upvote the answer(s) that helped you solve the issue
            Use "Topic Tools" button to mark your post as Solved
            Add screenshots via postimage.org
            Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

            1 Reply Last reply
            2
            • R Offline
              R Offline
              robro
              wrote on last edited by
              #6

              Hi,

              thanks!

              I am using Qt. 5.12.2 MSVC2017 x64.
              I tried the example suggested and there everything works fine.

              Still I have no clue why with my codes the slot is called twice.

              I might try a newer Qt version or stay with my disconnect call in the slot.

              For the moment I mark this as solved.

              Again, thank you very much.

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved