mirror of
https://github.com/Team-Resurgent/xbmc4xbox-redux.git
synced 2026-08-15 20:18:49 -07:00
[Weather] added: implement Gismeteo API as internal weather
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<addon id="weather.xbmc.builtin" version="1.0.0" name="Weather API (Internal Weather)" provider-name="Team XBMC">
|
||||
<requires>
|
||||
<import addon="xbmc.python" version="2.19.0"/>
|
||||
</requires>
|
||||
<extension point="xbmc.python.weather" library="default.py"/>
|
||||
<extension point="xbmc.addon.metadata">
|
||||
<summary lang="en_GB">Internal weather provided by Weather API.</summary>
|
||||
<description>This is the default weather source. It provides current weather conditions and a five day outlook.</description>
|
||||
<platform>all</platform>
|
||||
<website>https://www.weatherapi.com/</website>
|
||||
<assets>
|
||||
<icon>icon.png</icon>
|
||||
</assets>
|
||||
</extension>
|
||||
</addon>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<addon id="weather.xbmc.builtin" version="1.0.0" name="Gismeteo (Internal Weather)" provider-name="Team XBMC">
|
||||
<requires>
|
||||
<import addon="xbmc.python" version="2.19.0"/>
|
||||
</requires>
|
||||
<extension point="xbmc.python.weather" library="default.py"/>
|
||||
<extension point="xbmc.addon.metadata">
|
||||
<summary lang="en_GB">Internal weather provided by Gismeteo API.</summary>
|
||||
<description>This is the default weather source. It provides current weather conditions and a seven day outlook.</description>
|
||||
<platform>all</platform>
|
||||
<website>https://www.gismeteo.ru/</website>
|
||||
<assets>
|
||||
<icon>icon.png</icon>
|
||||
</assets>
|
||||
</extension>
|
||||
</addon>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import sys, urllib, urllib2, json, xbmc, xbmcgui, xbmcaddon
|
||||
import sys, urllib, urllib2, xbmc, xbmcgui, xbmcaddon
|
||||
import xml.etree.ElementTree as ET
|
||||
from urlparse import urlparse, parse_qs
|
||||
|
||||
heading = "Weather API"
|
||||
|
||||
class WeatherError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Location:
|
||||
@@ -15,31 +18,54 @@ class Location:
|
||||
|
||||
|
||||
class WeatherAPI:
|
||||
api = "http://api.weatherapi.com/v1/search.json"
|
||||
api = "https://services.gismeteo.net/inform-service/inf_chrome/cities"
|
||||
|
||||
@staticmethod
|
||||
def _extract_xml(r):
|
||||
|
||||
try:
|
||||
return ET.fromstring(r)
|
||||
except (ValueError, ET.ParseError) as e:
|
||||
xbmc.log("Weather API: error when parsing response\n Error {1}".format(str(e)))
|
||||
|
||||
return None
|
||||
|
||||
def make_request(self, url):
|
||||
try:
|
||||
request = urllib2.Request(url)
|
||||
request.add_header("User-Agent", "XBMC4Xbox/4.0")
|
||||
response = urllib2.urlopen(request)
|
||||
response_data = response.read()
|
||||
body = json.loads(response_data)
|
||||
return body
|
||||
return response.read()
|
||||
except Exception as e:
|
||||
xbmc.log(
|
||||
"Weather API: error when calling: {0}\n Error {1}".format(url, str(e))
|
||||
)
|
||||
xbmcgui.Dialog().notification(
|
||||
heading, xbmc.getLocalizedString(15301), xbmcgui.NOTIFICATION_ERROR
|
||||
)
|
||||
xbmc.log("Weather API: error when calling: {0}\n Error {1}".format(url, str(e)))
|
||||
|
||||
xbmcgui.Dialog().notification("Weather API", xbmc.getLocalizedString(15301), xbmcgui.NOTIFICATION_ERROR)
|
||||
return None
|
||||
|
||||
def search_location(self, query):
|
||||
url = "{0}?{1}".format(
|
||||
self.api,
|
||||
urllib.urlencode({"key": "e74f39b17d374e86ad4233506220912", "q": query}),
|
||||
urllib.urlencode({"lang": "en", "startsWith": query}),
|
||||
)
|
||||
return self.make_request(url)
|
||||
|
||||
body = self.make_request(url)
|
||||
if not body:
|
||||
return []
|
||||
|
||||
root = self._extract_xml(body)
|
||||
if root is None:
|
||||
return []
|
||||
|
||||
items = []
|
||||
for item in root.findall("item"):
|
||||
items.append({"id": item.attrib["id"],
|
||||
"name": item.attrib["n"],
|
||||
"region": item.attrib["district_name"],
|
||||
"country": item.attrib["country_name"],
|
||||
"lat": item.attrib["lat"],
|
||||
"lon": item.attrib["lng"]})
|
||||
|
||||
return items
|
||||
|
||||
|
||||
def run(id, addon):
|
||||
@@ -72,10 +98,7 @@ def run(id, addon):
|
||||
selected = xbmcgui.Dialog().select(xbmc.getLocalizedString(396), labels)
|
||||
if selected != -1:
|
||||
selected_location = locations[selected]
|
||||
addon.setSetting(
|
||||
"Location{}".format(id),
|
||||
"{0}, {1}".format(selected_location.name, selected_location.country),
|
||||
)
|
||||
addon.setSetting("Location{}".format(id), selected_location.name)
|
||||
addon.setSetting("Location{}ID".format(id), str(selected_location.id))
|
||||
addon.setSetting(
|
||||
"Location{}LAT".format(id), str(selected_location.lat)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 21 KiB |
@@ -1,7 +1,7 @@
|
||||
# Kodi Media Center language file
|
||||
# Addon Name: Gismeteo
|
||||
# Addon id: weather.gismeteo
|
||||
# Addon Provider: vl.maksime
|
||||
# Addon Name: Built-in Weather
|
||||
# Addon id: weather.xbmc.builtin
|
||||
# Addon Provider: Team XBMC
|
||||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
@@ -14,10 +14,6 @@ msgctxt "#32101"
|
||||
msgid "Location setup"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "#32110"
|
||||
msgid "Current Location"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "#32111"
|
||||
msgid "Location 1"
|
||||
msgstr ""
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<settings>
|
||||
<category label="32101">
|
||||
<setting id="CurrentLocation" label="32110" type="select" lvalues="32111|32112|32113|32114|32115" default="0"/>
|
||||
<setting id="Location1" label="32111" type="action" action="RunScript($ID,action=location&id=1)" default=""/>
|
||||
<setting id="Location2" label="32112" type="action" action="RunScript($ID,action=location&id=2)" enable="!eq(-1,)" default=""/>
|
||||
<setting id="Location3" label="32113" type="action" action="RunScript($ID,action=location&id=3)" enable="!eq(-1,)" default=""/>
|
||||
|
||||
+393
-38
@@ -34,6 +34,8 @@
|
||||
#ifdef _XBOX
|
||||
#include "filesystem/CurlFile.h"
|
||||
#include "utils/JSONVariantParser.h"
|
||||
#include "utils/MathUtils.h"
|
||||
#include "utils/XBMCTinyXML.h"
|
||||
#endif
|
||||
#include "guilib/GUIWindowManager.h"
|
||||
#include "guilib/LocalizeStrings.h"
|
||||
@@ -100,23 +102,29 @@ bool CWeatherJob::DoWork()
|
||||
CLog::Log(LOGINFO, "WEATHER: Downloading weather");
|
||||
// call our script, passing the areacode
|
||||
int scriptId = -1;
|
||||
#ifdef _XBOX
|
||||
if (addon->ID() == "weather.xbmc.builtin")
|
||||
{
|
||||
int iCurrentLocation = atoi(addon->GetSetting("CurrentLocation").c_str());
|
||||
std::string lat = addon->GetSetting(StringUtils::Format("Location%iLAT", iCurrentLocation + 1));
|
||||
std::string lon = addon->GetSetting(StringUtils::Format("Location%iLON", iCurrentLocation + 1));
|
||||
if (FetchInternalWeather(lat, lon))
|
||||
int maxLocations = 0;
|
||||
for (int i = 1; i <= 5; ++i)
|
||||
{
|
||||
SetFromProperties();
|
||||
|
||||
// and send a message that we're done
|
||||
CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_WEATHER_FETCHED);
|
||||
g_windowManager.SendThreadMessage(msg);
|
||||
if (!addon->GetSetting(StringUtils::Format("Location%i", i)).empty())
|
||||
maxLocations++;
|
||||
}
|
||||
// locations are still not set
|
||||
if (!maxLocations)
|
||||
return true;
|
||||
|
||||
std::string strLocation = addon->GetSetting(StringUtils::Format("Location%i", m_location));
|
||||
std::string strLocationID = addon->GetSetting(StringUtils::Format("Location%iID", m_location));
|
||||
FetchInternalWeather(strLocationID, strLocation, maxLocations);
|
||||
|
||||
SetFromProperties();
|
||||
|
||||
// and send a message that we're done
|
||||
CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_WEATHER_FETCHED);
|
||||
g_windowManager.SendThreadMessage(msg);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ((scriptId = CScriptInvocationManager::GetInstance().ExecuteAsync(argv[0], addon, argv)) >= 0)
|
||||
{
|
||||
while (true)
|
||||
@@ -144,12 +152,164 @@ const CWeatherInfo &CWeatherJob::GetInfo() const
|
||||
}
|
||||
|
||||
#ifdef _XBOX
|
||||
bool CWeatherJob::FetchInternalWeather(std::string strLat, std::string strLon) const
|
||||
const struct WeatherCode {
|
||||
const char* key;
|
||||
const char* value;
|
||||
} WEATHER_ICONS[] =
|
||||
{
|
||||
{"c4", "26"},
|
||||
{"c4.st", "26"},
|
||||
{"c4.r1", "11"},
|
||||
{"c4.r1.st", "4"},
|
||||
{"c4.r2", "11"},
|
||||
{"c4.r2.st", "4"},
|
||||
{"c4.r3", "12"},
|
||||
{"c4.r3.st", "4"},
|
||||
{"c4.s1", "16"},
|
||||
{"c4.s1.st", "16"},
|
||||
{"c4.s2", "16"},
|
||||
{"c4.s2.st", "16"},
|
||||
{"c4.s3", "16"},
|
||||
{"c4.s3.st", "16"},
|
||||
{"c4.rs1", "5"},
|
||||
{"c4.rs1.st", "5"},
|
||||
{"c4.rs2", "5"},
|
||||
{"c4.rs2.st", "5"},
|
||||
{"c4.rs3", "5"},
|
||||
{"c4.rs3.st", "5"},
|
||||
{"d", "32"},
|
||||
{"d.st", "32"},
|
||||
{"d.c2", "30"},
|
||||
{"d.c2.r1", "39"},
|
||||
{"d.c2.r1.st", "37"},
|
||||
{"d.c2.r2", "39"},
|
||||
{"d.c2.r2.st", "37"},
|
||||
{"d.c2.r3", "39"},
|
||||
{"d.c2.r3.st", "37"},
|
||||
{"d.c2.rs1", "42"},
|
||||
{"d.c2.rs1.st", "42"},
|
||||
{"d.c2.rs2", "42"},
|
||||
{"d.c2.rs2.st", "42"},
|
||||
{"d.c2.rs3", "42"},
|
||||
{"d.c2.rs3.st", "42"},
|
||||
{"d.c2.s1", "41"},
|
||||
{"d.c2.s1.st", "41"},
|
||||
{"d.c2.s2", "41"},
|
||||
{"d.c2.s2.st", "41"},
|
||||
{"d.c2.s3", "41"},
|
||||
{"d.c2.s3.st", "41"},
|
||||
{"d.c3", "28"},
|
||||
{"d.c3.r1", "11"},
|
||||
{"d.c3.r1.st", "38"},
|
||||
{"d.c3.r2", "11"},
|
||||
{"d.c3.r2.st", "38"},
|
||||
{"d.c3.r3", "11"},
|
||||
{"d.c3.r3.st", "38"},
|
||||
{"d.c3.s1", "14"},
|
||||
{"d.c3.s1.st", "14"},
|
||||
{"d.c3.s2", "14"},
|
||||
{"d.c3.s2.st", "14"},
|
||||
{"d.c3.s3", "14"},
|
||||
{"d.c3.s3.st", "14"},
|
||||
{"d.c3.rs1", "42"},
|
||||
{"d.c3.rs1.st", "42"},
|
||||
{"d.c3.rs2", "42"},
|
||||
{"d.c3.rs2.st", "42"},
|
||||
{"d.c3.rs3", "42"},
|
||||
{"d.c3.rs3.st", "42"},
|
||||
{"n", "31"},
|
||||
{"n.st", "31"},
|
||||
{"n.c2", "29"},
|
||||
{"n.c2.r1", "45"},
|
||||
{"n.c2.r1.st", "47"},
|
||||
{"n.c2.r2", "45"},
|
||||
{"n.c2.r2.st", "47"},
|
||||
{"n.c2.r3", "45"},
|
||||
{"n.c2.r3.st", "47"},
|
||||
{"n.c2.rs1", "42"},
|
||||
{"n.c2.rs1.st", "42"},
|
||||
{"n.c2.rs2", "42"},
|
||||
{"n.c2.rs2.st", "42"},
|
||||
{"n.c2.rs3", "42"},
|
||||
{"n.c2.rs3.st", "42"},
|
||||
{"n.c2.s1", "46"},
|
||||
{"n.c2.s1.st", "46"},
|
||||
{"n.c2.s2", "46"},
|
||||
{"n.c2.s2.st", "46"},
|
||||
{"n.c2.s3", "46"},
|
||||
{"n.c2.s3.st", "46"},
|
||||
{"n.c3", "27"},
|
||||
{"n.c3.r1", "11"},
|
||||
{"n.c3.r1.st", "4"},
|
||||
{"n.c3.r2", "11"},
|
||||
{"n.c3.r2.st", "4"},
|
||||
{"n.c3.r3", "11"},
|
||||
{"n.c3.r3.st", "4"},
|
||||
{"n.c3.rs1", "42"},
|
||||
{"n.c3.rs1.st", "42"},
|
||||
{"n.c3.rs2", "42"},
|
||||
{"n.c3.rs2.st", "42"},
|
||||
{"n.c3.rs3", "42"},
|
||||
{"n.c3.rs3.st", "42"},
|
||||
{"n.c3.s1", "14"},
|
||||
{"n.c3.s1.st", "14"},
|
||||
{"n.c3.s2", "14"},
|
||||
{"n.c3.s2.st", "14"},
|
||||
{"n.c3.s3", "14"},
|
||||
{"n.c3.s3.st", "14"},
|
||||
{"mist", "32"},
|
||||
{"r1.mist", "11"},
|
||||
{"r1.st.mist", "38"},
|
||||
{"r2.mist", "11"},
|
||||
{"r2.st.mist", "38"},
|
||||
{"r3.mist", "11"},
|
||||
{"r3.st.mist", "38"},
|
||||
{"s1.mist", "14"},
|
||||
{"s1.st.mist", "14"},
|
||||
{"s2.mist", "14"},
|
||||
{"s2.st.mist", "14"},
|
||||
{"s3.mist", "14"},
|
||||
{"s3.st.mist", "14"},
|
||||
{"rs1.mist", "42"},
|
||||
{"rs1.st.mist", "42"},
|
||||
{"rs2.mist", "42"},
|
||||
{"rs2.st.mist", "42"},
|
||||
{"rs3.mist", "42"},
|
||||
{"rs3.st.mist", "42"}
|
||||
};
|
||||
|
||||
static const size_t WEATHER_ICONS_SIZE = sizeof(WEATHER_ICONS) / sizeof(WEATHER_ICONS[0]);
|
||||
|
||||
std::string weather_code_lookup(const std::string& key)
|
||||
{
|
||||
for (size_t i = 0; i < WEATHER_ICONS_SIZE; ++i)
|
||||
{
|
||||
if (key == WEATHER_ICONS[i].key)
|
||||
return std::string(WEATHER_ICONS[i].value) + ".png";
|
||||
}
|
||||
return "na.png";
|
||||
}
|
||||
|
||||
int CalculateDewPoint(double Tc = 0.0, double RH = 93.0, bool ext = true, double minRH = 0.0)
|
||||
{
|
||||
// thanks to FrostBox @ http://forum.kodi.tv/showthread.php?tid=114637&pid=937168#pid937168
|
||||
double Es = 6.11 * std::pow(10.0, (7.5 * Tc) / (237.7 + Tc));
|
||||
if (RH == 0.0)
|
||||
RH = minRH;
|
||||
double E = (RH * Es) / 100.0;
|
||||
if (E > 0.0)
|
||||
{
|
||||
double lnE = std::log(E);
|
||||
double dewPoint = (-430.22 + 237.7 * lnE) / (-lnE + 19.08);
|
||||
return MathUtils::round_int(dewPoint);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CWeatherJob::FetchInternalWeather(const std::string& strLocationID, const std::string& strLocation, const int maxLocations) const
|
||||
{
|
||||
std::string strLocale = g_langInfo.GetLocale().GetLanguageCode();
|
||||
std::string strURL = StringUtils::Format(
|
||||
"http://api.weatherapi.com/v1/forecast.json?key=be7c11e4b6f04d1fb8d142241221112&q=%s,%s&days=7&aqi=no&alerts=no&lang=%s", strLat.c_str(), strLon.c_str(), strLocale.c_str()
|
||||
);
|
||||
std::string strURL = "https://services.gismeteo.net/inform-service/inf_chrome/forecast/?lang=en&city=" + strLocationID;
|
||||
|
||||
XFILE::CCurlFile httpUtil;
|
||||
std::string bodyResponse;
|
||||
@@ -158,35 +318,230 @@ bool CWeatherJob::FetchInternalWeather(std::string strLat, std::string strLon) c
|
||||
CLog::Log(LOGWARNING, "Internal weather fetching failed");
|
||||
return false;
|
||||
}
|
||||
CVariant obj = CJSONVariantParser::Parse((const unsigned char *)bodyResponse.c_str(), bodyResponse.size());
|
||||
|
||||
CGUIWindow* window = g_windowManager.GetWindow(WINDOW_WEATHER);
|
||||
window->SetProperty("Current.Condition", obj["current"]["condition"]["text"].asString());
|
||||
window->SetProperty("Current.OutlookIcon", StringUtils::Format("https:%s", obj["current"]["condition"]["icon"].asString().c_str()));
|
||||
window->SetProperty("Current.Temperature", obj["current"]["temp_c"].asString());
|
||||
window->SetProperty("Current.FeelsLike", obj["current"]["feelslike_c"].asString());
|
||||
window->SetProperty("Current.UVIndex", obj["current"]["uv"].asString());
|
||||
window->SetProperty("Current.Wind", obj["current"]["wind_kph"].asString());
|
||||
window->SetProperty("Current.WindDirection", obj["current"]["wind_dir"].asString());
|
||||
window->SetProperty("Current.DewPoint", obj["current"]["dewpoint_c"].asString());
|
||||
window->SetProperty("Current.Humidity", obj["current"]["humidity"].asString());
|
||||
window->SetProperty("Current.Location", obj["location"]["name"].asString());
|
||||
window->SetProperty("Current.Location", strLocation);
|
||||
window->SetProperty("Locations", maxLocations);
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
CXBMCTinyXML doc;
|
||||
if (doc.Parse(bodyResponse))
|
||||
{
|
||||
CDateTime dateTime = CDateTime::FromDBDate(obj["forecast"]["forecastday"][i]["date"].asString());
|
||||
std::string strDay = StringUtils::Format("Day%i.Title",i);
|
||||
window->SetProperty(strDay, g_localizeStrings.Get(dateTime.GetDayOfWeek() + 10));
|
||||
strDay = StringUtils::Format("Day%i.HighTemp",i);
|
||||
window->SetProperty(strDay, obj["forecast"]["forecastday"][i]["day"]["maxtemp_c"].asString());
|
||||
strDay = StringUtils::Format("Day%i.LowTemp",i);
|
||||
window->SetProperty(strDay, obj["forecast"]["forecastday"][i]["day"]["mintemp_c"].asString());
|
||||
strDay = StringUtils::Format("Day%i.OutlookIcon",i);
|
||||
window->SetProperty(strDay, StringUtils::Format("https:%s", obj["forecast"]["forecastday"][i]["day"]["condition"]["icon"].asString().c_str()));
|
||||
strDay = StringUtils::Format("Day%i.Outlook",i);
|
||||
window->SetProperty(strDay, obj["forecast"]["forecastday"][i]["day"]["condition"]["text"].asString());
|
||||
TiXmlElement* element = doc.RootElement();
|
||||
if (!element)
|
||||
return false;
|
||||
|
||||
element = element->FirstChildElement("location");
|
||||
if (!element)
|
||||
return false;
|
||||
|
||||
// Parse current forecast
|
||||
element = element->FirstChildElement("fact");
|
||||
std::string strValue, strTemp;
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "sunrise");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
time_t t = static_cast<time_t>(strtol(strValue.c_str(), 0, 10));
|
||||
CDateTime dateTime = CDateTime::FromUTCDateTime(t);
|
||||
window->SetProperty("Today.Sunrise", dateTime.GetAsLocalizedTime("HH:mm"));
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "sunset");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
time_t t = static_cast<time_t>(strtol(strValue.c_str(), 0, 10));
|
||||
CDateTime dateTime = CDateTime::FromUTCDateTime(t);
|
||||
window->SetProperty("Today.Sunset", dateTime.GetAsLocalizedTime("HH:mm"));
|
||||
}
|
||||
|
||||
element = element->FirstChildElement("values");
|
||||
strValue = XMLUtils::GetAttribute(element, "hum");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
window->SetProperty("Current.Humidity", strValue);
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "ws");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
int speed = MathUtils::round_int(atoi(strValue.c_str()) * 3.6);
|
||||
window->SetProperty("Current.Wind", speed);
|
||||
window->SetProperty("Current.WindSpeed", speed);
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "wd");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
if (strValue == "0")
|
||||
window->SetProperty("Current.WindDirection", "CALM");
|
||||
else if (strValue == "1")
|
||||
window->SetProperty("Current.WindDirection", "N");
|
||||
else if (strValue == "2")
|
||||
window->SetProperty("Current.WindDirection", "NE");
|
||||
else if (strValue == "3")
|
||||
window->SetProperty("Current.WindDirection", "E");
|
||||
else if (strValue == "4")
|
||||
window->SetProperty("Current.WindDirection", "SE");
|
||||
else if (strValue == "5")
|
||||
window->SetProperty("Current.WindDirection", "S");
|
||||
else if (strValue == "6")
|
||||
window->SetProperty("Current.WindDirection", "SW");
|
||||
else if (strValue == "7")
|
||||
window->SetProperty("Current.WindDirection", "W");
|
||||
else if (strValue == "8")
|
||||
window->SetProperty("Current.WindDirection", "NW");
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "t");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
window->SetProperty("Current.Temperature", strValue);
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "hi");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
window->SetProperty("Current.FeelsLike", strValue);
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "descr");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
window->SetProperty("Current.Condition", strValue);
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "icon");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
window->SetProperty("Current.OutlookIcon", "10.png");
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "pt");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
strValue += ".0 mm";
|
||||
window->SetProperty("Current.Precipitation", strValue);
|
||||
}
|
||||
|
||||
int temperature = window->GetProperty("Current.Temperature").asInteger32();
|
||||
int humidity = window->GetProperty("Current.Humidity").asInteger32();
|
||||
window->SetProperty("Current.DewPoint", CalculateDewPoint(temperature, humidity));
|
||||
|
||||
element = doc.RootElement()->FirstChildElement("location")->FirstChildElement("day");
|
||||
if (!element)
|
||||
return false;
|
||||
|
||||
// Parse hourly forecast
|
||||
element = element->FirstChildElement("forecast");
|
||||
int i = 1;
|
||||
while(element)
|
||||
{
|
||||
const std::string strKey = StringUtils::Format("Hourly.%i.", i);
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "valid");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
CDateTime dateTime = CDateTime::FromDBDateTime(strValue);
|
||||
window->SetProperty(strKey + "Time", dateTime.GetAsLocalizedTime("HH:mm"));
|
||||
|
||||
strValue = StringUtils::Format("%i %s", dateTime.GetDay(), g_localizeStrings.Get(dateTime.GetMonth() + 50).c_str());
|
||||
window->SetProperty(strKey + "ShortDate", strValue);
|
||||
}
|
||||
|
||||
TiXmlElement* elValues = element->FirstChildElement("values");
|
||||
strTemp = XMLUtils::GetAttribute(elValues, "t");
|
||||
if (!strTemp.empty())
|
||||
{
|
||||
FormatTemperature(strValue, strtod(strTemp.c_str(), nullptr));
|
||||
strValue += g_langInfo.GetTemperatureUnitString();
|
||||
window->SetProperty(strKey + "Temperature", strValue);
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(elValues, "pr");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
strValue += ".0 mm";
|
||||
window->SetProperty(strKey + "Precipitation", strValue);
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(elValues, "descr");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
window->SetProperty(strKey + "Outlook", strValue);
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(elValues, "icon");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
window->SetProperty(strKey + "OutlookIcon", weather_code_lookup(strValue));
|
||||
}
|
||||
|
||||
++i;
|
||||
element = element->NextSiblingElement("forecast");
|
||||
}
|
||||
|
||||
// Parse daily forecast
|
||||
element = doc.RootElement()->FirstChildElement("location")->FirstChildElement("day");
|
||||
i = 1;
|
||||
while(element)
|
||||
{
|
||||
const std::string strKey = StringUtils::Format("Daily.%i.", i);
|
||||
const std::string strKey2 = StringUtils::Format("Day%i.", i);
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "date");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
CDateTime dateTime = CDateTime::FromDBDate(strValue);
|
||||
int dayOfWeek = dateTime.GetDayOfWeek();
|
||||
if (dayOfWeek == 0)
|
||||
dayOfWeek = 7;
|
||||
std::string strValue = g_localizeStrings.Get(dayOfWeek + 40);
|
||||
window->SetProperty(strKey + "ShortDay", strValue);
|
||||
window->SetProperty(strKey2 + "Title", strValue);
|
||||
strValue = StringUtils::Format("%i %s", dateTime.GetDay(), g_localizeStrings.Get(dateTime.GetMonth() + 50).c_str());
|
||||
window->SetProperty(strKey + "ShortDate", strValue);
|
||||
}
|
||||
|
||||
strTemp = XMLUtils::GetAttribute(element, "tmin");
|
||||
if (!strTemp.empty())
|
||||
{
|
||||
FormatTemperature(strValue, strtod(strTemp.c_str(), nullptr));
|
||||
strValue += g_langInfo.GetTemperatureUnitString();
|
||||
window->SetProperty(strKey + "LowTemperature", strValue);
|
||||
window->SetProperty(strKey2 + "LowTemp", strValue);
|
||||
}
|
||||
|
||||
strTemp = XMLUtils::GetAttribute(element, "tmax");
|
||||
if (!strTemp.empty())
|
||||
{
|
||||
FormatTemperature(strValue, strtod(strTemp.c_str(), nullptr));
|
||||
strValue += g_langInfo.GetTemperatureUnitString();
|
||||
window->SetProperty(strKey + "HighTemperature", strValue);
|
||||
window->SetProperty(strKey2 + "HighTemp", strValue);
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "descr");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
window->SetProperty(strKey + "Outlook", strValue);
|
||||
window->SetProperty(strKey2 + "Outlook", strValue);
|
||||
}
|
||||
|
||||
strValue = XMLUtils::GetAttribute(element, "icon");
|
||||
if (!strValue.empty())
|
||||
{
|
||||
std::string strIcon = weather_code_lookup(strValue);
|
||||
window->SetProperty(strKey + "OutlookIcon", strIcon);
|
||||
window->SetProperty(strKey2 + "OutlookIcon", strIcon);
|
||||
}
|
||||
|
||||
++i;
|
||||
element = element->NextSiblingElement("day");
|
||||
}
|
||||
}
|
||||
|
||||
window->SetProperty("Hourly.IsFetched", "true");
|
||||
window->SetProperty("Daily.IsFetched", "true");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
const CWeatherInfo &GetInfo() const;
|
||||
private:
|
||||
#ifdef _XBOX
|
||||
bool FetchInternalWeather(std::string strLat, std::string strLon) const;
|
||||
bool FetchInternalWeather(const std::string& strLocationID, const std::string& strLocation, const int maxLocations) const;
|
||||
#endif
|
||||
void LocalizeOverview(std::string &str);
|
||||
void LocalizeOverviewToken(std::string &str);
|
||||
|
||||
Reference in New Issue
Block a user