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"
|
#include "Backend.hpp"
|
||||||
|
|
||||||
|
enum MsgType {
|
||||||
|
MSG_STATUS,
|
||||||
|
MSG_UNKNOWN,
|
||||||
|
};
|
||||||
|
|
||||||
void Backend::registerTypes(const char *uri) {
|
void Backend::registerTypes(const char *uri) {
|
||||||
qmlRegisterType<Backend>(uri, 0, 1, "Backend");
|
qmlRegisterType<Backend>(uri, 0, 1, "Backend");
|
||||||
}
|
}
|
||||||
@@ -25,6 +32,8 @@ Backend::Backend(QObject *parent) : QObject(parent) {
|
|||||||
&Backend::brokerStateChanged);
|
&Backend::brokerStateChanged);
|
||||||
connect(this->m_client, &QMqttClient::stateChanged, this,
|
connect(this->m_client, &QMqttClient::stateChanged, this,
|
||||||
&Backend::onBrokerStateChanged);
|
&Backend::onBrokerStateChanged);
|
||||||
|
connect(this->m_client, &QMqttClient::messageReceived, this,
|
||||||
|
&Backend::onMqttMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Backend::connectToBroker() { this->m_client->connectToHost(); }
|
void Backend::connectToBroker() { this->m_client->connectToHost(); }
|
||||||
@@ -56,8 +65,63 @@ void Backend::onBrokerStateChanged(const QMqttClient::ClientState &state) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
this->m_client->subscribe(QMqttTopicFilter("/spec"), 1);
|
this->m_client->subscribe(QMqttTopicFilter("/spec"), 1);
|
||||||
|
this->m_client->publish(QMqttTopicName("/status"));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Spec::SpecStatus Backend::specStatus() const {
|
const Spec::SpecStatus Backend::specStatus() const {
|
||||||
return this->m_specStatus;
|
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
|
// Spectrometer properties
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
Spec::SpecStatus specStatus READ specStatus NOTIFY specStatusChanged)
|
Spec::SpecStatus specStatus READ specStatus NOTIFY specStatusChanged)
|
||||||
|
Q_PROPERTY(
|
||||||
|
QString specStatusReason READ specStatusReason NOTIFY specStatusChanged)
|
||||||
|
|
||||||
QML_EXTENDED_NAMESPACE(Spec)
|
QML_EXTENDED_NAMESPACE(Spec)
|
||||||
|
|
||||||
@@ -77,6 +79,7 @@ public:
|
|||||||
const QMqttClient::ClientState brokerState() const;
|
const QMqttClient::ClientState brokerState() const;
|
||||||
|
|
||||||
const Spec::SpecStatus specStatus() const;
|
const Spec::SpecStatus specStatus() const;
|
||||||
|
const QString specStatusReason() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void brokerHostChanged();
|
void brokerHostChanged();
|
||||||
@@ -86,9 +89,13 @@ signals:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onBrokerStateChanged(const QMqttClient::ClientState &state);
|
void onBrokerStateChanged(const QMqttClient::ClientState &state);
|
||||||
|
void onMqttMessage(const QByteArray &message, const QMqttTopicName &topic);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(Backend)
|
Q_DISABLE_COPY(Backend)
|
||||||
QMqttClient *m_client;
|
QMqttClient *m_client;
|
||||||
Spec::SpecStatus m_specStatus = Spec::SPEC_UNKNOWN;
|
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 {
|
PTextButton {
|
||||||
id: btn
|
id: btn
|
||||||
text: qsTr("Connect")
|
text: qsTr("Next")
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
enabled: false
|
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 "../PStyle"
|
||||||
import ".."
|
import ".."
|
||||||
|
|
||||||
PStackView {
|
BrokerInput {
|
||||||
id: login
|
onTryConnect: (url, user, pass) => {
|
||||||
initialItem: brokerInput
|
App.tryConnect(url, user, pass)
|
||||||
|
|
||||||
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.Window
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
import QtQml
|
||||||
|
|
||||||
import "PStyle"
|
import "PStyle"
|
||||||
import "Login"
|
import "Login"
|
||||||
import "."
|
import "."
|
||||||
|
|
||||||
ApplicationWindow {
|
ApplicationWindow {
|
||||||
|
id: mainWindow
|
||||||
visible: true
|
visible: true
|
||||||
width: 640
|
|
||||||
height: 480
|
|
||||||
title: Qt.application.displayName
|
title: Qt.application.displayName
|
||||||
|
|
||||||
|
minimumWidth: 840
|
||||||
|
minimumHeight: 640
|
||||||
|
|
||||||
|
property string loadingTitle: qsTr("Loading application...")
|
||||||
|
property string loadingDesc
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
App.setup()
|
App.setup()
|
||||||
loadingTimer.running = true
|
loadingTimer.running = true
|
||||||
|
}
|
||||||
|
|
||||||
App.brokerStateChanged.connect(() => {
|
Connections {
|
||||||
if (App.brokerState == 2)
|
target: App
|
||||||
connectTimer.running = true
|
|
||||||
})
|
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 {
|
Timer {
|
||||||
@@ -41,50 +68,35 @@ ApplicationWindow {
|
|||||||
|
|
||||||
running: false
|
running: false
|
||||||
repeat: false
|
repeat: false
|
||||||
interval: 750
|
interval: 500
|
||||||
|
|
||||||
onTriggered: loader.sourceComponent = mainPane
|
onTriggered: loader.sourceComponent = mainPane
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: loader
|
id: loader
|
||||||
anchors.fill: parent
|
anchors.centerIn: parent
|
||||||
sourceComponent: loadingComponent
|
sourceComponent: loadingComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: loadingComponent
|
id: loadingComponent
|
||||||
|
|
||||||
PBackground {
|
Loading {
|
||||||
ColumnLayout {
|
id: loading
|
||||||
anchors.centerIn: parent
|
title: loadingTitle
|
||||||
spacing: 24
|
description: loadingDesc
|
||||||
|
|
||||||
PBusyIndicator {
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
Layout.preferredHeight: 48
|
|
||||||
running: true
|
|
||||||
}
|
|
||||||
|
|
||||||
PText {
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
text: qsTr("Loading application...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
function showLoading(title, desc = "") {
|
||||||
id: mainPane
|
loadingTitle = title
|
||||||
|
loadingDesc = desc
|
||||||
PBackground {
|
loader.sourceComponent = loadingComponent
|
||||||
PText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: qsTr("YAAAAY I AM CONNECTED")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
background: PBackground {}
|
||||||
|
|
||||||
footer: ToolBar {
|
footer: ToolBar {
|
||||||
visible: false
|
visible: false
|
||||||
|
|
||||||
@@ -101,7 +113,7 @@ ApplicationWindow {
|
|||||||
RowLayout {
|
RowLayout {
|
||||||
PText {
|
PText {
|
||||||
font: PStyle.getFont(10)
|
font: PStyle.getFont(10)
|
||||||
text: qsTr("Connection status:")
|
text: qsTr("Connection:")
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -128,7 +140,7 @@ ApplicationWindow {
|
|||||||
|
|
||||||
PText {
|
PText {
|
||||||
font: PStyle.getFont(10)
|
font: PStyle.getFont(10)
|
||||||
text: qsTr("Spectrometer status:")
|
text: qsTr("Spectrometer:")
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|||||||
@@ -11,10 +11,7 @@ QtObject {
|
|||||||
|
|
||||||
property double animationDuration: 100
|
property double animationDuration: 100
|
||||||
|
|
||||||
property font font: Qt.font({
|
property font font: getFont()
|
||||||
family: "HackGen Console",
|
|
||||||
pointSize: 12,
|
|
||||||
})
|
|
||||||
|
|
||||||
function getFont(size = 12) {
|
function getFont(size = 12) {
|
||||||
return Qt.font({
|
return Qt.font({
|
||||||
|
|||||||
@@ -2,15 +2,18 @@
|
|||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
<file alias="Splash.qml">Gui/Splash.qml</file>
|
<file alias="Splash.qml">Gui/Splash.qml</file>
|
||||||
<file alias="App.qml">Gui/App.qml</file>
|
<file alias="App.qml">Gui/App.qml</file>
|
||||||
|
<file alias="Loading.qml">Gui/Loading.qml</file>
|
||||||
<file alias="qmldir">Gui/qmldir</file>
|
<file alias="qmldir">Gui/qmldir</file>
|
||||||
|
|
||||||
<!-- login -->
|
<!-- login -->
|
||||||
<file alias="Login/Login.qml">Gui/Login/Login.qml</file>
|
<file alias="Login/Login.qml">Gui/Login/Login.qml</file>
|
||||||
<file alias="Login/BrokerInput.qml">Gui/Login/BrokerInput.qml</file>
|
<file alias="Login/BrokerInput.qml">Gui/Login/BrokerInput.qml</file>
|
||||||
<file alias="Login/LoadingInfo.qml">Gui/Login/LoadingInfo.qml</file>
|
|
||||||
|
|
||||||
<!-- settings -->
|
<!-- settings -->
|
||||||
<file alias="Settings/Settings.qml">Gui/Settings/Settings.qml</file>
|
<file alias="Settings/Settings.qml">Gui/Settings/Settings.qml</file>
|
||||||
<file alias="Settings/qmldir">Gui/Settings/qmldir</file>
|
<file alias="Settings/qmldir">Gui/Settings/qmldir</file>
|
||||||
|
|
||||||
|
<!-- calibration -->
|
||||||
|
<file alias="Calibration/Calibration.qml">Gui/Calibration/Calibration.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
Reference in New Issue
Block a user