From c3776f5908c9b6ef6252d905a416cfc8ebeebe83 Mon Sep 17 00:00:00 2001 From: Juny Date: Thu, 15 Feb 2024 22:48:31 -0300 Subject: [PATCH] Initial calibration page - Fetch spectrometer status upon connection - Display appropriate page depending on the status TODO: - Write calibration instructions - Timer for periodic status fetch --- src/Backend.cpp | 64 ++++++++++++++++++++++ src/Backend.hpp | 7 +++ src/Gui/AppPage.qml | 5 ++ src/Gui/Calibration/Calibration.qml | 40 ++++++++++++++ src/Gui/Loading.qml | 29 ++++++++++ src/Gui/Login/BrokerInput.qml | 2 +- src/Gui/Login/LoadingInfo.qml | 20 ------- src/Gui/Login/Login.qml | 32 ++--------- src/Gui/Splash.qml | 84 ++++++++++++++++------------- src/Gui/Style/PStyle/PStyle.qml | 5 +- src/resources.qrc | 5 +- 11 files changed, 202 insertions(+), 91 deletions(-) create mode 100644 src/Gui/AppPage.qml create mode 100644 src/Gui/Calibration/Calibration.qml create mode 100644 src/Gui/Loading.qml delete mode 100644 src/Gui/Login/LoadingInfo.qml diff --git a/src/Backend.cpp b/src/Backend.cpp index 5d8bed0..b531ad6 100644 --- a/src/Backend.cpp +++ b/src/Backend.cpp @@ -9,8 +9,15 @@ * */ +#include + #include "Backend.hpp" +enum MsgType { + MSG_STATUS, + MSG_UNKNOWN, +}; + void Backend::registerTypes(const char *uri) { qmlRegisterType(uri, 0, 1, "Backend"); } @@ -25,6 +32,8 @@ Backend::Backend(QObject *parent) : QObject(parent) { &Backend::brokerStateChanged); connect(this->m_client, &QMqttClient::stateChanged, this, &Backend::onBrokerStateChanged); + connect(this->m_client, &QMqttClient::messageReceived, this, + &Backend::onMqttMessage); } void Backend::connectToBroker() { this->m_client->connectToHost(); } @@ -56,8 +65,63 @@ void Backend::onBrokerStateChanged(const QMqttClient::ClientState &state) { return; this->m_client->subscribe(QMqttTopicFilter("/spec"), 1); + this->m_client->publish(QMqttTopicName("/status")); } const Spec::SpecStatus Backend::specStatus() const { return this->m_specStatus; +} + +const QString Backend::specStatusReason() const { + return this->m_specStatusReason; +} + +void Backend::onMqttMessage(const QByteArray &message, + const QMqttTopicName &topic) { + QJsonParseError err; + QJsonDocument doc = QJsonDocument::fromJson(message, &err); + + if (err.error != err.NoError) { + qWarning() << "Failed to parse json message, ignoring." + << err.errorString(); + return; + } else if (doc.isObject() == false) { + qWarning() << "Wrong json format received, ignoring."; + return; + } + + QJsonObject o = doc.object(); + + if (o.contains("type") == false) { + qWarning() << "Wrong json message received, ignoring."; + return; + } + + MsgType type = (MsgType)o["type"].toInt(); + + switch (type) { + case MSG_STATUS: + this->handleStatus(o); + break; + + default: + qWarning() << "Unknown message type received, ignoring."; + return; + } +} + +void Backend::handleStatus(QJsonObject o) { + if (o.contains("status") == false) { + qWarning() << "Invalid status message received, ignoring."; + return; + } + + this->m_specStatus = (Spec::SpecStatus)o["status"].toInt(); + + if (o.contains("reason") == false) + this->m_specStatusReason = ""; + else + this->m_specStatusReason = o["reason"].toString(); + + emit this->specStatusChanged(); } \ No newline at end of file diff --git a/src/Backend.hpp b/src/Backend.hpp index feedb5f..abd9a04 100644 --- a/src/Backend.hpp +++ b/src/Backend.hpp @@ -52,6 +52,8 @@ class Backend : public QObject { // Spectrometer properties Q_PROPERTY( Spec::SpecStatus specStatus READ specStatus NOTIFY specStatusChanged) + Q_PROPERTY( + QString specStatusReason READ specStatusReason NOTIFY specStatusChanged) QML_EXTENDED_NAMESPACE(Spec) @@ -77,6 +79,7 @@ public: const QMqttClient::ClientState brokerState() const; const Spec::SpecStatus specStatus() const; + const QString specStatusReason() const; signals: void brokerHostChanged(); @@ -86,9 +89,13 @@ signals: private slots: void onBrokerStateChanged(const QMqttClient::ClientState &state); + void onMqttMessage(const QByteArray &message, const QMqttTopicName &topic); private: Q_DISABLE_COPY(Backend) QMqttClient *m_client; Spec::SpecStatus m_specStatus = Spec::SPEC_UNKNOWN; + QString m_specStatusReason = ""; + + void handleStatus(QJsonObject o); }; \ No newline at end of file diff --git a/src/Gui/AppPage.qml b/src/Gui/AppPage.qml new file mode 100644 index 0000000..f3a0a88 --- /dev/null +++ b/src/Gui/AppPage.qml @@ -0,0 +1,5 @@ +import QtQuick.Controls + +Page { + +} \ No newline at end of file diff --git a/src/Gui/Calibration/Calibration.qml b/src/Gui/Calibration/Calibration.qml new file mode 100644 index 0000000..5b4a6a1 --- /dev/null +++ b/src/Gui/Calibration/Calibration.qml @@ -0,0 +1,40 @@ +import QtQuick +import QtQuick.Layouts + +import "../PStyle" +import ".." + +ColumnLayout { + spacing: 64 + + ColumnLayout { + PText { + text: qsTr("Spectrometer needs calibration") + wrapMode: Text.WordWrap + font: PStyle.getFont(24) + } + + PText { + text: qsTr("Reason: ") + App.specStatusReason + } + } + + PText { + Layout.alignment: Qt.AlignHCenter + Layout.maximumWidth: 886 + Layout.preferredWidth: mainWindow.width * 0.7 + + font: PStyle.getFont(10) + text: qsTr( + "This is needed so the system knows where the diffraction grating " + + "is pointing at.\naaaa" + ) + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignJustify + } + + PTextButton { + Layout.alignment: Qt.AlignHCenter + text: qsTr("Continue") + } +} \ No newline at end of file diff --git a/src/Gui/Loading.qml b/src/Gui/Loading.qml new file mode 100644 index 0000000..b429343 --- /dev/null +++ b/src/Gui/Loading.qml @@ -0,0 +1,29 @@ +import QtQuick.Layouts + +import "PStyle" + +ColumnLayout { + property string title: "" + property string description: "" + + spacing: 64 + + PText { + Layout.alignment: Qt.AlignHCenter + visible: title + text: title + font: PStyle.getFont(24) + } + + PBusyIndicator { + Layout.alignment: Qt.AlignHCenter + Layout.preferredHeight: 48 + running: true + } + + PText { + Layout.alignment: Qt.AlignHCenter + visible: description + text: description + } +} \ No newline at end of file diff --git a/src/Gui/Login/BrokerInput.qml b/src/Gui/Login/BrokerInput.qml index 836035e..1179f47 100644 --- a/src/Gui/Login/BrokerInput.qml +++ b/src/Gui/Login/BrokerInput.qml @@ -72,7 +72,7 @@ ColumnLayout { PTextButton { id: btn - text: qsTr("Connect") + text: qsTr("Next") Layout.fillWidth: true enabled: false diff --git a/src/Gui/Login/LoadingInfo.qml b/src/Gui/Login/LoadingInfo.qml deleted file mode 100644 index 11e7488..0000000 --- a/src/Gui/Login/LoadingInfo.qml +++ /dev/null @@ -1,20 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls - -import "../PStyle" - -ColumnLayout { - spacing: 24 - - PBusyIndicator { - Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: 48 - running: true - } - - PText { - Layout.alignment: Qt.AlignHCenter - text: qsTr("Trying to connect...") - } -} \ No newline at end of file diff --git a/src/Gui/Login/Login.qml b/src/Gui/Login/Login.qml index 46c6556..701d2ee 100644 --- a/src/Gui/Login/Login.qml +++ b/src/Gui/Login/Login.qml @@ -6,34 +6,8 @@ import QtQml import "../PStyle" import ".." -PStackView { - id: login - initialItem: brokerInput - - property var instanceInfo - - Component { - id: brokerInput - - PBackground { - BrokerInput { - anchors.centerIn: parent - - onTryConnect: (url, user, pass) => { - App.tryConnect(url, user, pass) - login.push(loadInstance) - } - } - } - } - - Component { - id: loadInstance - - PBackground { - LoadingInfo { - anchors.centerIn: parent - } - } +BrokerInput { + onTryConnect: (url, user, pass) => { + App.tryConnect(url, user, pass) } } \ No newline at end of file diff --git a/src/Gui/Splash.qml b/src/Gui/Splash.qml index d8b2b48..7cfa38e 100644 --- a/src/Gui/Splash.qml +++ b/src/Gui/Splash.qml @@ -2,25 +2,52 @@ import QtQuick import QtQuick.Window import QtQuick.Layouts import QtQuick.Controls +import QtQml import "PStyle" import "Login" import "." ApplicationWindow { + id: mainWindow visible: true - width: 640 - height: 480 title: Qt.application.displayName + minimumWidth: 840 + minimumHeight: 640 + + property string loadingTitle: qsTr("Loading application...") + property string loadingDesc + Component.onCompleted: { App.setup() loadingTimer.running = true + } - App.brokerStateChanged.connect(() => { - if (App.brokerState == 2) - connectTimer.running = true - }) + Connections { + target: App + + function onBrokerStateChanged() { + switch (App.brokerState) { + case App.BROKER_CONNECTING: + showLoading("Connecting to broker...") + break; + + case App.BROKER_CONNECTED: + showLoading("Getting spectrometer...") + break; + } + } + + function onSpecStatusChanged() { + switch (App.specStatus) { + case App.SPEC_NEEDS_CALIBRATION: + loader.setSource( + "qrc:/Calibration/Calibration.qml", + ) + break; + } + } } Timer { @@ -41,50 +68,35 @@ ApplicationWindow { running: false repeat: false - interval: 750 + interval: 500 onTriggered: loader.sourceComponent = mainPane } - + Loader { id: loader - anchors.fill: parent + anchors.centerIn: parent sourceComponent: loadingComponent } Component { id: loadingComponent - PBackground { - ColumnLayout { - anchors.centerIn: parent - spacing: 24 - - PBusyIndicator { - Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: 48 - running: true - } - - PText { - Layout.alignment: Qt.AlignHCenter - text: qsTr("Loading application...") - } - } + Loading { + id: loading + title: loadingTitle + description: loadingDesc } } - Component { - id: mainPane - - PBackground { - PText { - anchors.centerIn: parent - text: qsTr("YAAAAY I AM CONNECTED") - } - } + function showLoading(title, desc = "") { + loadingTitle = title + loadingDesc = desc + loader.sourceComponent = loadingComponent } + background: PBackground {} + footer: ToolBar { visible: false @@ -101,7 +113,7 @@ ApplicationWindow { RowLayout { PText { font: PStyle.getFont(10) - text: qsTr("Connection status:") + text: qsTr("Connection:") } Rectangle { @@ -128,7 +140,7 @@ ApplicationWindow { PText { font: PStyle.getFont(10) - text: qsTr("Spectrometer status:") + text: qsTr("Spectrometer:") } Rectangle { diff --git a/src/Gui/Style/PStyle/PStyle.qml b/src/Gui/Style/PStyle/PStyle.qml index 0140fce..c9f8671 100644 --- a/src/Gui/Style/PStyle/PStyle.qml +++ b/src/Gui/Style/PStyle/PStyle.qml @@ -11,10 +11,7 @@ QtObject { property double animationDuration: 100 - property font font: Qt.font({ - family: "HackGen Console", - pointSize: 12, - }) + property font font: getFont() function getFont(size = 12) { return Qt.font({ diff --git a/src/resources.qrc b/src/resources.qrc index 1e8eca0..323c4ee 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -2,15 +2,18 @@ Gui/Splash.qml Gui/App.qml + Gui/Loading.qml Gui/qmldir Gui/Login/Login.qml Gui/Login/BrokerInput.qml - Gui/Login/LoadingInfo.qml Gui/Settings/Settings.qml Gui/Settings/qmldir + + + Gui/Calibration/Calibration.qml \ No newline at end of file