File indexing completed on 2025-01-12 05:01:50

0001 /*
0002     SPDX-FileCopyrightText: 2007-2009, 2019 Shawn Starr <shawn.starr@rogers.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 /* Ion for NOAA's National Weather Service XML data */
0008 
0009 #pragma once
0010 
0011 #include "../ion.h"
0012 
0013 #include <Plasma5Support/DataEngineConsumer>
0014 
0015 #include <QDateTime>
0016 #include <QXmlStreamReader>
0017 
0018 class KJob;
0019 namespace KIO
0020 {
0021 class Job;
0022 } // namespace KIO
0023 
0024 class WeatherData
0025 {
0026 public:
0027     WeatherData();
0028 
0029     QString locationName;
0030     QString stationID;
0031     double stationLatitude;
0032     double stationLongitude;
0033     QString stateName;
0034     QString countyID;
0035 
0036     // Current observation information.
0037     QString observationTime;
0038     QDateTime observationDateTime;
0039     QString weather;
0040 
0041     float temperature_F;
0042     float temperature_C;
0043     float humidity;
0044     QString windString;
0045     QString windDirection;
0046     float windSpeed;
0047     float windGust;
0048     float pressure;
0049     float dewpoint_F;
0050     float dewpoint_C;
0051     float heatindex_F;
0052     float heatindex_C;
0053     float windchill_F;
0054     float windchill_C;
0055     float visibility;
0056 
0057     struct Forecast {
0058         QString day;
0059         QString summary;
0060         QString low;
0061         QString high;
0062         int precipitation = 0;
0063     };
0064     QList<Forecast> forecasts;
0065 
0066     struct Alert {
0067         QString headline;
0068         QString description;
0069         QString infoUrl;
0070         int priority;
0071         QDateTime startTime;
0072         QDateTime endTime;
0073     };
0074     QList<Alert> alerts;
0075 
0076     bool isForecastsDataPending = false;
0077 
0078     QString solarDataTimeEngineSourceName;
0079     bool isNight = false;
0080     bool isSolarDataPending = false;
0081 };
0082 
0083 Q_DECLARE_TYPEINFO(WeatherData::Forecast, Q_RELOCATABLE_TYPE);
0084 Q_DECLARE_TYPEINFO(WeatherData, Q_RELOCATABLE_TYPE);
0085 
0086 class Q_DECL_EXPORT NOAAIon : public IonInterface, public Plasma5Support::DataEngineConsumer
0087 {
0088     Q_OBJECT
0089 
0090 public:
0091     NOAAIon(QObject *parent);
0092     ~NOAAIon() override;
0093 
0094 public: // IonInterface API
0095     bool updateIonSource(const QString &source) override;
0096 
0097 public Q_SLOTS:
0098     // for solar data pushes from the time engine
0099     void dataUpdated(const QString &sourceName, const Plasma5Support::DataEngine::Data &data);
0100 
0101 protected: // IonInterface API
0102     void reset() override;
0103 
0104 private Q_SLOTS:
0105     void setup_slotJobFinished(KJob *);
0106     void slotJobFinished(KJob *);
0107     void forecast_slotJobFinished(KJob *);
0108     void county_slotJobFinished(KJob *);
0109     void alerts_slotJobFinished(KJob *);
0110 
0111 private:
0112     void updateWeather(const QString &source);
0113 
0114     /* NOAA Methods - Internal for Ion */
0115     QMap<QString, ConditionIcons> setupConditionIconMappings() const;
0116     QMap<QString, ConditionIcons> const &conditionIcons() const;
0117     QMap<QString, WindDirections> setupWindIconMappings() const;
0118     QMap<QString, WindDirections> const &windIcons() const;
0119 
0120     // Current Conditions Weather info
0121     // bool night(const QString& source);
0122     IonInterface::ConditionIcons getConditionIcon(const QString &weather, bool isDayTime) const;
0123 
0124     // Helper to make an API request
0125     KJob *apiRequestJob(const QUrl &url, const QString &source);
0126 
0127     // Load and Parse the place XML listing
0128     void getXMLSetup();
0129     bool readXMLSetup(QXmlStreamReader &xml);
0130 
0131     // Load and parse the specific place(s)
0132     void getXMLData(const QString &source);
0133     bool readXMLData(const QString &source, QXmlStreamReader &xml);
0134 
0135     // Load and parse upcoming forecast for the next N days
0136     void getForecast(const QString &source);
0137     void readForecast(const QString &source, QXmlStreamReader &xml);
0138 
0139     // Methods to get alerts. We need the county ID first
0140     void getCountyID(const QString &source);
0141     void readCountyID(const QString &source, const QJsonDocument &doc);
0142     void getAlerts(const QString &source);
0143     void readAlerts(const QString &source, const QJsonDocument &doc);
0144 
0145     // Check if place specified is valid or not
0146     QStringList validate(const QString &source) const;
0147 
0148     // Catchall for unknown XML tags
0149     void parseUnknownElement(QXmlStreamReader &xml) const;
0150 
0151     // Parse weather XML data
0152     void parseWeatherSite(WeatherData &data, QXmlStreamReader &xml);
0153     void parseStationID(QXmlStreamReader &xml);
0154     void parseStationList(QXmlStreamReader &xml);
0155 
0156     void parseFloat(float &value, const QString &string);
0157     void parseFloat(float &value, QXmlStreamReader &xml);
0158     void parseDouble(double &value, QXmlStreamReader &xml);
0159 
0160 private:
0161     struct XMLMapInfo {
0162         QString stateName;
0163         QString stationName;
0164         QString stationID;
0165         QString XMLurl;
0166     };
0167 
0168     // Key dicts
0169     QHash<QString, NOAAIon::XMLMapInfo> m_places;
0170 
0171     // Weather information
0172     QHash<QString, WeatherData> m_weatherData;
0173 
0174     // Store KIO jobs
0175     QHash<KJob *, QByteArray> m_jobData;
0176     QHash<KJob *, QString> m_jobList;
0177 
0178     // bool emitWhenSetup;
0179     QStringList m_sourcesToReset;
0180 };