ukui-screensaver/screensaver/weathermanager.cpp

376 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Authors: ZHAI Kang-ning <zhaikangning@kylinos.cn>
**/
#include "weathermanager.h"
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <QJsonParseError>
#include <QTimer>
#include <QString>
#include <QEventLoop>
#include <QDebug>
#include <QtNetwork>
#include <QPixmap>
const QString weatherServerAddr = "http://service.ubuntukylin.com:8001/weather/api/3.0/heweather_data_s6/";
const QString defaultCityId = "101030100"; //"101030100" 默认天津
const int weatherReqInterval = 1000 * 60 * 20; //定时更新天气,和麒麟天气保持一致
const QByteArray schemaWeather = "org.china-weather-data.settings";
static const QMap<QString, QString> weatherMap {
{"", "100"},{"多云", "101"},{"少云", "102"},{"晴间多云", "103"},{"", "104"},
{"有风", "200"},{"平静", "201"},{"微风", "202"},{"和风", "203"},{"清风", "204"},{"强风劲风", "205"},{"疾风", "206"},{"大风", "207"},{"烈风", "208"},{"风暴", "209"},
{"狂暴风", "210"},{"飓风", "211"},{"龙卷风", "212"},{"热带风暴", "213"},
{"阵雨", "300"},{"强阵雨", "301"},{"雷阵雨", "302"},{"强雷阵雨", "303"},{"雷阵雨伴有冰雹", "304"},{"小雨", "305"},{"中雨", "306"},{"大雨", "307"},{"极端降雨", "308"},{"毛毛雨细雨", "309"},
{"暴雨", "310"},{"大暴雨", "311"},{"特大暴雨", "312"},{"冻雨", "313"},{"小到中雨", "314"},{"中到大雨", "315"},{"大到暴雨", "316"},{"暴雨到大暴雨", "317"},{"大暴雨到特大暴雨", "318"},
{"", "399"},
{"小雪", "400"},{"中雪", "401"},{"大雪", "402"},{"暴雪", "403"},{"雨夹雪", "404"},{"雨雪天气", "405"},{"阵雨夹雪", "406"},{"阵雪", "407"},{"小到中雪", "408"},{"中到大雪", "409"},
{"大到暴雪", "410"},{"", "499"},
{"薄雾", "500"},{"", "501"},{"", "502"},{"扬沙", "503"},{"浮尘", "504"},{"沙尘暴", "507"},{"强沙尘暴", "508"},{"大雾", "509"},
{"强浓雾", "510"},{"中度霾", "511"},{"重度霾", "512"},{"严重霾", "513"},{"大雾", "514"},{"特强浓雾", "515"},
{"", "900"},{"", "901"},
{"未知", "999"}
};
WeatherManager::WeatherManager(QObject *parent) : QObject(parent)
{
//初始化m_net_manager请求天气
m_net_manager = new QNetworkAccessManager(this);
QObject::connect(m_net_manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
m_timer = new QTimer(this);
m_timer->setInterval(weatherReqInterval);
m_local_weather_info = new LocalWeatherInfo(this);
connect(m_timer, &QTimer::timeout, this, &WeatherManager::weatherRequest);
m_networkWatcher = new NetWorkWatcher(this);
connect(m_networkWatcher, &NetWorkWatcher::NetworkStateChanged, this, &WeatherManager::onNetworkStateChanged);
m_networkWatcher->checkOnline();
}
void WeatherManager::onNetworkStateChanged(uint state)
{
qDebug() << state;
if (NM_STATE_CONNECTED_GLOBAL != state)
emit onWeatherUpdate("天气不可用", NULL, NULL);
else
getWeather();
}
void WeatherManager::getWeather()
{
weatherRequest();
if (m_timer != NULL)
{
m_timer->start();
}
return;
}
void WeatherManager::weatherRequest()
{
if (updateLocation())
return;
QNetworkRequest request(QUrl(weatherServerAddr + m_city_id + "/"));
m_net_manager->get(request);
}
bool WeatherManager::updateLocation()
{
//更新城市信息 未实现 麒麟天气提供gsettings完成后对接
if (QGSettings::isSchemaInstalled(schemaWeather)) {
m_settings = new QGSettings(schemaWeather,"",this); //org/ukui/indicator-china-weather path
if(getLogcalWeather())
{
emit onWeatherUpdate(m_local_weather_info->getCityName(),
m_local_weather_info->getCondText(),
m_local_weather_info->getTemperature());
m_networkWatcher->checkOnline();
return true;
}
m_city_id = getLogcalCityId();
}
if (m_city_id.isEmpty())
m_city_id = defaultCityId;
return false;
}
bool WeatherManager::getLogcalWeather()
{
if (m_settings != nullptr)
{
//"1920-08-27 10:17:42,101310204,澄迈,小雨,95%25℃,北风,1级," 时间,城市编码,城市名称,天气,湿度,温度,风向,风力
QString weather = m_settings->get("weather").toString();
QStringList weatherInfoList = weather.split(",");
if (weatherInfoList.size() < 9)
return false;
m_local_weather_info->setTime(weatherInfoList.at(0));
if(!m_local_weather_info->isTimeValid())
return false;
m_local_weather_info->setCityId(weatherInfoList.at(1));
m_local_weather_info->setCityName(weatherInfoList.at(2));
m_local_weather_info->setCondText(weatherInfoList.at(3));
m_local_weather_info->setAirHumidity(weatherInfoList.at(4));
m_local_weather_info->setTemperature(weatherInfoList.at(5));
m_local_weather_info->setWindDirection(weatherInfoList.at(6));
m_local_weather_info->setWindForce(weatherInfoList.at(7));
return true;
}
return false;
}
QString WeatherManager::getLogcalCityId()
{
if (m_settings != nullptr) {
QString citys = m_settings->get("citylist").toString();//"101010100,"
if (citys.isEmpty())
return "";
QStringList cityList = citys.split(",");
if (cityList.size() >= 1)
{
QString s = cityList.at(0);
qDebug() << "local city id = " << s;
return s;
}
}
return "";
}
void WeatherManager::replyFinished(QNetworkReply *reply)
{
if(reply != nullptr && reply->error() != QNetworkReply::NoError)
{
qWarning() << "[WeatherManager][replyFinished] get weather error:("
<< reply->error() << ")" << reply->errorString();
if (m_networkTryNum < 15)
{
m_networkTryNum++;
QTimer::singleShot(1000, this, [=]{
weatherRequest();
});
} else {
m_networkTryNum = 0;
}
emit onWeatherUpdate("天气不可用", "", "");
return;
}
//注:天气信息只解析了锁屏需要展示的部分
QByteArray BA;
QJsonDocument JD;
QJsonParseError JPE;
BA = reply->readAll();
// QTextCodec *codec = QTextCodec::codecForName("UTF-8");
// QString all = codec->toUnicode(BA);
// qDebug() << "reply is:" << all;
JD = QJsonDocument::fromJson(BA, &JPE);
if (JPE.error == QJsonParseError::NoError)
{
if (JD.isObject())
{
QJsonObject kylinWeatherObj = JD.object().value("KylinWeather").toObject();
QString nowWeather = kylinWeatherObj.value("weather").toObject().value("now").toString();
m_city_name = kylinWeatherObj.value("weather").toObject().value("location").toString();
QStringList nowList = nowWeather.split(",");
for(QString now : nowList)
{
if(now.contains("cond_txt")) {
m_cond_txt = now.mid(9);
}
if (now.contains("tmp")){
m_temperature = now.mid(4) + "°C";
}
}
emit onWeatherUpdate(m_city_name, m_cond_txt, m_temperature);
}
} else {
qWarning() << "get weather info error : " << JPE.errorString();
emit onWeatherUpdate("天气不可用", "", "");
}
reply->deleteLater();
}
QPixmap WeatherManager::getWeatherIcon()
{
return getWeatherIcon(m_cond_txt);
}
QPixmap WeatherManager::getWeatherIcon(QString cond)
{
if (cond.isEmpty())
{
qWarning() << "cond info is unknown";
return QPixmap(":/weather/assets/weather-icon/999.svg").scaled(32,32);
}
//根据m_cond_txt
QString numStr = weatherMap.value(cond);
if (!numStr.isEmpty()) {
qDebug() << "----------------numStr=" + numStr;
return QPixmap(":/weather/assets/weather-icon/" + numStr +".svg").scaled(32,32);
}
qWarning() << "天气为|" << cond << "|";
return QPixmap(":/weather/assets/weather-icon/999.svg").scaled(32,32);
}
QString WeatherManager::getCityName()
{
return "";
}
QString WeatherManager::getCond()
{
return "";
}
QString WeatherManager::getTemperature()
{
return "";
}
LocalWeatherInfo::LocalWeatherInfo(QObject *parent)
{
}
bool LocalWeatherInfo::isTimeValid()
{
if (m_update_time != nullptr && !m_update_time.isEmpty())
{
QString strBuffer;
QDateTime time = QDateTime::fromString(m_update_time, "yyyy-MM-dd hh:mm:ss");
QDateTime currentTime = QDateTime::currentDateTime();
if (!time.isValid())
return false;
uint timeInterval = currentTime.toTime_t() - time.toTime_t();
if((timeInterval <= 21 * 60)
&& (timeInterval > 0))
{
//麒麟天气更新时间为20分钟加入1分钟容错机制
return true;
}
}
return false;
}
void LocalWeatherInfo::setTime(QString time)
{
m_update_time = time;
}
QString LocalWeatherInfo::getTime()
{
return m_update_time;
}
void LocalWeatherInfo::setCityId(QString cityId)
{
m_city_id = cityId;
}
QString LocalWeatherInfo::getCityId()
{
return m_city_id;
}
void LocalWeatherInfo::setCityName(QString cityName)
{
m_city_name = cityName;
}
QString LocalWeatherInfo::getCityName()
{
return m_city_name;
}
void LocalWeatherInfo::setCondText(QString condText)
{
m_cond_text = condText;
}
QString LocalWeatherInfo::getCondText()
{
return m_cond_text;
}
void LocalWeatherInfo::setAirHumidity(QString airHumidity)
{
m_air_humidity = airHumidity;
}
QString LocalWeatherInfo::getAirHumidity()
{
return m_air_humidity;
}
void LocalWeatherInfo::setTemperature(QString temperature)
{
m_temperature = temperature;
}
QString LocalWeatherInfo::getTemperature()
{
return m_temperature;
}
void LocalWeatherInfo::setWindDirection(QString windDirection)
{
m_wind_direction = windDirection;
}
QString LocalWeatherInfo::getWindDirection()
{
return m_wind_direction;
}
void LocalWeatherInfo::setWindForce(QString windForce)
{
m_wind_force = windForce;
}
QString LocalWeatherInfo::getWindForce()
{
return m_wind_force;
}