Add weather routes project progress

This commit is contained in:
2025-04-07 19:40:38 +02:00
parent 8941d84bc8
commit fa5f6b2588
52 changed files with 2027 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
#include "networkmanager.h"
#include "QStandardPaths"
#include <QFile>
#include <QGuiApplication>
#include <QJsonDocument>
#include <QNetworkAccessManager>
#include <QNetworkReply>
NetworkManager *NetworkManager::m_instance;
NetworkManager::NetworkManager(QObject *parent) : QObject{parent} {}
NetworkManager *NetworkManager::Instance() {
if (m_instance != nullptr) {
return m_instance;
}
m_instance = new NetworkManager();
return m_instance;
}
void NetworkManager::fetchJSONfromAPI(QUrl url, QJsonDocument &doc)
{
qDebug() << "Fetch URL::" << url.toDisplayString();
QNetworkAccessManager m_manager;
QNetworkRequest request(url);
QNetworkReply *reply = m_manager.get(request);
QEventLoop loop;
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
if (reply->error() == QNetworkReply::NoError)
{
QByteArray response = reply->readAll();
doc = QJsonDocument::fromJson(response);
}
else
{
qDebug() << "Invalid JSON response:: " << reply->errorString();
}
reply->deleteLater();
}

View File

@@ -0,0 +1,22 @@
#ifndef NETWORKMANAGER_H
#define NETWORKMANAGER_H
#include <QObject>
class NetworkManager : public QObject {
Q_OBJECT
public:
void fetchJSONfromAPI(QUrl url, QJsonDocument &doc);
static NetworkManager *m_instance;
static NetworkManager *Instance();
NetworkManager(const NetworkManager&) = delete;
NetworkManager& operator=(const NetworkManager&) = delete;
signals:
private:
explicit NetworkManager(QObject *parent = nullptr);
};
#endif // NETWORKMANAGER_H

View File

@@ -0,0 +1,30 @@
#include "stylecontroller.h"
StyleController* StyleController::m_instance;
StyleController *StyleController::Instance()
{
if(m_instance != nullptr)
{
return m_instance;
}
m_instance = new StyleController();
return m_instance;
}
StyleController::StyleController(QObject *parent)
: QObject{parent}
{}
int StyleController::colorMode() const
{
return m_colorMode;
}
void StyleController::setColorMode(int newColorMode)
{
if (m_colorMode == newColorMode)
return;
m_colorMode = newColorMode;
emit colorModeChanged();
}

View File

@@ -0,0 +1,59 @@
#ifndef STYLECONTROLLER_H
#define STYLECONTROLLER_H
#include <QObject>
#include <QColor>
class StyleController : public QObject
{
Q_OBJECT
public:
static StyleController* m_instance;
StyleController(const StyleController&) = delete;
StyleController& operator=(const StyleController&) = delete;
StyleController* Instance();
enum COLOR_MODE
{
DARK = 0,
LIGHT,
SYSTEM
}
Q_ENUMS(COLOR_MODE);
Q_PROPERTY(int colorMode READ colorMode WRITE setColorMode NOTIFY colorModeChanged FINAL)
//Dark Mode
Q_PROPERTY(QColor textPrimary READ textPrimary NOTIFY colorChanged FINAL)
QColor textPrimary() const {return QColor(255,255,255);}
Q_PROPERTY(QColor textSecondary READ textSecondary NOTIFY colorChanged FINAL)
QColor textSecondary() const {return QColor(255,255,255,179);}
Q_PROPERTY(QColor textDisabled READ textDisabled NOTIFY colorChanged FINAL)
QColor textDisabled() const {return QColor(255,255,255,125);}
Q_PROPERTY(QColor buttonActive READ buttonActive NOTIFY colorChanged FINAL)
QColor buttonActive() const {return QColor(255,255,255);}
Q_PROPERTY(QColor buttonDisabled READ buttonDisabled NOTIFY colorChanged FINAL)
QColor buttonDisabled() const {return QColor(255,255,255, 77);}
Q_PROPERTY(QColor buttonSelected READ buttonSelected NOTIFY colorChanged FINAL)
QColor buttonSelected() const {return QColor(255,255,255, 40);}
int colorMode() const;
void setColorMode(int newColorMode);
signals:
void colorChanged();
void colorModeChanged();
private:
explicit StyleController(QObject *parent = nullptr);
int m_colorMode = COLOR_MODE::DARK;
};
#endif // STYLECONTROLLER_H

