-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
request weather data and send them to the wirst #29
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,11 +19,12 @@ | |
|
||
#include "dbusinterface.h" | ||
#include "watchesmanager.h" | ||
|
||
#include "libasteroid/watch.h" | ||
|
||
#include <QDBusConnection> | ||
#include <QDebug> | ||
#include <QNetworkRequest> | ||
#include <QNetworkReply> | ||
|
||
/* Watch Interface */ | ||
|
||
|
@@ -44,6 +45,9 @@ DBusWatch::DBusWatch(Watch *watch, WatchesManager* wm, QObject *parent): QObject | |
connect(m_screenshotService, SIGNAL(screenshotReceived(QByteArray)), this, SIGNAL(ScreenshotReceived(QByteArray))); | ||
connect(m_weatherService, SIGNAL(ready()), this, SLOT(onWeatherServiceReady())); | ||
connect(wm, SIGNAL(disconnected()), this, SLOT(onDisconnected())); | ||
|
||
m_nam = new QNetworkAccessManager(this); | ||
m_wmp = new OpenWeatherMapParser(this); | ||
} | ||
|
||
void DBusWatch::onDisconnected() | ||
|
@@ -86,11 +90,6 @@ void DBusWatch::RequestScreenshot() | |
m_screenshotService->requestScreenshot(); | ||
} | ||
|
||
void DBusWatch::WeatherSetCityName(QString cityName) | ||
{ | ||
m_weatherService->setCity(cityName); | ||
} | ||
|
||
void DBusWatch::onTimeServiceReady() | ||
{ | ||
m_timeServiceReady = true; | ||
|
@@ -150,6 +149,52 @@ bool DBusWatch::StatusWeatherService() | |
return m_weatherServiceReady; | ||
} | ||
|
||
void DBusWatch::SetWeatherLocation(const QString lat, const QString lng) | ||
{ | ||
owmRequest(lat, lng); | ||
} | ||
|
||
void DBusWatch::owmRequest(const QString lat, const QString lng) const | ||
{ | ||
QString owmApiKey = "b1af1d2053458fb4ab724f038ed499aa"; | ||
QUrl url; | ||
url.setUrl("http://api.openweathermap.org/data/2.5/forecast"); | ||
|
||
QUrlQuery query; | ||
query.addQueryItem("lat", lat); | ||
query.addQueryItem("lon", lng); | ||
query.addQueryItem("appid", owmApiKey); | ||
url.setQuery(query); | ||
|
||
QNetworkRequest request(url); | ||
QNetworkReply* reply = m_nam->get(request); | ||
connect(reply, &QNetworkReply::finished, this, &DBusWatch::onOwmReplyFinished); | ||
} | ||
|
||
void DBusWatch::onOwmReplyFinished() | ||
{ | ||
QJsonObject rootObj; | ||
QNetworkReply *reply = static_cast<QNetworkReply*>(sender()); | ||
reply->deleteLater(); | ||
|
||
if (reply->error() == QNetworkReply::NoError) { | ||
QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); | ||
rootObj = document.object(); | ||
} else { | ||
qDebug() << "Network error" << reply->errorString(); | ||
return; | ||
} | ||
|
||
m_wmp->prepareData(rootObj); | ||
m_weatherService->setCity(m_wmp->getCity()); | ||
qDebug() << "WeatherID" << m_wmp->getWeatherId(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it help to keep those qDebug in the app ? |
||
m_weatherService->setIds(m_wmp->getWeatherId()); | ||
qDebug() << "Min Temp" << m_wmp->getTempMin(); | ||
m_weatherService->setMinTemps(m_wmp->getTempMin()); | ||
qDebug() << "Max Temp" << m_wmp->getTempMax(); | ||
m_weatherService->setMaxTemps(m_wmp->getTempMax()); | ||
} | ||
|
||
/* Manager Interface */ | ||
|
||
DBusInterface::DBusInterface(WatchesManager *wm, QObject *parent) : QObject(parent) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
#include "openweathermapparser.h" | ||
|
||
OpenWeatherMapParser::OpenWeatherMapParser(QObject *parent) : QObject(parent) | ||
{ | ||
} | ||
|
||
void OpenWeatherMapParser::prepareData(QJsonObject obj) | ||
{ | ||
m_weatherId.clear(); | ||
m_tempMin.clear(); | ||
m_tempMax.clear(); | ||
m_dateTempMin.setDate(0, 0, 0); | ||
m_dateTempMax.setDate(0, 0, 0); | ||
|
||
QDateTime timestamp; | ||
QJsonArray list = obj.value("list").toArray(); | ||
|
||
for(auto element : list) { | ||
QJsonObject dayInfo = element.toObject(); | ||
timestamp.setTime_t(dayInfo.value("dt").toInt()); | ||
|
||
setWeatherId(dayInfo.value("weather").toArray(), timestamp.time()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see that every method has a different way of determining "what day it is" but ultimately it should be the same day for every method.
I propose that you extract here in this loop once for each element the "day index" which is going to be the index at which any value will be inserted (whether that is a weather id or a max/min temperature in their respective arrays). You could calculate this offset quite easily with https://doc.qt.io/qt-5/qdate.html#daysTo by comparing the date to the first date in the json document. If you provide this day index to all your methods, you should find that your code becomes greatly simplified. Especially your "setM**Temp" functions should have less special cases for empty arrays/new dates etc... They could just insert their value at the right index. This also provides you stronger guarantees that the "weatherId"/"maxTemp"/"minTemp" will be aligned. |
||
setMinTemp(dayInfo.value("main").toObject(), timestamp.date()); | ||
setMaxTemp(dayInfo.value("main").toObject(), timestamp.date()); | ||
} | ||
|
||
setCity(obj.value("city").toObject()); | ||
} | ||
|
||
void OpenWeatherMapParser::setWeatherId(QJsonArray weather, QTime time) | ||
{ | ||
QTime elevenoclock, thirteenoclock; | ||
elevenoclock.setHMS(11,0,0,0); | ||
thirteenoclock.setHMS(13,0,0,0); | ||
|
||
if(time >= elevenoclock && time <= thirteenoclock) { | ||
QJsonObject firstEntry = weather.first().toObject(); | ||
m_weatherId << firstEntry.value("id").toInt(); | ||
} | ||
} | ||
|
||
QList<short> OpenWeatherMapParser::getWeatherId() | ||
{ | ||
return m_weatherId; | ||
} | ||
|
||
void OpenWeatherMapParser::setMinTemp(const QJsonObject obj, const QDate date) | ||
{ | ||
if(m_tempMin.isEmpty()) { | ||
m_tempMin << obj.value("temp_min").toDouble(); | ||
m_dateTempMin = date; | ||
return; | ||
} | ||
|
||
if(m_dateTempMin == date && obj.value("temp_min").toDouble() < m_tempMin[m_tempMin.size() - 1]) { | ||
m_tempMin.replace(m_tempMin.size() - 1, obj.value("temp_min").toDouble()); | ||
} else if(m_dateTempMin != date) { | ||
if(m_tempMin.size() >= 5) return; | ||
|
||
m_tempMin << obj.value("temp_min").toDouble(); | ||
m_dateTempMin = date; | ||
} | ||
} | ||
|
||
QList<short> OpenWeatherMapParser::getTempMin() | ||
{ | ||
return m_tempMin; | ||
} | ||
|
||
void OpenWeatherMapParser::setMaxTemp(const QJsonObject obj, const QDate date) | ||
{ | ||
if(m_tempMax.isEmpty()) { | ||
m_tempMax << obj.value("temp_max").toDouble(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You often extract this "obj.value("temp_max").toDouble()" could you make it a variable that you only extract once to make the code easier to read ? |
||
m_dateTempMax = date; | ||
return; | ||
} | ||
|
||
if(m_dateTempMax == date && obj.value("temp_max").toDouble() > m_tempMax[m_tempMax.size() - 1]) { | ||
m_tempMax.replace(m_tempMax.size() - 1, obj.value("temp_max").toDouble()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something along the line of |
||
} else if(m_dateTempMax != date) { | ||
if(m_tempMax.size() >= 5) return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why 5? If this is a requirement of the protocol, I'd recommend that you enforce this in the "weatherservice" rather than in the parser. Ideally, the parser shouldn't have to care about limitations of the protocol that will transfer its data. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For example, it is easy for setWeatherId to ignore this restriction. |
||
|
||
m_tempMax << obj.value("temp_max").toDouble(); | ||
m_dateTempMax = date; | ||
} | ||
} | ||
|
||
QList<short> OpenWeatherMapParser::getTempMax() | ||
{ | ||
return m_tempMax; | ||
} | ||
|
||
void OpenWeatherMapParser::setCity(const QJsonObject obj) | ||
{ | ||
m_city = obj.value("name").toString().trimmed(); | ||
} | ||
|
||
QString OpenWeatherMapParser::getCity() | ||
{ | ||
return m_city; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#ifndef OPENWEATHERMAPPARSER_H | ||
#define OPENWEATHERMAPPARSER_H | ||
|
||
#include <QObject> | ||
#include <QJsonObject> | ||
#include <QList> | ||
#include <QJsonArray> | ||
#include <QDateTime> | ||
|
||
class OpenWeatherMapParser : public QObject | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the methods are all stateless you don't really need a class here (an object of type OpenWeatherMapParser doesn't carry any ownership/lifetime semantic) |
||
{ | ||
Q_OBJECT | ||
|
||
public: | ||
OpenWeatherMapParser(QObject *parent = nullptr); | ||
|
||
void prepareData(QJsonObject obj); | ||
QList<short> getWeatherId(); | ||
QList<short> getTempMin(); | ||
QList<short> getTempMax(); | ||
QString getCity(); | ||
|
||
private: | ||
void setWeatherId(const QJsonArray weather, const QTime time); | ||
void setMinTemp(const QJsonObject obj, const QDate date); | ||
void setMaxTemp(const QJsonObject obj, const QDate date); | ||
void setCity(const QJsonObject obj); | ||
|
||
QList<short> m_weatherId; | ||
QList<short> m_tempMin; | ||
QList<short> m_tempMax; | ||
QDate m_dateTempMin; | ||
QDate m_dateTempMax; | ||
QString m_city; | ||
}; | ||
|
||
#endif // OPENWEATHERMAPPARSER_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why you have one m_wmp that you keep updating. Could you just create a new wmp here and give rootObj to its constructor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You also wouldn't have to clear fields like you do in your prepareData method