Utilitário de clima do console C # usando .Net

O que você precisa obter e aprender para começar a obter uma previsão do tempo para 5 dias? 





Primeiro, escolha um provedor de dados meteorológicos. Em segundo lugar, para analisar de que forma os dados são fornecidos e como podemos coletá-los e exibi-los usando a linguagem de programação C #. 





Escolhi o serviço Accuweather como meu provedor de dados meteorológicos. A conta gratuita atualmente permite 50 solicitações por dia. Isso é o suficiente para poder ver os dados meteorológicos várias vezes ao dia (você pode até compartilhá-los com um amigo!). 





Para se inscrever, acesse o link: https://developer.accuweather.com . Após o registro, você precisa clicar no botão "Adicionar um novo aplicativo" e preencher um pequeno formulário. Como resultado, você receberá sua ApiKey pessoal com a qual poderá receber dados atualizados posteriormente. 





Então a diversão começa. Analisaremos como e de que forma as informações chegam e o que é necessário para receber dados meteorológicos para uma determinada cidade. 





Na seção "Referência da API", a primeira lista é definida para a seção " API de locais " com ela e vamos começar. Olhando para o futuro, direi imediatamente que você não pode simplesmente pegar e enviar o nome da cidade em uma solicitação GET. Para fazer isso, primeiro precisamos obter a Chave de Localização de uma cidade específica. Este valor é apresentado na forma de números e é único para cada cidade. 





Portanto, na seção API de locais, estamos interessados ​​no método City Search . Lemos uma breve descrição dele: Retorna informações para uma série de cidades que correspondem ao texto da pesquisa. Observe imediatamente que uma matriz com os nomes das cidades é retornada para nós. 





Na página da solicitação, insira ApiKey, o nome da cidade de interesse e coloque RU, se quisermos receber dados localizados. 





Após clicar no botão "Enviar esta solicitação" abaixo na página, você receberá o resultado da execução. No meu caso, é assim:





[
  {
    "Version": 1,
    "Key": "292332",
    "Type": "City",
    "Rank": 21,
    "LocalizedName": "Chelyabinsk",
    "EnglishName": "Chelyabinsk",
    "PrimaryPostalCode": "",
    "Region": {
      "ID": "ASI",
      "LocalizedName": "Asia",
      "EnglishName": "Asia"
    },
    "Country": {
      "ID": "RU",
      "LocalizedName": "Russia",
      "EnglishName": "Russia"
    },
    "AdministrativeArea": {
      "ID": "CHE",
      "LocalizedName": "Chelyabinsk",
      "EnglishName": "Chelyabinsk",
      "Level": 1,
      "LocalizedType": "Oblast",
      "EnglishType": "Oblast",
      "CountryID": "RU"
    },
    "TimeZone": {
      "Code": "YEKT",
      "Name": "Asia/Yekaterinburg",
      "GmtOffset": 5,
      "IsDaylightSaving": false,
      "NextOffsetChange": null
    },
    "GeoPosition": {
      "Latitude": 55.16,
      "Longitude": 61.403,
      "Elevation": {
        "Metric": {
          "Value": 233,
          "Unit": "m",
          "UnitType": 5
        },
        "Imperial": {
          "Value": 764,
          "Unit": "ft",
          "UnitType": 0
        }
      }
    },
    "IsAlias": false,
    "SupplementalAdminAreas": [
      {
        "Level": 2,
        "LocalizedName": "Chelyabinsk",
        "EnglishName": "Chelyabinsk"
      }
    ],
    "DataSets": [
      "AirQualityCurrentConditions",
      "AirQualityForecasts",
      "Alerts",
      "ForecastConfidence"
    ]
  }
]
      
      



Como você pode ver, retornamos um array de uma cidade. Qual será o resultado se houver duas ou mais cidades com o mesmo nome:





