summaryrefslogtreecommitdiffstats
path: root/xbmc/weather/WeatherJob.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/weather/WeatherJob.cpp')
-rw-r--r--xbmc/weather/WeatherJob.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/xbmc/weather/WeatherJob.cpp b/xbmc/weather/WeatherJob.cpp
new file mode 100644
index 0000000..17a0995
--- /dev/null
+++ b/xbmc/weather/WeatherJob.cpp
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2012-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "WeatherJob.h"
+
+#include "GUIUserMessages.h"
+#include "LangInfo.h"
+#include "ServiceBroker.h"
+#include "XBDateTime.h"
+#include "addons/AddonManager.h"
+#include "addons/addoninfo/AddonType.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/LocalizeStrings.h"
+#include "interfaces/generic/ScriptInvocationManager.h"
+#include "network/Network.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
+#include "settings/lib/Setting.h"
+#include "utils/POUtils.h"
+#include "utils/StringUtils.h"
+#include "utils/URIUtils.h"
+#include "utils/Variant.h"
+#include "utils/XTimeUtils.h"
+#include "utils/log.h"
+
+#define LOCALIZED_TOKEN_FIRSTID 370
+#define LOCALIZED_TOKEN_LASTID 395
+#define LOCALIZED_TOKEN_FIRSTID2 1350
+#define LOCALIZED_TOKEN_LASTID2 1449
+#define LOCALIZED_TOKEN_FIRSTID3 11
+#define LOCALIZED_TOKEN_LASTID3 17
+#define LOCALIZED_TOKEN_FIRSTID4 71
+#define LOCALIZED_TOKEN_LASTID4 97
+
+using namespace ADDON;
+
+using namespace std::chrono_literals;
+
+CWeatherJob::CWeatherJob(int location)
+{
+ m_location = location;
+}
+
+bool CWeatherJob::DoWork()
+{
+ // wait for the network
+ if (!CServiceBroker::GetNetwork().IsAvailable())
+ return false;
+
+ AddonPtr addon;
+ if (!CServiceBroker::GetAddonMgr().GetAddon(
+ CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(
+ CSettings::SETTING_WEATHER_ADDON),
+ addon, AddonType::SCRIPT_WEATHER, OnlyEnabled::CHOICE_YES))
+ return false;
+
+ // initialize our sys.argv variables
+ std::vector<std::string> argv;
+ argv.push_back(addon->LibPath());
+
+ std::string strSetting = std::to_string(m_location);
+ argv.push_back(strSetting);
+
+ // Download our weather
+ CLog::Log(LOGINFO, "WEATHER: Downloading weather");
+ // call our script, passing the areacode
+ int scriptId = -1;
+ if ((scriptId = CScriptInvocationManager::GetInstance().ExecuteAsync(argv[0], addon, argv)) >= 0)
+ {
+ while (true)
+ {
+ if (!CScriptInvocationManager::GetInstance().IsRunning(scriptId))
+ break;
+ KODI::TIME::Sleep(100ms);
+ }
+
+ SetFromProperties();
+
+ // and send a message that we're done
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_WEATHER_FETCHED);
+ CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg);
+ }
+ else
+ CLog::Log(LOGERROR, "WEATHER: Weather download failed!");
+
+ return true;
+}
+
+const CWeatherInfo &CWeatherJob::GetInfo() const
+{
+ return m_info;
+}
+
+void CWeatherJob::LocalizeOverviewToken(std::string &token)
+{
+ // This routine is case-insensitive.
+ std::string strLocStr;
+ if (!token.empty())
+ {
+ ilocalizedTokens i;
+ i = m_localizedTokens.find(token);
+ if (i != m_localizedTokens.end())
+ {
+ strLocStr = g_localizeStrings.Get(i->second);
+ }
+ }
+ if (strLocStr == "")
+ strLocStr = token; //if not found, let fallback
+ token = strLocStr;
+}
+
+void CWeatherJob::LocalizeOverview(std::string &str)
+{
+ std::vector<std::string> words = StringUtils::Split(str, " ");
+ for (std::vector<std::string>::iterator i = words.begin(); i != words.end(); ++i)
+ LocalizeOverviewToken(*i);
+ str = StringUtils::Join(words, " ");
+}
+
+void CWeatherJob::FormatTemperature(std::string &text, double temp)
+{
+ CTemperature temperature = CTemperature::CreateFromCelsius(temp);
+ text = StringUtils::Format("{:.0f}", temperature.To(g_langInfo.GetTemperatureUnit()));
+}
+
+void CWeatherJob::LoadLocalizedToken()
+{
+ // We load the english strings in to get our tokens
+ std::string language = LANGUAGE_DEFAULT;
+ std::shared_ptr<CSettingString> languageSetting = std::static_pointer_cast<CSettingString>(CServiceBroker::GetSettingsComponent()->GetSettings()->GetSetting(CSettings::SETTING_LOCALE_LANGUAGE));
+ if (languageSetting != NULL)
+ language = languageSetting->GetDefault();
+
+ // Load the strings.po file
+ CPODocument PODoc;
+ if (PODoc.LoadFile(URIUtils::AddFileToFolder(CLangInfo::GetLanguagePath(language), "strings.po")))
+ {
+ int counter = 0;
+
+ while (PODoc.GetNextEntry())
+ {
+ if (PODoc.GetEntryType() != ID_FOUND)
+ continue;
+
+ uint32_t id = PODoc.GetEntryID();
+ PODoc.ParseEntry(ISSOURCELANG);
+
+ if (id > LOCALIZED_TOKEN_LASTID2) break;
+ if ((LOCALIZED_TOKEN_FIRSTID <= id && id <= LOCALIZED_TOKEN_LASTID) ||
+ (LOCALIZED_TOKEN_FIRSTID2 <= id && id <= LOCALIZED_TOKEN_LASTID2) ||
+ (LOCALIZED_TOKEN_FIRSTID3 <= id && id <= LOCALIZED_TOKEN_LASTID3) ||
+ (LOCALIZED_TOKEN_FIRSTID4 <= id && id <= LOCALIZED_TOKEN_LASTID4))
+ {
+ if (!PODoc.GetMsgid().empty())
+ {
+ m_localizedTokens.insert(make_pair(PODoc.GetMsgid(), id));
+ counter++;
+ }
+ }
+ }
+
+ CLog::Log(LOGDEBUG, "POParser: loaded {} weather tokens", counter);
+ return;
+ }
+}
+
+std::string CWeatherJob::ConstructPath(std::string in) // copy intended
+{
+ if (in.find('/') != std::string::npos || in.find('\\') != std::string::npos)
+ return in;
+ if (in.empty() || in == "N/A")
+ in = "na.png";
+
+ return URIUtils::AddFileToFolder(ICON_ADDON_PATH, in);
+}
+
+void CWeatherJob::SetFromProperties()
+{
+ // Load in our tokens if necessary
+ if (m_localizedTokens.empty())
+ LoadLocalizedToken();
+
+ CGUIWindow* window = CServiceBroker::GetGUI()->GetWindowManager().GetWindow(WINDOW_WEATHER);
+ if (window)
+ {
+ CDateTime time = CDateTime::GetCurrentDateTime();
+ m_info.lastUpdateTime = time.GetAsLocalizedDateTime(false, false);
+ m_info.currentConditions = window->GetProperty("Current.Condition").asString();
+ m_info.currentIcon = ConstructPath(window->GetProperty("Current.OutlookIcon").asString());
+ LocalizeOverview(m_info.currentConditions);
+ FormatTemperature(m_info.currentTemperature,
+ strtod(window->GetProperty("Current.Temperature").asString().c_str(), nullptr));
+ FormatTemperature(m_info.currentFeelsLike,
+ strtod(window->GetProperty("Current.FeelsLike").asString().c_str(), nullptr));
+ m_info.currentUVIndex = window->GetProperty("Current.UVIndex").asString();
+ LocalizeOverview(m_info.currentUVIndex);
+ CSpeed speed = CSpeed::CreateFromKilometresPerHour(strtol(window->GetProperty("Current.Wind").asString().c_str(),0,10));
+ std::string direction = window->GetProperty("Current.WindDirection").asString();
+ if (direction == "CALM")
+ m_info.currentWind = g_localizeStrings.Get(1410);
+ else
+ {
+ LocalizeOverviewToken(direction);
+ m_info.currentWind = StringUtils::Format(g_localizeStrings.Get(434), direction,
+ (int)speed.To(g_langInfo.GetSpeedUnit()),
+ g_langInfo.GetSpeedUnitString());
+ }
+ std::string windspeed = StringUtils::Format("{} {}", (int)speed.To(g_langInfo.GetSpeedUnit()),
+ g_langInfo.GetSpeedUnitString());
+ window->SetProperty("Current.WindSpeed",windspeed);
+ FormatTemperature(m_info.currentDewPoint,
+ strtod(window->GetProperty("Current.DewPoint").asString().c_str(), nullptr));
+ if (window->GetProperty("Current.Humidity").asString().empty())
+ m_info.currentHumidity.clear();
+ else
+ m_info.currentHumidity =
+ StringUtils::Format("{}%", window->GetProperty("Current.Humidity").asString());
+ m_info.location = window->GetProperty("Current.Location").asString();
+ for (int i=0;i<NUM_DAYS;++i)
+ {
+ std::string strDay = StringUtils::Format("Day{}.Title", i);
+ m_info.forecast[i].m_day = window->GetProperty(strDay).asString();
+ LocalizeOverviewToken(m_info.forecast[i].m_day);
+ strDay = StringUtils::Format("Day{}.HighTemp", i);
+ FormatTemperature(m_info.forecast[i].m_high,
+ strtod(window->GetProperty(strDay).asString().c_str(), nullptr));
+ strDay = StringUtils::Format("Day{}.LowTemp", i);
+ FormatTemperature(m_info.forecast[i].m_low,
+ strtod(window->GetProperty(strDay).asString().c_str(), nullptr));
+ strDay = StringUtils::Format("Day{}.OutlookIcon", i);
+ m_info.forecast[i].m_icon = ConstructPath(window->GetProperty(strDay).asString());
+ strDay = StringUtils::Format("Day{}.Outlook", i);
+ m_info.forecast[i].m_overview = window->GetProperty(strDay).asString();
+ LocalizeOverview(m_info.forecast[i].m_overview);
+ }
+ }
+}