Lazarus Pascal İle Yahoo Hava Durumu Tahmini Nasıl Gösterilir?

Lazarus Pascal bilindiği platform bağımsız ve ücretsiz dağıtılan Pascal IDE olarak bilinir. Lazarus ile Windows, Mac ve Linux uygulamaları yapmak kolaydır.

Şimdi örnek olarak Lazarus ile Yahoo Hava Tahmin API leri kullanarak Lazarus ile uygulama yazıp nasıl gösteririz bir bakalım.

Yahoo SQL Benzeri Hava Tahmin Sorgulaması

Yahoo Hava Tahmin API sitesine girdiğinizde bildiğiniz SQL sorgu diline çok benzeyen bir YQL sorgulama dizilimi göreceksiniz.

Örnek olarak İstanbul için hava tahmini sorgulatmak için aşağıdaki göndermemiz gerekiyor.

SELECT * FROM weather.forecast WHERE woeid IN (SELECT woeid FROM geo.places(1) WHERE text="istanbul")

Burada İstanbul için hava tahmini almak isterken, Yahoo‘nun bir alt sorgu yaparak woe diye bilinen id’nin ne olduğunu bulmasını sağlıyoruz.

SELECT woeid FROM geo.places(1) WHERE text="istanbul"

Hava tahmini dönen değer: JSON veya XML

Yahoo tarafından verdiğimiz parametrelere göre sonucu JSON veya XML olarak seçebiliyoruz. Burada biz JSON kullanacağız.

Sorguyu gönderdiğimizde sorguyu gönderen URL aşağıdaki gibi olmaktadır.

https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22istanbul%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys

Şimdi Lazarus Pascal ile kodlarımızı yazmaya başlayalım. Öncelikle hava tahmin Unit olarak yazalım.

JSON verileri otomatik olarak ayrılacak ve bir kayıtta (TYahooForecast) saklanacaktır.Yahoo hava tahminini 10 günlük verdği için tek bir gün için ayrı TDayForecast ile günlük bakacağız.

TDayForcast = record
    code:string;
    date:string;
    day:string;
    high:string;
    low:string;
    text:string;
  end;

  TYahooForecast = record
    success:boolean;
    distance:string;
    pressure:string;
    speed:string;
    temperature:string;
    location_city:string;
    location_country:string;
    location_region:string;
    wind_chill:string;
    wind_direction:string;
    wind_speed:string;
    atmosphere_humidity:string;
    atmosphere_pressure:string;
    atmosphere_rising:string;
    atmosphere_visibility:string;
    astronomy_sunrise:string;
    astronomy_sunset:string;
    location_latitude:string;
    location_longitude:string;
    last_updated:string;
    current_code:string;
    current_date:string;
    current_temp:string;
    current_text:string;
    forecast: array [0..9] of TDayForcast;
  end;

Hva tahmini bilgisini almak için basitçe aşağıdakileri yazabiliriz.

// varsayılan olarak (Sisteminiz hangisi ayarlı ise Celsius/Fahrenheit)
tmpData := GetYahooForecast('istanbul'); 

// Fahrenheit olarak istenirse
tmpData := GetYahooForecast('istanbul','f'); 

// Celsius olarak istersek
tmpData := GetYahooForecast('istanbul','c');

Herşeyin düzgün çalışıp veri geldiğini anlamak için aşağıdakini deneyelim:

if tmpData.success then
    begin
      with tmpData do
        begin
          memo1.lines.add('Uzaklık: '+distance);
          memo1.lines.add('Basınç: '+pressure);
          ...
        end;
    end
  else
    // VERİ GELMEMESİ DURUMUNDA YAPILACAKLAR

Görüldüğü üzere verilere ulaşmak çok kolay. Ancak unutmamalı ki gelen veriler 10 günlüktür. Yani bu durumda aşağıdaki gibi basit bir döngü ile gelen bilgileri parse edip 10 gün ayrı ayrı gösterebiliriz.

for Counter:=0 to 9 do
  begin
    memo1.lines.add('Kod: '+tmpdata.forecast[Counter].code);
    memo1.lines.add('Tarih: '+tmpdata.forecast[Counter].date);
    memo1.lines.add('Gün: ' +tmpdata.forecast[Counter].day);
    memo1.lines.add('Yüksek: '+tmpdata.forecast[Counter].high);
    memo1.lines.add('Düşük: ' +tmpdata.forecast[Counter].low);
    memo1.lines.add('Bilgi: '+tmpdata.forecast[Counter].text);
  end;

