KWeatherCore

sunrisesource.cpp
1 /*
2  * SPDX-FileCopyrightText: 2020-2021 Han Young <[email protected]>
3  * SPDX-FileCopyrightText: 2020 Devin Lin <[email protected]>
4  *
5  * SPDX-License-Identifier: LGPL-2.0-or-later
6  */
7 #include "sunrisesource.h"
8 #include "kweathercore_p.h"
9 #include <QJsonArray>
10 #include <QJsonDocument>
11 #include <QJsonObject>
12 #include <QNetworkAccessManager>
13 #include <QNetworkReply>
14 #include <QTimeZone>
15 #include <QUrlQuery>
16 
17 namespace KWeatherCore
18 {
19 SunriseSource::SunriseSource(double latitude, double longitude, const QString &timezone, const std::vector<Sunrise> &sunrise, QObject *parent)
20  : QObject(parent)
21  , m_latitude(latitude)
22  , m_longitude(longitude)
23  , m_timezone(timezone)
24  , m_sunriseVec(sunrise)
25  , m_manager(new QNetworkAccessManager(this))
26 {
27  connect(m_manager, &QNetworkAccessManager::finished, this, &SunriseSource::parseResults);
28 }
30 {
31  // pop older data
32  popDay();
33 
34  if (m_sunriseVec.size() >= 10) // don't update if we have enough data
35  {
36  Q_EMIT finished();
37  return;
38  }
39 
40  auto m_offset = QDateTime::currentDateTime().toTimeZone(QTimeZone(m_timezone.toUtf8())).offsetFromUtc();
41 
42  QUrl url(QStringLiteral("https://api.met.no/weatherapi/sunrise/2.0/.json"));
43  QUrlQuery query;
44  query.addQueryItem(QStringLiteral("lat"), self()->toFixedString(m_latitude));
45  query.addQueryItem(QStringLiteral("lon"), self()->toFixedString(m_longitude));
46  // if we already have data, request data beyond the last day
47  query.addQueryItem(QStringLiteral("date"),
48  !m_sunriseVec.size() ? QDate::currentDate().toString(QStringLiteral("yyyy-MM-dd"))
49  : QDate::currentDate().addDays(m_sunriseVec.size()).toString(QStringLiteral("yyyy-MM-dd")));
50  query.addQueryItem(QStringLiteral("days"), !m_sunriseVec.size() ? QString::number(10) : QString::number(11 - m_sunriseVec.size()));
51 
52  // calculate offset (form example: -04:00)
53  QString offset = m_offset < 0 ? QStringLiteral("-") : QStringLiteral("+");
54  int hour = std::abs(m_offset) / 3600;
55  if (hour >= 10) {
56  offset.append(QString::number(hour) + QStringLiteral(":"));
57  } else {
58  offset.append(QStringLiteral("0") + QString::number(hour) + QStringLiteral(":"));
59  }
60  int min = (std::abs(m_offset) - hour * 3600) / 60;
61  if (min >= 10) {
62  offset.append(QString::number(min));
63  } else {
64  offset.append(QStringLiteral("0") + QString::number(min));
65  }
66  query.addQueryItem(QStringLiteral("offset"), offset);
67 
68  url.setQuery(query);
69  QNetworkRequest req(url);
70 
71  // see ┬žIdentification on https://api.met.no/conditions_service.html
73  QString(QStringLiteral("KWeatherCore/") + VERSION_NUMBER + QStringLiteral(" [email protected]")));
74 
75  m_manager->get(req);
76 }
77 void SunriseSource::parseResults(QNetworkReply *reply)
78 {
79  reply->deleteLater();
80  if (reply->error()) {
81  qWarning() << "nmisunriseapi network error:" << reply->errorString();
83  return;
84  }
85 
86  auto timezone = QTimeZone(m_timezone.toUtf8());
87 
89  QJsonArray array = doc[QStringLiteral("location")].toObject()[QStringLiteral("time")].toArray();
90 
91  m_sunriseVec.reserve(array.size());
92 
93  for (int i = 0; i <= array.count() - 2; i++) // we don't want last one
94  {
95  // clang-format off
96  Sunrise sr;
97  sr.setSunSet(
98  QDateTime::fromString(array.at(i)
99  .toObject()[QStringLiteral("sunset")]
100  .toObject()[QStringLiteral("time")]
101  .toString(), Qt::ISODate));
102  sr.setSunRise(QDateTime::fromString(array.at(i)
103  .toObject()[QStringLiteral("sunrise")]
104  .toObject()[QStringLiteral("time")]
105  .toString(), Qt::ISODate));
106  sr.setMoonSet(
107  QDateTime::fromString(array.at(i)
108  .toObject()[QStringLiteral("moonset")]
109  .toObject()[QStringLiteral("time")]
110  .toString(), Qt::ISODate));
111  sr.setMoonRise(
112  QDateTime::fromString(array.at(i)
113  .toObject()[QStringLiteral("moonrise")]
114  .toObject()[QStringLiteral("time")]
115  .toString(), Qt::ISODate));
118  array.at(i)
119  .toObject()[QStringLiteral("solarmidnight")]
120  .toObject()[QStringLiteral("time")]
121  .toString(), Qt::ISODate),
122  array.at(i)
123  .toObject()[QStringLiteral("solarmidnight")]
124  .toObject()[QStringLiteral("elevation")]
125  .toString()
126  .toDouble()));
128  QDateTime::fromString(array.at(i)
129  .toObject()[QStringLiteral("solarnoon")]
130  .toObject()[QStringLiteral("time")]
131  .toString()
132  .left(19), Qt::ISODate),
133  array.at(i)
134  .toObject()[QStringLiteral("solarnoon")]
135  .toObject()[QStringLiteral("elevation")]
136  .toString()
137  .toDouble()));
139  QDateTime::fromString(array.at(i)
140  .toObject()[QStringLiteral("high_moon")]
141  .toObject()[QStringLiteral("time")]
142  .toString(), Qt::ISODate),
143  array.at(i)
144  .toObject()[QStringLiteral("high_moon")]
145  .toObject()[QStringLiteral("elevation")]
146  .toString()
147  .toDouble()));
149  QDateTime::fromString(array.at(i)
150  .toObject()[QStringLiteral("low_moon")]
151  .toObject()[QStringLiteral("time")]
152  .toString(), Qt::ISODate),
153  array.at(i)
154  .toObject()[QStringLiteral("low_moon")]
155  .toObject()[QStringLiteral("elevation")]
156  .toString()
157  .toDouble()));
158  sr.setMoonPhase(array.at(i)
159  .toObject()[QStringLiteral("moonposition")]
160  .toObject()[QStringLiteral("phase")]
161  .toString()
162  .toDouble());
163  // clang-format on
164 
165  m_sunriseVec.emplace_back(std::move(sr));
166  }
167 
168  Q_EMIT finished();
169 }
170 void SunriseSource::setTimezone(const QString &timezone)
171 {
172  m_timezone = timezone;
173 }
174 
175 void SunriseSource::popDay()
176 {
177  auto today = QDateTime::currentDateTime();
178  auto popIndex = 0;
179  for (const auto &day : qAsConst(m_sunriseVec)) {
180  if (day.sunRise().daysTo(today) > 0) {
181  popIndex++;
182  } else {
183  // since vector is always sorted
184  break;
185  }
186  }
187 
188  m_sunriseVec.erase(m_sunriseVec.begin(), m_sunriseVec.begin() + popIndex);
189 }
190 
191 const std::vector<Sunrise> &SunriseSource::value() const
192 {
193  return m_sunriseVec;
194 }
195 }
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
QString toString(Qt::DateFormat format) const const
QString & append(QChar ch)
QString toString(Qt::DateFormat format) const const
QString errorString() const const
The Sunrise class contains the information of sunrise/set on a day and more.
Definition: sunrise.h:24
double toDouble(bool *ok) const const
void setMoonRise(const QDateTime &moonRise)
set moon rise time
Definition: sunrise.cpp:157
QDateTime toTimeZone(const QTimeZone &timeZone) const const
void setMoonSet(const QDateTime &moonSet)
set moon set time
Definition: sunrise.cpp:161
void addQueryItem(const QString &key, const QString &value)
QString number(int n, int base)
void setSolarNoon(const QPair< QDateTime, double > &solarNoon)
set solar noon time and elevation
Definition: sunrise.cpp:141
QByteArray readAll()
void setHighMoon(const QPair< QDateTime, double > &highMoon)
set high moon time and elevation
Definition: sunrise.cpp:133
void setSunRise(const QDateTime &sunRise)
sun rise time
Definition: sunrise.cpp:149
void deleteLater()
void requestData()
start downloading data
void finished()
query finished
QDateTime fromString(const QString &string, Qt::DateFormat format)
void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
void setSolarMidnight(const QPair< QDateTime, double > &solarMidnight)
set solar midnight time and elevation
Definition: sunrise.cpp:137
void setMoonPhase(double moonPhase)
set moon phase
Definition: sunrise.cpp:165
QDateTime currentDateTime()
void networkError()
network error
QDate currentDate()
void finished(QNetworkReply *reply)
void setQuery(const QString &query, QUrl::ParsingMode mode)
void setSunSet(const QDateTime &sunSet)
set sun set time
Definition: sunrise.cpp:153
QNetworkReply::NetworkError error() const const
SunriseSource(double latitude, double longitude, const QString &timezone=QString(), const std::vector< Sunrise > &sunrise=std::vector< Sunrise >(), QObject *parent=nullptr)
SunriseSource.
QNetworkReply * get(const QNetworkRequest &request)
QDate addDays(qint64 ndays) const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int offsetFromUtc() const const
const std::vector< Sunrise > & value() const
get the value
void setTimezone(const QString &timezone)
change the timezone
void setLowMoon(const QPair< QDateTime, double > &lowMoon)
set low moon time time and elevation
Definition: sunrise.cpp:145
Q_EMITQ_EMIT
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 23 2021 23:03:28 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.