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 <QUrlQuery>
15 #include <QTimeZone>
16 
17 namespace KWeatherCore
18 {
20  double longitude,
21  const QString &timezone,
22  const std::vector<Sunrise> &sunrise,
23  QObject *parent)
24  : QObject(parent)
25  , m_latitude(latitude)
26  , m_longitude(longitude)
27  , m_timezone(timezone)
28  , m_sunriseVec(sunrise)
29  , m_manager(new QNetworkAccessManager(this))
30 {
31  connect(m_manager,
33  this,
34  &SunriseSource::parseResults);
35 }
37 {
38  // pop older data
39  popDay();
40 
41  if (m_sunriseVec.size() >= 10) // don't update if we have enough data
42  {
43  Q_EMIT finished();
44  return;
45  }
46 
47  auto m_offset = QDateTime::currentDateTime().toTimeZone(QTimeZone(m_timezone.toUtf8())).offsetFromUtc();
48 
49  QUrl url(QStringLiteral("https://api.met.no/weatherapi/sunrise/2.0/.json"));
50  QUrlQuery query;
51  query.addQueryItem(QStringLiteral("lat"), self()->toFixedString(m_latitude));
52  query.addQueryItem(QStringLiteral("lon"), self()->toFixedString(m_longitude));
53  // if we already have data, request data beyond the last day
54  query.addQueryItem(
55  QStringLiteral("date"),
56  !m_sunriseVec.size()
57  ? QDate::currentDate().toString(QStringLiteral("yyyy-MM-dd"))
59  .addDays(m_sunriseVec.size())
60  .toString(QStringLiteral("yyyy-MM-dd")));
61  query.addQueryItem(QStringLiteral("days"),
62  !m_sunriseVec.size()
63  ? QString::number(10)
64  : QString::number(11 - m_sunriseVec.size()));
65 
66  // calculate offset (form example: -04:00)
67  QString offset = m_offset < 0 ? QStringLiteral("-") : QStringLiteral("+");
68  int hour = std::abs(m_offset) / 3600;
69  if (hour >= 10)
70  offset.append(QString::number(hour) + QStringLiteral(":"));
71  else {
72  offset.append(QStringLiteral("0") + QString::number(hour) +
73  QStringLiteral(":"));
74  }
75  int min = (std::abs(m_offset) - hour * 3600) / 60;
76  if (min >= 10) {
77  offset.append(QString::number(min));
78  } else {
79  offset.append(QStringLiteral("0") + QString::number(min));
80  }
81  query.addQueryItem(QStringLiteral("offset"), offset);
82 
83  url.setQuery(query);
84  QNetworkRequest req(url);
85 
86  // see ┬žIdentification on https://api.met.no/conditions_service.html
88  QString(QStringLiteral("KWeatherCore/") +
89  VERSION_NUMBER +
90  QStringLiteral(" [email protected]")));
91 
92  m_manager->get(req);
93 }
94 void SunriseSource::parseResults(QNetworkReply *reply)
95 {
96  reply->deleteLater();
97  if (reply->error()) {
98  qWarning() << "nmisunriseapi network error:" << reply->errorString();
100  return;
101  }
102 
103  auto timezone = QTimeZone(m_timezone.toUtf8());
104 
106  QJsonArray array = doc[QStringLiteral("location")]
107  .toObject()[QStringLiteral("time")]
108  .toArray();
109 
110  m_sunriseVec.reserve(array.size());
111 
112  for (int i = 0; i <= array.count() - 2; i++) // we don't want last one
113  {
114  Sunrise sr;
115  sr.setSunSet(
116  QDateTime::fromString(array.at(i)
117  .toObject()[QStringLiteral("sunset")]
118  .toObject()[QStringLiteral("time")]
119  .toString(), Qt::ISODate));
120  sr.setSunRise(QDateTime::fromString(array.at(i)
121  .toObject()[QStringLiteral("sunrise")]
122  .toObject()[QStringLiteral("time")]
123  .toString(), Qt::ISODate));
124  sr.setMoonSet(
125  QDateTime::fromString(array.at(i)
126  .toObject()[QStringLiteral("moonset")]
127  .toObject()[QStringLiteral("time")]
128  .toString(), Qt::ISODate));
129  sr.setMoonRise(
130  QDateTime::fromString(array.at(i)
131  .toObject()[QStringLiteral("moonrise")]
132  .toObject()[QStringLiteral("time")]
133  .toString(), Qt::ISODate));
136  array.at(i)
137  .toObject()[QStringLiteral("solarmidnight")]
138  .toObject()[QStringLiteral("time")]
139  .toString(), Qt::ISODate),
140  array.at(i)
141  .toObject()[QStringLiteral("solarmidnight")]
142  .toObject()[QStringLiteral("elevation")]
143  .toString()
144  .toDouble()));
146  QDateTime::fromString(array.at(i)
147  .toObject()[QStringLiteral("solarnoon")]
148  .toObject()[QStringLiteral("time")]
149  .toString()
150  .left(19), Qt::ISODate),
151  array.at(i)
152  .toObject()[QStringLiteral("solarnoon")]
153  .toObject()[QStringLiteral("elevation")]
154  .toString()
155  .toDouble()));
157  QDateTime::fromString(array.at(i)
158  .toObject()[QStringLiteral("high_moon")]
159  .toObject()[QStringLiteral("time")]
160  .toString(), Qt::ISODate),
161  array.at(i)
162  .toObject()[QStringLiteral("high_moon")]
163  .toObject()[QStringLiteral("elevation")]
164  .toString()
165  .toDouble()));
167  QDateTime::fromString(array.at(i)
168  .toObject()[QStringLiteral("low_moon")]
169  .toObject()[QStringLiteral("time")]
170  .toString(), Qt::ISODate),
171  array.at(i)
172  .toObject()[QStringLiteral("low_moon")]
173  .toObject()[QStringLiteral("elevation")]
174  .toString()
175  .toDouble()));
176  sr.setMoonPhase(array.at(i)
177  .toObject()[QStringLiteral("moonposition")]
178  .toObject()[QStringLiteral("phase")]
179  .toString()
180  .toDouble());
181 
182  m_sunriseVec.emplace_back(std::move(sr));
183  }
184 
185  Q_EMIT finished();
186 }
187 void SunriseSource::setTimezone(const QString &timezone)
188 {
189  m_timezone = timezone;
190 }
191 
192 void SunriseSource::popDay()
193 {
194  auto today = QDateTime::currentDateTime();
195  auto popIndex = 0;
196  for (const auto &day : qAsConst(m_sunriseVec)) {
197  if (day.sunRise().daysTo(today) > 0) {
198  popIndex++;
199  } else {
200  // since vector is always sorted
201  break;
202  }
203  }
204 
205  m_sunriseVec.erase(m_sunriseVec.begin(), m_sunriseVec.begin() + popIndex);
206 }
207 
208 const std::vector<Sunrise> &SunriseSource::value() const
209 {
210  return m_sunriseVec;
211 }
212 }
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:166
QDateTime toTimeZone(const QTimeZone &timeZone) const const
void setMoonSet(const QDateTime &moonSet)
set moon set time
Definition: sunrise.cpp:170
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:150
QByteArray readAll()
void setHighMoon(const QPair< QDateTime, double > &highMoon)
set high moon time and elevation
Definition: sunrise.cpp:142
void setSunRise(const QDateTime &sunRise)
sun rise time
Definition: sunrise.cpp:158
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:146
void setMoonPhase(double moonPhase)
set moon phase
Definition: sunrise.cpp:174
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:162
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:154
Q_EMITQ_EMIT
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Thu Jul 29 2021 23:03:41 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.