wtorek, 2 stycznia 2018

C# - JSON aplikacja pogodowa V1.0 z pobieraniem danych z openweathermap.org

W tym poście chciałbym przedstawić aplikację napisaną w języku C#, której zadaniem jest pobranie danych z informacjami o pogodzie w wybranym mieście. Następnie dane są przetwarzane i wyświetlane użytkownikowi.

[Źródło: https://docs.microsoft.com/en-us/dotnet/]

Wstęp:

Do pobrania danych wykorzystuje portal openweathermap.org. Aby podłączyć się do tego serwisu wystarczy założyć konto i odebrać kod APPD, który zostanie przesłany na adres email. Podaje się go  do adresu w trakcie pobierania informacji z serwera. Odświeżanie danych o pogodzie może następować raz na 10 minut (w przypadku wersji płatnej) lub co 2-3 godziny (dla wersji darmowej). Częstsze odpytywanie nie spowoduje żadnego błędu, natomiast jest ono zupełnie niepotrzebne ponieważ pobrane dane będą takie same jak poprzednio.

Po wysłaniu zapytania z własnym wygenerowanym kodem otrzyma się następującą odpowiedź w formacie JSON:

  1. {  
  2.     "coord":{
  3.                 "lon":19.92,
  4.                 "lat":50.08
  5.             },
  6.     "weather":[
  7.             {
  8.                 "id":701,
  9.                 "main":"Mist",
  10.                 "description":"mist",
  11.                 "icon":"50d"
  12.             }],
  13.             "base":"stations",
  14.             "main":{
  15.                     "temp":273.15,
  16.                     "pressure":1009,
  17.                     "humidity":89,
  18.                     "temp_min":273.15,
  19.                     "temp_max":273.15},
  20.                     "visibility":2500,
  21.                     "wind":{
  22.                             "speed":1.5,
  23.                             "deg":170
  24.                             },
  25.                     "clouds":{
  26.                             "all":0
  27.                              },
  28.                     "dt":1514282400,
  29.                     "sys":{
  30.                             "type":1,
  31.                             "id":5352,
  32.                             "message":0.004,
  33.                             "country":"PL",
  34.                             "sunrise":1514270321,
  35.                             "sunset":1514299423
  36.                             },
  37.                     "id":3094802,
  38.                     "name":"Krakow",
  39.                     "cod":200
  40. }

Te dane następnie będziemy obrabiać w programie aby zaprezentować dane użytkownikowi.

Kolejną opcją na pobranie danych są prognozy 5 dniowe z pogodą odświeżaną co 3 godziny. W tym przypadku otrzymujemy dosyć dużo danych do obrobienia bo aż 39. Ich składnia wygląda następująco:


Powyżej uporządkowane dane z odczytu prognozy na 5 dni.

Z prognoz pogody w wersji darmowej w formacie JSON dostępne są jeszcze informacje o alarmach pogodowych oraz odczytu smogu (wersja beta). 

Kod programu:


Do dekodowania wykorzystuję bibliotekę Newtonsoft.Json, którą należy zainstalować przez menadżer pakietów NuGet.

Najpierw sam wygląd aplikacji oraz pobieranie danych z serwera.

Poniżej zdjęcie aplikacji:


Na początku wybierane jest miasto z którego mają zostać pobrane informacje. Wyświetlane są informacje w kontrolce ComboBox z ostatnio wybraną lokalizacją.

Lista miast zdefiniowana jest w klasie DEFINECITIES. Tam dopisywane są kolejne miasta jako stałe ciągi znaków, które przechowują informacje z Id miasta w danym kraju. Wszystkie dostępne miasta można pobrać ze strony. W programie uwzględniłem następujące miasta:

Jak już wspomniałem miasta można bardzo łatwo dodawać. Wystarczy dodać je do klasy z nazwami oraz do klasy z Id.

  1. class DEFINECITIES
  2. {
  3.    //From Poland
  4.    public const string GDANSK_CITY_ID = "id=3099434&";
  5.    public const string KRAKOW_CITY_ID = "id=3094802&";
  6.    public const string RZESZOW_CITY_ID = "id=7530819&";
  7.    public const string WARSZAWA_CITY_ID = "id=6695624&";
  8.    //From US
  9.    public const string NEW_YORK_CITY_ID = "id=5128638&";
  10.    //Definition of names to collection
  11.    public static string[] cityNames = new string[]
  12.    {
  13.         "Gdansk",
  14.         "Krakow",
  15.         "Rzeszow",
  16.         "Warsaw",
  17.         "New York"
  18.     };
  19. }

Ich dodanie do ComboBox wygląda następująco:

  1. private void updateComboBoxCitiesData()
  2. {
  3.     foreach(string cityName in DEFINECITIES.cityNames)
  4.     {
  5.         countriesComboBox.Items.Add(cityName);
  6.     }
  7.     countriesComboBox.Sorted = true;
  8.     countriesComboBox.DropDownStyle = ComboBoxStyle.DropDown;
  9.     countriesComboBox.AutoCompleteSource = AutoCompleteSource.ListItems;
  10.     countriesComboBox.AutoCompleteMode = AutoCompleteMode.Suggest;
  11. }

Dane pobierane są z tablicy po czym za pomocą operacji Add są dodawane do kolekcji kontrolki.

Dane z informacją o czasie są przedstawione jako epoch. Jest to ilość sekund jaka upłynęła od daty pierwszego stycznia 1970. Aby ją szybko sformatować na bardziej czytelny format wykorzystuję następującą funkcję:

  1. public static DateTime UnixTimeStampToDateTime(int epochTime)
  2. {
  3.     DateTime newTime = new DateTime(197011).AddSeconds(epochTime);
  4.     return newTime;
  5. }

Pobranie informacji polega na przesłaniu zapytania do strony. Wykonanie wygląda następująco:

  1. private JsonWeatherReport getJsonData(string url)
  2. {
  3.     using (WebClient client = new WebClient())
  4.     {
  5.         string receiveJson = client.DownloadString(url);
  6.         JsonWeatherReport weather;
  7.         weather = JsonConvert.DeserializeObject<JsonWeatherReport>(receiveJson);
  8.         UpdateDataRichTxtBox(weather);
  9.         return weather;
  10.      }
  11. }

W tym przypadku wykorzystuje klasę WebClient. Zawiera metody wspólne dla przesłania oraz odebrania danych. Pobranie danych odbywa się poprzez DownloadString. Pobiera dane z żądanego adresu jako string.

Dane z ComboBox zapisywane są do ustawień aplikacji. Przez co po każdym otwarciu automatycznie zostanie przypisane ostatnio wyszukiwane miasto.

  1. private void saveDataBetweenOpen()
  2. {
  3.     Properties.Settings.Default.countryRTBData = countriesComboBox.SelectedItem.ToString();
  4.     Properties.Settings.Default.Save();
  5. }

Zdekodowanie informacji pogodowej następuje w klasie JsonWeatherReport, która zawiera referencję do klas zewnętrznych przechowujących odczytane wyniki:

  1.     public class JsonWeatherReport
  2.     {
  3.         [JsonProperty("coord")]
  4.         public Coord Coord { get; set; }
  5.         [JsonProperty("weather")]
  6.         public Weather[] Weather { get; set; }
  7.         [JsonProperty("base")]
  8.         public string Base { get; set; }
  9.         [JsonProperty("main")]
  10.         public Main Main { get; set; }
  11.         [JsonProperty("visibility")]
  12.         public int Visibility { get; set; }
  13.         [JsonProperty("wind")]
  14.         public Wind Wind { get; set; }
  15.         [JsonProperty("clouds")]
  16.         public Clouds Clouds { get; set; }
  17.         [JsonProperty("dt")]
  18.         public int Dt { get; set; }
  19.         [JsonProperty("sys")]
  20.         public Sys Sys { get; set; }
  21.         [JsonProperty("id")]
  22.         public int Id { get; set; }
  23.         [JsonProperty("name")]
  24.         public string Name { get; set; }
  25.         [JsonProperty("cod")]
  26.         public int Cod { get; set; }
  27.     }

Wyświetlenie informacji na ekranie polega na odczytaniu odpowiedniego pola z Json'a, zdekodowaniu go do bardziej czytelnego formatu jeśli zachodzi taka potrzeba, i wyświetleniu.

Pliki do projektu można pobrać z dysku Google pod tym linkiem. Dalej należy wejść w folder Csharp a następnie pobrać CSharp_-_AplikacjaPogodowaV1.0.

W kolejnej wersji tego programu rozwinę bardziej stronie graficzną oraz zwiększę dowolność wyboru miasta.