Burada TCP/IP üzerinden veri trafiği için ücretsiz olarak dağıtılan Synapse paketini kullanacağız. http://synapse.ararat.cz/lib/exe/fetch.php/file:synapse40.zip adresinden indirip zip dosyayı projenizin “/source/lib” kılasörü içine açınız.

Tüm kod aşağıdaki gibi olacaktır.

unit YahooWeather;

{  Unit to retrieve Yahoo Weather Forecast

   (C)2015 Hans Luijten, //www.tweaking4all.com
   Version 1.0

   Uses:  Synapse (http://synapse.ararat.cz/,
          fpjson  (Comes with Lazarus)
          openssl (part of synapse, weather is retrieved with https://)

   Common use:
          GetYahooForecast(location);

          Retrieves current weather and weather forecast, and returns this in a record for easy access.
}

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, httpsend, ssl_openssl, fpjson, jsonparser;

type
  TDayForcast = record
    code:string;
    date:string;
    day:string;
    high:string;
    low:string;
    text:string;
  end;

  TYahooForecast = record
    success:boolean;
    distance:string;
    pressure:string;
    speed:string;
    temperature:string;
    location_city:string;
    location_country:string;
    location_region:string;
    wind_chill:string;
    wind_direction:string;
    wind_speed:string;
    atmosphere_humidity:string;
    atmosphere_pressure:string;
    atmosphere_rising:string;
    atmosphere_visibility:string;
    astronomy_sunrise:string;
    astronomy_sunset:string;
    location_latitude:string;
    location_longitude:string;
    last_updated:string;
    current_code:string;
    current_date:string;
    current_temp:string;
    current_text:string;
    forecast: array [0..9] of TDayForcast;
  end;

function GetYahooWeatherData(Location:string; AsJSON:boolean =true; TemperatureUnits:string = 'c'):string;
function GetYahooForecast(Location:string; TemperatureUnits:string = 'c'):TYahooForecast;
function YahooURLEncode(s: string): string;

implementation

{
  URLEncode

  Encodes string to be suitable as an URL.

  Example: myencodeURL:=YahooURLEncode(myURL);
}
function YahooURLEncode(s: string): string;
var
  i: integer;
  source: PAnsiChar;
begin
  result := '';
  source := pansichar(s);
  for i := 1 to length(source) do
    if not (source[i - 1] in ['A'..'Z', 'a'..'z', '0'..'9', '-', '_', '~', '.', ':', '/']) then
      result := result + '%' + inttohex(ord(source[i - 1]), 2)
    else
      result := result + source[i - 1];
end;

{ Retrieve Yahoo Weather with forcast and place it in a record for easy access

  MyYahooForcast := GetYahooForecast('town,country',true,'c')
}
function GetYahooForecast(Location:string; TemperatureUnits:string = 'c'):TYahooForecast;
var JSONData:TJSONData;
    RawData:string;
    tmpData:TYahooForecast;
    Counter:integer;
begin
  RawData := GetYahooWeatherData(Location,true,TemperatureUnits);

  Counter:=0;
  while ((RawData='') or (pos('ERROR',RawData)>0)) and (Counter<3) do
    begin
      RawData := GetYahooWeatherData(Location,true,TemperatureUnits);
      inc(Counter);
    end;

  if ((RawData='') or (pos('ERROR',RawData)>0)) then
    tmpData.success:=false
  else
    begin
      JSONData := GetJSON(RawData);

      with tmpdata do
        begin
          success:=true;

          distance:=JSONData.FindPath('query.results.channel.units.distance').AsString;
          pressure:=JSONData.FindPath('query.results.channel.units.pressure').AsString;
          speed:=JSONData.FindPath('query.results.channel.units.speed').AsString;
          temperature:=JSONData.FindPath('query.results.channel.units.temperature').AsString;

          location_city:=JSONData.FindPath('query.results.channel.location.city').AsString;
          location_country:=JSONData.FindPath('query.results.channel.location.country').AsString;
          location_region:=JSONData.FindPath('query.results.channel.location.region').AsString;

          wind_chill:=JSONData.FindPath('query.results.channel.wind.chill').AsString;
          wind_direction:=JSONData.FindPath('query.results.channel.wind.direction').AsString;
          wind_speed:=JSONData.FindPath('query.results.channel.wind.speed').AsString;

          atmosphere_humidity:=JSONData.FindPath('query.results.channel.atmosphere.humidity').AsString;
          atmosphere_pressure:=JSONData.FindPath('query.results.channel.atmosphere.pressure').AsString;
          atmosphere_rising:=JSONData.FindPath('query.results.channel.atmosphere.rising').AsString;
          atmosphere_visibility:=JSONData.FindPath('query.results.channel.atmosphere.visibility').AsString;

          astronomy_sunrise:=JSONData.FindPath('query.results.channel.astronomy.sunrise').AsString;
          astronomy_sunset:=JSONData.FindPath('query.results.channel.astronomy.sunset').AsString;

          location_latitude:=JSONData.FindPath('query.results.channel.item.lat').AsString;
          location_longitude:=JSONData.FindPath('query.results.channel.item.long').AsString;

          last_updated:=JSONData.FindPath('query.results.channel.item.pubDate').AsString;

          current_code:=JSONData.FindPath('query.results.channel.item.condition.code').AsString;
          current_date:=JSONData.FindPath('query.results.channel.item.condition.date').AsString;
          current_temp:=JSONData.FindPath('query.results.channel.item.condition.temp').AsString;
          current_text:=JSONData.FindPath('query.results.channel.item.condition.text').AsString;

          for Counter:=0 to 9 do
            begin
              with tmpData.forecast[Counter] do
                begin
                  code:=JSONData.FindPath('query.results.channel.item.forecast['+IntToStr(Counter)+'].code').AsString;
                  date:=JSONData.FindPath('query.results.channel.item.forecast['+IntToStr(Counter)+'].date').AsString;
                  day:=JSONData.FindPath('query.results.channel.item.forecast['+IntToStr(Counter)+'].day').AsString;
                  high:=JSONData.FindPath('query.results.channel.item.forecast['+IntToStr(Counter)+'].high').AsString;
                  low:=JSONData.FindPath('query.results.channel.item.forecast['+IntToStr(Counter)+'].low').AsString;
                  text:=JSONData.FindPath('query.results.channel.item.forecast['+IntToStr(Counter)+'].text').AsString;
                end;
            end;
       end;
    end;

  GetYahooForecast := tmpData;
end;

{ Retrieve Yahoo Weather information

  myString := GetYahooWeatherData('town,country',true,'c');

  Location: typically use town,country, for example: 'osceola,wi.usa', 'amsterdam,netherlands', 'breda,nederland'
  AsJSON  : return as a JSON string if TRUE, otherwise in XML format (JSON default)
  TemperatureUnits: 'c' for Celcius, and 'f' for Fahrentheit         (C default)
}
function GetYahooWeatherData(Location:string; AsJSON:boolean =true; TemperatureUnits:string = 'c'):string;
var HTTPSender : THTTPSend;
    tmpData : TStringList;
    resultString, resultFormat: String;
begin
  if Location='' then
    GetYahooWeatherData:='ERROR: Missing Location'
  else
    begin
      if AsJSON then
        resultFormat := 'json'
      else
        resultFormat := 'xml';

      tmpData    := TStringList.Create;
      HTTPSender := THTTPSend.Create;

      try
        HTTPSender.HTTPMethod('GET',
                              'https://query.yahooapis.com/v1/public/yql?'+
                                'q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20('+                           // get forecast
                                  'select%20woeid%20from%20geo.places(1)%20where%20text%3D%22'+YahooURLEncode(Location)+'%22)'+              // find location based on string
                                '%20and%20u%3D%22'+TemperatureUnits+'%22'+                                                   // force units (c or f)
                                '&format='+resultFormat+'&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys');

        if (HTTPSender.ResultCode >= 100) and (HTTPSender.ResultCode<=299) then
          tmpData.LoadFromStream(HTTPSender.Document)
      finally
        HTTPSender.Free;
      end;

      if tmpData.Text='' then
        resultString:='ERROR: Unable to retrieve data'
      else
        resultString:=tmpData.Text;

      tmpData.Free;

      GetYahooWeatherData := resultString;
    end;
end;

end.

Kodları indirmek için buraya tıklayınız.

 


Kaynak: https://www.tweaking4all.com/software-development/lazarus-development/yahoo-weather-forecast/