Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Property of object is not a function
QtWS25 Last Chance

Property of object is not a function

Scheduled Pinned Locked Moved Solved QML and Qt Quick
mqttqmlqtquickqtcharts
6 Posts 3 Posters 13.8k 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.
  • L Offline
    L Offline
    lopeztel
    wrote on 19 Jun 2019, 17:39 last edited by
    #1

    I've been working on a MQTT Dashboard, the idea is to cross compile it to run on a Raspberry Pi (topic for another time perhaps) but I've been running into some problems. I am familiar with C++ but this is the first time I try my hand at Qt and qml for a project, I've also been reading documentation and going through some tutorials but I think this case is too specific.

    First, a bit of context: My code is heavily based on both the QT MQTT quick subscription example: https://doc.qt.io/QtMQTT/qtmqtt-quicksubscription-example.html and the Oscilloscope example: https://doc.qt.io/qt-5/qtcharts-qmloscilloscope-example.html. My application is split in pages in a swipe view.

    My main idea was to add the missing update function from the Oscilloscope example's datasource.h and datasource.cpp to my qtmqttclient.h and qtmqttclient.cpp (see below) with some modifications because I am not generating my data, I get it from the mqtt message payload. The code compiles and I am able to run the application and receive messages from my MQTT broker (a Raspberry Pi) but I get this error message every time the update function should be called to replace the series in my Spline Chart:

    Message Handling
    Received 22.000000
    Message Handling
    Received 23.000000
    Message Handling
    Received 24.000000
    qrc:/main.qml:82: TypeError: Property 'update' of object [object Object] is not a function
    

    For reference, here are my source code files (please point out any noob mistakes as it helps speed up my learning process):

    main.cpp:

    #include "qmlmqttclient.h"
    //#include <QGuiApplication>
    #include <QtWidgets/QApplication>
    #include <QQmlApplicationEngine>
    #include <QLoggingCategory>
    
    int main(int argc, char *argv[])
    {
        qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
    
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        //QGuiApplication app(argc, argv);
        QApplication app(argc, argv);
    
        qmlRegisterType<QmlMqttClient>("MqttClient", 1, 0, "MqttClient");
        qmlRegisterUncreatableType<QmlMqttSubscription>("MqttClient", 1, 0, "MqttSubscription", QLatin1String("Subscriptions are read-only"));
    
        QQmlApplicationEngine engine;
        const QUrl url(QStringLiteral("qrc:/main.qml"));
    //    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
    //                     &app, [url](QObject *obj, const QUrl &objUrl) {
    //        if (!obj && url == objUrl)
    //            QCoreApplication::exit(-1);
    //    }, Qt::QueuedConnection);
        engine.load(url);
        if (engine.rootObjects().isEmpty())
                return -1;
    
        return app.exec();
    }
    

    I commented out the QGuiApplication, I read that QtCharts needs QApplication.
    Here are my qtmqttclient.h and qtmqttclient.cpp files:

    /****************************************************************************
    **
    ** Copyright (C) 2017 The Qt Company Ltd.
    ** Contact: https://www.qt.io/licensing/
    **
    ** This file is part of the examples of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:BSD$
    ** Commercial License Usage
    ** Licensees holding valid commercial Qt licenses may use this file in
    ** accordance with the commercial license agreement provided with the
    ** Software or, alternatively, in accordance with the terms contained in
    ** a written agreement between you and The Qt Company. For licensing terms
    ** and conditions see https://www.qt.io/terms-conditions. For further
    ** information use the contact form at https://www.qt.io/contact-us.
    **
    ** BSD License Usage
    ** Alternatively, you may use this file under the terms of the BSD license
    ** as follows:
    **
    ** "Redistribution and use in source and binary forms, with or without
    ** modification, are permitted provided that the following conditions are
    ** met:
    **   * Redistributions of source code must retain the above copyright
    **     notice, this list of conditions and the following disclaimer.
    **   * Redistributions in binary form must reproduce the above copyright
    **     notice, this list of conditions and the following disclaimer in
    **     the documentation and/or other materials provided with the
    **     distribution.
    **   * Neither the name of The Qt Company Ltd nor the names of its
    **     contributors may be used to endorse or promote products derived
    **     from this software without specific prior written permission.
    **
    **
    ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/
    
    #ifndef QMLMQTTCLIENT_H
    #define QMLMQTTCLIENT_H
    
    #include <QtCore/QMap>
    #include <QtCore/QObject>
    #include <QtMqtt/QMqttClient>
    #include <QtMqtt/QMqttSubscription>
    #include <QtCharts/QAbstractSeries>
    #include <QDateTime>
    
    class QmlMqttClient;
    
    QT_CHARTS_USE_NAMESPACE
    
    class QmlMqttSubscription : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QMqttTopicFilter topic MEMBER m_topic NOTIFY topicChanged)
    public:
        QmlMqttSubscription(QMqttSubscription *s, QmlMqttClient *c, QObject *parent = 0);
        ~QmlMqttSubscription();
    
    Q_SIGNALS:
        void topicChanged(QString);
        void messageReceived(const QString &msg);
    
    public slots:
        void handleMessage(const QMqttMessage &qmsg);
        Q_INVOKABLE void update(QAbstractSeries *series);
    
    private:
        Q_DISABLE_COPY(QmlMqttSubscription)
        QMqttSubscription *sub;
        QmlMqttClient *client;
        QMqttTopicFilter m_topic;
        //QDateTime current = QDateTime::currentDateTime();
        //qint64 timeRef = current.toSecsSinceEpoch();
        //qreal x = timeRef;
        qreal x = 0.0;
        QVector<QPointF> points;
        uint8_t samples = 0;
    };
    
    class QmlMqttClient : public QMqttClient
    {
        Q_OBJECT
    public:
        QmlMqttClient(QObject *parent = nullptr);
    
        Q_INVOKABLE QmlMqttSubscription *subscribe(const QString &topic);
        Q_INVOKABLE int publish(const QString &topic, const QString &message, int qos = 0, bool retain = false);
    private:
        Q_DISABLE_COPY(QmlMqttClient)
    };
    
    #endif // QMLMQTTCLIENT_H
    

    In this file I even made the update function invokable but it seems that it didn't do the trick...

    /****************************************************************************
    **
    ** Copyright (C) 2017 The Qt Company Ltd.
    ** Contact: https://www.qt.io/licensing/
    **
    ** This file is part of the examples of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:BSD$
    ** Commercial License Usage
    ** Licensees holding valid commercial Qt licenses may use this file in
    ** accordance with the commercial license agreement provided with the
    ** Software or, alternatively, in accordance with the terms contained in
    ** a written agreement between you and The Qt Company. For licensing terms
    ** and conditions see https://www.qt.io/terms-conditions. For further
    ** information use the contact form at https://www.qt.io/contact-us.
    **
    ** BSD License Usage
    ** Alternatively, you may use this file under the terms of the BSD license
    ** as follows:
    **
    ** "Redistribution and use in source and binary forms, with or without
    ** modification, are permitted provided that the following conditions are
    ** met:
    **   * Redistributions of source code must retain the above copyright
    **     notice, this list of conditions and the following disclaimer.
    **   * Redistributions in binary form must reproduce the above copyright
    **     notice, this list of conditions and the following disclaimer in
    **     the documentation and/or other materials provided with the
    **     distribution.
    **   * Neither the name of The Qt Company Ltd nor the names of its
    **     contributors may be used to endorse or promote products derived
    **     from this software without specific prior written permission.
    **
    **
    ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/
    
    #include "qmlmqttclient.h"
    #include <QDebug>
    #include <QtCharts/QXYSeries>
    #include <QtCore/QtMath>
    
    QT_CHARTS_USE_NAMESPACE
    
    QmlMqttClient::QmlMqttClient(QObject *parent)
        : QMqttClient(parent)
    {
    }
    
    QmlMqttSubscription* QmlMqttClient::subscribe(const QString &topic)
    {
        auto sub = QMqttClient::subscribe(topic, 0);
        auto result = new QmlMqttSubscription(sub, this);
        return result;
    }
    
    QmlMqttSubscription::QmlMqttSubscription(QMqttSubscription *s, QmlMqttClient *c, QObject *parent)
        : QObject(parent),
          sub(s),
          client(c)
    {
        connect(sub, &QMqttSubscription::messageReceived, this, &QmlMqttSubscription::handleMessage);
        m_topic = sub->topic();
    }
    
    QmlMqttSubscription::~QmlMqttSubscription()
    {
    }
    
    void QmlMqttSubscription::update(QAbstractSeries *series)
    {
        qDebug("Updating");
        if (series) {
            QXYSeries *xySeries = static_cast<QXYSeries *>(series);
            qDebug("Series: %s",xySeries->name().toLocal8Bit().data());
            xySeries->replace(points);
            points.clear();
        }
    }
    
    void QmlMqttSubscription::handleMessage(const QMqttMessage &qmsg)
    {
        qDebug()<<"Message Handling";
        emit messageReceived(qmsg.payload());
        x = x + 60;
        QString y_temp = qmsg.payload();
        qreal y = y_temp.toDouble();
        points.append(QPointF(x,y));
        qDebug("Received %f",y);
    }
    
    int QmlMqttClient::publish(const QString &topic, const QString &message, int qos, bool retain)
    {
        auto result = QMqttClient::publish(QMqttTopicName(topic), message.toUtf8(), qos, retain);
        return result;
    }
    

    and here are my qml files and ui :
    main.qml:

    import QtQuick 2.12
    import QtQuick.Controls 2.5
    import QtQuick.VirtualKeyboard 2.4
    import MqttClient 1.0
    import QtQuick.Window 2.2
    import QtQuick.Layouts 1.1
    import QtCharts 2.3
    
    ApplicationWindow {
        id: window
        visible: true
        width: 480
        height: 320
        title: qsTr("MQTT Dashboard")
    
        property var tempSubscription: 0
        property var humtySubscription: 0
        property var heatIdxSubscription: 0
        property real time: 0.0
    
        MqttClient {
            id: client
            clientId: "Qt_MQTT_Dashboard"
            username: "pi"
            password: "D3vi@ntart"
            cleanSession: true
        }
    
        SwipeView {
            id: swipeView
            anchors.fill: parent
            currentIndex: tabBar.currentIndex
    
            Page1Form {
                connectButton.onClicked: {
                    client.hostname = hostnameField.text
                    client.port = portField.text
                    if (client.state === MqttClient.Connected) {
                        client.disconnectFromHost()
                        tempSubscription.destroy()
                        tempSubscription = 0
                    } else {
                        client.connectToHost()
                    }
                }
    
                function stateToString(value) {
                    if (value === 0)
                        return "Disconnected"
                    else if (value === 1)
                        return "Connecting"
                    else if (value === 2)
                        return "Connected"
                    else
                        return "Unknown"
                }
    
                status.text: "Status:" + stateToString(client.state)
    
            }
    
            Page2Form {
                function tempMessage(payload)
                {
                    messageModel.insert(0, {"payload" : payload})
    
                    if (messageModel.count >= 5){
                        messageModel.remove(4)
                    }
                }
                subscribebutton.onClicked: {
                    tempSubscription = client.subscribe(qsTr("/mqtt/temperature"))
                    tempSubscription.messageReceived.connect(tempMessage)
                }
    
                Timer {
                    id: refreshTimer
                    interval: 180000 // every 3 mins
                    running: true
                    repeat: true
                    onTriggered: {
                        MqttSubscription.update(Page2Form.splineseries);
                        //dataSource.update(chartView.series(0));
                        //dataSource.update(chartView.series(1));
                    }
                }
            }
    
            Page3Form{
    
            }
        }
    
        footer: TabBar {
            id: tabBar
            currentIndex: swipeView.currentIndex
    
            TabButton {
                text: qsTr("Broker setup")
            }
            TabButton {
                text: qsTr("View Data")
            }
            TabButton {
                text: qsTr("Page 3")
            }
        }
    
        InputPanel {
            id: inputPanel
            z: 99
            x: 0
            y: window.height
            width: window.width
    
            states: State {
                name: "visible"
                when: inputPanel.active
                PropertyChanges {
                    target: inputPanel
                    y: window.height - inputPanel.height
                }
            }
            transitions: Transition {
                from: ""
                to: "visible"
                reversible: true
                ParallelAnimation {
                    NumberAnimation {
                        properties: "y"
                        duration: 250
                        easing.type: Easing.InOutQuad
                    }
                }
            }
        }
    }
    

    The Page2Form part is the one with problems, MqttSubscription.update(Page2Form.splineseries); is the referenced line, as you can see I left the similar function call from the oscilloscope example there. I also tried to call the function with argument splineseries since that is the name of the exported alias property I used in the ui file below:

    Page1Form.ui.qml:

    import QtQuick 2.12
    import QtQuick.Controls 2.5
    import QtQuick.Layouts 1.1
    import MqttClient 1.0
    import QtCharts 2.3
    
    Page {
        width: 480
        height: 320
        property alias messageView: messageView
        property alias messageModel: messageModel
        property alias subscribebutton: subscribebutton
        property alias splineseries: splineseries
        property alias spline: spline
    
        ChartView {
            enabled: client.state === MqttClient.Connected
            id: spline
            antialiasing: true
            theme: ChartView.ChartThemeDark
            title: "Temperature"
            x: 12
            y: 12
            width: 332
            height: 235
            SplineSeries {
                name: "tempSeries"
                id: splineseries
                useOpenGL: true
            }
        }
    
        ListModel {
            id: messageModel
        }
    
        ListView {
            id: messageView
            x: 365
            y: 66
            model: messageModel
            height: 181
            width: 99
            Layout.columnSpan: 2
            Layout.fillHeight: true
            Layout.fillWidth: true
            clip: true
            delegate: Rectangle {
                width: messageView.width
                height: 30
                color: index % 2 ? "#DDDDDD" : "#888888"
                radius: 5
                Text {
                    text: payload
                    anchors.centerIn: parent
                }
            }
        }
    
        Button {
            id: subscribebutton
            x: 382
            y: 12
            text: qsTr("Start")
            enabled: client.state === MqttClient.Connected
        }
    }
    
    

    Now, to the best of my knowledge the only difference between my Subscription class and the Oscilloscope example's Datasource class is that it was registered with qmlRegisterUncreatableType in main.cpp and somehow that may prevent me from calling the update function...

    Any pointers or references will be greatly appreciated!

    G 1 Reply Last reply 19 Jun 2019, 18:31
    0
    • L lopeztel
      19 Jun 2019, 17:39

      I've been working on a MQTT Dashboard, the idea is to cross compile it to run on a Raspberry Pi (topic for another time perhaps) but I've been running into some problems. I am familiar with C++ but this is the first time I try my hand at Qt and qml for a project, I've also been reading documentation and going through some tutorials but I think this case is too specific.

      First, a bit of context: My code is heavily based on both the QT MQTT quick subscription example: https://doc.qt.io/QtMQTT/qtmqtt-quicksubscription-example.html and the Oscilloscope example: https://doc.qt.io/qt-5/qtcharts-qmloscilloscope-example.html. My application is split in pages in a swipe view.

      My main idea was to add the missing update function from the Oscilloscope example's datasource.h and datasource.cpp to my qtmqttclient.h and qtmqttclient.cpp (see below) with some modifications because I am not generating my data, I get it from the mqtt message payload. The code compiles and I am able to run the application and receive messages from my MQTT broker (a Raspberry Pi) but I get this error message every time the update function should be called to replace the series in my Spline Chart:

      Message Handling
      Received 22.000000
      Message Handling
      Received 23.000000
      Message Handling
      Received 24.000000
      qrc:/main.qml:82: TypeError: Property 'update' of object [object Object] is not a function
      

      For reference, here are my source code files (please point out any noob mistakes as it helps speed up my learning process):

      main.cpp:

      #include "qmlmqttclient.h"
      //#include <QGuiApplication>
      #include <QtWidgets/QApplication>
      #include <QQmlApplicationEngine>
      #include <QLoggingCategory>
      
      int main(int argc, char *argv[])
      {
          qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
      
          QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
      
          //QGuiApplication app(argc, argv);
          QApplication app(argc, argv);
      
          qmlRegisterType<QmlMqttClient>("MqttClient", 1, 0, "MqttClient");
          qmlRegisterUncreatableType<QmlMqttSubscription>("MqttClient", 1, 0, "MqttSubscription", QLatin1String("Subscriptions are read-only"));
      
          QQmlApplicationEngine engine;
          const QUrl url(QStringLiteral("qrc:/main.qml"));
      //    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
      //                     &app, [url](QObject *obj, const QUrl &objUrl) {
      //        if (!obj && url == objUrl)
      //            QCoreApplication::exit(-1);
      //    }, Qt::QueuedConnection);
          engine.load(url);
          if (engine.rootObjects().isEmpty())
                  return -1;
      
          return app.exec();
      }
      

      I commented out the QGuiApplication, I read that QtCharts needs QApplication.
      Here are my qtmqttclient.h and qtmqttclient.cpp files:

      /****************************************************************************
      **
      ** Copyright (C) 2017 The Qt Company Ltd.
      ** Contact: https://www.qt.io/licensing/
      **
      ** This file is part of the examples of the Qt Toolkit.
      **
      ** $QT_BEGIN_LICENSE:BSD$
      ** Commercial License Usage
      ** Licensees holding valid commercial Qt licenses may use this file in
      ** accordance with the commercial license agreement provided with the
      ** Software or, alternatively, in accordance with the terms contained in
      ** a written agreement between you and The Qt Company. For licensing terms
      ** and conditions see https://www.qt.io/terms-conditions. For further
      ** information use the contact form at https://www.qt.io/contact-us.
      **
      ** BSD License Usage
      ** Alternatively, you may use this file under the terms of the BSD license
      ** as follows:
      **
      ** "Redistribution and use in source and binary forms, with or without
      ** modification, are permitted provided that the following conditions are
      ** met:
      **   * Redistributions of source code must retain the above copyright
      **     notice, this list of conditions and the following disclaimer.
      **   * Redistributions in binary form must reproduce the above copyright
      **     notice, this list of conditions and the following disclaimer in
      **     the documentation and/or other materials provided with the
      **     distribution.
      **   * Neither the name of The Qt Company Ltd nor the names of its
      **     contributors may be used to endorse or promote products derived
      **     from this software without specific prior written permission.
      **
      **
      ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
      **
      ** $QT_END_LICENSE$
      **
      ****************************************************************************/
      
      #ifndef QMLMQTTCLIENT_H
      #define QMLMQTTCLIENT_H
      
      #include <QtCore/QMap>
      #include <QtCore/QObject>
      #include <QtMqtt/QMqttClient>
      #include <QtMqtt/QMqttSubscription>
      #include <QtCharts/QAbstractSeries>
      #include <QDateTime>
      
      class QmlMqttClient;
      
      QT_CHARTS_USE_NAMESPACE
      
      class QmlMqttSubscription : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(QMqttTopicFilter topic MEMBER m_topic NOTIFY topicChanged)
      public:
          QmlMqttSubscription(QMqttSubscription *s, QmlMqttClient *c, QObject *parent = 0);
          ~QmlMqttSubscription();
      
      Q_SIGNALS:
          void topicChanged(QString);
          void messageReceived(const QString &msg);
      
      public slots:
          void handleMessage(const QMqttMessage &qmsg);
          Q_INVOKABLE void update(QAbstractSeries *series);
      
      private:
          Q_DISABLE_COPY(QmlMqttSubscription)
          QMqttSubscription *sub;
          QmlMqttClient *client;
          QMqttTopicFilter m_topic;
          //QDateTime current = QDateTime::currentDateTime();
          //qint64 timeRef = current.toSecsSinceEpoch();
          //qreal x = timeRef;
          qreal x = 0.0;
          QVector<QPointF> points;
          uint8_t samples = 0;
      };
      
      class QmlMqttClient : public QMqttClient
      {
          Q_OBJECT
      public:
          QmlMqttClient(QObject *parent = nullptr);
      
          Q_INVOKABLE QmlMqttSubscription *subscribe(const QString &topic);
          Q_INVOKABLE int publish(const QString &topic, const QString &message, int qos = 0, bool retain = false);
      private:
          Q_DISABLE_COPY(QmlMqttClient)
      };
      
      #endif // QMLMQTTCLIENT_H
      

      In this file I even made the update function invokable but it seems that it didn't do the trick...

      /****************************************************************************
      **
      ** Copyright (C) 2017 The Qt Company Ltd.
      ** Contact: https://www.qt.io/licensing/
      **
      ** This file is part of the examples of the Qt Toolkit.
      **
      ** $QT_BEGIN_LICENSE:BSD$
      ** Commercial License Usage
      ** Licensees holding valid commercial Qt licenses may use this file in
      ** accordance with the commercial license agreement provided with the
      ** Software or, alternatively, in accordance with the terms contained in
      ** a written agreement between you and The Qt Company. For licensing terms
      ** and conditions see https://www.qt.io/terms-conditions. For further
      ** information use the contact form at https://www.qt.io/contact-us.
      **
      ** BSD License Usage
      ** Alternatively, you may use this file under the terms of the BSD license
      ** as follows:
      **
      ** "Redistribution and use in source and binary forms, with or without
      ** modification, are permitted provided that the following conditions are
      ** met:
      **   * Redistributions of source code must retain the above copyright
      **     notice, this list of conditions and the following disclaimer.
      **   * Redistributions in binary form must reproduce the above copyright
      **     notice, this list of conditions and the following disclaimer in
      **     the documentation and/or other materials provided with the
      **     distribution.
      **   * Neither the name of The Qt Company Ltd nor the names of its
      **     contributors may be used to endorse or promote products derived
      **     from this software without specific prior written permission.
      **
      **
      ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
      **
      ** $QT_END_LICENSE$
      **
      ****************************************************************************/
      
      #include "qmlmqttclient.h"
      #include <QDebug>
      #include <QtCharts/QXYSeries>
      #include <QtCore/QtMath>
      
      QT_CHARTS_USE_NAMESPACE
      
      QmlMqttClient::QmlMqttClient(QObject *parent)
          : QMqttClient(parent)
      {
      }
      
      QmlMqttSubscription* QmlMqttClient::subscribe(const QString &topic)
      {
          auto sub = QMqttClient::subscribe(topic, 0);
          auto result = new QmlMqttSubscription(sub, this);
          return result;
      }
      
      QmlMqttSubscription::QmlMqttSubscription(QMqttSubscription *s, QmlMqttClient *c, QObject *parent)
          : QObject(parent),
            sub(s),
            client(c)
      {
          connect(sub, &QMqttSubscription::messageReceived, this, &QmlMqttSubscription::handleMessage);
          m_topic = sub->topic();
      }
      
      QmlMqttSubscription::~QmlMqttSubscription()
      {
      }
      
      void QmlMqttSubscription::update(QAbstractSeries *series)
      {
          qDebug("Updating");
          if (series) {
              QXYSeries *xySeries = static_cast<QXYSeries *>(series);
              qDebug("Series: %s",xySeries->name().toLocal8Bit().data());
              xySeries->replace(points);
              points.clear();
          }
      }
      
      void QmlMqttSubscription::handleMessage(const QMqttMessage &qmsg)
      {
          qDebug()<<"Message Handling";
          emit messageReceived(qmsg.payload());
          x = x + 60;
          QString y_temp = qmsg.payload();
          qreal y = y_temp.toDouble();
          points.append(QPointF(x,y));
          qDebug("Received %f",y);
      }
      
      int QmlMqttClient::publish(const QString &topic, const QString &message, int qos, bool retain)
      {
          auto result = QMqttClient::publish(QMqttTopicName(topic), message.toUtf8(), qos, retain);
          return result;
      }
      

      and here are my qml files and ui :
      main.qml:

      import QtQuick 2.12
      import QtQuick.Controls 2.5
      import QtQuick.VirtualKeyboard 2.4
      import MqttClient 1.0
      import QtQuick.Window 2.2
      import QtQuick.Layouts 1.1
      import QtCharts 2.3
      
      ApplicationWindow {
          id: window
          visible: true
          width: 480
          height: 320
          title: qsTr("MQTT Dashboard")
      
          property var tempSubscription: 0
          property var humtySubscription: 0
          property var heatIdxSubscription: 0
          property real time: 0.0
      
          MqttClient {
              id: client
              clientId: "Qt_MQTT_Dashboard"
              username: "pi"
              password: "D3vi@ntart"
              cleanSession: true
          }
      
          SwipeView {
              id: swipeView
              anchors.fill: parent
              currentIndex: tabBar.currentIndex
      
              Page1Form {
                  connectButton.onClicked: {
                      client.hostname = hostnameField.text
                      client.port = portField.text
                      if (client.state === MqttClient.Connected) {
                          client.disconnectFromHost()
                          tempSubscription.destroy()
                          tempSubscription = 0
                      } else {
                          client.connectToHost()
                      }
                  }
      
                  function stateToString(value) {
                      if (value === 0)
                          return "Disconnected"
                      else if (value === 1)
                          return "Connecting"
                      else if (value === 2)
                          return "Connected"
                      else
                          return "Unknown"
                  }
      
                  status.text: "Status:" + stateToString(client.state)
      
              }
      
              Page2Form {
                  function tempMessage(payload)
                  {
                      messageModel.insert(0, {"payload" : payload})
      
                      if (messageModel.count >= 5){
                          messageModel.remove(4)
                      }
                  }
                  subscribebutton.onClicked: {
                      tempSubscription = client.subscribe(qsTr("/mqtt/temperature"))
                      tempSubscription.messageReceived.connect(tempMessage)
                  }
      
                  Timer {
                      id: refreshTimer
                      interval: 180000 // every 3 mins
                      running: true
                      repeat: true
                      onTriggered: {
                          MqttSubscription.update(Page2Form.splineseries);
                          //dataSource.update(chartView.series(0));
                          //dataSource.update(chartView.series(1));
                      }
                  }
              }
      
              Page3Form{
      
              }
          }
      
          footer: TabBar {
              id: tabBar
              currentIndex: swipeView.currentIndex
      
              TabButton {
                  text: qsTr("Broker setup")
              }
              TabButton {
                  text: qsTr("View Data")
              }
              TabButton {
                  text: qsTr("Page 3")
              }
          }
      
          InputPanel {
              id: inputPanel
              z: 99
              x: 0
              y: window.height
              width: window.width
      
              states: State {
                  name: "visible"
                  when: inputPanel.active
                  PropertyChanges {
                      target: inputPanel
                      y: window.height - inputPanel.height
                  }
              }
              transitions: Transition {
                  from: ""
                  to: "visible"
                  reversible: true
                  ParallelAnimation {
                      NumberAnimation {
                          properties: "y"
                          duration: 250
                          easing.type: Easing.InOutQuad
                      }
                  }
              }
          }
      }
      

      The Page2Form part is the one with problems, MqttSubscription.update(Page2Form.splineseries); is the referenced line, as you can see I left the similar function call from the oscilloscope example there. I also tried to call the function with argument splineseries since that is the name of the exported alias property I used in the ui file below:

      Page1Form.ui.qml:

      import QtQuick 2.12
      import QtQuick.Controls 2.5
      import QtQuick.Layouts 1.1
      import MqttClient 1.0
      import QtCharts 2.3
      
      Page {
          width: 480
          height: 320
          property alias messageView: messageView
          property alias messageModel: messageModel
          property alias subscribebutton: subscribebutton
          property alias splineseries: splineseries
          property alias spline: spline
      
          ChartView {
              enabled: client.state === MqttClient.Connected
              id: spline
              antialiasing: true
              theme: ChartView.ChartThemeDark
              title: "Temperature"
              x: 12
              y: 12
              width: 332
              height: 235
              SplineSeries {
                  name: "tempSeries"
                  id: splineseries
                  useOpenGL: true
              }
          }
      
          ListModel {
              id: messageModel
          }
      
          ListView {
              id: messageView
              x: 365
              y: 66
              model: messageModel
              height: 181
              width: 99
              Layout.columnSpan: 2
              Layout.fillHeight: true
              Layout.fillWidth: true
              clip: true
              delegate: Rectangle {
                  width: messageView.width
                  height: 30
                  color: index % 2 ? "#DDDDDD" : "#888888"
                  radius: 5
                  Text {
                      text: payload
                      anchors.centerIn: parent
                  }
              }
          }
      
          Button {
              id: subscribebutton
              x: 382
              y: 12
              text: qsTr("Start")
              enabled: client.state === MqttClient.Connected
          }
      }
      
      

      Now, to the best of my knowledge the only difference between my Subscription class and the Oscilloscope example's Datasource class is that it was registered with qmlRegisterUncreatableType in main.cpp and somehow that may prevent me from calling the update function...

      Any pointers or references will be greatly appreciated!

      G Offline
      G Offline
      Gojir4
      wrote on 19 Jun 2019, 18:31 last edited by
      #2

      @lopeztel Hi,

      I don't think update is the issue.
      What MqttSubscription refer to ? I don't see any place in your code where an instance is created whith this name.
      Isn't that the problem ?

      L 1 Reply Last reply 19 Jun 2019, 19:09
      0
      • G Gojir4
        19 Jun 2019, 18:31

        @lopeztel Hi,

        I don't think update is the issue.
        What MqttSubscription refer to ? I don't see any place in your code where an instance is created whith this name.
        Isn't that the problem ?

        L Offline
        L Offline
        lopeztel
        wrote on 19 Jun 2019, 19:09 last edited by
        #3

        @Gojir4 Hi, thanks for having a look. As far as I know the class was created to just call QmlMqttSubscription* QmlMqttClient::subscribe somehow I think tempSubscription = client.subscribe(qsTr("/mqtt/temperature")) creates a subscription without creating an object of the class.

        QmlMqttSubscription* QmlMqttClient::subscribe(const QString &topic)
        {
            auto sub = QMqttClient::subscribe(topic, 0);
            auto result = new QmlMqttSubscription(sub, this);
            return result;
        }
        
        QmlMqttSubscription::QmlMqttSubscription(QMqttSubscription *s, QmlMqttClient *c, QObject *parent)
            : QObject(parent),
              sub(s),
              client(c)
        {
        

        and it is definitely working, adding to my overall confusion as to why update can't be called ....
        Also, wouldn't defining the type as uncreatable prevent me from creating an object of the class in the traditional way?

        G 1 Reply Last reply 19 Jun 2019, 19:29
        0
        • L lopeztel
          19 Jun 2019, 19:09

          @Gojir4 Hi, thanks for having a look. As far as I know the class was created to just call QmlMqttSubscription* QmlMqttClient::subscribe somehow I think tempSubscription = client.subscribe(qsTr("/mqtt/temperature")) creates a subscription without creating an object of the class.

          QmlMqttSubscription* QmlMqttClient::subscribe(const QString &topic)
          {
              auto sub = QMqttClient::subscribe(topic, 0);
              auto result = new QmlMqttSubscription(sub, this);
              return result;
          }
          
          QmlMqttSubscription::QmlMqttSubscription(QMqttSubscription *s, QmlMqttClient *c, QObject *parent)
              : QObject(parent),
                sub(s),
                client(c)
          {
          

          and it is definitely working, adding to my overall confusion as to why update can't be called ....
          Also, wouldn't defining the type as uncreatable prevent me from creating an object of the class in the traditional way?

          G Offline
          G Offline
          Gojir4
          wrote on 19 Jun 2019, 19:29 last edited by
          #4

          @lopeztel said in Property of object is not a function:

          tempSubscription = client.subscribe(qsTr("/mqtt/temperature"))

          Ok, I didn't see it sorry. So should not it be :

          tempSubscription.update(Page2Form.splineseries); 
          
          L 1 Reply Last reply 19 Jun 2019, 19:41
          4
          • G Gojir4
            19 Jun 2019, 19:29

            @lopeztel said in Property of object is not a function:

            tempSubscription = client.subscribe(qsTr("/mqtt/temperature"))

            Ok, I didn't see it sorry. So should not it be :

            tempSubscription.update(Page2Form.splineseries); 
            
            L Offline
            L Offline
            lopeztel
            wrote on 19 Jun 2019, 19:41 last edited by
            #5

            @Gojir4 shoot, you're right, the subscribe function returns the actual subscription object! All along I had what I needed! Noob mistake, thanks a lot!
            This is what happens when you spend hours staring at the screen ...

            1 Reply Last reply
            1
            • F Offline
              F Offline
              fcarney
              wrote on 19 Jun 2019, 19:52 last edited by
              #6

              @lopeztel said in Property of object is not a function:

              This is what happens when you spend hours staring at the screen ...

              Sometimes when you have had too much to think you need a break and coffee.

              C++ is a perfectly valid school of magic.

              1 Reply Last reply
              1

              3/6

              19 Jun 2019, 19:09

              • Login

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