using System.Globalization; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Weather; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Weather; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.WorldWeatherOnline { /// /// Based on http://www.worldweatheronline.com/free-weather-feed.aspx /// The classes in this file are a reproduction of the json output, which will then be converted to our weather model classes /// public class WeatherProvider : IWeatherProvider { /// /// Gets or sets the logger. /// /// The logger. private ILogger Logger { get; set; } /// /// Gets the json serializer. /// /// The json serializer. protected IJsonSerializer JsonSerializer { get; private set; } /// /// The _HTTP client /// private IHttpClient HttpClient { get; set; } /// /// Initializes a new instance of the class. /// /// The json serializer. /// The HTTP client. /// The logger. /// logger public WeatherProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogger logger) { if (logger == null) { throw new ArgumentNullException("logger"); } if (httpClient == null) { throw new ArgumentNullException("httpClient"); } if (jsonSerializer == null) { throw new ArgumentNullException("jsonSerializer"); } JsonSerializer = jsonSerializer; HttpClient = httpClient; Logger = logger; } /// /// The _weather semaphore /// private readonly SemaphoreSlim _weatherSemaphore = new SemaphoreSlim(10, 10); /// /// Gets the weather info async. /// /// The location. /// The cancellation token. /// Task{WeatherInfo}. /// location public async Task GetWeatherInfoAsync(string location, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(location)) { throw new ArgumentNullException("location"); } if (cancellationToken == null) { throw new ArgumentNullException("cancellationToken"); } const int numDays = 5; const string apiKey = "24902f60f1231941120109"; var url = "http://free.worldweatheronline.com/feed/weather.ashx?q=" + location + "&format=json&num_of_days=" + numDays + "&key=" + apiKey; Logger.Info("Accessing weather from " + url); using (var stream = await HttpClient.Get(url, _weatherSemaphore, cancellationToken).ConfigureAwait(false)) { var data = JsonSerializer.DeserializeFromStream(stream).data; return GetWeatherInfo(data); } } /// /// Converst the json output to our WeatherInfo model class /// /// The data. /// WeatherInfo. private WeatherInfo GetWeatherInfo(WeatherData data) { var info = new WeatherInfo(); if (data.current_condition != null) { var condition = data.current_condition.FirstOrDefault(); if (condition != null) { info.CurrentWeather = condition.ToWeatherStatus(); } } if (data.weather != null) { info.Forecasts = data.weather.Select(w => w.ToWeatherForecast()).ToArray(); } return info; } } /// /// Class WeatherResult /// class WeatherResult { /// /// Gets or sets the data. /// /// The data. public WeatherData data { get; set; } } /// /// Class WeatherData /// public class WeatherData { /// /// Gets or sets the current_condition. /// /// The current_condition. public WeatherCondition[] current_condition { get; set; } /// /// Gets or sets the weather. /// /// The weather. public DailyWeatherInfo[] weather { get; set; } } /// /// Class WeatherCondition /// public class WeatherCondition { /// /// Gets or sets the temp_ C. /// /// The temp_ C. public string temp_C { get; set; } /// /// Gets or sets the temp_ F. /// /// The temp_ F. public string temp_F { get; set; } /// /// Gets or sets the humidity. /// /// The humidity. public string humidity { get; set; } /// /// Gets or sets the weather code. /// /// The weather code. public string weatherCode { get; set; } protected static readonly CultureInfo UsCulture = new CultureInfo("en-US"); /// /// To the weather status. /// /// WeatherStatus. public WeatherStatus ToWeatherStatus() { return new WeatherStatus { TemperatureCelsius = int.Parse(temp_C, UsCulture), TemperatureFahrenheit = int.Parse(temp_F, UsCulture), Humidity = int.Parse(humidity, UsCulture), Condition = DailyWeatherInfo.GetCondition(weatherCode) }; } } /// /// Class DailyWeatherInfo /// public class DailyWeatherInfo { /// /// Gets or sets the date. /// /// The date. public string date { get; set; } /// /// Gets or sets the precip MM. /// /// The precip MM. public string precipMM { get; set; } /// /// Gets or sets the temp max C. /// /// The temp max C. public string tempMaxC { get; set; } /// /// Gets or sets the temp max F. /// /// The temp max F. public string tempMaxF { get; set; } /// /// Gets or sets the temp min C. /// /// The temp min C. public string tempMinC { get; set; } /// /// Gets or sets the temp min F. /// /// The temp min F. public string tempMinF { get; set; } /// /// Gets or sets the weather code. /// /// The weather code. public string weatherCode { get; set; } /// /// Gets or sets the winddir16 point. /// /// The winddir16 point. public string winddir16Point { get; set; } /// /// Gets or sets the winddir degree. /// /// The winddir degree. public string winddirDegree { get; set; } /// /// Gets or sets the winddirection. /// /// The winddirection. public string winddirection { get; set; } /// /// Gets or sets the windspeed KMPH. /// /// The windspeed KMPH. public string windspeedKmph { get; set; } /// /// Gets or sets the windspeed miles. /// /// The windspeed miles. public string windspeedMiles { get; set; } protected static readonly CultureInfo UsCulture = new CultureInfo("en-US"); /// /// To the weather forecast. /// /// WeatherForecast. public WeatherForecast ToWeatherForecast() { return new WeatherForecast { Date = DateTime.Parse(date, UsCulture), HighTemperatureCelsius = int.Parse(tempMaxC, UsCulture), HighTemperatureFahrenheit = int.Parse(tempMaxF, UsCulture), LowTemperatureCelsius = int.Parse(tempMinC, UsCulture), LowTemperatureFahrenheit = int.Parse(tempMinF, UsCulture), Condition = GetCondition(weatherCode) }; } /// /// Gets the condition. /// /// The weather code. /// WeatherConditions. public static WeatherConditions GetCondition(string weatherCode) { switch (weatherCode) { case "362": case "365": case "320": case "317": case "182": return WeatherConditions.Sleet; case "338": case "335": case "332": case "329": case "326": case "323": case "377": case "374": case "371": case "368": case "395": case "392": case "350": case "227": case "179": return WeatherConditions.Snow; case "314": case "311": case "308": case "305": case "302": case "299": case "296": case "293": case "284": case "281": case "266": case "263": case "359": case "356": case "353": case "185": case "176": return WeatherConditions.Rain; case "260": case "248": return WeatherConditions.Fog; case "389": case "386": case "200": return WeatherConditions.Thunderstorm; case "230": return WeatherConditions.Blizzard; case "143": return WeatherConditions.Mist; case "122": return WeatherConditions.Overcast; case "119": return WeatherConditions.Cloudy; case "115": return WeatherConditions.PartlyCloudy; default: return WeatherConditions.Sunny; } } } }