Http Version - Initial Commit

This commit is contained in:
unrealdragon 2026-08-04 21:31:40 +05:30
commit 026ea97284
12 changed files with 978 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
build/*
.qtcreator/*

46
CMakeLists.txt Normal file
View file

@ -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}
)

55
ConnectButton.qml Normal file
View file

@ -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
}
}
}

156
Main.qml Normal file
View file

@ -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);
}
}
}

46
SettingsBarIcon.qml Normal file
View file

@ -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
}
}
}

251
SettingsPopup.qml Normal file
View file

@ -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
}
}
}
}
}

162
WaterTank.qml Normal file
View file

@ -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;
}
}

53
configinterface.cpp Normal file
View file

@ -0,0 +1,53 @@
#include "configinterface.h"
#include <fstream>
#include <sstream>
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());
}

28
configinterface.h Normal file
View file

@ -0,0 +1,28 @@
#ifndef CONFIGINTERFACE_H
#define CONFIGINTERFACE_H
#include <QObject>
#include <QQmlEngine>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
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

18
main.cpp Normal file
View file

@ -0,0 +1,18 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
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();
}

112
requestworker.cpp Normal file
View file

@ -0,0 +1,112 @@
#include "requestworker.h"
#include <QJsonArray>
#include <QJsonValue>
#include <QJsonObject>
#include <QJsonDocument>
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<std::chrono::microseconds>(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();
}

49
requestworker.h Normal file
View file

@ -0,0 +1,49 @@
#ifndef REQUESTWORKER_H
#define REQUESTWORKER_H
#include <QObject>
#include <QQmlEngine>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QTimer>
#include <QThread>
#include <chrono>
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<std::chrono::high_resolution_clock> 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