[
  {
    "Version": 1,
    "Key": "294021",
    "Type": "City",
    "Rank": 10,
    "LocalizedName": "",
    "EnglishName": "Moscow",
    "PrimaryPostalCode": "",
    "Region": {
      "ID": "ASI",
      "LocalizedName": "",
      "EnglishName": "Asia"
    },
    "Country": {
      "ID": "RU",
      "LocalizedName": "",
      "EnglishName": "Russia"
    },
    "AdministrativeArea": {
      "ID": "MOW",
      "LocalizedName": "",
      "EnglishName": "Moscow",
      "Level": 1,
      "LocalizedType": "  ",
      "EnglishType": "Federal City",
      "CountryID": "RU"
    },
    "TimeZone": {
      "Code": "MSK",
      "Name": "Europe/Moscow",
      "GmtOffset": 3,
      "IsDaylightSaving": false,
      "NextOffsetChange": null
    },
    "GeoPosition": {
      "Latitude": 55.752,
      "Longitude": 37.619,
      "Elevation": {
        "Metric": {
          "Value": 155,
          "Unit": "m",
          "UnitType": 5
        },
        "Imperial": {
          "Value": 508,
          "Unit": "ft",
          "UnitType": 0
        }
      }
    },
    "IsAlias": false,
    "SupplementalAdminAreas": [
      {
        "Level": 2,
        "LocalizedName": "Tsentralny",
        "EnglishName": "Tsentralny"
      }
    ],
    "DataSets": [
      "AirQualityCurrentConditions",
      "AirQualityForecasts",
      "Alerts",
      "ForecastConfidence"
    ]
  },
  {
    "Version": 1,
    "Key": "1397263",
    "Type": "City",
    "Rank": 85,
    "LocalizedName": "",
    "EnglishName": "Moskwa",
    "PrimaryPostalCode": "",
    "Region": {
      "ID": "EUR",
      "LocalizedName": "",
      "EnglishName": "Europe"
    },
    "Country": {
      "ID": "PL",
      "LocalizedName": "",
      "EnglishName": "Poland"
    },
    "AdministrativeArea": {
      "ID": "10",
      "LocalizedName": " ",
      "EnglishName": "Łódź",
      "Level": 1,
      "LocalizedType": "",
      "EnglishType": "Voivodship",
      "CountryID": "PL"
    },
    "TimeZone": {
      "Code": "CET",
      "Name": "Europe/Warsaw",
      "GmtOffset": 1,
      "IsDaylightSaving": false,
      "NextOffsetChange": "2021-03-28T01:00:00Z"
    },
    "GeoPosition": {
      "Latitude": 51.816,
      "Longitude": 19.657,
      "Elevation": {
        "Metric": {
          "Value": 238,
          "Unit": "m",
          "UnitType": 5
        },
        "Imperial": {
          "Value": 780,
          "Unit": "ft",
          "UnitType": 0
        }
      }
    },
    "IsAlias": false,
    "SupplementalAdminAreas": [
      {
        "Level": 2,
        "LocalizedName": "- ",
        "EnglishName": "Łódź East"
      },
      {
        "Level": 3,
        "LocalizedName": "",
        "EnglishName": "Nowosolna"
      }
    ],
    "DataSets": [
      "AirQualityCurrentConditions",
      "AirQualityForecasts",
      "Alerts",
      "ForecastConfidence",
      "FutureRadar",
      "MinuteCast",
      "Radar"
    ]
  },
  {
    "Version": 1,
    "Key": "580845",
    "Type": "City",
    "Rank": 85,
    "LocalizedName": "",
    "EnglishName": "Moskva",
    "PrimaryPostalCode": "",
    "Region": {
      "ID": "ASI",
      "LocalizedName": "",
      "EnglishName": "Asia"
    },
    "Country": {
      "ID": "RU",
      "LocalizedName": "",
      "EnglishName": "Russia"
    },
    "AdministrativeArea": {
      "ID": "KIR",
      "LocalizedName": "",
      "EnglishName": "Kirov",
      "Level": 1,
      "LocalizedType": "",
      "EnglishType": "Republic",
      "CountryID": "RU"
    },
    "TimeZone": {
      "Code": "MSK",
      "Name": "Europe/Moscow",
      "GmtOffset": 3,
      "IsDaylightSaving": false,
      "NextOffsetChange": null
    },
    "GeoPosition": {
      "Latitude": 57.968,
      "Longitude": 49.104,
      "Elevation": {
        "Metric": {
          "Value": 207,
          "Unit": "m",
          "UnitType": 5
        },
        "Imperial": {
          "Value": 678,
          "Unit": "ft",
          "UnitType": 0
        }
      }
    },
    "IsAlias": false,
    "SupplementalAdminAreas": [
      {
        "Level": 2,
        "LocalizedName": "Verkhoshizhemsky",
        "EnglishName": "Verkhoshizhemsky"
      }
    ],
    "DataSets": [
      "AirQualityCurrentConditions",
      "AirQualityForecasts",
      "Alerts",
      "ForecastConfidence"
    ]
  },
  {
    "Version": 1,
    "Key": "2488304",
    "Type": "City",
    "Rank": 85,
    "LocalizedName": "",
    "EnglishName": "Moskva",
    "PrimaryPostalCode": "",
    "Region": {
      "ID": "ASI",
      "LocalizedName": "",
      "EnglishName": "Asia"
    },
    "Country": {
      "ID": "RU",
      "LocalizedName": "",
      "EnglishName": "Russia"
    },
    "AdministrativeArea": {
      "ID": "PSK",
      "LocalizedName": "",
      "EnglishName": "Pskov",
      "Level": 1,
      "LocalizedType": "",
      "EnglishType": "Oblast",
      "CountryID": "RU"
    },
    "TimeZone": {
      "Code": "MSK",
      "Name": "Europe/Moscow",
      "GmtOffset": 3,
      "IsDaylightSaving": false,
      "NextOffsetChange": null
    },
    "GeoPosition": {
      "Latitude": 57.449,
      "Longitude": 29.185,
      "Elevation": {
        "Metric": {
          "Value": 161,
          "Unit": "m",
          "UnitType": 5
        },
        "Imperial": {
          "Value": 528,
          "Unit": "ft",
          "UnitType": 0
        }
      }
    },
    "IsAlias": false,
    "SupplementalAdminAreas": [
      {
        "Level": 2,
        "LocalizedName": "Porkhovsky",
        "EnglishName": "Porkhovsky"
      }
    ],
    "DataSets": [
      "AirQualityCurrentConditions",
      "AirQualityForecasts",
      "Alerts",
      "Radar"
    ]
  },
  {
    "Version": 1,
    "Key": "580847",
    "Type": "City",
    "Rank": 85,
    "LocalizedName": "",
    "EnglishName": "Moskva",
    "PrimaryPostalCode": "",
    "Region": {
      "ID": "ASI",
      "LocalizedName": "",
      "EnglishName": "Asia"
    },
    "Country": {
      "ID": "RU",
      "LocalizedName": "",
      "EnglishName": "Russia"
    },
    "AdministrativeArea": {
      "ID": "TVE",
      "LocalizedName": "",
      "EnglishName": "Tver'",
      "Level": 1,
      "LocalizedType": "",
      "EnglishType": "Oblast",
      "CountryID": "RU"
    },
    "TimeZone": {
      "Code": "MSK",
      "Name": "Europe/Moscow",
      "GmtOffset": 3,
      "IsDaylightSaving": false,
      "NextOffsetChange": null
    },
    "GeoPosition": {
      "Latitude": 56.918,
      "Longitude": 32.163,
      "Elevation": {
        "Metric": {
          "Value": 251,
          "Unit": "m",
          "UnitType": 5
        },
        "Imperial": {
          "Value": 823,
          "Unit": "ft",
          "UnitType": 0
        }
      }
    },
    "IsAlias": false,
    "SupplementalAdminAreas": [
      {
        "Level": 2,
        "LocalizedName": "Penovsky",
        "EnglishName": "Penovsky"
      }
    ],
    "DataSets": [
      "AirQualityCurrentConditions",
      "AirQualityForecasts",
      "Alerts"
    ]
  }
]
      
      



