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

QWebSockets problems!



  • MySocket.h

    #ifndef MYSOCKET_H
    #define MYSOCKET_H
    
    // =========================================================================================================== //
    // INCLUDE
    // =========================================================================================================== //
    #include <QObject>
    #include <QtWebSockets/QWebSocket>
    
    // =========================================================================================================== //
    // Socket CLASS
    // =========================================================================================================== //
    class MySocket : public QObject
    {
        Q_OBJECT
    
    public:
        explicit MySocket(QObject *parent = nullptr);
        void doConnect(QString URL);
    
    Q_SIGNALS:
        void closed();
        void connected();
        void onError();
    
    private Q_SLOTS:
        void sendCommandStrip(const QString &bName, int bValue);
        void sendCommandMatrix(QString bValue);
        void close();
    
    private:
        QWebSocket m_webSocket;
        QUrl m_url;
        bool m_debug;
    };
    
    #endif // MYSOCKET_H
    

    MySocket.cpp

    #include "MySocket.h"
    #include <QDebug>
    
    QT_USE_NAMESPACE
    
    // =========================================================================================================== //
    // CONSTRUCTOR
    // =========================================================================================================== //
    MySocket::MySocket(QObject *parent) : QObject(parent)
    {
        connect(&m_webSocket, &QWebSocket::connected, this, emit &MySocket::connected);
        connect(&m_webSocket, &QWebSocket::disconnected, this, &MySocket::closed);
        connect(&m_webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error), this, &MySocket::onError);
        /*connect(&m_webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error), [=](QAbstractSocket::SocketError error)
        {
           qDebug() << "[ERROR][SOCKET] " << error;
        });*/
    
    }
    
    
    // Socket Connected
    // =========================================================================================================== //
    void MySocket::doConnect(QString URL)
    {
        m_webSocket.open(QUrl(URL));
    }
    
    // Send Message (For Strips)
    // =========================================================================================================== //
    void MySocket::sendCommandStrip(const QString &bName, int bValue)
    {
        m_webSocket.sendTextMessage(QStringLiteral("{%0:%1}").arg(bName).arg(bValue));
    }
    
    // Send Message (For Matrix)
    // =========================================================================================================== //
    void MySocket::sendCommandMatrix(QString bValue)
    {
        m_webSocket.sendTextMessage(bValue);
    }
    
    // Socket Close
    // =========================================================================================================== //
    void MySocket::close()
    {
        m_webSocket.close();
        qDebug() << "This is from MySocket, We are closing the connection";
    }
    
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QMap>
    #include <QString>
    #include "Structs.h"
    #include "MySocket.h"
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
        QMap<QString, DeviceInfo> board;
        QMap<QString, Pattern> pattern;
        Hue hue;
        MySocket Socket;
    
    public slots:
        void whenConnected();
        void onError();
    
    private slots:
        void on_BUTTON_ADD_DEVICE_clicked();
    
        void on_BUTTON_QUIT_clicked();
        void on_BUTTON_MINIMIZE_clicked();
        void on_BUTTON_MAXIMIZE_clicked();
    
        void on_BUTTON_STUDIOLIGHT_clicked();
        void on_BUTTON_NEONHEAVEN_clicked();
        void on_BUTTON_VITRINESKAP_clicked();
        void on_BUTTON_VOODOOMASK_clicked();
        void on_BUTTON_TESTDEVICE_clicked();
    
        void connectTo(QString selected_board);
    
    private:
        Ui::MainWindow *ui;
    
    protected:
        void mousePressEvent(QMouseEvent *) override;
    };
    #endif // MAINWINDOW_H
    

    mainwindow.cpp

    // =========================================================================================================== //
    // INCLUDE
    // =========================================================================================================== //
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "adddevice.h"
    #include "QMouseEvent"
    #include "QWindow"
    #include "Structs.h"
    #include <QFile>
    #include <QFileInfo>
    #include <QObject>
    
    #include <QCoreApplication>
    #include <QCommandLineParser>
    #include <QCommandLineOption>
    #include "MySocket.h"
    #include "QDebug"
    
    // =========================================================================================================== //
    // MainWindow
    // =========================================================================================================== //
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent),
        Socket(this),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        // Remove the Microsoft Windows Window Frame
        // ======================================================================================================= //
        setWindowFlag(Qt::FramelessWindowHint);
    
        // Set window to fullscreen
        // ======================================================================================================= //
        //showFullScreen();
    
        // Set software defaults at startup
        // ======================================================================================================= //
        ui->stackedWidget->setCurrentIndex(0);                // Set Stack Widget to Welcome Page ( 0 )
        ui->TEXT_DEFAULT->setText("Please Select A Board!");  // Set TEXT_DEFAULT
        ui->TEXT_ERROR->setVisible(false);                    // Hide TEXT_ERROR
        ui->TEXT_SOFTWARE_DEVICE->setVisible(false);          // Hide Device Name
        ui->TEXT_SOFTWARE_ARROW->setVisible(false);           // Hide Device Arrow
        ui->TEXT_SOFTWARE_WALL->setVisible(false);            // Hide Device Wall
    
        // Setup Device Struct
        // ======================================================================================================= //
        board.insert("Studio Lights", DeviceInfo{"Studio Lights", false, "192.168.10.122", "online", "off"});
        board.insert("Neon Heaven", DeviceInfo{"Neon Heaven", true, "192.168.10.146", "online", "off"});
        board.insert("Vitrineskap", DeviceInfo{"Vitrineskap", false, "vitrineskap", "online", "off"});
        board.insert("Voodoo Mask", DeviceInfo{"Voodoo Mask", false, "voodoomask", "online", "off"});
        board.insert("Test Device", DeviceInfo{"Test Device", false, "test123", "online", "off"});
    
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    // =========================================================================================================== //
    // ReEnable moving of window
    // =========================================================================================================== //
    void MainWindow::mousePressEvent(QMouseEvent *) {
        if (QWindow *window = windowHandle())
            window->startSystemMove();
    }
    
    // =========================================================================================================== //
    // FUNCTIONS
    // =========================================================================================================== //
    void MainWindow::connectTo(QString selected_board)
    {
        // Set some UI defaults
        ui->stackedWidget->setCurrentIndex(0);                        // Show WelcomePage(0)
        ui->TEXT_SOFTWARE_WALL->setVisible(false);                    // Hide Wall in titel bar
        ui->TEXT_SOFTWARE_DEVICE->setVisible(false);                  // Hide Device Name connected to in titel bar
        ui->TEXT_SOFTWARE_ARROW->setVisible(false);                   // Hide Arrows in titel bar
        ui->COMBO_SELECT_STRIP->setVisible(false);                    // Hide Combo Box in titel bar
        ui->COMBO_SELECT_STRIP->setEnabled(false);                    // Disable Combo Box
        ui->TEXT_DEFAULT->setText("Connecting to " + selected_board); // Set Text_Default
        ui->TEXT_SOFTWARE_DEVICE->setText(selected_board);            // Set text for Device connecting to in titel bar
    
        qDebug() << "[SOCKET][INFO] : Trying to connect to : " << selected_board;    // Debugging
        connect(&Socket, &MySocket::connected, this, &MainWindow::whenConnected);    // Connect Socket Signal to MainWindow Slot
        connect(&Socket, &MySocket::onError, this, &MainWindow::onError);            // Connect Socket Signal to MainWindow Slot
    
        auto key = selected_board; // Lookup IP for the device selected
            if ( board.count(key) ) {
                DeviceInfo &di = board[key];
                Socket.doConnect(QStringLiteral("ws://%1:80").arg(di.ip)); // Do The Socket Connection
            }
            else
            {
                qDebug() << "[STRUCT][ERROR] Did not find key @ " << selected_board; // Debugging
            }
    }
    
    void MainWindow::whenConnected()
    {
        qDebug() << "[SOCKET][INFO] : We are connected!"; // Debugging
        ui->stackedWidget->setCurrentIndex(1);            // Show NeonPage(1)
        ui->TEXT_SOFTWARE_WALL->setVisible(true);         // Show Wall in titel bar
        ui->TEXT_SOFTWARE_DEVICE->setVisible(true);       // Show Device Name connected to in titel bar
        ui->TEXT_SOFTWARE_ARROW->setVisible(true);        // Show Arrows in titel bar
        ui->COMBO_SELECT_STRIP->setVisible(true);         // Show Combo Box in titel bar
        ui->COMBO_SELECT_STRIP->setEnabled(true);         // Enable Combo Box
    
    }
    
    void MainWindow::onError()
    {
        qDebug() << "[SOCKET][ERROR] : Something happened!";
    }
    // =========================================================================================================== //
    // BUTTONS
    // =========================================================================================================== //
    
    // ADD DEVICE
    // =========================================================================================================== //
    void MainWindow::on_BUTTON_ADD_DEVICE_clicked()
    {
        AddDevice addDevice;
        addDevice.setModal(true);
        addDevice.exec();
    
    }
    
    // TITLE BAR
    // =========================================================================================================== //
    void MainWindow::on_BUTTON_QUIT_clicked() { close(); }
    void MainWindow::on_BUTTON_MINIMIZE_clicked() { showMinimized(); }
    void MainWindow::on_BUTTON_MAXIMIZE_clicked() { if(isMaximized() == false){ showMaximized(); }else{ showNormal(); }}
    
    // DEVICE MENU
    // =========================================================================================================== //
    void MainWindow::on_BUTTON_STUDIOLIGHT_clicked() { connectTo("Studio Lights"); }
    void MainWindow::on_BUTTON_NEONHEAVEN_clicked() { connectTo("Neon Heaven"); }
    void MainWindow::on_BUTTON_VITRINESKAP_clicked() { connectTo("Vitrineskap"); }
    void MainWindow::on_BUTTON_VOODOOMASK_clicked() { connectTo("Voodoo Mask"); }
    void MainWindow::on_BUTTON_TESTDEVICE_clicked() { connectTo("Test Device"); }
    
    // DEVICE MENU
    // =========================================================================================================== //
    
    

    PROBLEM

    i connect to a Online device

    [SOCKET][INFO] : Trying to connect to :  "Studio Lights"
    [SOCKET][INFO] : We are connected!
    

    now that's fine and works as it should but if i now go on to connect to another device (either offline or online) in this case offline i get this

    [SOCKET][INFO] : Trying to connect to :  "Neon Heaven"
    [SOCKET][ERROR] : Something happened!
    

    when i now go back to connecting to Studio Lights device i get this

    [SOCKET][INFO] : Trying to connect to :  "Studio Lights"
    [SOCKET][INFO] : We are connected!
    [SOCKET][INFO] : We are connected!
    [SOCKET][INFO] : We are connected!
    

    so im getting 3 x We Are Connected! what am i doing wrong?



  • @Kris-Revi said in QWebSockets problems!:
    Each time you call MainWindow::connectTo(QString selected_board) you are creating new connect()s. And since I don't see that you disconnect them, this leads to duplicate connections (Qt does not ignore them for you), leading to multiple calls of the slots.

    Since your connect()s do not do anything with the passed-in selected_board, they only care about Socket, the connect()s should only be done where Socket changes, i.e. MainWindow::MainWindow() constructor, to ensure the connection is only made once.



  • @JonB moved both connect()s to the MainWindow Constructor :) now behaves like it should!

    alltho im still unsure if the Socket closes properly... in MySocket.cpp i have this

    connect(&m_webSocket, &QWebSocket::disconnected, this, &MySocket::close);
    
    void MySocket::close()
    {
        m_webSocket.close();
        qDebug() << "This is from MySocket, We are closing the connection";
    }
    

    This gets fired IF i close the GUI or the Device is offline and gets an error, shouldn't this also be fired off between devices? when i go from 1 device to another?



  • @Kris-Revi said in QWebSockets problems!:

    when i go from 1 device to another?

    Probably. Where do you open() the socket?



  • @JonB that happens in MainWindow.cpp

    in MainWindow.h in the MainWindow Class i have

    MySocket Socket;
    

    and in MainWindow.cpp i have

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent),
        Socket(this), // <-------------------------- Socket as parent 
        ui(new Ui::MainWindow)
    {
    
    void MainWindow::connectTo(QString selected_board)
    {
        qDebug() << "[SOCKET][INFO] : Trying to connect to : " << selected_board;    // Debugging
    
        auto key = selected_board; // Lookup IP for the device selected
            if ( board.count(key) ) {
                DeviceInfo &di = board[key];
                Socket.doConnect(QStringLiteral("ws://%1:80").arg(di.ip)); // Do The Socket Connection
            }
            else
            {
                qDebug() << "[STRUCT][ERROR] Did not find key @ " << selected_board; // Debugging
            }
    }
    


  • @Kris-Revi said in QWebSockets problems!:

    MySocket Socket;
    

    Just a side note: it's an accepted practice to name objects with lowercase; classes with uppercase.



  • @Pablo-J-Rogina noted! and changed!

    Socket socket;



  • @Kris-Revi said in QWebSockets problems!:

    Socket socket;

    Well, based on your previous code snippets, it looks it would be:

    MySocket socket;
    


  • @Pablo-J-Rogina i changed the class name aswell to match :)

    Socket class
    socket object


Log in to reply