Initial calibration page
- Fetch spectrometer status upon connection - Display appropriate page depending on the status TODO: - Write calibration instructions - Timer for periodic status fetch
This commit is contained in:
@@ -9,8 +9,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include "Backend.hpp"
|
||||
|
||||
enum MsgType {
|
||||
MSG_STATUS,
|
||||
MSG_UNKNOWN,
|
||||
};
|
||||
|
||||
void Backend::registerTypes(const char *uri) {
|
||||
qmlRegisterType<Backend>(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();
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
5
src/Gui/AppPage.qml
Normal file
5
src/Gui/AppPage.qml
Normal file
@@ -0,0 +1,5 @@
|
||||
import QtQuick.Controls
|
||||
|
||||
Page {
|
||||
|
||||
}
|
||||
40
src/Gui/Calibration/Calibration.qml
Normal file
40
src/Gui/Calibration/Calibration.qml
Normal file
@@ -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")
|
||||
}
|
||||
}
|
||||
29
src/Gui/Loading.qml
Normal file
29
src/Gui/Loading.qml
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ ColumnLayout {
|
||||
|
||||
PTextButton {
|
||||
id: btn
|
||||
text: qsTr("Connect")
|
||||
text: qsTr("Next")
|
||||
Layout.fillWidth: true
|
||||
enabled: false
|
||||
|
||||
|
||||
@@ -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...")
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,49 +68,34 @@ 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
|
||||
function showLoading(title, desc = "") {
|
||||
loadingTitle = title
|
||||
loadingDesc = desc
|
||||
loader.sourceComponent = loadingComponent
|
||||
}
|
||||
|
||||
PBackground {
|
||||
PText {
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("YAAAAY I AM CONNECTED")
|
||||
}
|
||||
}
|
||||
}
|
||||
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 {
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
<qresource prefix="/">
|
||||
<file alias="Splash.qml">Gui/Splash.qml</file>
|
||||
<file alias="App.qml">Gui/App.qml</file>
|
||||
<file alias="Loading.qml">Gui/Loading.qml</file>
|
||||
<file alias="qmldir">Gui/qmldir</file>
|
||||
|
||||
<!-- login -->
|
||||
<file alias="Login/Login.qml">Gui/Login/Login.qml</file>
|
||||
<file alias="Login/BrokerInput.qml">Gui/Login/BrokerInput.qml</file>
|
||||
<file alias="Login/LoadingInfo.qml">Gui/Login/LoadingInfo.qml</file>
|
||||
|
||||
<!-- settings -->
|
||||
<file alias="Settings/Settings.qml">Gui/Settings/Settings.qml</file>
|
||||
<file alias="Settings/qmldir">Gui/Settings/qmldir</file>
|
||||
|
||||
<!-- calibration -->
|
||||
<file alias="Calibration/Calibration.qml">Gui/Calibration/Calibration.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
Reference in New Issue
Block a user