, . , Key, . .





, , . , C#. , C# VSCodium. OpenSuSe Leap 15.2.





, ApiKey, , ApiKey , ApiKey .





, UserApi:





namespace habraweatherappconsole
{
    public class UserApi
    {
        public string UserApiProperty { get;set; }
    }
}
      
      



, , :





        /// <summary>
        ///      APIKey  
        /// </summary>
        public static void ReadUserApiToLocalStorage()
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(ObservableCollection<UserApi>));

            try
            {
                using (StreamReader sr = new StreamReader("UserApi.xml"))
                {
                    userApiList = xmlSerializer.Deserialize(sr) as ObservableCollection<UserApi>;
                }
            }

            catch(Exception ex)
            {
                /*      .  ,     
                /     .       - -    
                /          ?
                */
            }
        }
      
      



, XML , , , XML.





. , , . , Json . , .





, :





    "Version": 1,
    "Key": "292332",
    "Type": "City",
    "Rank": 21,
    "LocalizedName": "Chelyabinsk",
    "EnglishName": "Chelyabinsk",
    "PrimaryPostalCode": "",

      
      



API , , , ( , ) , . , , - .





, :





    public class RootBasicCityInfo    {
        public int Version { get; set; } 
        public string Key { get; set; } 
        public string Type { get; set; } 
        public int Rank { get; set; } 
        public string LocalizedName { get; set; } 
        public string EnglishName { get; set; } 
        public string PrimaryPostalCode { get; set; } 

      
      



, json :





      "Region": {
        "ID": "ASI",
        "LocalizedName": "",
        "EnglishName": "Asia"
      },
      "Country": {
        "ID": "RU",
        "LocalizedName": "",
        "EnglishName": "Russia"
      },
      "AdministrativeArea": {
        "ID": "MOW",
        "LocalizedName": "",
        "EnglishName": "Moscow",
        "Level": 1,
        "LocalizedType": "  ",
        "EnglishType": "Federal City",
        "CountryID": "RU"
      },

      
      



, Region, Country, AdministrativeArea :





public class Region    {
        public string ID { get; set; } 
        public string LocalizedName { get; set; } 
        public string EnglishName { get; set; } 
    }

    public class Country    {
        public string ID { get; set; } 
        public string LocalizedName { get; set; } 
        public string EnglishName { get; set; } 
    }

    public class AdministrativeArea    {
        public string ID { get; set; } 
        public string LocalizedName { get; set; } 
        public string EnglishName { get; set; } 
        public int Level { get; set; } 
        public string LocalizedType { get; set; } 
        public string EnglishType { get; set; } 
        public string CountryID { get; set; } 
    }

      
      



:





    public class RootBasicCityInfo    {
        public int Version { get; set; } 
        public string Key { get; set; } 
        public string Type { get; set; } 
        public int Rank { get; set; } 
        public string LocalizedName { get; set; } 
        public string EnglishName { get; set; } 
        public string PrimaryPostalCode { get; set; } 
        public Region Region { get; set; } 
        public Country Country { get; set; } 
        public AdministrativeArea AdministrativeArea { get; set; } 
        public TimeZone TimeZone { get; set; } 
        public GeoPosition GeoPosition { get; set; } 
        public bool IsAlias { get; set; } 
        public List<SupplementalAdminArea> SupplementalAdminAreas { get; set; } 
        public List<string> DataSets { get; set; } 
    }

      
      



, , :





using System;
using System.Collections.ObjectModel;
using System.Net;
using System.Text.Json;

using static System.Console;

namespace habraweatherappconsole
{
    /// <summary>
    ///     
    ///       .
    /// </summary>
    public static class SearchCity
    {
        /// <summary>
        ///      .
        ///       
        ///       MainMenu.
        /// </summary>
        /// <param name="formalCityName"></param>
        public static void GettingListOfCitiesOnRequest(string formalCityName)
        {
            //  ApiKey  
            string apiKey = UserApiManager.userApiList[0].UserApiProperty;
            try
            {
                string jsonOnWeb = $"http://dataservice.accuweather.com/locations/v1/cities/search?apikey={apiKey}&q={formalCityName}";

                WebClient webClient = new WebClient();
                string prepareString = webClient.DownloadString(jsonOnWeb);

                ObservableCollection<RootBasicCityInfo> rbci = JsonSerializer.Deserialize<ObservableCollection<RootBasicCityInfo>>(prepareString);

                DataRepo.Printeceivedities(rbci);
            }
            catch (Exception ex)
            {
                WriteLine("   ."
                + " : \n" + 
                "*    \n"
                + "*    \n"
                + " : \n"
                + ex.Message);
            }

        }
    }
}
      
      



, :





        /// <summary>
        ///       
        /// (     ,  1).
        /// </summary>
        /// <param name="formalListOfCityes"></param>
        public static void Printeceivedities (ObservableCollection<RootBasicCityInfo> formalListOfCityes)
        {
            string pattern = "=====\n" + "  : {0}\n" + "  : {1}\n"
            + " :  {2} \n" + ": {3}\n" + " : {4}\n"
            + ": {5}\n" + "====\n";
            int numberInList = 0;

            foreach (var item in formalListOfCityes)
            {
                WriteLine(pattern, numberInList.ToString(),
                item.EnglishName, item.LocalizedName, item.Country.LocalizedName,
                item.AdministrativeArea.LocalizedName, item.AdministrativeArea.LocalizedType);
                numberInList++;
            }

            Write ("     : ");
            int num = Convert.ToInt32(Console.ReadLine());

            try
            {
                listOfCityForMonitorWeather.Add(formalListOfCityes[num]);
            }

            catch (Exception ex)
            {
                WriteLine(",   .\n");
                WriteLine(ex.Message);
            }
            WriteListOfCityMonitoring();
        }

      
      



, ( APIKey)





         /// <summary>
        ///       
        ///   .
        /// </summary>
        private static void WriteListOfCityMonitoring()
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(ObservableCollection<RootBasicCityInfo>));

            using (StreamWriter sw = new StreamWriter("RootBasicCityInfo.xml"))
            {
                xmlSerializer.Serialize(sw, listOfCityForMonitorWeather);
            }
        }

      
      



