WeatherProvider.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. using MediaBrowser.Common.Serialization;
  2. using MediaBrowser.Controller;
  3. using MediaBrowser.Controller.Weather;
  4. using MediaBrowser.Model.Logging;
  5. using MediaBrowser.Model.Weather;
  6. using System;
  7. using System.ComponentModel.Composition;
  8. using System.Linq;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. namespace MediaBrowser.Server.WorldWeatherOnline
  12. {
  13. /// <summary>
  14. /// Based on http://www.worldweatheronline.com/free-weather-feed.aspx
  15. /// The classes in this file are a reproduction of the json output, which will then be converted to our weather model classes
  16. /// </summary>
  17. [Export(typeof(IWeatherProvider))]
  18. public class WeatherProvider : IWeatherProvider
  19. {
  20. /// <summary>
  21. /// Gets or sets the logger.
  22. /// </summary>
  23. /// <value>The logger.</value>
  24. private ILogger Logger { get; set; }
  25. /// <summary>
  26. /// Initializes a new instance of the <see cref="WeatherProvider" /> class.
  27. /// </summary>
  28. /// <param name="logger">The logger.</param>
  29. /// <exception cref="System.ArgumentNullException">logger</exception>
  30. [ImportingConstructor]
  31. public WeatherProvider([Import("logger")] ILogger logger)
  32. {
  33. if (logger == null)
  34. {
  35. throw new ArgumentNullException("logger");
  36. }
  37. Logger = logger;
  38. }
  39. /// <summary>
  40. /// The _weather semaphore
  41. /// </summary>
  42. private readonly SemaphoreSlim _weatherSemaphore = new SemaphoreSlim(10, 10);
  43. /// <summary>
  44. /// Gets the weather info async.
  45. /// </summary>
  46. /// <param name="location">The location.</param>
  47. /// <param name="cancellationToken">The cancellation token.</param>
  48. /// <returns>Task{WeatherInfo}.</returns>
  49. /// <exception cref="System.ArgumentNullException">location</exception>
  50. public async Task<WeatherInfo> GetWeatherInfoAsync(string location, CancellationToken cancellationToken)
  51. {
  52. if (string.IsNullOrWhiteSpace(location))
  53. {
  54. throw new ArgumentNullException("location");
  55. }
  56. if (cancellationToken == null)
  57. {
  58. throw new ArgumentNullException("cancellationToken");
  59. }
  60. const int numDays = 5;
  61. const string apiKey = "24902f60f1231941120109";
  62. var url = "http://free.worldweatheronline.com/feed/weather.ashx?q=" + location + "&format=json&num_of_days=" + numDays + "&key=" + apiKey;
  63. Logger.Info("Accessing weather from " + url);
  64. using (var stream = await Kernel.Instance.HttpManager.Get(url, _weatherSemaphore, cancellationToken).ConfigureAwait(false))
  65. {
  66. var data = JsonSerializer.DeserializeFromStream<WeatherResult>(stream).data;
  67. return GetWeatherInfo(data);
  68. }
  69. }
  70. /// <summary>
  71. /// Converst the json output to our WeatherInfo model class
  72. /// </summary>
  73. /// <param name="data">The data.</param>
  74. /// <returns>WeatherInfo.</returns>
  75. private WeatherInfo GetWeatherInfo(WeatherData data)
  76. {
  77. var info = new WeatherInfo();
  78. if (data.current_condition != null)
  79. {
  80. var condition = data.current_condition.FirstOrDefault();
  81. if (condition != null)
  82. {
  83. info.CurrentWeather = condition.ToWeatherStatus();
  84. }
  85. }
  86. if (data.weather != null)
  87. {
  88. info.Forecasts = data.weather.Select(w => w.ToWeatherForecast()).ToArray();
  89. }
  90. return info;
  91. }
  92. }
  93. /// <summary>
  94. /// Class WeatherResult
  95. /// </summary>
  96. class WeatherResult
  97. {
  98. /// <summary>
  99. /// Gets or sets the data.
  100. /// </summary>
  101. /// <value>The data.</value>
  102. public WeatherData data { get; set; }
  103. }
  104. /// <summary>
  105. /// Class WeatherData
  106. /// </summary>
  107. public class WeatherData
  108. {
  109. /// <summary>
  110. /// Gets or sets the current_condition.
  111. /// </summary>
  112. /// <value>The current_condition.</value>
  113. public WeatherCondition[] current_condition { get; set; }
  114. /// <summary>
  115. /// Gets or sets the weather.
  116. /// </summary>
  117. /// <value>The weather.</value>
  118. public DailyWeatherInfo[] weather { get; set; }
  119. }
  120. /// <summary>
  121. /// Class WeatherCondition
  122. /// </summary>
  123. public class WeatherCondition
  124. {
  125. /// <summary>
  126. /// Gets or sets the temp_ C.
  127. /// </summary>
  128. /// <value>The temp_ C.</value>
  129. public string temp_C { get; set; }
  130. /// <summary>
  131. /// Gets or sets the temp_ F.
  132. /// </summary>
  133. /// <value>The temp_ F.</value>
  134. public string temp_F { get; set; }
  135. /// <summary>
  136. /// Gets or sets the humidity.
  137. /// </summary>
  138. /// <value>The humidity.</value>
  139. public string humidity { get; set; }
  140. /// <summary>
  141. /// Gets or sets the weather code.
  142. /// </summary>
  143. /// <value>The weather code.</value>
  144. public string weatherCode { get; set; }
  145. /// <summary>
  146. /// To the weather status.
  147. /// </summary>
  148. /// <returns>WeatherStatus.</returns>
  149. public WeatherStatus ToWeatherStatus()
  150. {
  151. return new WeatherStatus
  152. {
  153. TemperatureCelsius = int.Parse(temp_C),
  154. TemperatureFahrenheit = int.Parse(temp_F),
  155. Humidity = int.Parse(humidity),
  156. Condition = DailyWeatherInfo.GetCondition(weatherCode)
  157. };
  158. }
  159. }
  160. /// <summary>
  161. /// Class DailyWeatherInfo
  162. /// </summary>
  163. public class DailyWeatherInfo
  164. {
  165. /// <summary>
  166. /// Gets or sets the date.
  167. /// </summary>
  168. /// <value>The date.</value>
  169. public string date { get; set; }
  170. /// <summary>
  171. /// Gets or sets the precip MM.
  172. /// </summary>
  173. /// <value>The precip MM.</value>
  174. public string precipMM { get; set; }
  175. /// <summary>
  176. /// Gets or sets the temp max C.
  177. /// </summary>
  178. /// <value>The temp max C.</value>
  179. public string tempMaxC { get; set; }
  180. /// <summary>
  181. /// Gets or sets the temp max F.
  182. /// </summary>
  183. /// <value>The temp max F.</value>
  184. public string tempMaxF { get; set; }
  185. /// <summary>
  186. /// Gets or sets the temp min C.
  187. /// </summary>
  188. /// <value>The temp min C.</value>
  189. public string tempMinC { get; set; }
  190. /// <summary>
  191. /// Gets or sets the temp min F.
  192. /// </summary>
  193. /// <value>The temp min F.</value>
  194. public string tempMinF { get; set; }
  195. /// <summary>
  196. /// Gets or sets the weather code.
  197. /// </summary>
  198. /// <value>The weather code.</value>
  199. public string weatherCode { get; set; }
  200. /// <summary>
  201. /// Gets or sets the winddir16 point.
  202. /// </summary>
  203. /// <value>The winddir16 point.</value>
  204. public string winddir16Point { get; set; }
  205. /// <summary>
  206. /// Gets or sets the winddir degree.
  207. /// </summary>
  208. /// <value>The winddir degree.</value>
  209. public string winddirDegree { get; set; }
  210. /// <summary>
  211. /// Gets or sets the winddirection.
  212. /// </summary>
  213. /// <value>The winddirection.</value>
  214. public string winddirection { get; set; }
  215. /// <summary>
  216. /// Gets or sets the windspeed KMPH.
  217. /// </summary>
  218. /// <value>The windspeed KMPH.</value>
  219. public string windspeedKmph { get; set; }
  220. /// <summary>
  221. /// Gets or sets the windspeed miles.
  222. /// </summary>
  223. /// <value>The windspeed miles.</value>
  224. public string windspeedMiles { get; set; }
  225. /// <summary>
  226. /// To the weather forecast.
  227. /// </summary>
  228. /// <returns>WeatherForecast.</returns>
  229. public WeatherForecast ToWeatherForecast()
  230. {
  231. return new WeatherForecast
  232. {
  233. Date = DateTime.Parse(date),
  234. HighTemperatureCelsius = int.Parse(tempMaxC),
  235. HighTemperatureFahrenheit = int.Parse(tempMaxF),
  236. LowTemperatureCelsius = int.Parse(tempMinC),
  237. LowTemperatureFahrenheit = int.Parse(tempMinF),
  238. Condition = GetCondition(weatherCode)
  239. };
  240. }
  241. /// <summary>
  242. /// Gets the condition.
  243. /// </summary>
  244. /// <param name="weatherCode">The weather code.</param>
  245. /// <returns>WeatherConditions.</returns>
  246. public static WeatherConditions GetCondition(string weatherCode)
  247. {
  248. switch (weatherCode)
  249. {
  250. case "362":
  251. case "365":
  252. case "320":
  253. case "317":
  254. case "182":
  255. return WeatherConditions.Sleet;
  256. case "338":
  257. case "335":
  258. case "332":
  259. case "329":
  260. case "326":
  261. case "323":
  262. case "377":
  263. case "374":
  264. case "371":
  265. case "368":
  266. case "395":
  267. case "392":
  268. case "350":
  269. case "227":
  270. case "179":
  271. return WeatherConditions.Snow;
  272. case "314":
  273. case "311":
  274. case "308":
  275. case "305":
  276. case "302":
  277. case "299":
  278. case "296":
  279. case "293":
  280. case "284":
  281. case "281":
  282. case "266":
  283. case "263":
  284. case "359":
  285. case "356":
  286. case "353":
  287. case "185":
  288. case "176":
  289. return WeatherConditions.Rain;
  290. case "260":
  291. case "248":
  292. return WeatherConditions.Fog;
  293. case "389":
  294. case "386":
  295. case "200":
  296. return WeatherConditions.Thunderstorm;
  297. case "230":
  298. return WeatherConditions.Blizzard;
  299. case "143":
  300. return WeatherConditions.Mist;
  301. case "122":
  302. return WeatherConditions.Overcast;
  303. case "119":
  304. return WeatherConditions.Cloudy;
  305. case "115":
  306. return WeatherConditions.PartlyCloudy;
  307. default:
  308. return WeatherConditions.Sunny;
  309. }
  310. }
  311. }
  312. }