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. QSerialPort closed when access from another class
QtWS25 Last Chance

QSerialPort closed when access from another class

Scheduled Pinned Locked Moved Unsolved General and Desktop
18 Posts 7 Posters 1.7k Views
  • 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.
  • douglasD douglas

    @jsulm I change my code in the following way:

    mainwindow.h:

    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
        void send_serialport(QByteArray &data);
    ...
    private:
        QSerialPort *serialport;
    

    mainwindow.cpp:

    void MainWindow::send_serialport(QByteArray &data)
    {
        const qint64 bytesWritten = serialport->write(data);
    }
    

    class seriale.cpp:

    void seriale::function(void)
    {
    QByteArray ba;
        ba.resize(50);
    // fill 'ba'
    MainWindow m;
    m.send_serialport(ba);
    

    I build without errors, but when the "function" calls "send_serialport(ba)" a messagebox error appears in the UI saying:

    "Permission error while locking the device"
    

    and when I click "OK" on it, the console shows:

    QIODevice::write (QSerialPort): device not open
    

    Are there any other solutions I could try?
    Thank you!

    jsulmJ Offline
    jsulmJ Offline
    jsulm
    Lifetime Qt Champion
    wrote on last edited by
    #9

    @douglas You are still creating a LOCAL MainWindow instance!

    void seriale::function(void)
    {
    QByteArray ba;
        ba.resize(50);
    // fill 'ba'
    MainWindow m; // !!! You again create a new MainWindow instance!
    m.send_serialport(ba);
    

    Your seriale class should not know ANYTHING about MainWindow - this is simply bad design. And a UI class like MainWindow should not be the manager for serial port communication. Put your serial port in another class.

    https://forum.qt.io/topic/113070/qt-code-of-conduct

    1 Reply Last reply
    4
    • BuckwheatB Offline
      BuckwheatB Offline
      Buckwheat
      wrote on last edited by
      #10

      @douglas said in QSerialPort closed when access from another class:

      open

      Hi @douglas ,

      I am going to sound presumptuous here because I do not know if that is your exact code in the snippet but I do not see serialport->open (...) anywhere. I would think that if you are getting the "device not open" error that could be the case.
      I use QSerialPort and QCanBusDevice in an extreme multi-threaded environment and commands can be written to the port from anywhere and the input is processed on the threads to keep the user interface free without issue.

      Dave Fileccia

      douglasD 1 Reply Last reply
      0
      • BuckwheatB Buckwheat

        @douglas said in QSerialPort closed when access from another class:

        open

        Hi @douglas ,

        I am going to sound presumptuous here because I do not know if that is your exact code in the snippet but I do not see serialport->open (...) anywhere. I would think that if you are getting the "device not open" error that could be the case.
        I use QSerialPort and QCanBusDevice in an extreme multi-threaded environment and commands can be written to the port from anywhere and the input is processed on the threads to keep the user interface free without issue.

        douglasD Offline
        douglasD Offline
        douglas
        wrote on last edited by douglas
        #11

        @Buckwheat thank you for your reply. The "open" function is actually present in my code: for some reasons i forgot to paste it in the snipped I reported above, sorry!
        I changed a little my code in order to follow your suggestion, but I did not succeded yet.
        Now, I created a class "test_class" in which a declared the Serialport and other functions related to it:
        "test_class.h":

        class test_class : public QObject
        {
            Q_OBJECT
        
        public:
            explicit test_class(QObject *parent = 0);
            void serialport_init(void);
            void init_timer_RTS(void);
            void init_timer_gestione_seriale(void);
            void init_timer_lettura_s1(void);
            void InviaSuSeriale(QByteArray &data);
        
            QTimer *timer_disattivazione_RTS;
            QTimer *timer_seriale;
            QTimer *timer_lettura_S1;
        
        private:
            QSerialPort *serialport;   // serial port declaration
        ...
        

        "test_class.cpp":

        test_class::test_class(QObject *parent) : QObject(parent)
        {
        
        }
        
        
        
        /**
         * @brief serialport_manager::serialport_init
         */
        void test_class::serialport_init(void)
        {
        // this is called from MainWindow.cpp at the startup
            serialport = new QSerialPort(this);
            connect(serialport, SIGNAL(readyRead()), this, SLOT(readData()));
        
            serialport->setPortName("/dev/ttymxc2");
            serialport->setBaudRate(QSerialPort::Baud9600);
            serialport->setDataBits(QSerialPort::Data8);
            serialport->setParity(QSerialPort::NoParity);
            serialport->setStopBits(QSerialPort::OneStop);
            serialport->setFlowControl(QSerialPort::NoFlowControl);
            if (serialport->open(QIODevice::ReadWrite))   // open serialport
            {
                //showStatusMessage(tr("system status: OK"));
            }
            else
            {
                //showStatusMessage(tr("system status: COM error"));
            }
        
        /**
         * @brief serialport_manager::InviaSuSeriale
         * @param data
         */
        void test_class::InviaSuSeriale(QByteArray &data)
        {
            const qint64 bytesWritten = serialport->write(data);
        
            timer_disattivazione_RTS->start(bytesWritten);
        }
        

        In my MainWindow class I call the serialport_init function defined in the "test_class". For debug purposes, I added a pushButton that calls a function (defined always in test_class) that write through the serial port:
        MainWindow.cpp:

        void MainWindow::on_pushButton1_clicked()
        {
        QByteArray ba;
        ba.resize(50);
        /* here I fill the ba QByteArray */
        test_class tc;
        tc.InviaSuSeriale(ba);   // defined in the "test_class"
        }
        

        When I push the pushButton, nothing is sent to the serialport and the application is killed (segmentation fault error)!
        Anyone could give some advice in order to solve the issue ore give an example to analize? I think there is something wrong in the basic structure of the program.
        Thanks a lot!

        J.HilkJ 1 Reply Last reply
        0
        • douglasD douglas

          @Buckwheat thank you for your reply. The "open" function is actually present in my code: for some reasons i forgot to paste it in the snipped I reported above, sorry!
          I changed a little my code in order to follow your suggestion, but I did not succeded yet.
          Now, I created a class "test_class" in which a declared the Serialport and other functions related to it:
          "test_class.h":

          class test_class : public QObject
          {
              Q_OBJECT
          
          public:
              explicit test_class(QObject *parent = 0);
              void serialport_init(void);
              void init_timer_RTS(void);
              void init_timer_gestione_seriale(void);
              void init_timer_lettura_s1(void);
              void InviaSuSeriale(QByteArray &data);
          
              QTimer *timer_disattivazione_RTS;
              QTimer *timer_seriale;
              QTimer *timer_lettura_S1;
          
          private:
              QSerialPort *serialport;   // serial port declaration
          ...
          

          "test_class.cpp":

          test_class::test_class(QObject *parent) : QObject(parent)
          {
          
          }
          
          
          
          /**
           * @brief serialport_manager::serialport_init
           */
          void test_class::serialport_init(void)
          {
          // this is called from MainWindow.cpp at the startup
              serialport = new QSerialPort(this);
              connect(serialport, SIGNAL(readyRead()), this, SLOT(readData()));
          
              serialport->setPortName("/dev/ttymxc2");
              serialport->setBaudRate(QSerialPort::Baud9600);
              serialport->setDataBits(QSerialPort::Data8);
              serialport->setParity(QSerialPort::NoParity);
              serialport->setStopBits(QSerialPort::OneStop);
              serialport->setFlowControl(QSerialPort::NoFlowControl);
              if (serialport->open(QIODevice::ReadWrite))   // open serialport
              {
                  //showStatusMessage(tr("system status: OK"));
              }
              else
              {
                  //showStatusMessage(tr("system status: COM error"));
              }
          
          /**
           * @brief serialport_manager::InviaSuSeriale
           * @param data
           */
          void test_class::InviaSuSeriale(QByteArray &data)
          {
              const qint64 bytesWritten = serialport->write(data);
          
              timer_disattivazione_RTS->start(bytesWritten);
          }
          

          In my MainWindow class I call the serialport_init function defined in the "test_class". For debug purposes, I added a pushButton that calls a function (defined always in test_class) that write through the serial port:
          MainWindow.cpp:

          void MainWindow::on_pushButton1_clicked()
          {
          QByteArray ba;
          ba.resize(50);
          /* here I fill the ba QByteArray */
          test_class tc;
          tc.InviaSuSeriale(ba);   // defined in the "test_class"
          }
          

          When I push the pushButton, nothing is sent to the serialport and the application is killed (segmentation fault error)!
          Anyone could give some advice in order to solve the issue ore give an example to analize? I think there is something wrong in the basic structure of the program.
          Thanks a lot!

          J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by
          #12

          @douglas to quote jsulm :

          @jsulm said in QSerialPort closed when access from another class:

          @douglas You are still creating a LOCAL [...] instance!

          void MainWindow::on_pushButton1_clicked()
          {
          QByteArray ba;
          ba.resize(50);
          /* here I fill the ba QByteArray */
          test_class tc;
          tc.InviaSuSeriale(ba);   // defined in the "test_class"
          }
          

          test_class tc; is local and therefore your init was not called for that instance of your class. -> Qserialport pointer to nothingness -> segfault error


          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          douglasD 1 Reply Last reply
          0
          • J.HilkJ J.Hilk

            @douglas to quote jsulm :

            @jsulm said in QSerialPort closed when access from another class:

            @douglas You are still creating a LOCAL [...] instance!

            void MainWindow::on_pushButton1_clicked()
            {
            QByteArray ba;
            ba.resize(50);
            /* here I fill the ba QByteArray */
            test_class tc;
            tc.InviaSuSeriale(ba);   // defined in the "test_class"
            }
            

            test_class tc; is local and therefore your init was not called for that instance of your class. -> Qserialport pointer to nothingness -> segfault error

            douglasD Offline
            douglasD Offline
            douglas
            wrote on last edited by
            #13

            @J.Hilk I see. The functions in test_class are declared as "public" in .h. Which is the correct way to call them from another class without falling in my previous error? Should I simply declare "test_class tc" out of the calling function (global declaration)?

            J.HilkJ 1 Reply Last reply
            0
            • douglasD douglas

              @J.Hilk I see. The functions in test_class are declared as "public" in .h. Which is the correct way to call them from another class without falling in my previous error? Should I simply declare "test_class tc" out of the calling function (global declaration)?

              J.HilkJ Offline
              J.HilkJ Offline
              J.Hilk
              Moderators
              wrote on last edited by
              #14

              @douglas the usual way to do this, would be to make test_class tc a memeber of your class (MainWindow in this case), that allows you to access it throught your MainWindow class without the need to create a new instance of it.


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              douglasD 1 Reply Last reply
              1
              • J.HilkJ J.Hilk

                @douglas the usual way to do this, would be to make test_class tc a memeber of your class (MainWindow in this case), that allows you to access it throught your MainWindow class without the need to create a new instance of it.

                douglasD Offline
                douglasD Offline
                douglas
                wrote on last edited by
                #15

                @J.Hilk said in QSerialPort closed when access from another class:

                @douglas the usual way to do this, would be to make test_class tc a memeber of your class (MainWindow in this case), that allows you to access it throught your MainWindow class without the need to create a new instance of it.

                Can you give a very basic example on how to implement this?
                Thanks!

                J.HilkJ 1 Reply Last reply
                0
                • douglasD douglas

                  @J.Hilk said in QSerialPort closed when access from another class:

                  @douglas the usual way to do this, would be to make test_class tc a memeber of your class (MainWindow in this case), that allows you to access it throught your MainWindow class without the need to create a new instance of it.

                  Can you give a very basic example on how to implement this?
                  Thanks!

                  J.HilkJ Offline
                  J.HilkJ Offline
                  J.Hilk
                  Moderators
                  wrote on last edited by
                  #16

                  @douglas

                  //.h
                  #include "test_class.h"
                  class MainWindow : public QMainWindow
                  {
                      Q_OBJECT
                  ...
                  ...
                  
                  private:
                     test_class tc;
                  }
                  
                  //.cpp 
                  MainWindow::MainWindow(QWidget *parent) :
                      QMainWindow(parent),
                      ui(new Ui::MainWindow)
                  {
                      ....
                      tc.serialport_init();
                  }
                  
                  
                  void MainWindow::on_pushButton1_clicked()
                  {
                      QByteArray ba;
                      ba.resize(50);
                  /* here I fill the ba QByteArray */
                      
                      tc.InviaSuSeriale(ba); 
                  }
                  

                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  douglasD 1 Reply Last reply
                  1
                  • J.HilkJ J.Hilk

                    @douglas

                    //.h
                    #include "test_class.h"
                    class MainWindow : public QMainWindow
                    {
                        Q_OBJECT
                    ...
                    ...
                    
                    private:
                       test_class tc;
                    }
                    
                    //.cpp 
                    MainWindow::MainWindow(QWidget *parent) :
                        QMainWindow(parent),
                        ui(new Ui::MainWindow)
                    {
                        ....
                        tc.serialport_init();
                    }
                    
                    
                    void MainWindow::on_pushButton1_clicked()
                    {
                        QByteArray ba;
                        ba.resize(50);
                    /* here I fill the ba QByteArray */
                        
                        tc.InviaSuSeriale(ba); 
                    }
                    
                    douglasD Offline
                    douglasD Offline
                    douglas
                    wrote on last edited by
                    #17

                    @J.Hilk thanks a lot. If a "test_class" should be "visible" from 2 or more classes (say MainWindow and Class2) have I to declare

                    private:
                       test_class tc;
                    

                    in both MainWindow.h and Class2.h?

                    J.HilkJ 1 Reply Last reply
                    0
                    • douglasD douglas

                      @J.Hilk thanks a lot. If a "test_class" should be "visible" from 2 or more classes (say MainWindow and Class2) have I to declare

                      private:
                         test_class tc;
                      

                      in both MainWindow.h and Class2.h?

                      J.HilkJ Offline
                      J.HilkJ Offline
                      J.Hilk
                      Moderators
                      wrote on last edited by
                      #18

                      @douglas
                      ok, now it's getting tricky

                      here's what I usually end up doing

                      Let's asume 3 classes,

                      • class1 = your Mainwindow
                      • class2 = your Serialport communication
                      • class3 = some other class who wants to send data via serial port

                      If class 2 and class 3 objects are both members of class1, than I would suggest SIGNAL/SLOT mechanism to connect class3 Signals to class 2 slots, the connect statement is to be made in class1

                      if class3 and class1 are siblings, hirachily, than connect class1 to class 3 via signal slot or bump class2 up and make it also a sibling and connet class1 to class 2 via SignalSlot and class3 to class2 via SignalSlot

                      There are many, many other ways of course,

                      However do not create 2 seperate objects of class2, normaly that would be fine, but you're trying to access hardware at the end of the line. -> only the instance that is first to be created/connected will actually be able to communictae with the hardware.


                      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                      Q: What's that?
                      A: It's blue light.
                      Q: What does it do?
                      A: It turns blue.

                      1 Reply Last reply
                      3

                      • Login

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