View File

@@ -0,0 +1,224 @@
#include "weathercontroller.h"
#include "QDir"
#include "QFile"
#include "QGuiApplication"
#include "QStandardPaths"
#include "networkmanager.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <qdebug.h>
const QString WeatherController::FILENAME = "static.json";
WeatherController::WeatherController(QObject *parent) : QObject{parent} {}
bool WeatherController::parseJSONData() {
QJsonDocument doc;
if (this->checkToDownload(doc)) {
QJsonObject jsonObject = doc.object();
QJsonArray dataArray = jsonObject["data"].toArray();
for (QJsonArray::const_iterator iter = dataArray.constBegin();
iter != dataArray.constEnd(); ++iter) {
QJsonObject weatherObject = (*iter).toObject();
// Extract values from the JSON object
long tijd = weatherObject["tijd"].toString().toLong();
QString tijd_nl = weatherObject["tijd_nl"].toString();
int offset = weatherObject["offset"].toInt();
float temp = weatherObject["temp"].toString().toFloat();
int wind_ms = weatherObject["windb"].toInt();
int wind_bf = weatherObject["winds"].toInt();
int wind_knp = weatherObject["windknp"].toInt();
int wind_kmh = weatherObject["windkmh"].toString().toFloat();
int wind_r = weatherObject["windr"].toInt();
QString wind_ltr = weatherObject["windrltr"].toString();
int visibility = weatherObject["vis"].toInt();
int neersl = weatherObject["neersl"].toString().toFloat() *
10; // Converted from 0.1 to 1 decimal scale
float luchtd_bar = weatherObject["luchtd"].toString().toFloat();
float luchtdmmhg = weatherObject["luchtdmmhg"].toString().toFloat();
float luchtdinHg = weatherObject["luchtdinhg"].toString().toFloat();
int hw = weatherObject["hw"].toInt();
int mw = weatherObject["mw"].toInt();
int lw = weatherObject["lw"].toInt();
int tw = weatherObject["tw"].toInt();
int rv = weatherObject["rv"].toInt();
int gr = weatherObject["gr"].toInt();
int gr_w = weatherObject["gr_w"].toInt();
QString cape = weatherObject["cape"].toString();
int snd = weatherObject["snd"].toInt();
int snv = weatherObject["snv"].toInt();
int cond = weatherObject["cond"].toInt();
int iconCode = weatherObject["ico"].toInt();
QString sameenv = weatherObject["samenv"].toString();
QString icoon = weatherObject["icoon"].toString();
// Create WeatherData object and add it to the list using initializer list
// constructor
mData.append(WeatherData(tijd, tijd_nl, offset, temp, wind_ms, wind_bf,
wind_knp, wind_kmh, wind_r, wind_ltr, visibility,
neersl, luchtd_bar, luchtdmmhg, luchtdinHg, hw,
mw, lw, tw, rv, gr, gr_w, cape, snd, snv, cond,
iconCode, sameenv, icoon));
}
}
else
return false;
return true;
}
QJsonObject WeatherController::fetchCurrentWeatherData(const QGeoCoordinate &coord)
{
QJsonDocument doc;
readWeatherData(doc, "liveweer");
QJsonArray liveweerArray = doc.array();
QJsonObject firstEntry = liveweerArray.at(0).toObject();
//Will fetch live data when the time difference is more than 10 mins from last fetch
if (qAbs(QDateTime::currentSecsSinceEpoch() - firstEntry["timestamp"].toString().toUInt()) > 600)
{
// NetworkManager::Instance()->fetchJSONfromAPI(prepareURL(coord), doc);
// if(!doc.isNull() && doc.isObject())
// {
// updateWeatherData(doc);
// }
}
return doc.object();
}
bool WeatherController::readWeatherData(QJsonDocument &doc, QString objName)
{
QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
QString fileName = cacheDir + "/" + WeatherController::FILENAME;
QFile file(fileName);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
QJsonParseError error;
doc = QJsonDocument::fromJson(in.readAll().toStdString().c_str(), &error);
file.close();
if(doc.isNull())
{
qWarning() << "Error:: " << error.errorString();
return false;
}
if (!doc.isObject()) {
qWarning() << "Invalid JSON format";
return false;
}
if(!objName.isNull())
{
QJsonArray ary = doc.object()[objName].toArray();
QJsonDocument temp_doc(ary);
doc = temp_doc;
}
}
return true;
}
bool WeatherController::saveWeatherData(QJsonDocument &doc)
{
QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
// Ensure the directory exists
QDir dir(cacheDir);
if (!dir.exists()) {
dir.mkpath(cacheDir);
}
QString fileName = cacheDir + "/" + WeatherController::FILENAME;
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
out << doc.toJson();
file.close();
qDebug() << "Data saved to hidden cache file.";
return true;
} else {
qDebug() << "Failed to open file for writing";
return false;
}
}
bool WeatherController::fetchWeatherData(QUrl url, QJsonDocument &doc)
{
NetworkManager::Instance()->fetchJSONfromAPI(url, doc);
if (doc.isObject() && !doc.isNull()) {
QJsonObject jsonObject = doc.object();
QString todayDate = QDate::currentDate().toString("dd-MM-yyyy");
jsonObject["downloaddatum"] = todayDate;
QString timeOfDownload = QDateTime::currentDateTime().toString("hh:mm:ss");
jsonObject["downloadtime"] = timeOfDownload;
QJsonDocument updatedDoc(jsonObject);
saveWeatherData(updatedDoc);
}
return true;
}
void WeatherController::updateWeatherData(QJsonDocument &inputDoc)
{
QJsonDocument doc;
readWeatherData(doc);
QJsonObject rootObj = doc.object();
QJsonObject inputObj = inputDoc.object();
QJsonArray liveweerArray = inputObj["liveweer"].toArray();
rootObj["liveweer"] = liveweerArray;
QJsonDocument updatedDoc(rootObj);
saveWeatherData(updatedDoc);
}
QUrl WeatherController::prepareURL(const QString &plaats)
{
return QUrl(QString("http://data.meteoserver.nl/api/uurverwachting.php?locatie=%1&key=785f0630f0").arg(plaats));
}
QUrl WeatherController::prepareURL(const QGeoCoordinate &coord)
{
return QUrl(QString("http://data.meteoserver.nl/api/liveweer_synop.php?lat=%1&long=%2&key=785f0630f0&select=1").arg(coord.latitude()).arg(coord.longitude()));
}
bool WeatherController::checkToDownload(QJsonDocument &doc)
{
bool toDownloadData = false;
readWeatherData(doc);
if (doc.isObject() && !doc.isNull()) {
// Get the root object
QJsonObject jsonObject = doc.object();
// Extract the 'downloaddatum' value
QString downloaddatum = jsonObject.value("downloaddatum").toString();
if(downloaddatum != QDate::currentDate().toString("dd-MM-yyyy"))
toDownloadData = true;
QJsonArray plaatsnaamArray = jsonObject.value("plaatsnaam").toArray();
if (!plaatsnaamArray.isEmpty()) {
QJsonObject plaatsObject = plaatsnaamArray.at(0).toObject();
QString plaats = plaatsObject.value("plaats").toString();
if(plaats != "Raalte")
toDownloadData = true;
} else {
qWarning() << "plaatsnaam array is empty";
return false;
}
} else {
qWarning() << "Failed to open file for reading";
return false;
}
if(toDownloadData)
return fetchWeatherData(prepareURL("Raalte"), doc);
return false;
}

View File

@@ -0,0 +1,30 @@
#ifndef WEATHERCONTROLLER_H
#define WEATHERCONTROLLER_H
#include "../data/weatherdata.h"
#include <QGeoCoordinate>
#include <QObject>
class WeatherController : public QObject {
Q_OBJECT
public:
explicit WeatherController(QObject *parent = nullptr);
static const QString FILENAME;
bool parseJSONData();
QJsonObject fetchCurrentWeatherData(const QGeoCoordinate &coord);
signals:
private:
bool readWeatherData(QJsonDocument &doc, QString objName = NULL);
bool checkToDownload(QJsonDocument &doc);
bool saveWeatherData(QJsonDocument &doc);
bool fetchWeatherData(QUrl url, QJsonDocument &doc);
void updateWeatherData(QJsonDocument &inputDoc);
QUrl prepareURL(const QString &plaats);
QUrl prepareURL(const QGeoCoordinate &coord);
QList<WeatherData> mData;
};
#endif // WEATHERCONTROLLER_H