Initial backend with MQTT support
This commit is contained in:
@@ -11,18 +11,20 @@ set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
find_package(Qt6 COMPONENTS Widgets Qml QuickControls2 REQUIRED)
|
||||
find_package(Qt6 COMPONENTS Widgets Qml QuickControls2 Mqtt REQUIRED)
|
||||
|
||||
add_executable(${PROJECT}
|
||||
src/main.cpp
|
||||
src/FileIO.cpp
|
||||
src/Backend.cpp
|
||||
src/resources.qrc
|
||||
src/Gui/Style/resources.qrc)
|
||||
|
||||
target_link_libraries(${PROJECT}
|
||||
Qt::Widgets
|
||||
Qt::Qml
|
||||
Qt::QuickControls2)
|
||||
Qt::QuickControls2
|
||||
Qt::Mqtt)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
set_property(TARGET ${PROJECT} PROPERTY WIN32_EXECUTABLE true)
|
||||
|
||||
62
src/Backend.cpp
Normal file
62
src/Backend.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* @file Backend.cpp
|
||||
* @author Juny <marisa@fwmari.net>
|
||||
* @brief Implementation of backend module for QML
|
||||
* @version 0.1
|
||||
* @date 2024-02-13
|
||||
*
|
||||
* @copyright Copyright (c) 2024
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Backend.hpp"
|
||||
|
||||
void Backend::registerTypes(const char *uri) {
|
||||
qmlRegisterType<Backend>(uri, 0, 1, "Backend");
|
||||
}
|
||||
Backend::Backend(QObject *parent) : QObject(parent) {
|
||||
this->m_client = new QMqttClient(this);
|
||||
|
||||
connect(this->m_client, &QMqttClient::hostnameChanged, this,
|
||||
&Backend::brokerHostChanged);
|
||||
connect(this->m_client, &QMqttClient::portChanged, this,
|
||||
&Backend::brokerPortChanged);
|
||||
connect(this->m_client, &QMqttClient::stateChanged, this,
|
||||
&Backend::brokerStateChanged);
|
||||
connect(this->m_client, &QMqttClient::stateChanged, this,
|
||||
&Backend::onBrokerStateChanged);
|
||||
}
|
||||
|
||||
void Backend::connectToBroker() { this->m_client->connectToHost(); }
|
||||
void Backend::disconnectFromBroker() { this->m_client->disconnectFromHost(); }
|
||||
|
||||
const QString Backend::brokerHost() const { return this->m_client->hostname(); }
|
||||
void Backend::setBrokerHost(const QString &host) {
|
||||
this->m_client->setHostname(host);
|
||||
}
|
||||
|
||||
int Backend::brokerPort() const { return this->m_client->port(); }
|
||||
void Backend::setBrokerPort(int port) {
|
||||
if (port < 0 || port > std::numeric_limits<quint16>::max()) {
|
||||
qWarning() << "Invalid port: " << port;
|
||||
return;
|
||||
}
|
||||
|
||||
this->m_client->setPort(static_cast<quint16>(port));
|
||||
}
|
||||
|
||||
const QMqttClient::ClientState Backend::brokerState() const {
|
||||
return this->m_client->state();
|
||||
}
|
||||
void Backend::setBrokerState(const QMqttClient::ClientState &state) {
|
||||
this->m_client->setState(state);
|
||||
}
|
||||
|
||||
void Backend::onBrokerStateChanged(const QMqttClient::ClientState &state) {
|
||||
qWarning() << "State change" << state;
|
||||
|
||||
if (state != QMqttClient::Connected)
|
||||
return;
|
||||
|
||||
// TODO: subscribe
|
||||
}
|
||||
61
src/Backend.hpp
Normal file
61
src/Backend.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @file Backend.hpp
|
||||
* @author Juny <marisa@fwmari.net>
|
||||
* @brief Backend module for QML
|
||||
* @version 0.1
|
||||
* @date 2024-02-13
|
||||
*
|
||||
* @copyright Copyright (c) 2024
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMqttClient>
|
||||
#include <QObject>
|
||||
#include <QtQml>
|
||||
|
||||
class Backend : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString brokerHost READ brokerHost WRITE setBrokerHost NOTIFY
|
||||
brokerHostChanged)
|
||||
Q_PROPERTY(int brokerPort READ brokerPort WRITE setBrokerPort NOTIFY
|
||||
brokerPortChanged)
|
||||
Q_PROPERTY(QMqttClient::ClientState brokerState READ brokerState WRITE
|
||||
setBrokerState NOTIFY brokerStateChanged)
|
||||
QML_NAMED_ELEMENT(Backend)
|
||||
|
||||
public:
|
||||
explicit Backend(QObject *parent = nullptr);
|
||||
|
||||
static void registerTypes(const char *uri);
|
||||
static QObject *singletonProvider(QQmlEngine *engine, QJSEngine *);
|
||||
|
||||
// QML functions
|
||||
|
||||
Q_INVOKABLE void connectToBroker();
|
||||
Q_INVOKABLE void disconnectFromBroker();
|
||||
|
||||
// QML Properties
|
||||
|
||||
const QString brokerHost() const;
|
||||
void setBrokerHost(const QString &host);
|
||||
|
||||
int brokerPort() const;
|
||||
void setBrokerPort(int port);
|
||||
|
||||
const QMqttClient::ClientState brokerState() const;
|
||||
void setBrokerState(const QMqttClient::ClientState &state);
|
||||
|
||||
signals:
|
||||
void brokerHostChanged();
|
||||
void brokerPortChanged();
|
||||
void brokerStateChanged();
|
||||
|
||||
private slots:
|
||||
void onBrokerStateChanged(const QMqttClient::ClientState &state);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(Backend)
|
||||
QMqttClient *m_client;
|
||||
};
|
||||
@@ -4,12 +4,12 @@ import QtQuick
|
||||
|
||||
import "Settings"
|
||||
|
||||
QtObject {
|
||||
import QSpec.Backend
|
||||
|
||||
Backend {
|
||||
id: app
|
||||
|
||||
property string brokerURL: Settings._json.brokerURL || ""
|
||||
property string brokerHost
|
||||
property string brokerPort
|
||||
|
||||
property string brokerUsername: Settings._json.brokerUsername || ""
|
||||
property string brokerPassword: Settings._json.brokerPassword || ""
|
||||
@@ -19,11 +19,13 @@ QtObject {
|
||||
brokerPort = brokerURL.split(":")[1] || 1883
|
||||
}
|
||||
|
||||
function saveBroker(url, user, pass) {
|
||||
Settings._json.brokerURL = url
|
||||
Settings._json.brokerUsername = user
|
||||
Settings._json.brokerPassword = pass
|
||||
function tryConnect(url, user, pass) {
|
||||
brokerURL = Settings._json.brokerURL = url
|
||||
brokerUsername = Settings._json.brokerUsername = user
|
||||
brokerPassword = Settings._json.brokerPassword = pass
|
||||
Settings.save()
|
||||
|
||||
connectToBroker()
|
||||
}
|
||||
|
||||
function setup() {
|
||||
|
||||
@@ -11,6 +11,8 @@ ColumnLayout {
|
||||
|
||||
signal tryConnect(url: string, username: string, password: string)
|
||||
|
||||
Component.onCompleted: checkUrl(brokerURL.tfText)
|
||||
|
||||
Timer {
|
||||
id: focusTimer
|
||||
running: true
|
||||
@@ -40,19 +42,7 @@ ColumnLayout {
|
||||
tfText: App.brokerURL || ""
|
||||
|
||||
onTfAccepted: _tryConnect()
|
||||
|
||||
onTfChanged: (text) => {
|
||||
let url;
|
||||
|
||||
try {
|
||||
url = new URL(`https://${text}`)
|
||||
} catch (_) {
|
||||
btn.enabled = false
|
||||
return
|
||||
}
|
||||
|
||||
btn.enabled = true
|
||||
}
|
||||
onTfChanged: (text) => checkUrl(text)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +74,7 @@ ColumnLayout {
|
||||
id: btn
|
||||
text: qsTr("Connect")
|
||||
Layout.fillWidth: true
|
||||
// enabled: false
|
||||
enabled: false
|
||||
|
||||
onClicked: _tryConnect()
|
||||
}
|
||||
@@ -92,4 +82,22 @@ ColumnLayout {
|
||||
function _tryConnect() {
|
||||
tryConnect(brokerURL.tfText, brokerUsername.tfText, brokerPassword.tfText)
|
||||
}
|
||||
|
||||
function checkUrl(text) {
|
||||
let url;
|
||||
|
||||
if (text == "") {
|
||||
btn.enabled = false
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
url = new URL(`https://${text}`)
|
||||
} catch (_) {
|
||||
btn.enabled = false
|
||||
return
|
||||
}
|
||||
|
||||
btn.enabled = true
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ PStackView {
|
||||
anchors.centerIn: parent
|
||||
|
||||
onTryConnect: (url, user, pass) => {
|
||||
App.saveBroker(url, user, pass)
|
||||
App.tryConnect(url, user, pass)
|
||||
login.push(loadInstance)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ pragma Singleton
|
||||
import QtQuick
|
||||
import QtCore
|
||||
|
||||
import QSpec
|
||||
import QSpec.FileIO
|
||||
|
||||
QtObject {
|
||||
property string configDir: StandardPaths.writableLocation(StandardPaths.AppConfigLocation)
|
||||
|
||||
@@ -16,6 +16,11 @@ Window {
|
||||
Component.onCompleted: {
|
||||
App.setup()
|
||||
loadingTimer.running = true
|
||||
|
||||
App.brokerStateChanged.connect(() => {
|
||||
if (App.brokerState == 2)
|
||||
connectTimer.running = true
|
||||
})
|
||||
}
|
||||
|
||||
Timer {
|
||||
@@ -23,11 +28,21 @@ Window {
|
||||
|
||||
running: false
|
||||
repeat: false
|
||||
interval: 500
|
||||
interval: 750
|
||||
|
||||
onTriggered: loader.source = "qrc:/Login/Login.qml"
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: connectTimer
|
||||
|
||||
running: false
|
||||
repeat: false
|
||||
interval: 750
|
||||
|
||||
onTriggered: loader.sourceComponent = mainPane
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
anchors.fill: parent
|
||||
@@ -55,4 +70,15 @@ Window {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: mainPane
|
||||
|
||||
PBackground {
|
||||
PText {
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("YAAAAY I AM CONNECTED")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <QQuickStyle>
|
||||
#include <QQuickWindow>
|
||||
|
||||
#include "Backend.hpp"
|
||||
#include "FileIO.hpp"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
@@ -35,7 +36,8 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
QObject::connect(engine, &QQmlEngine::quit, &QApplication::quit);
|
||||
|
||||
FileIO::registerTypes("QSpec");
|
||||
FileIO::registerTypes("QSpec.FileIO");
|
||||
Backend::registerTypes("QSpec.Backend");
|
||||
|
||||
engine->addImportPath("qrc:/");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user