commit 026ea972841109f1e324073b536de5971e9b7cf2 Author: unrealdragon Date: Tue Aug 4 21:31:40 2026 +0530 Http Version - Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c9e89eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/* +.qtcreator/* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..103c3b1 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,46 @@ +cmake_minimum_required(VERSION 3.16) + +project(WaterLevelRewrite VERSION 0.1 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 REQUIRED COMPONENTS Quick) + +qt_standard_project_setup(REQUIRES 6.10) + +qt_add_executable(appWaterLevelRewrite + main.cpp +) + +qt_add_qml_module(appWaterLevelRewrite + URI WaterLevelRewrite + QML_FILES + Main.qml + QML_FILES WaterTank.qml + QML_FILES SettingsBarIcon.qml + QML_FILES SettingsPopup.qml + SOURCES configinterface.h configinterface.cpp + QML_FILES ConnectButton.qml + SOURCES requestworker.h requestworker.cpp +) + +# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. +# If you are developing for iOS or macOS you should consider setting an +# explicit, fixed bundle identifier manually though. +set_target_properties(appWaterLevelRewrite PROPERTIES +# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appWaterLevelRewrite + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + MACOSX_BUNDLE TRUE + WIN32_EXECUTABLE TRUE +) + +target_link_libraries(appWaterLevelRewrite + PRIVATE Qt6::Quick +) + +install(TARGETS appWaterLevelRewrite + BUNDLE DESTINATION . + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/ConnectButton.qml b/ConnectButton.qml new file mode 100644 index 0000000..9225e44 --- /dev/null +++ b/ConnectButton.qml @@ -0,0 +1,55 @@ +import QtQuick +import QtQuick.Effects +import QtQuick.Controls +import QtQuick.Controls.Material + +Rectangle { + id: root + property color accent_color: "#00000000" + property color font_color: "#00000000" + property int font_enlarged_text_size: 20 + property int font_normal_text_size: 16 + property string text: "Connect" + signal connect; + layer.enabled: true + layer.effect: MultiEffect { + shadowEnabled: true + } + + Text { + anchors.centerIn: parent + font.pointSize: root.font_enlarged_text_size + color: root.font_color + text: root.text + horizontalAlignment: Text.AlignHCenter + } + + radius: 5 + border { + color: root.accent_color + width: 0.5 + } + MouseArea { + id: settings_button_area + anchors.fill: parent + hoverEnabled: true + property color settings_rect_pressed_prev: "#00000000" + property color settings_rect_entered_prev: "#00000000" + onEntered: { + settings_rect_entered_prev = root.color + root.color = "#5A1F1F1F" + } + onExited: { + root.color = settings_rect_entered_prev + } + onPressed: { + settings_rect_pressed_prev = root.color + root.color = "#5A1F4F1F" + root.connect(); + } + onReleased: { + root.color = settings_rect_pressed_prev + } + } + +} diff --git a/Main.qml b/Main.qml new file mode 100644 index 0000000..db445e4 --- /dev/null +++ b/Main.qml @@ -0,0 +1,156 @@ +import QtQuick +import WaterLevelRewrite +import QtQuick.Effects +import QtQuick.Controls +import QtQuick.Controls.Material + +Window { + width: 640 + height: 1080 + visible: true + title: qsTr("Water Level Rewrite") + id: root + property color accent_color: "#F05FAF5F" + property color dark_accent_color: "#FF5F7F5F" + property color danger_color: "#F0AF2F1F" + property color water_color: "#F00F7FAF" + property color background_color: "#1F1F1F" + Material.accent: root.accent_color + property int font_enlarged_text_size: 20 + property int font_normal_text_size: 16 + property int distance_count_thres: 3 + property string mode: "http" + property string status: "Initializing" + + + Rectangle { + anchors.fill: parent + color: root.background_color + + Rectangle { + id: top_bar + height: Math.min(root.height / 12, 100) + width: root.width + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + topMargin: 25 + } + color: "#0A0F0F0F" + SettingsBarIcon { + height: top_bar.height - 20 + width: top_bar.width / 12 + anchors { + top: parent.top + left: parent.left + bottomMargin: 5 + topMargin: 5 + leftMargin: 5 + } + color: "#0A0F0F0F" + radius: 100 + accent_color: root.accent_color + onOpen: { + settings_popup.open() + } + } + } + + SettingsPopup { + id: settings_popup + accent_color: root.accent_color + font_enlarged_text_size: 20 + function setConfig(new_config: var) { + settings_popup.config.max = new_config.max + settings_popup.config.min = new_config.min + settings_popup.config.alert = new_config.alert + settings_popup.config.url = new_config.url + } + onSaveConfig: (config) => { + console.log("Saving config: ", config) + config_interface.saveConfig(config); + } + } + + WaterTank { + id: tank + anchors { + top: top_bar.bottom + horizontalCenter: parent.horizontalCenter + topMargin: 0 + } + height: (parent.height - top_bar.height) / 1.2 + width: parent.width / 1.2 + base_color: root.background_color + distance: 0 + tank_lid_color: "#F0121212" + tank_base_color: "#0FFFFFFF" + water_level_color: "#F00F7FAF" + tank_base_border_color: "#F0121212" + min_thres_input: 0 + max_thres_input: 0 + } + + Text { + id: status + text: root.status + anchors { + bottom: connect_button.top + bottomMargin: 20 + horizontalCenter: parent.horizontalCenter + } + horizontalAlignment: Text.AlignHCenter + color: root.accent_color + font.pointSize: root.font_normal_text_size + } + + ConnectButton { + id: connect_button + height: parent.height / 20 + width: parent.width / 4 + font_color: root.accent_color + font_enlarged_text_size: root.font_enlarged_text_size + font_normal_text_size: root.font_normal_text_size + color: root.background_color + accent_color: root.accent_color + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + bottomMargin: 50 + } + onConnect: { + requester.start(); + root.status = "Waiting to Send."; + } + } + } + + RequestWorker { + id: requester + onStatusChanged: () => { + root.status = requester.status; + } + onNetworkReply: (water_level, fill_rate, expected) => { + tank.setDistance(water_level); + tank.rate_of_fill = fill_rate; + tank.expected_to_fill = expected; + } + } + + ConfigInterface { + id: config_interface + fileName: "config.json" + onConfig: (config) => { + settings_popup.config = config + console.log("Loading initial config"); + setConfig(config); + if(root.status === "Initializing") { + root.status = "Waiting to connect."; + } + } + function setConfig(config) { + tank.setConfig(config); + requester.setConfig(config); + } + } +} diff --git a/SettingsBarIcon.qml b/SettingsBarIcon.qml new file mode 100644 index 0000000..d360331 --- /dev/null +++ b/SettingsBarIcon.qml @@ -0,0 +1,46 @@ +import QtQuick +import QtQuick.Effects +import QtQuick.Controls +import QtQuick.Controls.Material + +Rectangle { + id: settings_rect + signal open; + property color accent_color: "#00000000" + property int font_enlarged_text_size: 20 + Behavior on color { + ColorAnimation { + duration: 200 + } + } + Text { + id: settings_text + text: "⚙" + anchors.centerIn: parent + color: settings_rect.accent_color + font.pointSize: settings_rect.font_enlarged_text_size + } + + MouseArea { + id: settings_button_area + anchors.fill: parent + hoverEnabled: true + property color settings_rect_pressed_prev: "#00000000" + property color settings_rect_entered_prev: "#00000000" + onEntered: { + settings_rect_entered_prev = settings_rect.color + settings_rect.color = "#5A1F1F1F" + } + onExited: { + settings_rect.color = settings_rect_entered_prev + } + onPressed: { + settings_rect_pressed_prev = settings_rect.color + settings_rect.color = "#5A1F4F1F" + settings_rect.open(); + } + onReleased: { + settings_rect.color = settings_rect_pressed_prev + } + } +} diff --git a/SettingsPopup.qml b/SettingsPopup.qml new file mode 100644 index 0000000..051c306 --- /dev/null +++ b/SettingsPopup.qml @@ -0,0 +1,251 @@ +import QtQuick +import QtQuick.Effects +import QtQuick.Controls +import QtQuick.Controls.Material + +Popup { + id: settings_popup + signal saveConfig(config: var) + property color accent_color: "#00000000" + property int font_enlarged_text_size: 20 + property int font_normal_text_size: 16 + property var config: { + "max": 0, + "min": 0, + "alert": 0, + "interval": 0, + "url": "none" + } + + background: Rectangle { + color: "#F0121212" + radius: 5 + border.color: settings_popup.accent_color + border.width: 1 + } + height: Math.max(parent.height / 1.2, contentHeight) + width: parent.width / 1.1 + anchors.centerIn: Overlay.overlay + Rectangle { + id: settings_base + anchors.fill: parent + color: "#F0121212" + + Text { + id: settings_label + text: "Settings" + width: parent.width + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + } + horizontalAlignment: Text.AlignHCenter + color: settings_popup.accent_color + font.pointSize: settings_popup.font_enlarged_text_size + } + + + Text { + id: max_thres_label + text: "Max Threshold: " + anchors { + topMargin: 20 + top: settings_label.bottom + left: parent.left + verticalCenter: max_thres_input.verticalCenter + } + height: max_thres_input.height + verticalAlignment: Text.AlignVCenter + color: settings_popup.accent_color + font.pointSize: settings_popup.font_normal_text_size + } + + TextField { + id: max_thres_input + text: config.max + anchors { + right: parent.right + rightMargin: 5 + top: settings_label.bottom + topMargin: 20 + } + width: parent.width / 2 + color: settings_popup.accent_color + font.pointSize: settings_popup.font_normal_text_size + } + + + Text { + id: min_thres_label + text: "Min Threshold: " + anchors { + topMargin: 20 + top: max_thres_label.bottom + left: parent.left + verticalCenter: min_thres_input.verticalCenter + } + height: min_thres_input.height + verticalAlignment: Text.AlignVCenter + color: settings_popup.accent_color + font.pointSize: settings_popup.font_normal_text_size + } + + TextField { + id: min_thres_input + text: config.min + anchors { + right: parent.right + rightMargin: 5 + top: max_thres_label.bottom + topMargin: 20 + } + width: parent.width / 2 + color: root.accent_color + font.pointSize: root.font_normal_text_size + } + + + Text { + id: alert_thres_label + text: "Alert Percentage: " + anchors { + topMargin: 20 + top: min_thres_label.bottom + left: parent.left + verticalCenter: alert_thres_input.verticalCenter + } + height: alert_thres_input.height + verticalAlignment: Text.AlignVCenter + color: settings_popup.accent_color + font.pointSize: settings_popup.font_normal_text_size + } + + TextField { + id: alert_thres_input + text: config.alert + anchors { + right: parent.right + rightMargin: 5 + top: min_thres_label.bottom + topMargin: 20 + } + width: parent.width / 2 + color: settings_popup.accent_color + font.pointSize: settings_popup.font_normal_text_size + } + + Text { + id: interval_label + text: "Update Interval: " + anchors { + topMargin: 20 + top: alert_thres_label.bottom + left: parent.left + verticalCenter: interval_input.verticalCenter + } + height: interval_input.height + verticalAlignment: Text.AlignVCenter + color: settings_popup.accent_color + font.pointSize: settings_popup.font_normal_text_size + } + + + TextField { + id: interval_input + text: config.interval + anchors { + right: parent.right + rightMargin: 5 + top: alert_thres_input.bottom + topMargin: 20 + } + width: parent.width / 2 + color: settings_popup.accent_color + font.pointSize: settings_popup.font_normal_text_size + } + + Text { + id: http_url_label + text: "Url: " + anchors { + topMargin: 20 + top: interval_label.bottom + left: parent.left + verticalCenter: http_url_input.verticalCenter + } + height: http_url_input.height + verticalAlignment: Text.AlignVCenter + color: settings_popup.accent_color + font.pointSize: settings_popup.font_normal_text_size + } + + TextField { + id: http_url_input + text: config.url + anchors { + right: parent.right + rightMargin: 20 + leftMargin: 20 + top: interval_input.bottom + topMargin: 20 + } + width: Math.max(parent.width / 2, parent.width - http_url_label.width - anchors.leftMargin) + color: settings_popup.accent_color + font.pointSize: settings_popup.font_normal_text_size + cursorPosition: 0 + } + + Rectangle { + id: save_config + anchors { + topMargin: 10 + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + } + color: "#F0121212" + width: parent.width / 1.3 + height: 60 + border { + width: 1 + color: settings_popup.accent_color + } + radius: 3 + + Text { + anchors.centerIn: parent + text: "Save" + color: settings_popup.accent_color + font.pointSize: settings_popup.font_enlarged_text_size + } + MouseArea { + anchors.fill: parent + hoverEnabled: true + property color settings_rect_pressed_prev: "#00000000" + property color settings_rect_entered_prev: "#00000000" + onEntered: { + settings_rect_entered_prev = save_config.color + save_config.color = "#5A1F1F1F" + } + onExited: { + save_config.color = settings_rect_entered_prev + } + onPressed: { + settings_rect_pressed_prev = save_config.color + save_config.color = "#5A1F4F1F" + let max = parseFloat(max_thres_input.text); + let min = parseFloat(min_thres_input.text); + let alert = parseFloat(alert_thres_input.text); + let url = http_url_input.text; + let interval = parseInt(interval_input.text); + var new_config = {"max": max, "min": min, "alert": alert, "url": url, "interval": interval} + settings_popup.saveConfig(new_config) + settings_popup.close(); + } + onReleased: { + save_config.color = settings_rect_pressed_prev + } + } + + } + } +} \ No newline at end of file diff --git a/WaterTank.qml b/WaterTank.qml new file mode 100644 index 0000000..5c1b5af --- /dev/null +++ b/WaterTank.qml @@ -0,0 +1,162 @@ +import QtQuick +import QtQuick.Effects +import QtQuick.Controls +import QtQuick.Controls.Material + +Item { + id: root + property color base_color: "#000F0F0F" + property color tank_lid_color: "#F0121212" + property color tank_base_color: "#00FFFFFF" + property color water_level_color: "#F00F7FAF" + property color tank_base_border_color: "#F0121212" + property color text_color: "#F05FAF5F" + property double height_max: tank_base.height - 10 + property double current_level: 0 + property double percentage_filled: 0 + property double distance: 0 + property double min_thres_input: 0 + property double max_thres_input: 0 + property double rate_of_fill: 0 + property double expected_to_fill: 0 + + Rectangle { + id: base + color: root.base_color + anchors.fill: parent + Rectangle { + id: tank_lid + color: root.tank_lid_color + anchors { + bottom: tank_base.top + horizontalCenter: tank_base.horizontalCenter + bottomMargin: -5 + } + radius: 10 + width: parent.width / 4 + height: parent.height / 15 + } + + Rectangle { + id: tank_base + color: root.tank_base_color + anchors.centerIn: parent + width: parent.width / 2 + height: parent.height / 2 + border.color: root.tank_base_border_color + border.width: 5 + radius: 4 + } + + Rectangle { + id: water_level + color: root.water_level_color + height: root.current_level + width: tank_base.width - 10 + anchors { + bottom: tank_base.bottom + horizontalCenter: tank_base.horizontalCenter + bottomMargin: 5 + } + Behavior on color { + ColorAnimation { + duration: 200 + } + } + Behavior on height { + NumberAnimation { + duration: 200 + } + } + } + + Text { + id: water_level_reading + text: "Current Reading: " + root.distance + " cm" + font.pointSize: 16 + color: root.text_color + anchors { + margins: 5 + top: tank_base.bottom + horizontalCenter: parent.horizontalCenter + } + horizontalAlignment: Text.AlignHCenter + } + + Text { + id: water_level_percentage + text: "Percentage: " + root.percentage_filled + " %" + font.pointSize: 16 + color: root.text_color + anchors { + margins: 5 + top: water_level_reading.bottom + horizontalCenter: parent.horizontalCenter + } + horizontalAlignment: Text.AlignHCenter + } + + Text { + id: fill_status + text: "Filling status: " + (( root.rate_of_fill > 0)? "Filling" : "Discharging") + font.pointSize: 16 + color: root.text_color + anchors { + margins: 5 + top: water_level_percentage.bottom + horizontalCenter: parent.horizontalCenter + } + horizontalAlignment: Text.AlignHCenter + } + Text { + id: rate_of_fill_label + text: "Rate of fill: " + root.rate_of_fill + " cm/s" + font.pointSize: 16 + color: root.text_color + anchors { + margins: 5 + top: fill_status.bottom + horizontalCenter: parent.horizontalCenter + } + horizontalAlignment: Text.AlignHCenter + } + Text { + id: expected_to_fill_label + text: "Expected to fill in: " + root.expected_to_fill + " s" + font.pointSize: 16 + color: root.text_color + visible: (root.rate_of_fill > 1) ? true : false + anchors { + margins: 5 + top: rate_of_fill_label.bottom + horizontalCenter: parent.horizontalCenter + } + horizontalAlignment: Text.AlignHCenter + } + } + function setConfig(config: var) { + min_thres_input = config.min; + max_thres_input = config.max; + } + + function setDistance(distance) { + root.distance = distance; + console.log("Distance changed to: ", distance); + let current_min_reading = Math.max(0, min_thres_input); + let effective_max_reading = Math.max(0, max_thres_input) - current_min_reading; + let current_reading = Math.max(0, root.distance - current_min_reading); + console.log("Current reading is: " + current_reading) + console.log("Current min reading is: " + current_min_reading) + console.log("Effective max reading is: " + effective_max_reading) + + let height_max_possible = root.height_max; + let percentage_filled = Math.max(0, ((effective_max_reading - current_reading) / effective_max_reading * 100)) + let normalized_height = percentage_filled * height_max_possible / 100; + console.log("Current reading is: " + current_reading) + console.log("Normalized height is: " + normalized_height) + console.log("Percentage filled is: " + percentage_filled) + root.current_level = normalized_height; + root.percentage_filled = percentage_filled; + } +} + diff --git a/configinterface.cpp b/configinterface.cpp new file mode 100644 index 0000000..258560f --- /dev/null +++ b/configinterface.cpp @@ -0,0 +1,53 @@ +#include "configinterface.h" + +#include +#include + +ConfigInterface::ConfigInterface(QObject *parent) + : QObject{parent} +{ +} + +QString ConfigInterface::fileName() const +{ + return m_fileName; +} + +void ConfigInterface::setFileName(const QString &newFileName) +{ + if (m_fileName == newFileName) + return; + m_fileName = newFileName; + std::fstream input(newFileName.toStdString(), std::fstream::in); + if(!input.is_open()) { + return; + } + std::string data; + std::string temp; + while(std::getline(input, temp)) { + data += temp; + } + input.flush(); + input.close(); + QByteArray arr_data(data); + QJsonDocument doc = QJsonDocument::fromJson(arr_data); + // The following works even the qml part is not initailzed/connected + // do not change back to just emit config() + QMetaObject::invokeMethod(this, &ConfigInterface::config, Qt::QueuedConnection, doc.object()); + emit fileNameChanged(); +} + +void ConfigInterface::saveConfig(QJsonObject config) +{ + QJsonDocument doc; + doc.setObject(config); + std::string data = doc.toJson().toStdString(); + std::fstream output(m_fileName.toStdString(), std::fstream::out); + if(!output.is_open()) { + return; + } + output << data; + output.flush(); + output.close(); + QMetaObject::invokeMethod(this, &ConfigInterface::config, Qt::QueuedConnection, doc.object()); +} diff --git a/configinterface.h b/configinterface.h new file mode 100644 index 0000000..606b496 --- /dev/null +++ b/configinterface.h @@ -0,0 +1,28 @@ +#ifndef CONFIGINTERFACE_H +#define CONFIGINTERFACE_H + +#include +#include +#include +#include +#include + +class ConfigInterface : public QObject +{ + Q_OBJECT + QML_ELEMENT + Q_PROPERTY(QString fileName READ fileName WRITE setFileName NOTIFY fileNameChanged FINAL) +public: + explicit ConfigInterface(QObject *parent = nullptr); + QString fileName() const; + void setFileName(const QString &newFileName); +signals: + void config(QJsonObject config); + void fileNameChanged(); +public slots: + void saveConfig(QJsonObject config); +private: + QString m_fileName; +}; + +#endif // CONFIGINTERFACE_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..c438cd2 --- /dev/null +++ b/main.cpp @@ -0,0 +1,18 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + QObject::connect( + &engine, + &QQmlApplicationEngine::objectCreationFailed, + &app, + []() { QCoreApplication::exit(-1); }, + Qt::QueuedConnection); + engine.loadFromModule("WaterLevelRewrite", "Main"); + + return QCoreApplication::exec(); +} diff --git a/requestworker.cpp b/requestworker.cpp new file mode 100644 index 0000000..eff8079 --- /dev/null +++ b/requestworker.cpp @@ -0,0 +1,112 @@ +#include "requestworker.h" +#include +#include +#include +#include + +RequestWorker::RequestWorker(QObject *parent) + : QObject{parent} +{ + +} + +void RequestWorker::setConfig(QJsonObject config) +{ + this->url = config["url"].toString(); + this->interval = config["interval"].toInt(); + this->max_height = config["max"].toInt(); + this->min_height = config["min"].toInt(); + qDebug() << "In cpp config values are: "; + qDebug() << "Url: " << url; + qDebug() << "Interval: " << interval; + qDebug() << "Max Height: " << max_height; + qDebug() << "Min Height: " << min_height; +} + +void RequestWorker::start() +{ + if(manager) { + manager->deleteLater(); + manager = nullptr; + } + manager = new QNetworkAccessManager(); + if(timer) { + timer->deleteLater(); + timer = nullptr; + } + timer = new QTimer(this); + timer->setInterval(interval); + timer->setSingleShot(true); + connect(timer, &QTimer::timeout, this, &RequestWorker::makeRequest); + timer->start(); + stop_timer = false; + setStatus("Waiting to send."); +} + +void RequestWorker::stop() +{ + if(timer->isActive()) + timer->stop(); + stop_timer = true; +} + +void RequestWorker::makeRequest() +{ + if(stop_timer) + return; + QNetworkRequest req; + req.setUrl(this->url); + disconnect(manager, nullptr, nullptr, nullptr); + connect(manager, &QNetworkAccessManager::finished, this, &RequestWorker::requestFinished); + manager->setTransferTimeout(15000); + manager->get(req); + setStatus("Request sent; Waiting for Reply."); +} + +void RequestWorker::requestFinished(QNetworkReply *rep) +{ + QByteArray data = rep->readAll(); + rep->deleteLater(); + rep = nullptr; + auto now = std::chrono::high_resolution_clock::now(); + auto time_diff = std::chrono::duration_cast(now - prev_time); + unsigned int time_in_microseconds = time_diff.count(); + QJsonObject jdata = QJsonDocument::fromJson(data).object(); + auto data_water_level = jdata["water_level"].toInt(); + float water_level = (float) ((float) (data_water_level) / 10.0); + float rate_of_fill = ( float )(water_level - prev_distance) /(float) time_in_microseconds; + rate_of_fill = rate_of_fill * 1'000'000; + int expected_to_fill = (max_height - water_level) / rate_of_fill; + if(reply_number == 0) { + rate_of_fill = 0; + expected_to_fill = 0; + } + reply_number = 1; + qDebug() << "Got water level: " << water_level; + qDebug() << "Got rate of fill: " << rate_of_fill; + qDebug() << "Got expected to fill: " << expected_to_fill; + qDebug() << "Time difference: " << time_in_microseconds; + prev_distance = water_level; + emit networkReply(water_level, rate_of_fill, expected_to_fill); + if(stop_timer) { + setStatus("Timer stopped."); + return; + } + prev_time = now; + timer->start(); + QString status = "Got Reply on: " + QDateTime::currentDateTime().toString("hh:mm:ss") + "; Waiting to Send."; + setStatus(status); +} + +QString RequestWorker::status() const +{ + return m_status; +} + +void RequestWorker::setStatus(const QString &newStatus) +{ + if (m_status == newStatus) + return; + m_status = newStatus; + emit statusChanged(); +} diff --git a/requestworker.h b/requestworker.h new file mode 100644 index 0000000..05fbafa --- /dev/null +++ b/requestworker.h @@ -0,0 +1,49 @@ +#ifndef REQUESTWORKER_H +#define REQUESTWORKER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +class RequestWorker : public QObject +{ + Q_OBJECT + QML_ELEMENT + Q_PROPERTY(QString status READ status WRITE setStatus NOTIFY statusChanged FINAL) + QNetworkAccessManager *manager = nullptr; + QTimer *timer = nullptr; + QString url; + int interval; + float prev_distance = 0; + int max_height = 0; + int min_height = 0; + bool stop_timer = false; + int reply_number = 0; + std::chrono::time_point prev_time; +public: + explicit RequestWorker(QObject *parent = nullptr); + + QString status() const; + void setStatus(const QString &newStatus); + +signals: + void networkReply(float distance, float rate_of_fill, int expected_to_fill); + void statusChanged(); + +public slots: + void setConfig(QJsonObject config); + void start(); + void stop(); +private slots: + void makeRequest(); + void requestFinished(QNetworkReply *rep); +private: + QString m_status; +}; + +#endif // REQUESTWORKER_H