. , - 5 .





Json , , , .





Accuweather 1 , 5, 10 15 . json . Get .





, json :





  "Headline": {
    "EffectiveDate": "2021-02-23T07:00:00+03:00",
    "EffectiveEpochDate": 1614052800,
    "Severity": 3,
    "Text": "  : ",
    "Category": "cold",
    "EndDate": "2021-02-24T19:00:00+03:00",
    "EndEpochDate": 1614182400,
    "MobileLink": "http://m.accuweather.com/ru/ru/moscow/294021/extended-weather-forecast/294021?unit=c",
    "Link": "http://www.accuweather.com/ru/ru/moscow/294021/daily-weather-forecast/294021?unit=c"
  },
  "DailyForecasts": [
    {
      "Date": "2021-02-23T07:00:00+03:00",
      "EpochDate": 1614052800,
      "Temperature": {
        "Minimum": {
          "Value": -24.4,
          "Unit": "C",
          "UnitType": 17
        },
        "Maximum": {
          "Value": -20.6,
          "Unit": "C",
          "UnitType": 17
        }
      },
      "Day": {
        "Icon": 31,
        "IconPhrase": "",
        "HasPrecipitation": false
      },
      "Night": {
        "Icon": 31,
        "IconPhrase": "",
        "HasPrecipitation": false
      },
      "Sources": [
        "AccuWeather"
      ],
      "MobileLink": "http://m.accuweather.com/ru/ru/moscow/294021/daily-weather-forecast/294021?day=1&unit=c",
      "Link": "http://www.accuweather.com/ru/ru/moscow/294021/daily-weather-forecast/294021?day=1&unit=c"
    },

      
      



, :





    public class DailyForecast    {
        public DateTime Date { get; set; } 
        public int EpochDate { get; set; } 
        public Temperature Temperature { get; set; } 
        public Day Day { get; set; } 
        public Night Night { get; set; } 
        public List<string> Sources { get; set; } 
        public string MobileLink { get; set; } 
        public string Link { get; set; } 
    }
    

     public class RootWeather    {
        public Headline Headline { get; set; } 
        public List<DailyForecast> DailyForecasts { get; set; } 
    }

      
      



, ( ) . , , , :





            string pattern = "=====\n" + "  : {0}\n" + "  : {1}\n"
            + " :  {2} \n" + ": {3}\n" + " : {4}\n"
            + ": {5}\n" + "====\n";
            int numberInList = 0;

            foreach (var item in DataRepo.listOfCityForMonitorWeather)
            {
                WriteLine(pattern, numberInList.ToString(),
                item.EnglishName, item.LocalizedName, item.Country.LocalizedName,
                item.AdministrativeArea.LocalizedName, item.AdministrativeArea.LocalizedType);
                numberInList++;
            }
            
            bool ifNotExists = false;
            string cityKey = null;
            int num = 0;
            do
            {
                ifNotExists = false;
                Write("    : ");
                num = Convert.ToInt32(Console.ReadLine());
                
                if (num < 0 || num > DataRepo.listOfCityForMonitorWeather.Count - 1)
                {
                    WriteLine("  .   .");
                    ifNotExists = true;
                }
            } while(ifNotExists);
            
            cityKey = DataRepo.listOfCityForMonitorWeather[num].Key;

      
      



:





 //  ApiKey  
            string apiKey = UserApiManager.userApiList[0].UserApiProperty;
            
            string jsonUrl = $"http://dataservice.accuweather.com/forecasts/v1/daily/5day/{cityKey}?apikey={apiKey}&language=ru&metric=true";

            jsonUrl = webClient.DownloadString(jsonUrl);

            RootWeather weatherData = JsonSerializer.Deserialize<RootWeather>(jsonUrl);

            string patternWeather = "=====\n" + ": {0}\n" + " : {1}\n"
            +" : {2}\n" + "  : {3}\n" + "  : {4}\n" + "====\n";

            foreach (var item in weatherData.DailyForecasts)
            {
                WriteLine(patternWeather, item.Date, item.Temperature.Minimum.Value,
                item.Temperature.Maximum.Value, item.Day.IconPhrase, item.Night.IconPhrase);
            }
      
      



5 .





Em conclusão: neste artigo mostrei os principais pontos que foram necessários para que os dados meteorológicos fossem apresentados. O código-fonte completo do utilitário pode ser encontrado no GitLab e GitHub. Além disso, ficarei feliz com qualquer crítica ao caso e conselhos de programadores seniores.





Obrigado pelo seu tempo, boa sorte!








All Articles