I'm creating a gauge cluster using the Qt tutorial. I've gone through all those steps and have the visual side complete, so now I'm on the coding side and completely green.
The setup is an Arduino sending data to a Raspberry Pi. I'm trying to take that data and send it to my QML to update the 'rpmFrame' in the QML. As an experiment, I have the Arduino just sending '800' and I can't get the gauge to show it in any capacity (the data comes in perfect no problem and I have assigned it to the double 'rpmDouble'.) I have with several attempts gotten incoming:: valueToQML to show 800 in the debug, but it never translates to the QML. I think my I just have a fundamental poor understanding of how all the variables work across the header etc.
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Timeline 1.0
import incoming 1.0
Window {
width: 1280
height: 480
visible: true
color: "#FFFFFF"
SerialIncoming{
id:incoming
}
Rectangle {
id: rectangle
x: 0
y: -7
width: 1280
height: 487
color: "#ffffff"
}
Rectangle {
id: oil
x: 331
y: 52
width: 69
height: 47
color: "#ff0000"
}
Rectangle {
id: battery
x: 405
y: 52
width: 74
height: 47
color: "#ff0000"
}
Rectangle {
id: leftturn
x: 360
y: 105
width: 69
height: 47
color: "#15ff0d"
}
Rectangle {
id: hibeam
x: 807
y: 65
width: 69
height: 47
color: "#00caff"
}
Rectangle {
id: brake
x: 881
y: 64
width: 74
height: 47
color: "#ff0000"
}
Rectangle {
id: rightturn
x: 852
y: 117
width: 69
height: 47
color: "#15ff0d"
}
Rectangle {
id: oil1
x: 369
y: 386
width: 69
height: 47
color: "#ff0000"
}
Tachometer {
id: tachometer
x: 423
y: 27
rpmFrame: {incoming.valueToQML} // <-- this is where serial data goes
displaySpeed: "500"
scale: 0.9
}
}
incoming.cpp
incoming::incoming(QObject *parent) : QObject(parent) {
arduino = new QSerialPort(this);
serialBuffer="";
arduino->setPortName("ttyACM0");
arduino->setBaudRate (QSerialPort::Baud9600);
arduino->setDataBits (QSerialPort::Data8);
arduino->setParity(QSerialPort::NoParity);
arduino->setStopBits(QSerialPort::OneStop);
arduino->setFlowControl (QSerialPort::NoFlowControl);
arduino->open(QSerialPort::ReadOnly);
QObject::connect(arduino, SIGNAL(readyRead()), this, SLOT(readSerial()));
qDebug() << "KenDash v0.0";
}
void incoming::readSerial()
{
//Buffer to Filter Data
if(arduino->bytesAvailable()>0||arduino->waitForReadyRead(10))
{
QStringList bufferSplit = serialBuffer.split(",");
if(bufferSplit.length() < 5)
{
QByteArray serialData = arduino->readAll();
serialBuffer += QString::fromStdString(serialData.toStdString());
serialData.clear();
}else{
//Clean Data Output
serialBuffer="";
QString serialOutput = bufferSplit[1];
//Split the Clean Data To Sections
QStringList dataSplit = bufferSplit[1].split("/");
QString rpmOutput = dataSplit[0];
QString speedOutput = dataSplit[1];
//qDebug() << "RPM:" << rpmOutput << "Speed:" << speedOutput;
rpmDouble = rpmOutput.toDouble();
incoming *myinstance = new incoming;
QObject *object = myinstance;
object->setProperty("valueToQML", rpmDouble);
//Read Data in Debug Panel
qDebug() << "RPM(onheader2):" << incoming::valueToQML();
}
}
}
main.cpp
#include "incoming.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<incoming>("incoming", 1, 0, "SerialIncoming");
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);
void incomingserial();
return app.exec();
}
incoming.h
#ifndef INCOMING_H
#define INCOMING_H
#pragma once
#include <QString>
#include <QSerialPort>
#include <QDebug>
#include <QObject>
#include <iostream>
void incomingserial();
class incoming : public QObject
{
Q_OBJECT
Q_PROPERTY(double valueToQML READ valueToQML WRITE setValuetoQML NOTIFY valueToQMLChanged)
public:
explicit incoming(QObject *parent = 0);
//~incoming();
double valueToQML() const
{ return rpmDouble;}
void setValuetoQML(double valueToQML)
{
_valueString = valueToQML;
emit valueToQMLChanged(valueToQML);
}
signals:
void valueToQMLChanged(double);
private slots:
void readSerial();
private:
double _valueString;
QSerialPort *arduino;
static const quint16 arduino_uno_vendor_id = 9025;
static const quint16 arduino_uno_product_id = 67;
QByteArray serialData;
QString serialBuffer;
QString parsed_data;
double rpmTachOutput;
double rpmDouble;
QString rpmOutput;
double rpmToDisplay();
};
#endif // INCOMING_H
I can't understand why you set your new incoming value to _valueString but you read the value from rpmDouble. Your QProperty read and write function should refer to the same variable so when something come from serial you should call:
this->setValuetoQML(rpmOutput.toDouble());
And inside setValuetoQML function assign new value like this:
rpmDouble = valueToQML;
Because you're returning rpmDouble when valueToQML() is called.