djjd47130

Weather API Wrapper Unit - V4

Dec 31st, 2016
332
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 81.03 KB | None | 0 0
  1. unit JD.Weather;
  2.  
  3. (*
  4.   ------------------------------------------------------------------------------
  5.   XXXX    XXXXXX    XX    XXXX        XX   XX  XXXXXX   XX
  6.   XX  XX  XX      XX  XX  XX  XX      XXX XXX  XX       XX
  7.   XXXX    XXXXX   XXXXXX  XX  XX      XX X XX  XXXXX    XX
  8.   XX  XX  XX      XX  XX  XX  XX      XX   XX  XX
  9.   XX  XX  XXXXXX  XX  XX  XXXX        XX   XX  XXXXXX   XX
  10.   ------------------------------------------------------------------------------
  11.  
  12.   JD Weather
  13.   by Jerry Dodge
  14.  
  15.   VERSION 2 (Replaces JD.Weather, JD.Weather.OpenWeatherMap, JD.Weather.WUnderground)
  16.  
  17.   Main Class:
  18.     TJDWeather: TComponent
  19.       Encapsulates entire API wrapper system to pull weather data from various
  20.       different weather APIs.
  21.  
  22.   Features:
  23.   - Adapts a standard structure to multiple different weather services
  24.   - Dedicated thread to perform periodic checks on a given interval
  25.   - Events triggered upon changes on conditions, forecast, alerts, and maps
  26.  
  27.   How to use:
  28.   - Subscribe to one of the supported services
  29.   - Acquire an API Key which authenticates your account
  30.   - Select the service by assigning TJDWeather.Service
  31.   - Enter your API Key by assigning TJDWeather.Key
  32.   - Specify the frequency of each different weather information type
  33.       NOTE: The numbers are seconds between calls
  34.       IMPORTANT: Depending on which service you choose, your account will be likely
  35.       limited to a certain number of requests in a given day. Therefore, it is
  36.       very important to adjust these frequency properties to correspond with
  37.       your particular account's capabilities. Sometimes, this may mean
  38.       ten to twenty minutes between checks for weather, if your account
  39.       has a low limit, or if you use the app in multiple places.
  40.   - Select your desired location by assigning TJDWeather.LocationType
  41.     - wlAutoIP: Automatically detects your location based on your IP Address
  42.     - wlCityState: Assign City to "LocationDetail1" and State to "LocationDetail2"
  43.     - wlZip: Assign Zip Code to "LocationDetail1"
  44.     - wlCoords: Assign Longitude to "LocationDetail1" and Latitude to "LocationDetail2"
  45.         NOTE: Format of each property must be with numeric digits such as:
  46.         45.9764
  47.         -15.9724
  48.   - Assign event handlers to the desired weather information
  49.       NOTE: Weather information is actually provided when these events are fired.
  50.       You are responsible to acquire a copy of the corresponding weather interface
  51.       from the event handler's parameters and store your own reference.
  52.       These interfaces are by default reference-counted.
  53.  
  54.  
  55.   SUPPORTED WEATHER SERVICES:
  56.   - Weather Underground                         https://www.wunderground.com/weather/api/d/docs?d=index
  57.     - Location by Zip, City/State, IP, Coords
  58.     - Current Conditions
  59.     - Forecast - 8 Half Days
  60.     - Forecast - 4 Days
  61.     - Forecast - 10 Days
  62.     - Forecast - SURELY THEY HAVE TO HAVE HOURLY!!!
  63.     - Alerts
  64.     - Maps - Satellite
  65.     - Maps - Radar
  66.  
  67.   - [Coming Soon] Open Weather Maps             https://openweathermap.org/api
  68.     - Location by Zip, City/State, Coords
  69.     - Current Conditions
  70.     - Forecast - 40 x 3hrs (5 Days)
  71.     - Forecast - SURELY THEY HAVE TO HAVE HOURLY!!!
  72.     - Maps - Satellite
  73.     - Maps - Radar
  74.  
  75.   - [Coming Soon] Accu Weather                  http://apidev.accuweather.com/developers/
  76.     - Location by Zip, City/State, Coords
  77.     - Current Conditions
  78.     - Forecast - 1, 12, 24, 72, 120, 240 Hours
  79.     - Forecast - 1, 5, 10, 15, 25 Days
  80.     - Alerts
  81.     - Maps - Satellite
  82.     - Maps - Radar
  83.  
  84.   - [Coming Soon] Foreca                        http://corporate.foreca.com/en/products-services/data/weather-api
  85.     - Location by Coords
  86.     - Current Conditions
  87.     - Forecast - 56 Hours
  88.     - Forecast - 10 Days
  89.  
  90.   - [Coming Soon] National Weather Service      http://forecast-v3.weather.gov/documentation
  91.     - May remove - looks like just raw current weather station data
  92.  
  93.   - [Coming Soon] NOAA                          https://www.ncdc.noaa.gov/cdo-web/webservices/v2#gettingStarted
  94.     - May remove - looks like just raw current weather station data
  95.  
  96.  
  97.   TODO:
  98.   - Implement "Supported..." functions to reflect what each service supports
  99.   - Implement caching of weather data as to not fetch too often
  100.   - Implement weather maps
  101.     - Radar
  102.     - Satellite
  103.     - Radar AND Satellite Combined
  104.   - Standardize the forecast formats
  105.     - Hourly - X number of hours
  106.     - Daily - X number of days
  107.     - Summary - Half day, plain text
  108.   - Detect coordinates based on IP
  109.   - Finish implementing all services
  110.     - OpenWeatherMap
  111.       - Migrate from original API wrapper V1
  112.     - Weather Underground
  113.       - Detailed Forecast (Hourly/Daily)
  114.       - Maps
  115.     - National Weather Service
  116.     - AccuWeather
  117.     - NOAA
  118.     - Foreca
  119.  
  120. *)
  121.  
  122. interface
  123.  
  124. uses
  125.   System.Classes, System.SysUtils, System.Generics.Collections,
  126.   Vcl.Graphics, Vcl.Imaging.Jpeg, Vcl.Imaging.PngImage, Vcl.Imaging.GifImg,
  127.   SuperObject,
  128.   IdHTTP;
  129.  
  130. type
  131.   TWeatherService = (wsOpenWeatherMap, wsWUnderground, wsNWS,
  132.     wsNOAA, wsAccuWeather, wsForeca);
  133.   TWeatherUnits = (wuKelvin, wuImperial, wuMetric);
  134.   TWeatherAlertType = (waNone, waHurricaneStat, waTornadoWarn, waTornadoWatch, waSevThundWarn,
  135.     waSevThundWatch, waWinterAdv, waFloodWarn, waFloodWatch, waHighWind, waSevStat,
  136.     waHeatAdv, waFogAdv, waSpecialStat, waFireAdv, waVolcanicStat, waHurricaneWarn,
  137.     waRecordSet, waPublicRec, waPublicStat);
  138.   TWeatherAlertPhenomena = (wpWind, wpHeat, wpSmallCraft);
  139.  
  140.   TDayNight = (dnDay, dnNight);
  141.   TCloudCode = (ccClear = 0, ccAlmostClear = 1, ccHalfCloudy = 2, ccBroken = 3,
  142.     ccOvercast = 4, ccThinClouds = 5, ccFog = 6);
  143.   TPrecipCode = (pcNone = 0, pcSlight = 1, pcShowers = 2, pcPrecip = 3, pcThunder = 4);
  144.   TPrecipTypeCode = (ptRain = 0, ptSleet = 1, ptSnow = 2);
  145.  
  146.   TWeatherCode = record
  147.   public
  148.     DayNight: TDayNight;
  149.     Clouds: TCloudCode;
  150.     Precip: TPrecipCode;
  151.     PrecipType: TPrecipTypeCode;
  152.     class operator Implicit(const Value: TWeatherCode): String;
  153.     class operator Implicit(const Value: String): TWeatherCode;
  154.     class operator Implicit(const Value: TWeatherCode): Integer;
  155.     class operator Implicit(const Value: Integer): TWeatherCode;
  156.     function Description: String;
  157.     function DayNightStr: String;
  158.   end;
  159.  
  160. //Interface Definitions
  161.  
  162. {$REGION "Interface Definitions"}
  163.  
  164.   IWeatherLocation = interface
  165.     function GetDisplayName: WideString;
  166.     function GetCity: WideString;
  167.     function GetState: WideString;
  168.     function GetStateAbbr: WideString;
  169.     function GetCountry: WideString;
  170.     function GetCountryAbbr: WideString;
  171.     function GetLongitude: Double;
  172.     function GetLatitude: Double;
  173.     function GetElevation: Double;
  174.     function GetZipCode: WideString;
  175.     property DisplayName: WideString read GetDisplayName;
  176.     property City: WideString read GetCity;
  177.     property State: WideString read GetState;
  178.     property StateAbbr: WideString read GetStateAbbr;
  179.     property Country: WideString read GetCountry;
  180.     property CountryAbbr: WideString read GetCountryAbbr;
  181.     property Longitude: Double read GetLongitude;
  182.     property Latitude: Double read GetLatitude;
  183.     property Elevation: Double read GetElevation;
  184.     property ZipCode: WideString read GetZipCode;
  185.   end;
  186.  
  187.   TWeatherConditionsProp = (cpPressureMB, cpPressureIn, cpWindDir, cpWindSpeed,
  188.     cpHumidity, cpVisibility, cpDewPoint, cpHeatIndex, cpWindGust, cpWindChill,
  189.     cpFeelsLike, cpSolarRad, cpUV, cpTemp, cpTempMin, cpTempMax, cpPrecip,
  190.     cpIcon, cpCaption, cpDescription, cpStation, cpClouds,
  191.     cpRain, cpSnow, cpSunrise, cpSunset);
  192.   TWeatherConditionsProps = set of TWeatherConditionsProp;
  193.  
  194.   IWeatherConditions = interface
  195.     function GetPicture: TPicture;
  196.     function GetLocation: IWeatherLocation;
  197.     function GetDateTime: TDateTime;
  198.     function GetTemp: Single;
  199.     function GetHumidity: Single;
  200.     function GetPressure: Single;
  201.     function GetCondition: WideString;
  202.     function GetDescription: WideString;
  203.     function GetWindDir: Single;
  204.     function GetWindSpeed: Single;
  205.     function GetVisibility: Single;
  206.     function GetDewPoint: Single;
  207.     function SupportedProps: TWeatherConditionsProps;
  208.     property Picture: TPicture read GetPicture;
  209.     property Location: IWeatherLocation read GetLocation;
  210.     property DateTime: TDateTime read GetDateTime;
  211.     property Temp: Single read GetTemp;
  212.     property Humidity: Single read GetHumidity;
  213.     property Pressure: Single read GetPressure;
  214.     property Condition: WideString read GetCondition;
  215.     property Description: WideString read GetDescription;
  216.     property WindSpeed: Single read GetWindSpeed;
  217.     property WindDir: Single read GetWindDir;
  218.     property Visibility: Single read GetVisibility;
  219.     property DewPoint: Single read GetDewPoint;
  220.   end;
  221.  
  222.   TWeatherForecastProp = (fpPressureMB, fpPressureIn, fpWindDir, fpWindSpeed,
  223.     fpHumidity, fpVisibility, fpDewPoint, fpHeatIndex, fpWindGust, fpWindChill,
  224.     fpFeelsLike, fpSolarRad, fpUV, fpTemp, fpTempMin, fpTempMax, fpCaption,
  225.     fpDescription, fpIcon, fpGroundPressure, fpSeaPressure, fpPrecip, fpURL, fpDaylight);
  226.   TWeatherForecastProps = set of TWeatherForecastProp;
  227.  
  228.   IWeatherForecastItem = interface
  229.     function GetPicture: TPicture;
  230.     function GetDateTime: TDateTime;
  231.     function GetTemp: Single;
  232.     function GetTempMax: Single;
  233.     function GetTempMin: Single;
  234.     function GetHumidity: Single;
  235.     function GetPressure: Single;
  236.     function GetCondition: WideString;
  237.     function GetDescription: WideString;
  238.     function GetWindDir: Single;
  239.     function GetWindSpeed: Single;
  240.     function GetVisibility: Single;
  241.     function GetDewPoint: Single;
  242.     function SupportedProps: TWeatherForecastProps;
  243.     property Picture: TPicture read GetPicture;
  244.     property DateTime: TDateTime read GetDateTime;
  245.     property Temp: Single read GetTemp;
  246.     property TempMin: Single read GetTempMin;
  247.     property TempMax: Single read GetTempMax;
  248.     property Humidity: Single read GetHumidity;
  249.     property Pressure: Single read GetPressure;
  250.     property Condition: WideString read GetCondition;
  251.     property Description: WideString read GetDescription;
  252.     property WindSpeed: Single read GetWindSpeed;
  253.     property WindDir: Single read GetWindDir;
  254.     property Visibility: Single read GetVisibility;
  255.     property DewPoint: Single read GetDewPoint;
  256.   end;
  257.  
  258.   IWeatherForecast = interface
  259.     function GetLocation: IWeatherLocation;
  260.     function GetItem(const Index: Integer): IWeatherForecastItem;
  261.     function Count: Integer;
  262.     function MinTemp: Single;
  263.     function MaxTemp: Single;
  264.     property Location: IWeatherLocation read GetLocation;
  265.     property Items[const Index: Integer]: IWeatherForecastItem read GetItem; default;
  266.   end;
  267.  
  268.   IWeatherAlertZone = interface
  269.     function GetState: WideString;
  270.     function GetZone: WideString;
  271.     property State: WideString read GetState;
  272.     property Zone: WideString read GetZone;
  273.   end;
  274.  
  275.   IWeatherAlertZones = interface
  276.     function GetItem(const Index: Integer): IWeatherAlertZone;
  277.     function Count: Integer;
  278.     property Items[const Index: Integer]: IWeatherAlertZone read GetItem; default;
  279.   end;
  280.  
  281.   IWeatherStormVertex = interface
  282.     function GetLongitude: Double;
  283.     function GetLatitude: Double;
  284.     property Longitude: Double read GetLongitude;
  285.     property Latitude: Double read GetLatitude;
  286.   end;
  287.  
  288.   IWeatherStormVerticies = interface
  289.     function GetItem(const Index: Integer): IWeatherStormVertex;
  290.     function Count: Integer;
  291.     property Items[const Index: Integer]: IWeatherStormVertex read GetItem; default;
  292.   end;
  293.  
  294.   IWeatherAlertStorm = interface
  295.     function GetDateTime: TDateTime;
  296.     function GetDirection: Single;
  297.     function GetSpeed: Single;
  298.     function GetLongitude: Double;
  299.     function GetLatitude: Double;
  300.     function GetVerticies: IWeatherStormVerticies;
  301.     property DateTime: TDateTime read GetDateTime;
  302.     property Direction: Single read GetDirection;
  303.     property Speed: Single read GetDirection;
  304.     property Longitude: Double read GetLongitude;
  305.     property Latitude: Double read GetLatitude;
  306.     property Verticies: IWeatherStormVerticies read GetVerticies;
  307.   end;
  308.  
  309.   TWeatherAlertProp = (apZones, apVerticies, apStorm, apType, apDescription,
  310.     apExpires, apMessage, apPhenomena, apSignificance);
  311.   TWeatherAlertProps = set of TWeatherAlertProp;
  312.  
  313.   IWeatherAlert = interface
  314.     function GetAlertType: TWeatherAlertType;
  315.     function GetDescription: WideString;
  316.     function GetDateTime: TDateTime;
  317.     function GetExpires: TDateTime;
  318.     function GetMsg: WideString;
  319.     function GetPhenomena: WideString;
  320.     function GetSignificance: WideString;
  321.     function GetZones: IWeatherAlertZones;
  322.     function GetStorm: IWeatherAlertStorm;
  323.     function SupportedFunctions: TWeatherAlertProps;
  324.     property AlertType: TWeatherAlertType read GetAlertType;
  325.     property Description: WideString read GetDescription;
  326.     property DateTime: TDateTime read GetDateTime;
  327.     property Expires: TDateTime read GetExpires;
  328.     property Msg: WideString read GetMsg;
  329.     property Phenomena: WideString read GetPhenomena;
  330.     property Significance: WideString read GetSignificance;
  331.     property Zones: IWeatherAlertZones read GetZones;
  332.     property Storm: IWeatherAlertStorm read GetStorm;
  333.   end;
  334.  
  335.   IWeatherAlerts = interface
  336.     function GetItem(const Index: Integer): IWeatherAlert;
  337.     function Count: Integer;
  338.     property Items[const Index: Integer]: IWeatherAlert read GetItem; default;
  339.   end;
  340.  
  341.   TWeatherMapType = (mpSatellite, mpRadar, mpSatelliteRadar, mpRadarClouds,
  342.     mpClouds, mpTemp, mpTempChange, mpSnowCover, mpPrecip, mpAlerts, mpHeatIndex,
  343.     mpDewPoint, mpWindChill, mpPressureSea, mpWind);
  344.   TWeatherMapTypes = set of TWeatherMapType;
  345.  
  346.   IWeatherMaps = interface
  347.     function GetMap(const MapType: TWeatherMapType): TPicture;
  348.     function SupportedFunctions: TWeatherMapTypes;
  349.     property Maps[const MapType: TWeatherMapType]: TPicture read GetMap;
  350.   end;
  351.  
  352. {$ENDREGION}
  353.  
  354.  
  355.  
  356.  
  357.  
  358.  
  359.  
  360. //Interface Implementation Objects
  361.  
  362. {$REGION "Interface Implementation Objects"}
  363.  
  364.   { Interface Implementation Objects }
  365.  
  366.   TJDWeatherThread = class;
  367.  
  368.   TWeatherLocation = class(TInterfacedObject, IWeatherLocation)
  369.   private
  370.     FDisplayName: WideString;
  371.     FCity: WideString;
  372.     FState: WideString;
  373.     FStateAbbr: WideString;
  374.     FCountry: WideString;
  375.     FCountryAbbr: WideString;
  376.     FLongitude: Double;
  377.     FLatitude: Double;
  378.     FElevation: Double;
  379.     FZipCode: WideString;
  380.   public
  381.     constructor Create;
  382.     destructor Destroy; override;
  383.   public
  384.     function GetDisplayName: WideString;
  385.     function GetCity: WideString;
  386.     function GetState: WideString;
  387.     function GetStateAbbr: WideString;
  388.     function GetCountry: WideString;
  389.     function GetCountryAbbr: WideString;
  390.     function GetLongitude: Double;
  391.     function GetLatitude: Double;
  392.     function GetElevation: Double;
  393.     function GetZipCode: WideString;
  394.     property DisplayName: WideString read GetDisplayName;
  395.     property City: WideString read GetCity;
  396.     property State: WideString read GetState;
  397.     property StateAbbr: WideString read GetStateAbbr;
  398.     property Country: WideString read GetCountry;
  399.     property CountryAbbr: WideString read GetCountryAbbr;
  400.     property Longitude: Double read GetLongitude;
  401.     property Latitude: Double read GetLatitude;
  402.     property Elevation: Double read GetElevation;
  403.     property ZipCode: WideString read GetZipCode;
  404.   end;
  405.  
  406.   TWeatherConditions = class(TInterfacedObject, IWeatherConditions)
  407.   private
  408.     FPicture: TPicture;
  409.     FOwner: TJDWeatherThread;
  410.     FLocation: TWeatherLocation;
  411.     FDateTime: TDateTime;
  412.     FTemp: Single;
  413.     FHumidity: Single;
  414.     FPressure: Single;
  415.     FCondition: WideString;
  416.     FDescription: WideString;
  417.     FWindSpeed: Single;
  418.     FWindDir: Single;
  419.     FVisibility: Single;
  420.     FDewPoint: Single;
  421.   public
  422.     constructor Create(AOwner: TJDWeatherThread);
  423.     destructor Destroy; override;
  424.   public
  425.     function GetPicture: TPicture;
  426.     function GetLocation: IWeatherLocation;
  427.     function GetDateTime: TDateTime;
  428.     function GetTemp: Single;
  429.     function GetHumidity: Single;
  430.     function GetPressure: Single;
  431.     function GetCondition: WideString;
  432.     function GetDescription: WideString;
  433.     function GetWindDir: Single;
  434.     function GetWindSpeed: Single;
  435.     function GetVisibility: Single;
  436.     function GetDewPoint: Single;
  437.     function SupportedProps: TWeatherConditionsProps;
  438.     property Picture: TPicture read GetPicture;
  439.     property Location: IWeatherLocation read GetLocation;
  440.     property DateTime: TDateTime read GetDateTime;
  441.     property Temp: Single read GetTemp;
  442.     property Humidity: Single read GetHumidity;
  443.     property Pressure: Single read GetPressure;
  444.     property Condition: WideString read GetCondition;
  445.     property Description: WideString read GetDescription;
  446.     property WindSpeed: Single read GetWindSpeed;
  447.     property WindDir: Single read GetWindDir;
  448.     property Visibility: Single read GetVisibility;
  449.     property DewPoint: Single read GetDewPoint;
  450.   end;
  451.  
  452.   TWeatherForecast = class;
  453.  
  454.   TWeatherForecastItem = class(TInterfacedObject, IWeatherForecastItem)
  455.   private
  456.     FOwner: TWeatherForecast;
  457.     FPicture: TPicture;
  458.     FDateTime: TDateTime;
  459.     FTemp: Single;
  460.     FTempMin: Single;
  461.     FTempMax: Single;
  462.     FHumidity: Single;
  463.     FPressure: Single;
  464.     FCondition: WideString;
  465.     FDescription: WideString;
  466.     FWindSpeed: Single;
  467.     FWindDir: Single;
  468.     FVisibility: Single;
  469.     FDewPoint: Single;
  470.   public
  471.     constructor Create(AOwner: TWeatherForecast);
  472.     destructor Destroy; override;
  473.   public
  474.     function GetPicture: TPicture;
  475.     function GetDateTime: TDateTime;
  476.     function GetTemp: Single;
  477.     function GetTempMax: Single;
  478.     function GetTempMin: Single;
  479.     function GetHumidity: Single;
  480.     function GetPressure: Single;
  481.     function GetCondition: WideString;
  482.     function GetDescription: WideString;
  483.     function GetWindDir: Single;
  484.     function GetWindSpeed: Single;
  485.     function GetVisibility: Single;
  486.     function GetDewPoint: Single;
  487.     function SupportedProps: TWeatherForecastProps;
  488.     property Picture: TPicture read GetPicture;
  489.     property DateTime: TDateTime read GetDateTime;
  490.     property Temp: Single read GetTemp;
  491.     property TempMin: Single read GetTempMin;
  492.     property TempMax: Single read GetTempMax;
  493.     property Humidity: Single read GetHumidity;
  494.     property Pressure: Single read GetPressure;
  495.     property Condition: WideString read GetCondition;
  496.     property Description: WideString read GetDescription;
  497.     property WindSpeed: Single read GetWindSpeed;
  498.     property WindDir: Single read GetWindDir;
  499.     property Visibility: Single read GetVisibility;
  500.     property DewPoint: Single read GetDewPoint;
  501.   end;
  502.  
  503.   TWeatherForecast = class(TInterfacedObject, IWeatherForecast)
  504.   private
  505.     FOwner: TJDWeatherThread;
  506.     FItems: TList<IWeatherForecastItem>;
  507.     FLocation: TWeatherLocation;
  508.     procedure Clear;
  509.   public
  510.     constructor Create(AOwner: TJDWeatherThread);
  511.     destructor Destroy; override;
  512.   public
  513.     function GetLocation: IWeatherLocation;
  514.     function GetItem(const Index: Integer): IWeatherForecastItem;
  515.     function Count: Integer;
  516.     function MinTemp: Single;
  517.     function MaxTemp: Single;
  518.     property Location: IWeatherLocation read GetLocation;
  519.     property Items[const Index: Integer]: IWeatherForecastItem read GetItem; default;
  520.   end;
  521.  
  522.   TWeatherStormVertex = class(TInterfacedObject, IWeatherStormVertex)
  523.   private
  524.     FLongitude: Double;
  525.     FLatitude: Double;
  526.   public
  527.     function GetLongitude: Double;
  528.     function GetLatitude: Double;
  529.     property Longitude: Double read GetLongitude;
  530.     property Latitude: Double read GetLatitude;
  531.   end;
  532.  
  533.   TWeatherStormVerticies = class(TInterfacedObject, IWeatherStormVerticies)
  534.   private
  535.     FItems: TList<IWeatherStormVertex>;
  536.     procedure Clear;
  537.   public
  538.     constructor Create;
  539.     destructor Destroy; override;
  540.   public
  541.     function GetItem(const Index: Integer): IWeatherStormVertex;
  542.     function Count: Integer;
  543.     property Items[const Index: Integer]: IWeatherStormVertex read GetItem; default;
  544.   end;
  545.  
  546.   TWeatherAlertStorm = class(TInterfacedObject, IWeatherAlertStorm)
  547.   private
  548.     FDateTime: TDateTime;
  549.     FDirection: Single;
  550.     FSpeed: Single;
  551.     FLongitude: Double;
  552.     FLatitude: Double;
  553.     FVerticies: TWeatherStormVerticies;
  554.   public
  555.     constructor Create;
  556.     destructor Destroy; override;
  557.   public
  558.     function GetDateTime: TDateTime;
  559.     function GetDirection: Single;
  560.     function GetSpeed: Single;
  561.     function GetLongitude: Double;
  562.     function GetLatitude: Double;
  563.     function GetVerticies: IWeatherStormVerticies;
  564.     property DateTime: TDateTime read GetDateTime;
  565.     property Direction: Single read GetDirection;
  566.     property Speed: Single read GetDirection;
  567.     property Longitude: Double read GetLongitude;
  568.     property Latitude: Double read GetLatitude;
  569.     property Verticies: IWeatherStormVerticies read GetVerticies;
  570.   end;
  571.  
  572.   TWeatherAlertZone = class(TInterfacedObject, IWeatherAlertZone)
  573.   private
  574.     FState: WideString;
  575.     FZone: WideString;
  576.   public
  577.     function GetState: WideString;
  578.     function GetZone: WideString;
  579.     property State: WideString read GetState;
  580.     property Zone: WideString read GetZone;
  581.   end;
  582.  
  583.   TWeatherAlertZones = class(TInterfacedObject, IWeatherAlertZones)
  584.   private
  585.     FItems: TList<TWeatherAlertZone>;
  586.     procedure Clear;
  587.   public
  588.     constructor Create;
  589.     destructor Destroy; override;
  590.   public
  591.     function GetItem(const Index: Integer): IWeatherAlertZone;
  592.     function Count: Integer;
  593.     property Items[const Index: Integer]: IWeatherAlertZone read GetItem; default;
  594.   end;
  595.  
  596.   TWeatherAlert = class(TInterfacedObject, IWeatherAlert)
  597.   private
  598.     FOwner: TJDWeatherThread;
  599.     FAlertType: TWeatherAlertType;
  600.     FDescription: WideString;
  601.     FDateTime: TDateTime;
  602.     FExpires: TDateTime;
  603.     FMsg: WideString;
  604.     FPhenomena: WideString;
  605.     FSignificance: WideString;
  606.     FZones: TWeatherAlertZones;
  607.     FStorm: TWeatherAlertStorm;
  608.   public
  609.     constructor Create(AOwner: TJDWeatherThread);
  610.     destructor Destroy; override;
  611.   public
  612.     function GetAlertType: TWeatherAlertType;
  613.     function GetDescription: WideString;
  614.     function GetDateTime: TDateTime;
  615.     function GetExpires: TDateTime;
  616.     function GetMsg: WideString;
  617.     function GetPhenomena: WideString;
  618.     function GetSignificance: WideString;
  619.     function GetZones: IWeatherAlertZones;
  620.     function GetStorm: IWeatherAlertStorm;
  621.     function SupportedFunctions: TWeatherAlertProps;
  622.     property AlertType: TWeatherAlertType read GetAlertType;
  623.     property Description: WideString read GetDescription;
  624.     property DateTime: TDateTime read GetDateTime;
  625.     property Expires: TDateTime read GetExpires;
  626.     property Msg: WideString read GetMsg;
  627.     property Phenomena: WideString read GetPhenomena;
  628.     property Significance: WideString read GetSignificance;
  629.     property Zones: IWeatherAlertZones read GetZones;
  630.     property Storm: IWeatherAlertStorm read GetStorm;
  631.   end;
  632.  
  633.   TWeatherAlerts = class(TInterfacedObject, IWeatherAlerts)
  634.   private
  635.     FItems: TList<IWeatherAlert>;
  636.     procedure Clear;
  637.   public
  638.     constructor Create;
  639.     destructor Destroy; override;
  640.   public
  641.     function GetItem(const Index: Integer): IWeatherAlert;
  642.     function Count: Integer;
  643.     property Items[const Index: Integer]: IWeatherAlert read GetItem; default;
  644.   end;
  645.  
  646.   TMapArray = array[TWeatherMapType] of TPicture;
  647.  
  648.   TWeatherMaps = class(TInterfacedObject, IWeatherMaps)
  649.   private
  650.     FOwner: TJDWeatherThread;
  651.     FMaps: TMapArray;
  652.   public
  653.     constructor Create(AOwner: TJDWeatherThread);
  654.     destructor Destroy; override;
  655.   public
  656.     function GetMap(const MapType: TWeatherMapType): TPicture;
  657.     function SupportedFunctions: TWeatherMapTypes;
  658.     property Maps[const MapType: TWeatherMapType]: TPicture read GetMap;
  659.   end;
  660.  
  661. {$ENDREGION}
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668.  
  669.  
  670.  
  671. //Service Threads
  672.  
  673. {$REGION "Service Threads"}
  674.  
  675.   { Service Specific Thread Base }
  676.  
  677.   TJDWeatherLocationType = (wlZip, wlCityState, wlCoords, wlAutoIP);
  678.  
  679.   TWeatherConditionsEvent = procedure(Sender: TObject; const Conditions: IWeatherConditions) of object;
  680.  
  681.   TWeatherForecastEvent = procedure(Sender: TObject; const Forecast: IWeatherForecast) of object;
  682.  
  683.   TWeatherAlertEvent = procedure(Sender: TObject; const Alert: IWeatherAlerts) of object;
  684.  
  685.   TWeatherMapEvent = procedure(Sender: TObject; const Image: IWeatherMaps) of object;
  686.  
  687.   TJDWeather = class;
  688.  
  689.   TWeatherThreadFunction = (tfConditionByZip, tfConditionByCoords, tfConditionByCity,
  690.     tfConditionByIP, tafForecastByZip, tfForecastByCoords, tfForecastByCity, tfForecastByIP,
  691.     tfAlertsByZip, tfAlertsByCoords, tfAlertsByCity, tfAlertsByIP, tfMapsByZip,
  692.     tfMapsByCoords, tfMapsByCity, tfMapsByIP);
  693.   TWeatherThreadFunctions = set of TWeatherThreadFunction;
  694.  
  695.   TJDWeatherThread = class(TThread)
  696.   private
  697.     FOwner: TJDWeather;
  698.     FWeb: TIdHTTP;
  699.     FLastAll: TDateTime;
  700.     FConditions: TWeatherConditions;
  701.     FLastConditions: TDateTime;
  702.     FForecast: TWeatherForecast;
  703.     FLastForecast: TDateTime;
  704.     FMaps: TWeatherMaps;
  705.     FLastMaps: TDateTime;
  706.     FAlerts: TWeatherAlerts;
  707.     FLastAlerts: TDateTime;
  708.     FOnConditions: TWeatherConditionsEvent;
  709.     FOnForecast: TWeatherForecastEvent;
  710.     FOnAlerts: TWeatherAlertEvent;
  711.     FOnMaps: TWeatherMapEvent;
  712.     procedure CheckAll;
  713.     procedure CheckConditions;
  714.     procedure CheckForecast;
  715.     procedure CheckAlerts;
  716.     procedure CheckMaps;
  717.     function LoadPicture(const U: String; const P: TPicture): Boolean;
  718.   protected
  719.     procedure Execute; override;
  720.     procedure Process;
  721.     procedure SYNC_DoOnConditions;
  722.     procedure SYNC_DoOnForecast;
  723.     procedure SYNC_DoOnAlerts;
  724.     procedure SYNC_DoOnMaps;
  725.   public
  726.     constructor Create(AOwner: TJDWeather); reintroduce;
  727.     destructor Destroy; override;
  728.   public
  729.     property OnConditions: TWeatherConditionsEvent read FOnConditions write FOnConditions;
  730.     property OnForecast: TWeatherForecastEvent read FOnForecast write FOnForecast;
  731.     property OnAlerts: TWeatherAlertEvent read FOnAlerts write FOnAlerts;
  732.     property OnMaps: TWeatherMapEvent read FOnMaps write FOnMaps;
  733.   public
  734.     function Support: TWeatherThreadFunctions; virtual; abstract;
  735.     function GetUrl: String; virtual; abstract;
  736.     function DoAll(Conditions: TWeatherConditions; Forecast: TWeatherForecast;
  737.       Alerts: TWeatherAlerts; Maps: TWeatherMaps): Boolean; virtual; abstract;
  738.     function DoConditions(Conditions: TWeatherConditions): Boolean; virtual; abstract;
  739.     function DoForecast(Forecast: TWeatherForecast): Boolean; virtual; abstract;
  740.     function DoAlerts(Alerts: TWeatherAlerts): Boolean; virtual; abstract;
  741.     function DoMaps(Maps: TWeatherMaps): Boolean; virtual; abstract;
  742.   end;
  743.  
  744.  
  745.  
  746.  
  747.  
  748.  
  749.  
  750.  
  751.  
  752.  
  753.   { Service Specific Thread Implementation }
  754.  
  755.   { OpenWeatherMap Service }
  756.  
  757.   TOWMEndpoint = (oeConditions, oeForecast, oeAlerts, oeMaps);
  758.  
  759.   TOWMWeatherThread = class(TJDWeatherThread)
  760.   public
  761.     function GetEndpointUrl(const Endpoint: TOWMEndpoint): String;
  762.   public
  763.     function Support: TWeatherThreadFunctions; override;
  764.     function GetUrl: String; override;
  765.     function DoAll(Conditions: TWeatherConditions; Forecast: TWeatherForecast;
  766.       Alerts: TWeatherAlerts; Maps: TWeatherMaps): Boolean; override;
  767.     function DoConditions(Conditions: TWeatherConditions): Boolean; override;
  768.     function DoForecast(Forecast: TWeatherForecast): Boolean; override;
  769.     function DoAlerts(Alerts: TWeatherAlerts): Boolean; override;
  770.     function DoMaps(Maps: TWeatherMaps): Boolean; override;
  771.   end;
  772.  
  773.  
  774.   { Weather Underground Service }
  775.  
  776.   TWUEndpoint = (weAll, weAlerts, weAlmanac, weAstronomy, weConditions,
  777.     weCurrentHurricane, weForecast, weForecast10Day, weGeoLookup, weHistory,
  778.     weHourly, weHourly10Day, wePlanner, weRawTide, weTide, weWebCams, weYesterday,
  779.     weRadar, weSatellite, weRadarSatellite);
  780.  
  781.   TWUForecastType = (wfSummary, wfDetail);
  782.  
  783.   TWUWeatherThread = class(TJDWeatherThread)
  784.   public
  785.     procedure FillConditions(const O: ISuperObject; Conditions: TWeatherConditions);
  786.     procedure FillForecast(const O: ISuperObject; Forecast: TWeatherForecast; const ForecastType: TWUForecastType);
  787.     procedure FillAlerts(const O: ISuperObject; Alerts: TWeatherAlerts);
  788.     procedure FillMaps(const O: ISuperObject; Maps: TWeatherMaps);
  789.     function GetEndpointUrl(const Endpoint: TWUEndpoint): String;
  790.   public
  791.     function Support: TWeatherThreadFunctions; override;
  792.     function GetUrl: String; override;
  793.     function DoAll(Conditions: TWeatherConditions; Forecast: TWeatherForecast;
  794.       Alerts: TWeatherAlerts; Maps: TWeatherMaps): Boolean; override;
  795.     function DoConditions(Conditions: TWeatherConditions): Boolean; override;
  796.     function DoForecast(Forecast: TWeatherForecast): Boolean; override;
  797.     function DoAlerts(Alerts: TWeatherAlerts): Boolean; override;
  798.     function DoMaps(Maps: TWeatherMaps): Boolean; override;
  799.   end;
  800.  
  801.  
  802.   { National Weather Service }
  803.  
  804.   TNWSWeatherThread = class(TJDWeatherThread)
  805.   public
  806.  
  807.   public
  808.     function Support: TWeatherThreadFunctions; override;
  809.     function GetUrl: String; override;
  810.     function DoAll(Conditions: TWeatherConditions; Forecast: TWeatherForecast;
  811.       Alerts: TWeatherAlerts; Maps: TWeatherMaps): Boolean; override;
  812.     function DoConditions(Conditions: TWeatherConditions): Boolean; override;
  813.     function DoForecast(Forecast: TWeatherForecast): Boolean; override;
  814.     function DoAlerts(Alerts: TWeatherAlerts): Boolean; override;
  815.     function DoMaps(Maps: TWeatherMaps): Boolean; override;
  816.   end;
  817.  
  818.  
  819.   { NOAA Service}
  820.  
  821.   TNOAAEndpoint = (noeDatasets, noeDataCategories, noeDataTypes, noeLocationCategories,
  822.     noeLocations, noeStations, noeData);
  823.  
  824.   TNOAAWeatherThread = class(TJDWeatherThread)
  825.   public
  826.     function GetEndpointUrl(const Endpoint: TNOAAEndpoint): String;
  827.   public
  828.     function Support: TWeatherThreadFunctions; override;
  829.     function GetUrl: String; override;
  830.     function DoAll(Conditions: TWeatherConditions; Forecast: TWeatherForecast;
  831.       Alerts: TWeatherAlerts; Maps: TWeatherMaps): Boolean; override;
  832.     function DoConditions(Conditions: TWeatherConditions): Boolean; override;
  833.     function DoForecast(Forecast: TWeatherForecast): Boolean; override;
  834.     function DoAlerts(Alerts: TWeatherAlerts): Boolean; override;
  835.     function DoMaps(Maps: TWeatherMaps): Boolean; override;
  836.   end;
  837.  
  838.  
  839.   { AccuWeather Service }
  840.  
  841.   TAWEndpoint = (aeLocations, aeConditions, aeAlerts, aeDailyIndices,
  842.     aeAlarms, aeClimo, aeTropical, aeTidal, aeDaily, aeHourly, aeImagery,
  843.     aeTranslate, aeLocal);
  844.  
  845.   TAWWeatherThread = class(TJDWeatherThread)
  846.   private
  847.     FLocationKey: String;
  848.     FLocationType: TJDWeatherLocationType;
  849.     FLocation1: String;
  850.     FLocation2: String;
  851.     FLocation: ISuperObject;
  852.     function Get(const U: String): ISuperObject;
  853.   public
  854.     function GetEndpointUrl(const Endpoint: TAWEndpoint;
  855.       const S: String): String;
  856.     procedure InvalidateLocation;
  857.     procedure CheckLocation;
  858.   public
  859.     function Support: TWeatherThreadFunctions; override;
  860.     function GetUrl: String; override;
  861.     function DoAll(Conditions: TWeatherConditions; Forecast: TWeatherForecast;
  862.       Alerts: TWeatherAlerts; Maps: TWeatherMaps): Boolean; override;
  863.     function DoConditions(Conditions: TWeatherConditions): Boolean; override;
  864.     function DoForecast(Forecast: TWeatherForecast): Boolean; override;
  865.     function DoAlerts(Alerts: TWeatherAlerts): Boolean; override;
  866.     function DoMaps(Maps: TWeatherMaps): Boolean; override;
  867.   end;
  868.  
  869.  
  870.   { Foreca Service}
  871.  
  872.   TForecaWeatherThread = class(TJDWeatherThread)
  873.   public
  874.     function Support: TWeatherThreadFunctions; override;
  875.     function GetUrl: String; override;
  876.     function DoAll(Conditions: TWeatherConditions; Forecast: TWeatherForecast;
  877.       Alerts: TWeatherAlerts; Maps: TWeatherMaps): Boolean; override;
  878.     function DoConditions(Conditions: TWeatherConditions): Boolean; override;
  879.     function DoForecast(Forecast: TWeatherForecast): Boolean; override;
  880.     function DoAlerts(Alerts: TWeatherAlerts): Boolean; override;
  881.     function DoMaps(Maps: TWeatherMaps): Boolean; override;
  882.   end;
  883.  
  884. {$ENDREGION}
  885.  
  886.  
  887.  
  888.  
  889.  
  890.  
  891.  
  892.  
  893. //Main Component
  894.  
  895. {$REGION "Main Component"}
  896.  
  897.   { Main Component }
  898.  
  899.   TJDWeather = class(TComponent)
  900.   private
  901.     FThread: TJDWeatherThread;
  902.     FService: TWeatherService;
  903.     FActive: Boolean;
  904.     FAllFreq: Integer;
  905.     FConditionFreq: Integer;
  906.     FForecastFreq: Integer;
  907.     FMapsFreq: Integer;
  908.     FAlertsFreq: Integer;
  909.     FOnConditions: TWeatherConditionsEvent;
  910.     FOnForecast: TWeatherForecastEvent;
  911.     FOnAlerts: TWeatherAlertEvent;
  912.     FOnMaps: TWeatherMapEvent;
  913.     FKey: String;
  914.     FLocationType: TJDWeatherLocationType;
  915.     FLocationDetail2: String;
  916.     FLocationDetail1: String;
  917.     FUnits: TWeatherUnits;
  918.     FAllAtOnce: Boolean;
  919.     procedure EnsureThread;
  920.     procedure DestroyThread;
  921.     procedure ThreadConditions(Sender: TObject; const Conditions: IWeatherConditions);
  922.     procedure ThreadForecast(Sender: TObject; const Forecast: IWeatherForecast);
  923.     procedure ThreadAlerts(Sender: TObject; const Alert: IWeatherAlerts);
  924.     procedure ThreadMaps(Sender: TObject; const Maps: IWeatherMaps);
  925.     procedure SetService(const Value: TWeatherService);
  926.     procedure SetConditionFreq(const Value: Integer);
  927.     procedure SetForecastFreq(const Value: Integer);
  928.     procedure SetActive(const Value: Boolean);
  929.     procedure SetMapsFreq(const Value: Integer);
  930.     procedure SetKey(const Value: String);
  931.     procedure SetLocationType(const Value: TJDWeatherLocationType);
  932.     procedure SetLocationDetail1(const Value: String);
  933.     procedure SetLocationDetail2(const Value: String);
  934.     procedure SetAlertsFreq(const Value: Integer);
  935.     procedure SetUnits(const Value: TWeatherUnits);
  936.     procedure SetAllFreq(const Value: Integer);
  937.     procedure SetAllAtOnce(const Value: Boolean);
  938.   public
  939.     constructor Create(AOwner: TComponent); override;
  940.     destructor Destroy; override;
  941.   published
  942.     property Service: TWeatherService read FService write SetService;
  943.     property AllAtOnce: Boolean read FAllAtOnce write SetAllAtOnce;
  944.     property Active: Boolean read FActive write SetActive;
  945.     property AllFreq: Integer read FAllFreq write SetAllFreq;
  946.     property ConditionFreq: Integer read FConditionFreq write SetConditionFreq;
  947.     property ForecastFreq: Integer read FForecastFreq write SetForecastFreq;
  948.     property MapsFreq: Integer read FMapsFreq write SetMapsFreq;
  949.     property AlertsFreq: Integer read FAlertsFreq write SetAlertsFreq;
  950.     property Key: String read FKey write SetKey;
  951.     property LocationType: TJDWeatherLocationType read FLocationType write SetLocationType;
  952.     property LocationDetail1: String read FLocationDetail1 write SetLocationDetail1;
  953.     property Units: TWeatherUnits read FUnits write SetUnits;
  954.     property LocationDetail2: String read FLocationDetail2 write SetLocationDetail2;
  955.     property OnConditions: TWeatherConditionsEvent read FOnConditions write FOnConditions;
  956.     property OnForecast: TWeatherForecastEvent read FOnForecast write FOnForecast;
  957.     property OnAlerts: TWeatherAlertEvent read FOnAlerts write FOnAlerts;
  958.     property OnMaps: TWeatherMapEvent read FOnMaps write FOnMaps;
  959.   end;
  960.  
  961. {$ENDREGION}
  962.  
  963. implementation
  964.  
  965. uses
  966.   DateUtils, StrUtils, Math;
  967.  
  968. { TWeatherCode }
  969.  
  970. class operator TWeatherCode.Implicit(const Value: TWeatherCode): String;
  971. begin
  972.   case Value.DayNight of
  973.     dnDay:    Result:= 'd';
  974.     dnNight:  Result:= 'n';
  975.   end;
  976.   Result:= Result + IntToStr(Integer(Value.Clouds));
  977.   Result:= Result + IntToStr(Integer(Value.Precip));
  978.   Result:= Result + IntToStr(Integer(Value.PrecipType));
  979. end;
  980.  
  981. class operator TWeatherCode.Implicit(const Value: String): TWeatherCode;
  982. begin
  983.   if Length(Value) <> 4 then raise Exception.Create('Value must be 4 characters.');
  984.  
  985.   case Value[1] of
  986.     'd','D': Result.DayNight:= TDayNight.dnDay;
  987.     'n','N': Result.DayNight:= TDayNight.dnNight;
  988.     else raise Exception.Create('First value must be either d, D, n, or N.');
  989.   end;
  990.  
  991.   if CharInSet(Value[2], ['0'..'6']) then
  992.     Result.Clouds:= TCloudCode(StrToIntDef(Value[2], 0))
  993.   else
  994.     raise Exception.Create('Second value must be between 0 and 6.');
  995.  
  996.   if CharInSet(Value[3], ['0'..'4']) then
  997.     Result.Precip:= TPrecipCode(StrToIntDef(Value[3], 0))
  998.   else
  999.     raise Exception.Create('Third value must be between 0 and 4.');
  1000.  
  1001.   if CharInSet(Value[4], ['0'..'2']) then
  1002.     Result.PrecipType:= TPrecipTypeCode(StrToIntDef(Value[4], 0))
  1003.   else
  1004.     raise Exception.Create('Fourth value must be between 0 and 2.');
  1005. end;
  1006.  
  1007. function TWeatherCode.DayNightStr: String;
  1008. begin
  1009.   case DayNight of
  1010.     dnDay:    Result:= 'Day';
  1011.     dnNight:  Result:= 'Night';
  1012.   end;
  1013. end;
  1014.  
  1015. function TWeatherCode.Description: String;
  1016. begin
  1017.   case Clouds of
  1018.     ccClear:        Result:= 'Clear';
  1019.     ccAlmostClear:  Result:= 'Mostly Clear';
  1020.     ccHalfCloudy:   Result:= 'Partly Cloudy';
  1021.     ccBroken:       Result:= 'Cloudy';
  1022.     ccOvercast:     Result:= 'Overcast';
  1023.     ccThinClouds:   Result:= 'Thin High Clouds';
  1024.     ccFog:          Result:= 'Fog';
  1025.   end;
  1026.   case PrecipType of
  1027.     ptRain: begin
  1028.       case Precip of
  1029.         pcNone:         Result:= Result + '';
  1030.         pcSlight:       Result:= Result + ' with Light Rain';
  1031.         pcShowers:      Result:= Result + ' with Rain Showers';
  1032.         pcPrecip:       Result:= Result + ' with Rain';
  1033.         pcThunder:      Result:= Result + ' with Rain and Thunderstorms';
  1034.       end;
  1035.     end;
  1036.     ptSleet: begin
  1037.       case Precip of
  1038.         pcNone:         Result:= Result + '';
  1039.         pcSlight:       Result:= Result + ' with Light Sleet';
  1040.         pcShowers:      Result:= Result + ' with Sleet Showers';
  1041.         pcPrecip:       Result:= Result + ' with Sleet';
  1042.         pcThunder:      Result:= Result + ' with Sleet and Thunderstorms';
  1043.       end;
  1044.     end;
  1045.     ptSnow: begin
  1046.       case Precip of
  1047.         pcNone:         Result:= Result + '';
  1048.         pcSlight:       Result:= Result + ' with Light Snow';
  1049.         pcShowers:      Result:= Result + ' with Snow Showers';
  1050.         pcPrecip:       Result:= Result + ' with Snow';
  1051.         pcThunder:      Result:= Result + ' with Snow and Thunderstorms';
  1052.       end;
  1053.     end;
  1054.   end;
  1055. end;
  1056.  
  1057. class operator TWeatherCode.Implicit(const Value: TWeatherCode): Integer;
  1058. begin
  1059.   Result:= Integer(Value.DayNight);
  1060.   Result:= Result + (Integer(Value.Clouds) * 10);
  1061.   Result:= Result + (Integer(Value.Precip) * 100);
  1062.   Result:= Result + (Integer(Value.PrecipType) * 1000);
  1063. end;
  1064.  
  1065. class operator TWeatherCode.Implicit(const Value: Integer): TWeatherCode;
  1066. begin
  1067.   //Result.DayNight:= TDayNight();
  1068. end;
  1069.  
  1070. //Common Object Implementation
  1071.  
  1072. {$REGION "Common Object Implementation"}
  1073.  
  1074. { TWeatherLocation }
  1075.  
  1076. constructor TWeatherLocation.Create;
  1077. begin
  1078.  
  1079. end;
  1080.  
  1081. destructor TWeatherLocation.Destroy;
  1082. begin
  1083.  
  1084.   inherited;
  1085. end;
  1086.  
  1087. function TWeatherLocation.GetCity: WideString;
  1088. begin
  1089.   Result:= FCity;
  1090. end;
  1091.  
  1092. function TWeatherLocation.GetCountry: WideString;
  1093. begin
  1094.   Result:= FCountry;
  1095. end;
  1096.  
  1097. function TWeatherLocation.GetCountryAbbr: WideString;
  1098. begin
  1099.   Result:= FCountryAbbr;
  1100. end;
  1101.  
  1102. function TWeatherLocation.GetDisplayName: WideString;
  1103. begin
  1104.   Result:= FDisplayName;
  1105. end;
  1106.  
  1107. function TWeatherLocation.GetElevation: Double;
  1108. begin
  1109.   Result:= FElevation;
  1110. end;
  1111.  
  1112. function TWeatherLocation.GetLatitude: Double;
  1113. begin
  1114.   Result:= FLatitude;
  1115. end;
  1116.  
  1117. function TWeatherLocation.GetLongitude: Double;
  1118. begin
  1119.   Result:= FLongitude;
  1120. end;
  1121.  
  1122. function TWeatherLocation.GetState: WideString;
  1123. begin
  1124.   Result:= FState;
  1125. end;
  1126.  
  1127. function TWeatherLocation.GetStateAbbr: WideString;
  1128. begin
  1129.   Result:= FStateAbbr;
  1130. end;
  1131.  
  1132. function TWeatherLocation.GetZipCode: WideString;
  1133. begin
  1134.   Result:= FZipCode;
  1135. end;
  1136.  
  1137. { TWeatherConditions }
  1138.  
  1139. constructor TWeatherConditions.Create(AOwner: TJDWeatherThread);
  1140. begin
  1141.   FOwner:= AOwner;
  1142.   FLocation:= TWeatherLocation.Create;
  1143.   FLocation._AddRef;
  1144.   FPicture:= TPicture.Create;
  1145. end;
  1146.  
  1147. destructor TWeatherConditions.Destroy;
  1148. begin
  1149.   FPicture.Free;
  1150.   FLocation._Release;
  1151.   FLocation:= nil;
  1152.   inherited;
  1153. end;
  1154.  
  1155. function TWeatherConditions.GetCondition: WideString;
  1156. begin
  1157.   Result:= FCondition;
  1158. end;
  1159.  
  1160. function TWeatherConditions.GetDateTime: TDateTime;
  1161. begin
  1162.   Result:= FDateTime;
  1163. end;
  1164.  
  1165. function TWeatherConditions.GetDescription: WideString;
  1166. begin
  1167.   Result:= FDescription;
  1168. end;
  1169.  
  1170. function TWeatherConditions.GetDewPoint: Single;
  1171. begin
  1172.   Result:= FDewPoint;
  1173. end;
  1174.  
  1175. function TWeatherConditions.GetHumidity: Single;
  1176. begin
  1177.   Result:= FHumidity;
  1178. end;
  1179.  
  1180. function TWeatherConditions.GetLocation: IWeatherLocation;
  1181. begin
  1182.   Result:= FLocation;
  1183. end;
  1184.  
  1185. function TWeatherConditions.GetPicture: TPicture;
  1186. begin
  1187.   Result:= FPicture;
  1188. end;
  1189.  
  1190. function TWeatherConditions.GetPressure: Single;
  1191. begin
  1192.   Result:= FPressure;
  1193. end;
  1194.  
  1195. function TWeatherConditions.GetTemp: Single;
  1196. begin
  1197.   Result:= FTemp;
  1198. end;
  1199.  
  1200. function TWeatherConditions.GetVisibility: Single;
  1201. begin
  1202.   Result:= FVisibility;
  1203. end;
  1204.  
  1205. function TWeatherConditions.GetWindDir: Single;
  1206. begin
  1207.   Result:= FWindDir;
  1208. end;
  1209.  
  1210. function TWeatherConditions.GetWindSpeed: Single;
  1211. begin
  1212.   Result:= FWindSpeed;
  1213. end;
  1214.  
  1215. function TWeatherConditions.SupportedProps: TWeatherConditionsProps;
  1216. begin
  1217.   case FOwner.FOwner.FService of
  1218.     wsOpenWeatherMap: Result:= [cpPressureMb, cpWindDir, cpWindSpeed,
  1219.       cpVisibility, cpHumidity, cpCaption, cpDescription, cpClouds,
  1220.       cpRain, cpSnow, cpSunrise, cpSunset, cpTemp, cpTempMin, cpTempMax];
  1221.     wsWUnderground: Result:= [cpPressureMB, cpPressureIn, cpWindDir,
  1222.       cpWindSpeed, cpHumidity, cpVisibility, cpDewPoint, cpHeatIndex,
  1223.       cpWindGust, cpWindChill, cpFeelsLike, cpSolarRad, cpUV, cpTemp,
  1224.       cpTempMin, cpTempMax, cpPrecip, cpIcon, cpCaption, cpDescription,
  1225.       cpStation];
  1226.     wsAccuWeather:      Result:= [
  1227.       ];
  1228.     wsNWS:              Result:= [
  1229.       ];
  1230.     wsNOAA:             Result:= [
  1231.       ];
  1232.   end;
  1233. end;
  1234.  
  1235. { TWeatherForecastItem }
  1236.  
  1237. constructor TWeatherForecastItem.Create(AOwner: TWeatherForecast);
  1238. begin
  1239.   FOwner:= AOwner;
  1240.   FPicture:= TPicture.Create;
  1241. end;
  1242.  
  1243. destructor TWeatherForecastItem.Destroy;
  1244. begin
  1245.   FPicture.Free;
  1246.   inherited;
  1247. end;
  1248.  
  1249. function TWeatherForecastItem.GetCondition: WideString;
  1250. begin
  1251.   Result:= FCondition;
  1252. end;
  1253.  
  1254. function TWeatherForecastItem.GetDateTime: TDateTime;
  1255. begin
  1256.   Result:= FDateTime;
  1257. end;
  1258.  
  1259. function TWeatherForecastItem.GetDescription: WideString;
  1260. begin
  1261.   Result:= FDescription;
  1262. end;
  1263.  
  1264. function TWeatherForecastItem.GetDewPoint: Single;
  1265. begin
  1266.   Result:= FDewPoint;
  1267. end;
  1268.  
  1269. function TWeatherForecastItem.GetHumidity: Single;
  1270. begin
  1271.   Result:= FHumidity;
  1272. end;
  1273.  
  1274. function TWeatherForecastItem.GetPicture: TPicture;
  1275. begin
  1276.   Result:= FPicture;
  1277. end;
  1278.  
  1279. function TWeatherForecastItem.GetPressure: Single;
  1280. begin
  1281.   Result:= FPressure;
  1282. end;
  1283.  
  1284. function TWeatherForecastItem.GetTemp: Single;
  1285. begin
  1286.   Result:= FTemp;
  1287. end;
  1288.  
  1289. function TWeatherForecastItem.GetTempMax: Single;
  1290. begin
  1291.   Result:= FTempMax;
  1292. end;
  1293.  
  1294. function TWeatherForecastItem.GetTempMin: Single;
  1295. begin
  1296.   Result:= FTempMin;
  1297. end;
  1298.  
  1299. function TWeatherForecastItem.GetVisibility: Single;
  1300. begin
  1301.   Result:= FVisibility;
  1302. end;
  1303.  
  1304. function TWeatherForecastItem.GetWindDir: Single;
  1305. begin
  1306.   Result:= FWindDir;
  1307. end;
  1308.  
  1309. function TWeatherForecastItem.GetWindSpeed: Single;
  1310. begin
  1311.   Result:= FWindSpeed;
  1312. end;
  1313.  
  1314. function TWeatherForecastItem.SupportedProps: TWeatherForecastProps;
  1315. begin
  1316.   case FOwner.FOwner.FOwner.FService of
  1317.     wsOpenWeatherMap:   Result:= [fpPressureMB, fpWindDir, fpWindSpeed,
  1318.       fpHumidity, fpTemp, fpTempMin, fpTempMax, fpCaption, fpDescription,
  1319.       fpIcon, fpGroundPressure, fpSeaPressure];
  1320.     wsWUnderground: begin
  1321.       Result:= [fpWindDir, fpWindSpeed, fpHumidity, fpTemp, fpTempMin,
  1322.         fpTempMax, fpCaption, fpDescription, fpIcon];
  1323.     end;
  1324.     wsAccuWeather:      Result:= [fpIcon, fpCaption, fpTemp, fpPrecip,
  1325.       fpURL, fpDaylight];
  1326.     wsNWS:              Result:= [
  1327.       ];
  1328.     wsNOAA:             Result:= [
  1329.       ];
  1330.   end;
  1331. end;
  1332.  
  1333. { TWeatherForecast }
  1334.  
  1335. constructor TWeatherForecast.Create(AOwner: TJDWeatherThread);
  1336. begin
  1337.   FOwner:= AOwner;
  1338.   FItems:= TList<IWeatherForecastItem>.Create;
  1339.   FLocation:= TWeatherLocation.Create;
  1340.   FLocation._AddRef;
  1341. end;
  1342.  
  1343. procedure TWeatherForecast.Clear;
  1344. var
  1345.   X: Integer;
  1346. begin
  1347.   for X := 0 to FItems.Count-1 do begin
  1348.     FItems[X]._Release;
  1349.   end;
  1350.   FLocation._Release;
  1351.   FLocation:= nil;
  1352.   FItems.Clear;
  1353. end;
  1354.  
  1355. destructor TWeatherForecast.Destroy;
  1356. begin
  1357.   Clear;
  1358.   FItems.Free;
  1359.   inherited;
  1360. end;
  1361.  
  1362. function TWeatherForecast.Count: Integer;
  1363. begin
  1364.   Result:= FItems.Count;
  1365. end;
  1366.  
  1367. function TWeatherForecast.GetItem(const Index: Integer): IWeatherForecastItem;
  1368. begin
  1369.   Result:= FItems[Index];
  1370. end;
  1371.  
  1372. function TWeatherForecast.GetLocation: IWeatherLocation;
  1373. begin
  1374.   Result:= FLocation;
  1375. end;
  1376.  
  1377. function TWeatherForecast.MaxTemp: Single;
  1378. var
  1379.   X: Integer;
  1380. begin
  1381.   Result:= -9999999;
  1382.   for X := 0 to FItems.Count-1 do begin
  1383.     if FItems[X].Temp > Result then
  1384.       Result:= FItems[X].Temp;
  1385.   end;
  1386. end;
  1387.  
  1388. function TWeatherForecast.MinTemp: Single;
  1389. var
  1390.   X: Integer;
  1391. begin
  1392.   Result:= 9999999;
  1393.   for X := 0 to FItems.Count-1 do begin
  1394.     if FItems[X].Temp < Result then
  1395.       Result:= FItems[X].Temp;
  1396.   end;
  1397. end;
  1398.  
  1399. { TWeatherStormVertex }
  1400.  
  1401. function TWeatherStormVertex.GetLatitude: Double;
  1402. begin
  1403.   Result:= FLatitude;
  1404. end;
  1405.  
  1406. function TWeatherStormVertex.GetLongitude: Double;
  1407. begin
  1408.   Result:= FLongitude;
  1409. end;
  1410.  
  1411. { TWeatherStormVerticies }
  1412.  
  1413. constructor TWeatherStormVerticies.Create;
  1414. begin
  1415.   FItems:= TList<IWeatherStormVertex>.Create;
  1416. end;
  1417.  
  1418. destructor TWeatherStormVerticies.Destroy;
  1419. begin
  1420.   Clear;
  1421.   FItems.Free;
  1422.   inherited;
  1423. end;
  1424.  
  1425. function TWeatherStormVerticies.Count: Integer;
  1426. begin
  1427.   Result:= FItems.Count;
  1428. end;
  1429.  
  1430. procedure TWeatherStormVerticies.Clear;
  1431. var
  1432.   X: Integer;
  1433. begin
  1434.   for X := 0 to FItems.Count-1 do begin
  1435.     FItems[X]._Release;
  1436.   end;
  1437.   FItems.Clear;
  1438. end;
  1439.  
  1440. function TWeatherStormVerticies.GetItem(
  1441.   const Index: Integer): IWeatherStormVertex;
  1442. begin
  1443.   Result:= FItems[Index];
  1444. end;
  1445.  
  1446. { TWeatherAlertStorm }
  1447.  
  1448. constructor TWeatherAlertStorm.Create;
  1449. begin
  1450.   FVerticies:= TWeatherStormVerticies.Create;
  1451.   FVerticies._AddRef;
  1452. end;
  1453.  
  1454. destructor TWeatherAlertStorm.Destroy;
  1455. begin
  1456.   FVerticies._Release;
  1457.   FVerticies:= nil;
  1458.   inherited;
  1459. end;
  1460.  
  1461. function TWeatherAlertStorm.GetDateTime: TDateTime;
  1462. begin
  1463.   Result:= FDateTime;
  1464. end;
  1465.  
  1466. function TWeatherAlertStorm.GetDirection: Single;
  1467. begin
  1468.   Result:= FDirection;
  1469. end;
  1470.  
  1471. function TWeatherAlertStorm.GetLatitude: Double;
  1472. begin
  1473.   Result:= FLatitude;
  1474. end;
  1475.  
  1476. function TWeatherAlertStorm.GetLongitude: Double;
  1477. begin
  1478.   Result:= FLongitude;
  1479. end;
  1480.  
  1481. function TWeatherAlertStorm.GetSpeed: Single;
  1482. begin
  1483.   Result:= FSpeed;
  1484. end;
  1485.  
  1486. function TWeatherAlertStorm.GetVerticies: IWeatherStormVerticies;
  1487. begin
  1488.   Result:= FVerticies;
  1489. end;
  1490.  
  1491. { TWeatherAlertZone }
  1492.  
  1493. function TWeatherAlertZone.GetState: WideString;
  1494. begin
  1495.   Result:= FState;
  1496. end;
  1497.  
  1498. function TWeatherAlertZone.GetZone: WideString;
  1499. begin
  1500.   Result:= FZone;
  1501. end;
  1502.  
  1503. { TWeatherAlertZones }
  1504.  
  1505. constructor TWeatherAlertZones.Create;
  1506. begin
  1507.   FItems:= TList<TWeatherAlertZone>.Create;
  1508.  
  1509. end;
  1510.  
  1511. destructor TWeatherAlertZones.Destroy;
  1512. begin
  1513.   Clear;
  1514.   FItems.Free;
  1515.   inherited;
  1516. end;
  1517.  
  1518. procedure TWeatherAlertZones.Clear;
  1519. var
  1520.   X: Integer;
  1521. begin
  1522.   for X := 0 to FItems.Count-1 do begin
  1523.     FItems[X]._Release;
  1524.   end;
  1525.   FItems.Clear;
  1526. end;
  1527.  
  1528. function TWeatherAlertZones.Count: Integer;
  1529. begin
  1530.   Result:= FItems.Count;
  1531. end;
  1532.  
  1533. function TWeatherAlertZones.GetItem(const Index: Integer): IWeatherAlertZone;
  1534. begin
  1535.   Result:= FItems[Index];
  1536. end;
  1537.  
  1538. { TWeatherAlert }
  1539.  
  1540. constructor TWeatherAlert.Create(AOwner: TJDWeatherThread);
  1541. begin
  1542.   FOwner:= AOwner;
  1543.   FZones:= TWeatherAlertZones.Create;
  1544.   FZones._AddRef;
  1545.   FStorm:= TWeatherAlertStorm.Create;
  1546.   FStorm._AddRef;
  1547. end;
  1548.  
  1549. destructor TWeatherAlert.Destroy;
  1550. begin
  1551.   FStorm._Release;
  1552.   FStorm:= nil;
  1553.   FZones._Release;
  1554.   FZones:= nil;
  1555.   inherited;
  1556. end;
  1557.  
  1558. function TWeatherAlert.SupportedFunctions: TWeatherAlertProps;
  1559. begin
  1560.   case FOwner.FOwner.FService of
  1561.     wsOpenWeatherMap: Result:= [];
  1562.     wsWUnderground: Result:= [apZones, apVerticies, apStorm, apType, apDescription,
  1563.       apExpires, apMessage, apPhenomena, apSignificance];
  1564.     wsAccuWeather: Result:= [];
  1565.     wsNWS: Result:= [];
  1566.     wsNOAA: Result:= [];
  1567.   end;
  1568. end;
  1569.  
  1570. function TWeatherAlert.GetAlertType: TWeatherAlertType;
  1571. begin
  1572.   Result:= FAlertType;
  1573. end;
  1574.  
  1575. function TWeatherAlert.GetDateTime: TDateTime;
  1576. begin
  1577.   Result:= FDateTime;
  1578. end;
  1579.  
  1580. function TWeatherAlert.GetDescription: WideString;
  1581. begin
  1582.   Result:= FDescription;
  1583. end;
  1584.  
  1585. function TWeatherAlert.GetExpires: TDateTime;
  1586. begin
  1587.   Result:= FExpires;
  1588. end;
  1589.  
  1590. function TWeatherAlert.GetMsg: WideString;
  1591. begin
  1592.   Result:= FMsg;
  1593. end;
  1594.  
  1595. function TWeatherAlert.GetPhenomena: WideString;
  1596. begin
  1597.   Result:= FPhenomena;
  1598. end;
  1599.  
  1600. function TWeatherAlert.GetSignificance: WideString;
  1601. begin
  1602.   Result:= FSignificance;
  1603. end;
  1604.  
  1605. function TWeatherAlert.GetStorm: IWeatherAlertStorm;
  1606. begin
  1607.   Result:= FStorm;
  1608. end;
  1609.  
  1610. function TWeatherAlert.GetZones: IWeatherAlertZones;
  1611. begin
  1612.   Result:= FZones;
  1613. end;
  1614.  
  1615. { TWeatherAlerts }
  1616.  
  1617. constructor TWeatherAlerts.Create;
  1618. begin
  1619.   FItems:= TList<IWeatherAlert>.Create;
  1620. end;
  1621.  
  1622. destructor TWeatherAlerts.Destroy;
  1623. begin
  1624.   Clear;
  1625.   FItems.Free;
  1626.   inherited;
  1627. end;
  1628.  
  1629. function TWeatherAlerts.Count: Integer;
  1630. begin
  1631.   Result:= FItems.Count;
  1632. end;
  1633.  
  1634. procedure TWeatherAlerts.Clear;
  1635. var
  1636.   X: Integer;
  1637. begin
  1638.   for X := 0 to FItems.Count-1 do begin
  1639.     FItems[X]._Release;
  1640.   end;
  1641.   FItems.Clear;
  1642. end;
  1643.  
  1644. function TWeatherAlerts.GetItem(const Index: Integer): IWeatherAlert;
  1645. begin
  1646.   Result:= FItems[Index];
  1647. end;
  1648.  
  1649. { TWeatherMaps }
  1650.  
  1651. constructor TWeatherMaps.Create(AOwner: TJDWeatherThread);
  1652. var
  1653.   X: TWeatherMapType;
  1654. begin
  1655.   for X := Low(TMapArray) to High(TMapArray) do begin
  1656.     FMaps[X]:= TPicture.Create;
  1657.   end;
  1658. end;
  1659.  
  1660. destructor TWeatherMaps.Destroy;
  1661. var
  1662.   X: TWeatherMapType;
  1663. begin
  1664.   for X := Low(TMapArray) to High(TMapArray) do begin
  1665.     FMaps[X].Free;
  1666.   end;
  1667.   inherited;
  1668. end;
  1669.  
  1670. function TWeatherMaps.GetMap(const MapType: TWeatherMapType): TPicture;
  1671. begin
  1672.   Result:= FMaps[MapType];
  1673. end;
  1674.  
  1675. function TWeatherMaps.SupportedFunctions: TWeatherMapTypes;
  1676. begin
  1677.   case Self.FOwner.FOwner.FService of
  1678.     wsOpenWeatherMap: Result:= [mpClouds, mpPrecip, mpPressureSea,
  1679.       mpWind, mpTemp, mpSnowCover];
  1680.     wsWUnderground: Result:= [mpSatellite, mpRadar, mpSatelliteRadar];
  1681.     wsAccuWeather: Result:= [];
  1682.     wsNWS: Result:= [];
  1683.     wsNOAA: Result:= [];
  1684.   end;
  1685. end;
  1686.  
  1687. {$ENDREGION}
  1688.  
  1689.  
  1690.  
  1691.  
  1692.  
  1693.  
  1694.  
  1695.  
  1696. //Base Weather Thread
  1697.  
  1698. {$REGION "Base Weather Thread"}
  1699.  
  1700. { TJDWeatherThread }
  1701.  
  1702. constructor TJDWeatherThread.Create(AOwner: TJDWeather);
  1703. begin
  1704.   inherited Create(True);
  1705.   FOwner:= AOwner;
  1706.   FWeb:= TIdHTTP.Create(nil);
  1707.   FLastAll:= 0;
  1708.   FLastConditions:= 0;
  1709.   FLastForecast:= 0;
  1710.   FLastAlerts:= 0;
  1711.   FLastMaps:= 0;
  1712. end;
  1713.  
  1714. destructor TJDWeatherThread.Destroy;
  1715. begin
  1716.   if Assigned(FConditions) then
  1717.     FConditions._Release;
  1718.   FConditions:= nil;
  1719.   if Assigned(FForecast) then
  1720.     FForecast._Release;
  1721.   FForecast:= nil;
  1722.   if Assigned(FAlerts) then
  1723.     FAlerts._Release;
  1724.   FAlerts:= nil;
  1725.   if Assigned(FMaps) then
  1726.     FMaps._Release;
  1727.   FMaps:= nil;
  1728.   FWeb.Free;
  1729.   inherited;
  1730. end;
  1731.  
  1732. procedure TJDWeatherThread.CheckAll;
  1733. var
  1734.   R: Boolean;
  1735. begin
  1736.   FLastAll:= Now;
  1737.   try
  1738.     if Assigned(FConditions) then
  1739.       FConditions._Release;
  1740.     if Assigned(FForecast) then
  1741.       FForecast._Release;
  1742.     if Assigned(FAlerts) then
  1743.       FAlerts._Release;
  1744.     if Assigned(FMaps) then
  1745.       FMaps._Release;
  1746.     FConditions:= TWeatherConditions.Create(Self);
  1747.     FConditions._AddRef;
  1748.     FForecast:= TWeatherForecast.Create(Self);
  1749.     FForecast._AddRef;
  1750.     FAlerts:= TWeatherAlerts.Create;
  1751.     FAlerts._AddRef;
  1752.     FMaps:= TWeatherMaps.Create(Self);
  1753.     FMaps._AddRef;
  1754.     R:= DoAll(FConditions, FForecast, FAlerts, FMaps);
  1755.     if R then begin
  1756.       Synchronize(SYNC_DoOnConditions);
  1757.       Synchronize(SYNC_DoOnForecast);
  1758.       Synchronize(SYNC_DoOnAlerts);
  1759.       Synchronize(SYNC_DoOnMaps);
  1760.     end else begin
  1761.       FConditions._Release;
  1762.       FConditions:= nil;
  1763.       FForecast._Release;
  1764.       FForecast:= nil;
  1765.       FAlerts._Release;
  1766.       FAlerts:= nil;
  1767.       FMaps._Release;
  1768.       FMaps:= nil;
  1769.     end;
  1770.   except
  1771.  
  1772.   end;
  1773. end;
  1774.  
  1775. procedure TJDWeatherThread.CheckConditions;
  1776. var
  1777.   R: Boolean;
  1778. begin
  1779.   FLastConditions:= Now;
  1780.   try
  1781.     if Assigned(FConditions) then
  1782.       FConditions._Release;
  1783.     FConditions:= TWeatherConditions.Create(Self);
  1784.     FConditions._AddRef;
  1785.     R:= DoConditions(FConditions);
  1786.     if R then begin
  1787.       Synchronize(SYNC_DoOnConditions);
  1788.     end else begin
  1789.       FConditions._Release;
  1790.       FConditions:= nil;
  1791.     end;
  1792.   except
  1793.  
  1794.   end;
  1795. end;
  1796.  
  1797. procedure TJDWeatherThread.CheckForecast;
  1798. var
  1799.   R: Boolean;
  1800. begin
  1801.   FLastForecast:= Now;
  1802.   try
  1803.     if Assigned(FForecast) then
  1804.       FForecast._Release;
  1805.     FForecast:= TWeatherForecast.Create(Self);
  1806.     FForecast._AddRef;
  1807.     R:= DoForecast(FForecast);
  1808.     if R then begin
  1809.       Synchronize(SYNC_DoOnForecast);
  1810.     end else begin
  1811.       FForecast._Release;
  1812.       FForecast:= nil;
  1813.     end;
  1814.   except
  1815.  
  1816.   end;
  1817. end;
  1818.  
  1819. procedure TJDWeatherThread.CheckAlerts;
  1820. var
  1821.   R: Boolean;
  1822. begin
  1823.   FLastAlerts:= Now;
  1824.   try
  1825.     if Assigned(FAlerts) then
  1826.       FAlerts._Release;
  1827.     FAlerts:= TWeatherAlerts.Create;
  1828.     FAlerts._AddRef;
  1829.     R:= DoAlerts(FAlerts);
  1830.     if R then begin
  1831.       Synchronize(SYNC_DoOnAlerts);
  1832.     end else begin
  1833.       FAlerts._Release;
  1834.       FAlerts:= nil;
  1835.     end;
  1836.   except
  1837.  
  1838.   end;
  1839. end;
  1840.  
  1841. procedure TJDWeatherThread.CheckMaps;
  1842. var
  1843.   R: Boolean;
  1844. begin
  1845.   FLastMaps:= Now;
  1846.   try
  1847.     if Assigned(FMaps) then
  1848.       FMaps._Release;
  1849.     FMaps:= TWeatherMaps.Create(Self);
  1850.     FMaps._AddRef;
  1851.     R:= DoMaps(FMaps);
  1852.     if R then begin
  1853.       Synchronize(SYNC_DoOnMaps);
  1854.     end else begin
  1855.       FMaps._Release;
  1856.       FMaps:= nil;
  1857.     end;
  1858.   except
  1859.  
  1860.   end;
  1861. end;
  1862.  
  1863. procedure TJDWeatherThread.Process;
  1864.   function TimePast(const DT: TDateTime; const Freq: Integer): Boolean;
  1865.   var
  1866.     N: TDateTime;
  1867.   begin
  1868.     N:= DateUtils.IncSecond(DT, Freq);
  1869.     Result:= Now >= N;
  1870.   end;
  1871. begin
  1872.   if FOwner.FAllAtOnce then begin
  1873.  
  1874.     if Terminated then Exit;
  1875.     if TimePast(FLastAll, FOwner.FAllFreq) then
  1876.       CheckAll;
  1877.  
  1878.   end else begin
  1879.  
  1880.     if Terminated then Exit;
  1881.     if TimePast(FLastConditions, FOwner.FConditionFreq) then
  1882.       CheckConditions;
  1883.  
  1884.     if Terminated then Exit;
  1885.     if TimePast(FLastForecast, FOwner.FForecastFreq) then
  1886.       CheckForecast;
  1887.  
  1888.     if Terminated then Exit;
  1889.     if TimePast(FLastAlerts, FOwner.FAlertsFreq) then
  1890.       CheckAlerts;
  1891.  
  1892.     if Terminated then Exit;
  1893.     if TimePast(FLastMaps, FOwner.FMapsFreq) then
  1894.       CheckMaps;
  1895.  
  1896.   end;
  1897.   if Terminated then Exit;
  1898.   Sleep(1);
  1899. end;
  1900.  
  1901. procedure TJDWeatherThread.Execute;
  1902. begin
  1903.   while not Terminated do begin
  1904.     try
  1905.       Process;
  1906.     except
  1907.       on E: Exception do begin
  1908.         //TODO
  1909.       end;
  1910.     end;
  1911.   end;
  1912. end;
  1913.  
  1914. function TJDWeatherThread.LoadPicture(const U: String; const P: TPicture): Boolean;
  1915. var
  1916.   S: TMemoryStream;
  1917.   I: TGifImage;
  1918. begin
  1919.   Result:= False;
  1920.   try
  1921.     S:= TMemoryStream.Create;
  1922.     try
  1923.       FWeb.Get(U, S);
  1924.       S.Position:= 0;
  1925.       I:= TGifImage.Create;
  1926.       try
  1927.         I.LoadFromStream(S);
  1928.         P.Assign(I);
  1929.         Result:= True;
  1930.       finally
  1931.         I.Free;
  1932.       end;
  1933.     finally
  1934.       S.Free;
  1935.     end;
  1936.   except
  1937.  
  1938.   end;
  1939. end;
  1940.  
  1941. procedure TJDWeatherThread.SYNC_DoOnConditions;
  1942. begin
  1943.   if Assigned(FOnConditions) then
  1944.     FOnConditions(Self, FConditions);
  1945. end;
  1946.  
  1947. procedure TJDWeatherThread.SYNC_DoOnForecast;
  1948. begin
  1949.   if Assigned(FOnForecast) then
  1950.     FOnForecast(Self, FForecast);
  1951. end;
  1952.  
  1953. procedure TJDWeatherThread.SYNC_DoOnAlerts;
  1954. begin
  1955.   if Assigned(FOnAlerts) then
  1956.     FOnAlerts(Self, FAlerts);
  1957. end;
  1958.  
  1959. procedure TJDWeatherThread.SYNC_DoOnMaps;
  1960. begin
  1961.   if Assigned(FOnMaps) then
  1962.     FOnMaps(Self, FMaps);
  1963. end;
  1964.  
  1965. {$ENDREGION}
  1966.  
  1967.  
  1968.  
  1969.  
  1970.  
  1971.  
  1972.  
  1973.  
  1974. //Open Weather Maps
  1975.  
  1976. {$REGION "Open Weather Map Thread"}
  1977.  
  1978. { TOWMWeatherThread }
  1979.  
  1980. function TOWMWeatherThread.Support: TWeatherThreadFunctions;
  1981. begin
  1982.   Result:= [tfConditionByZip, tfConditionByCoords, tfConditionByCity,
  1983.     tfConditionByIP, tafForecastByZip, tfForecastByCoords, tfForecastByCity,
  1984.     tfForecastByIP, tfMapsByZip, tfMapsByCoords, tfMapsByCity,
  1985.     tfMapsByIP];
  1986. end;
  1987.  
  1988. function TOWMWeatherThread.GetEndpointUrl(const Endpoint: TOWMEndpoint): String;
  1989. begin
  1990.   case Endpoint of
  1991.     oeConditions: Result:= 'weather';
  1992.     oeForecast:   Result:= 'forecast';
  1993.     oeAlerts:     Result:= 'alerts'; //TODO
  1994.     oeMaps:       Result:= 'maps'; //TODO
  1995.   end;
  1996.   Result:= GetUrl + Result + '?appid='+FOwner.Key;
  1997.   case FOwner.FUnits of
  1998.     wuKelvin:   ;
  1999.     wuImperial: Result:= Result + '&units=imperial';
  2000.     wuMetric:   Result:= Result + '&units=metric';
  2001.   end;
  2002. end;
  2003.  
  2004. function TOWMWeatherThread.GetUrl: String;
  2005. begin
  2006.   Result:= 'http://api.openweathermap.org/data/2.5/';
  2007. end;
  2008.  
  2009. function TOWMWeatherThread.DoAlerts(Alerts: TWeatherAlerts): Boolean;
  2010. begin
  2011.   Result:= False;
  2012.   //NOT SUPPORTED
  2013. end;
  2014.  
  2015. function TOWMWeatherThread.DoAll(Conditions: TWeatherConditions;
  2016.   Forecast: TWeatherForecast; Alerts: TWeatherAlerts;
  2017.   Maps: TWeatherMaps): Boolean;
  2018. begin
  2019.   Result:= False;
  2020.  
  2021. end;
  2022.  
  2023. function TOWMWeatherThread.DoConditions(
  2024.   Conditions: TWeatherConditions): Boolean;
  2025. begin
  2026.   Result:= False;
  2027.  
  2028. end;
  2029.  
  2030. function TOWMWeatherThread.DoForecast(Forecast: TWeatherForecast): Boolean;
  2031. begin
  2032.   Result:= False;
  2033.  
  2034. end;
  2035.  
  2036. function TOWMWeatherThread.DoMaps(Maps: TWeatherMaps): Boolean;
  2037. begin
  2038.   Result:= False;
  2039.  
  2040. end;
  2041.  
  2042. {$ENDREGION}
  2043.  
  2044.  
  2045. //Weather Underground
  2046.  
  2047. {$REGION "Weather Underground Thread"}
  2048.  
  2049. { TWUWeatherThread }
  2050.  
  2051. function TWUWeatherThread.Support: TWeatherThreadFunctions;
  2052. begin
  2053.   Result:= [tfConditionByZip, tfConditionByCoords, tfConditionByCity,
  2054.     tfConditionByIP, tafForecastByZip, tfForecastByCoords, tfForecastByCity, tfForecastByIP,
  2055.     tfAlertsByZip, tfAlertsByCoords, tfAlertsByCity, tfAlertsByIP,
  2056.     tfMapsByZip, tfMapsByCoords, tfMapsByCity, tfMapsByIP];
  2057. end;
  2058.  
  2059. function TWUWeatherThread.GetUrl: String;
  2060. begin
  2061.   Result:= 'http://api.wunderground.com/api/'+FOwner.Key+'/';
  2062. end;
  2063.  
  2064. function TWUWeatherThread.GetEndpointUrl(const Endpoint: TWUEndpoint): String;
  2065. var
  2066.   S: String;
  2067. begin
  2068.   case Endpoint of
  2069.     weAll:              S:= 'conditions/forecast/forecast10day/alerts/hourly';
  2070.     weAlerts:           S:= 'alerts';
  2071.     weAlmanac:          S:= 'almanac';
  2072.     weAstronomy:        S:= 'astronomy';
  2073.     weConditions:       S:= 'conditions';
  2074.     weCurrentHurricane: S:= 'currenthurricane';
  2075.     weForecast:         S:= 'forecast';
  2076.     weForecast10Day:    S:= 'forecast10day';
  2077.     weGeoLookup:        S:= 'geolookup';
  2078.     weHistory:          S:= 'history';
  2079.     weHourly:           S:= 'hourly';
  2080.     weHourly10Day:      S:= 'hourly10day';
  2081.     wePlanner:          S:= 'planner';
  2082.     weRawTide:          S:= 'rawtide';
  2083.     weTide:             S:= 'tide';
  2084.     weWebCams:          S:= 'webcams';
  2085.     weYesterday:        S:= 'yesterday';
  2086.     weRadar:            S:= 'radar';
  2087.     weSatellite:        S:= 'satellite';
  2088.     weRadarSatellite:   S:= 'radar/satellite';
  2089.   end;
  2090.   Result:= GetUrl + S + '/q/';
  2091. end;
  2092.  
  2093. function TWUWeatherThread.DoAll(Conditions: TWeatherConditions;
  2094.   Forecast: TWeatherForecast; Alerts: TWeatherAlerts;
  2095.   Maps: TWeatherMaps): Boolean;
  2096. var
  2097.   U: String;
  2098.   S: String;
  2099.   O: ISuperObject;
  2100.   //OConditions, OForecast, OAlerts, OMaps: ISuperObject;
  2101. begin
  2102.   Result:= False;
  2103.   try
  2104.     U:= GetEndpointUrl(TWUEndpoint.weAll);
  2105.     case FOwner.FLocationType of
  2106.       wlZip:        U:= U + FOwner.FLocationDetail1+'.json';
  2107.       wlCityState:  U:= U + FOwner.FLocationDetail2+'/'+FOwner.FLocationDetail1+'.json';
  2108.       wlCoords:     U:= U + FOwner.FLocationDetail1+','+FOwner.FLocationDetail2+'.json';
  2109.       wlAutoIP:     U:= U + 'autoip.json';
  2110.     end;
  2111.     S:= FWeb.Get(U);
  2112.     O:= SO(S);
  2113.  
  2114.     FillConditions(O, Conditions);
  2115.     FillForecast(O, Forecast, TWUForecastType.wfSummary);// TODO
  2116.     FillAlerts(O, Alerts);
  2117.     FillMaps(O, Maps);//TODO - Doesn't actually work this way
  2118.  
  2119.     Result:= True;
  2120.   except
  2121.     on E: Exception do begin
  2122.  
  2123.     end;
  2124.   end;
  2125. end;
  2126.  
  2127. function TWUWeatherThread.DoConditions(Conditions: TWeatherConditions): Boolean;
  2128. var
  2129.   U: String;
  2130.   S: String;
  2131.   O: ISuperObject;
  2132. begin
  2133.   Result:= False;
  2134.   try
  2135.     U:= GetEndpointUrl(TWUEndpoint.weConditions);
  2136.     case FOwner.FLocationType of
  2137.       wlZip:        U:= U + FOwner.FLocationDetail1+'.json';
  2138.       wlCityState:  U:= U + FOwner.FLocationDetail2+'/'+FOwner.FLocationDetail1+'.json';
  2139.       wlCoords:     U:= U + FOwner.FLocationDetail1+','+FOwner.FLocationDetail2+'.json';
  2140.       wlAutoIP:     U:= U + 'autoip.json';
  2141.     end;
  2142.     S:= FWeb.Get(U);
  2143.     O:= SO(S);
  2144.     FillConditions(O, Conditions);
  2145.     Result:= True;
  2146.   except
  2147.     on E: Exception do begin
  2148.  
  2149.     end;
  2150.   end;
  2151. end;
  2152.  
  2153. function TWUWeatherThread.DoForecast(Forecast: TWeatherForecast): Boolean;
  2154. var
  2155.   U: String;
  2156.   S: String;
  2157.   O: ISuperObject;
  2158. begin
  2159.   Result:= False;
  2160.   try
  2161.     U:= GetEndpointUrl(TWUEndpoint.weForecast);
  2162.     case FOwner.FLocationType of
  2163.       wlZip:        U:= U + FOwner.FLocationDetail1+'.json';
  2164.       wlCityState:  U:= U + FOwner.FLocationDetail2+'/'+FOwner.FLocationDetail1+'.json';
  2165.       wlCoords:     U:= U + FOwner.FLocationDetail1+','+FOwner.FLocationDetail2+'.json';
  2166.       wlAutoIP:     U:= U + 'autoip.json';
  2167.     end;
  2168.     S:= FWeb.Get(U);
  2169.     O:= SO(S);
  2170.     FillForecast(O, Forecast, TWUForecastType.wfSummary);
  2171.     Result:= True;
  2172.   except
  2173.     on E: Exception do begin
  2174.  
  2175.     end;
  2176.   end;
  2177. end;
  2178.  
  2179. function TWUWeatherThread.DoAlerts(Alerts: TWeatherAlerts): Boolean;
  2180. var
  2181.   U: String;
  2182.   S: String;
  2183.   O: ISuperObject;
  2184. begin
  2185.   Result:= False;
  2186.   try
  2187.     U:= GetEndpointUrl(TWUEndpoint.weAlerts);
  2188.     case FOwner.FLocationType of
  2189.       wlZip:        U:= U + FOwner.FLocationDetail1+'.json';
  2190.       wlCityState:  U:= U + FOwner.FLocationDetail2+'/'+FOwner.FLocationDetail1+'.json';
  2191.       wlCoords:     U:= U + FOwner.FLocationDetail1+','+FOwner.FLocationDetail2+'.json';
  2192.       wlAutoIP:     U:= U + 'autoip.json';
  2193.     end;
  2194.     S:= FWeb.Get(U);
  2195.     O:= SO(S);
  2196.     FillAlerts(O, Alerts);
  2197.     Result:= True;
  2198.   except
  2199.     on E: Exception do begin
  2200.  
  2201.     end;
  2202.   end;
  2203. end;
  2204.  
  2205. function TWUWeatherThread.DoMaps(Maps: TWeatherMaps): Boolean;
  2206. var
  2207.   S: TMemoryStream;
  2208.   U: String;
  2209.   I: TGifImage;
  2210.   procedure GetMap(const EP: TWUEndpoint; const MT: TWeatherMapType);
  2211.   begin
  2212.     U:= GetEndpointUrl(EP);
  2213.     case FOwner.FLocationType of
  2214.       wlZip:        U:= U + FOwner.FLocationDetail1+'.gif';
  2215.       wlCityState:  U:= U + FOwner.FLocationDetail2+'/'+FOwner.FLocationDetail1+'.gif';
  2216.       wlCoords:     U:= U + FOwner.FLocationDetail1+','+FOwner.FLocationDetail2+'.gif';
  2217.       wlAutoIP:     U:= U + 'autoip.gif';
  2218.     end;
  2219.     FWeb.Get(U, S);
  2220.     S.Position:= 0;
  2221.     I.LoadFromStream(S);
  2222.     S.Clear;
  2223.     S.Position:= 0;
  2224.     Maps.FMaps[MT].Assign(I);
  2225.   end;
  2226. begin
  2227.   Result:= False;
  2228.   try
  2229.     S:= TMemoryStream.Create;
  2230.     try
  2231.       I:= TGifImage.Create;
  2232.       try
  2233.  
  2234.         GetMap(weRadar, mpRadar);
  2235.         GetMap(weSatellite, mpSatellite);
  2236.         GetMap(weRadarSatellite, mpSatelliteRadar);
  2237.  
  2238.         Result:= True;
  2239.  
  2240.       finally
  2241.         I.Free;
  2242.       end;
  2243.     finally
  2244.       S.Free;
  2245.     end;
  2246.   except
  2247.  
  2248.   end;
  2249. end;
  2250.  
  2251. procedure TWUWeatherThread.FillAlerts(const O: ISuperObject;
  2252.   Alerts: TWeatherAlerts);
  2253. var
  2254.   A: TSuperArray;
  2255.   Tmp: Int64;
  2256.   I: TWeatherAlert;
  2257.   Obj: ISuperObject;
  2258.   X: Integer;
  2259.   function LD(const O: ISuperObject; const N: String): Double;
  2260.   var
  2261.     T: String;
  2262.   begin
  2263.     T:= O.S[N];
  2264.     Result:= StrToFloatDef(T, 0);
  2265.   end;
  2266. begin
  2267.   A:= O.A['alerts'];
  2268.   if not Assigned(A) then Exit;
  2269.  
  2270.   for X := 0 to A.Length-1 do begin
  2271.     Obj:= A.O[X];
  2272.     I:= TWeatherAlert.Create(Self);
  2273.     try
  2274.       I.FAlertType:= TWeatherAlertType.waNone; // Obj.S['type']; //TODO
  2275.       I.FDescription:= Obj.S['description'];
  2276.       Tmp:= StrToIntDef(Obj.S['date_epoch'], 0);
  2277.       I.FDateTime:= UnixToDateTime(Tmp);
  2278.       Tmp:= StrToIntDef(Obj.S['expires_epoch'], 0);
  2279.       I.FExpires:= UnixToDateTime(Tmp);
  2280.       I.FMsg:= Obj.S['message'];
  2281.       I.FPhenomena:= Obj.S['phenomena'];
  2282.       I.FSignificance:= Obj.S['significance'];
  2283.       //Zones
  2284.       //Storm
  2285.     finally
  2286.       Alerts.FItems.Add(I);
  2287.     end;
  2288.   end;
  2289. end;
  2290.  
  2291. procedure TWUWeatherThread.FillConditions(const O: ISuperObject; Conditions: TWeatherConditions);
  2292. var
  2293.   OB, L: ISuperObject;
  2294.   function LD(const O: ISuperObject; const N: String): Double;
  2295.   var
  2296.     T: String;
  2297.   begin
  2298.     T:= O.S[N];
  2299.     Result:= StrToFloatDef(T, 0);
  2300.   end;
  2301. begin
  2302.   OB:= O.O['current_observation'];
  2303.   if not Assigned(OB) then Exit;
  2304.  
  2305.   L:= OB.O['display_location'];
  2306.   if not Assigned(L) then Exit;
  2307.  
  2308.   Conditions.FLocation.FDisplayName:= L.S['full'];
  2309.   Conditions.FLocation.FCity:= L.S['city'];
  2310.   Conditions.FLocation.FState:= L.S['state_name'];
  2311.   Conditions.FLocation.FStateAbbr:= L.S['state'];
  2312.   Conditions.FLocation.FCountry:= L.S['country'];
  2313.   Conditions.FLocation.FCountryAbbr:= L.S['country_iso3166'];
  2314.   Conditions.FLocation.FLongitude:= LD(L, 'longitude');
  2315.   Conditions.FLocation.FLatitude:= LD(L, 'latitude');
  2316.   Conditions.FLocation.FElevation:= LD(L, 'elevation');
  2317.   Conditions.FLocation.FZipCode:= L.S['zip'];
  2318.  
  2319.   case FOwner.FUnits of
  2320.     wuKelvin: begin
  2321.       //Not Supported
  2322.     end;
  2323.     wuImperial: begin
  2324.       Conditions.FTemp:= OB.D['temp_f'];
  2325.       Conditions.FVisibility:= LD(OB, 'visibility_mi');
  2326.       Conditions.FDewPoint:= OB.D['dewpoint_f'];
  2327.     end;
  2328.     wuMetric: begin
  2329.       Conditions.FTemp:= OB.D['temp_c'];
  2330.       Conditions.FVisibility:= LD(OB, 'visibility_km');
  2331.       Conditions.FDewPoint:= OB.D['dewpoint_c'];
  2332.     end;
  2333.   end;
  2334.  
  2335.   Conditions.FDateTime:= Now; //TODO
  2336.   Conditions.FHumidity:= LD(OB, 'relative_humidity');
  2337.   Conditions.FPressure:= LD(OB, 'pressure_mb');
  2338.   Conditions.FCondition:= OB.S['weather'];
  2339.   Conditions.FDescription:= OB.S['weather'];
  2340.   Conditions.FWindSpeed:= OB.D['wind_mph'];
  2341.   Conditions.FWindDir:= OB.D['wind_degrees'];
  2342.  
  2343.   LoadPicture(OB.S['icon_url'], Conditions.FPicture);
  2344.  
  2345. end;
  2346.  
  2347. procedure TWUWeatherThread.FillForecast(const O: ISuperObject; Forecast: TWeatherForecast;
  2348.   const ForecastType: TWUForecastType);
  2349. var
  2350.   OB: ISuperObject;
  2351.   A: TSuperArray;
  2352.   I: TWeatherForecastItem;
  2353.   X: Integer;
  2354.   function CombineDateTime: String;
  2355.   var
  2356.     O: ISuperObject;
  2357.   begin
  2358.     O:= OB.O['date'];
  2359.     Result:= O.S['month'] + '/';
  2360.     Result:= Result + O.S['day'] + '/';
  2361.     Result:= Result + O.S['year'] + ' ';
  2362.     Result:= Result + O.S['hour']+':';
  2363.     Result:= Result + O.S['min']+':';
  2364.     Result:= Result + O.S['sec']+' ';
  2365.     Result:= Result + O.S['ampm'];
  2366.   end;
  2367.   function LD(const O: ISuperObject; const N: String): Double;
  2368.   var
  2369.     T: String;
  2370.   begin
  2371.     T:= O.S[N];
  2372.     Result:= StrToFloatDef(T, 0);
  2373.   end;
  2374. begin
  2375.   OB:= O.O['forecast'];
  2376.   if not Assigned(OB) then begin
  2377.     Exit;
  2378.   end;
  2379.  
  2380.   case ForecastType of
  2381.     TWUForecastType.wfSummary: begin
  2382.       OB:= OB.O['txt_forecast'];
  2383.     end;
  2384.     TWUForecastType.wfDetail: begin
  2385.       OB:= OB.O['simpleforecast'];
  2386.     end;
  2387.   end;
  2388.  
  2389.   if not Assigned(OB) then begin
  2390.     Exit;
  2391.   end;
  2392.  
  2393.   A:= OB.A['forecastday'];
  2394.   if not Assigned(A) then begin
  2395.     Exit;
  2396.   end;
  2397.  
  2398.   for X := 0 to A.Length-1 do begin
  2399.     OB:= A.O[X];
  2400.     I:= TWeatherForecastItem.Create(Forecast);
  2401.     try
  2402.       case ForecastType of
  2403.         TWUForecastType.wfSummary: begin
  2404.           I.FDateTime:= Now;
  2405.           I.FCondition:= OB.S['title'];
  2406.           I.FDescription:= OB.S['fcttext'];
  2407.           LoadPicture(OB.S['icon_url'], I.FPicture);
  2408.         end;
  2409.         TWUForecastType.wfDetail: begin
  2410.           case FOwner.FUnits of
  2411.             wuKelvin: begin
  2412.               //NOT SUPPORTED - Calculate?
  2413.               I.FWindSpeed:= OB.O['avewind'].D['kph'];
  2414.             end;
  2415.             wuImperial: begin
  2416.               I.FTempMin:= StrToFloatDef(OB.O['low'].S['farenheit'], 0);
  2417.               I.FTempMax:= StrToFloatDef(OB.O['high'].S['farenheit'], 0);
  2418.               I.FWindSpeed:= OB.O['avewind'].D['mph'];
  2419.             end;
  2420.             wuMetric: begin
  2421.               I.FTempMin:= StrToFloatDef(OB.O['low'].S['celsius'], 0);
  2422.               I.FTempMax:= StrToFloatDef(OB.O['high'].S['celsius'], 0);
  2423.               I.FWindSpeed:= OB.O['avewind'].D['kph'];
  2424.             end;
  2425.           end;
  2426.           I.FDateTime:= StrToDateTimeDef(CombineDateTime, 0);
  2427.           I.FTemp:= I.FTempMax; //TODO
  2428.           I.FHumidity:= OB.D['avehumidity'];
  2429.           I.FPressure:= 0;
  2430.           I.FCondition:= OB.S['conditions'];
  2431.           I.FDescription:= OB.S['conditions'];
  2432.           I.FWindDir:= OB.O['avewind'].D['degrees'];
  2433.           I.FVisibility:= 0;
  2434.           I.FDewPoint:= 0;
  2435.           LoadPicture(OB.S['icon_url'], I.FPicture);
  2436.         end;
  2437.       end;
  2438.     finally
  2439.       Forecast.FItems.Add(I);
  2440.     end;
  2441.   end;
  2442. end;
  2443.  
  2444. procedure TWUWeatherThread.FillMaps(const O: ISuperObject; Maps: TWeatherMaps);
  2445. begin
  2446.  
  2447. end;
  2448.  
  2449. {$ENDREGION}
  2450.  
  2451.  
  2452. //National Weather Service
  2453.  
  2454. {$REGION "National Weather Service Thread"}
  2455.  
  2456. { TNWSWeatherThread }
  2457.  
  2458. function TNWSWeatherThread.Support: TWeatherThreadFunctions;
  2459. begin
  2460.   Result:= [tfConditionByZip, tfConditionByCoords, tfConditionByCity,
  2461.     tfConditionByIP, tafForecastByZip, tfForecastByCoords, tfForecastByCity, tfForecastByIP,
  2462.     tfAlertsByZip, tfAlertsByCoords, tfAlertsByCity, tfAlertsByIP, tfMapsByZip,
  2463.     tfMapsByCoords, tfMapsByCity, tfMapsByIP];
  2464. end;
  2465.  
  2466. function TNWSWeatherThread.GetUrl: String;
  2467. begin
  2468.   Result:= ''; //TODO
  2469. end;
  2470.  
  2471. function TNWSWeatherThread.DoAlerts(Alerts: TWeatherAlerts): Boolean;
  2472. begin
  2473.   Result:= False;
  2474.  
  2475. end;
  2476.  
  2477. function TNWSWeatherThread.DoAll(Conditions: TWeatherConditions;
  2478.   Forecast: TWeatherForecast; Alerts: TWeatherAlerts;
  2479.   Maps: TWeatherMaps): Boolean;
  2480. begin
  2481.   Result:= False;
  2482.  
  2483. end;
  2484.  
  2485. function TNWSWeatherThread.DoConditions(
  2486.   Conditions: TWeatherConditions): Boolean;
  2487. begin
  2488.   Result:= False;
  2489.  
  2490. end;
  2491.  
  2492. function TNWSWeatherThread.DoForecast(Forecast: TWeatherForecast): Boolean;
  2493. begin
  2494.   Result:= False;
  2495.  
  2496. end;
  2497.  
  2498. function TNWSWeatherThread.DoMaps(Maps: TWeatherMaps): Boolean;
  2499. begin
  2500.   Result:= False;
  2501.  
  2502. end;
  2503.  
  2504. {$ENDREGION}
  2505.  
  2506.  
  2507. //NOAA
  2508.  
  2509. {$REGION "NOAA Thread"}
  2510.  
  2511. { TNOAAWeatherThread }
  2512.  
  2513. function TNOAAWeatherThread.Support: TWeatherThreadFunctions;
  2514. begin
  2515.   Result:= [tfConditionByZip, tfConditionByCoords, tfConditionByCity,
  2516.     tfConditionByIP, tafForecastByZip, tfForecastByCoords, tfForecastByCity, tfForecastByIP,
  2517.     tfAlertsByZip, tfAlertsByCoords, tfAlertsByCity, tfAlertsByIP, tfMapsByZip,
  2518.     tfMapsByCoords, tfMapsByCity, tfMapsByIP];
  2519. end;
  2520.  
  2521. function TNOAAWeatherThread.GetUrl: String;
  2522. begin
  2523.   Result:= 'http://www.ncdc.noaa.gov/cdo-web/api/v2/';
  2524. end;
  2525.  
  2526. function TNOAAWeatherThread.GetEndpointUrl(
  2527.   const Endpoint: TNOAAEndpoint): String;
  2528. begin
  2529.   Result:= GetUrl;
  2530.   case Endpoint of
  2531.     noeDatasets:            Result:= Result + 'datasets/';
  2532.     noeDataCategories:      Result:= Result + 'datacategories/';
  2533.     noeDataTypes:           Result:= Result + 'datatypes/';
  2534.     noeLocationCategories:  Result:= Result + 'locationcategories/';
  2535.     noeLocations:           Result:= Result + 'locations/';
  2536.     noeStations:            Result:= Result + 'stations/';
  2537.     noeData:                Result:= Result + 'data/';
  2538.   end;
  2539. end;
  2540.  
  2541. function TNOAAWeatherThread.DoAlerts(Alerts: TWeatherAlerts): Boolean;
  2542. begin
  2543.   Result:= False;
  2544.  
  2545. end;
  2546.  
  2547. function TNOAAWeatherThread.DoAll(Conditions: TWeatherConditions;
  2548.   Forecast: TWeatherForecast; Alerts: TWeatherAlerts;
  2549.   Maps: TWeatherMaps): Boolean;
  2550. begin
  2551.   Result:= False;
  2552.  
  2553. end;
  2554.  
  2555. function TNOAAWeatherThread.DoConditions(
  2556.   Conditions: TWeatherConditions): Boolean;
  2557. begin
  2558.   Result:= False;
  2559.  
  2560. end;
  2561.  
  2562. function TNOAAWeatherThread.DoForecast(Forecast: TWeatherForecast): Boolean;
  2563. begin
  2564.   Result:= False;
  2565.  
  2566. end;
  2567.  
  2568. function TNOAAWeatherThread.DoMaps(Maps: TWeatherMaps): Boolean;
  2569. begin
  2570.   Result:= False;
  2571.  
  2572. end;
  2573.  
  2574. {$ENDREGION}
  2575.  
  2576.  
  2577. //AccuWeather
  2578.  
  2579. {$REGION "AccuWeather Thread"}
  2580.  
  2581. { TAWWeatherThread }
  2582.  
  2583. function TAWWeatherThread.Support: TWeatherThreadFunctions;
  2584. begin
  2585.   Result:= [tfConditionByZip, tfConditionByCoords, tfConditionByCity,
  2586.     tfConditionByIP, tafForecastByZip, tfForecastByCoords, tfForecastByCity, tfForecastByIP,
  2587.     tfAlertsByZip, tfAlertsByCoords, tfAlertsByCity, tfAlertsByIP, tfMapsByZip,
  2588.     tfMapsByCoords, tfMapsByCity, tfMapsByIP];
  2589. end;
  2590.  
  2591. function TAWWeatherThread.GetEndpointUrl(const Endpoint: TAWEndpoint;
  2592.   const S: String): String;
  2593. begin
  2594.   case Endpoint of
  2595.     aeLocations:    Result:= 'locations/v1/';
  2596.     aeConditions:   Result:= 'currentconditions/v1/';
  2597.     aeAlerts:       Result:= 'alerts/v1/';
  2598.     aeDailyIndices: Result:= 'indices/v1/';
  2599.     aeAlarms:       Result:= 'alarms/v1/';
  2600.     aeClimo:        Result:= 'climo/v1/';
  2601.     aeTropical:     Result:= 'tropical/v1/';
  2602.     aeTidal:        Result:= 'tidal/v1/';
  2603.     aeDaily:        Result:= 'forecasts/v1/daily/';
  2604.     aeHourly:       Result:= 'forecasts/v1/hourly/';
  2605.     aeImagery:      Result:= 'imagery/v1/';
  2606.     aeTranslate:    Result:= 'translations/v1/';
  2607.     aeLocal:        Result:= 'localweather/v1/';
  2608.   end;
  2609.   Result:= GetUrl + Result;
  2610.   Result:= Result + S + '.json?apikey='+FOwner.Key;
  2611.  
  2612. //http://api.accuweather.com/alerts/v1/334907.json?apikey={your key}&details=true
  2613.  
  2614. //http://api.accuweather.com/locations/v1/cities/geoposition/search.json?q=40.59, -73.58&apikey={your key}
  2615.  
  2616. // http://api.accuweather.com/
  2617. // locations/
  2618. // v1/cities/geoposition/search
  2619. // .json
  2620. // ?apikey={your key}
  2621. // &q=40.59, -73.58
  2622.  
  2623. end;
  2624.  
  2625. function TAWWeatherThread.GetUrl: String;
  2626. begin
  2627.   Result:= 'http://apidev.accuweather.com/';
  2628. end;
  2629.  
  2630. procedure TAWWeatherThread.CheckLocation;
  2631. var
  2632.   U: String;
  2633.   S: String;
  2634.   O: ISuperObject;
  2635. begin
  2636.   if FLocationKey <> '' then Exit;
  2637.  
  2638.   //TODO: Connect to API and identify location
  2639.   //Save location identifier to FLocationKey
  2640.  
  2641.   case FOwner.FLocationType of
  2642.     wlZip:        U:= GetEndpointUrl(TAWEndpoint.aeLocations,
  2643.       'poastalcodes/search')+'&q='+FLocation1;
  2644.     wlCityState:  U:= GetEndpointUrl(TAWEndpoint.aeLocations,
  2645.       'cities/US/search')+'&q='+FLocation1+','+FLocation2;
  2646.     wlCoords:     U:= GetEndpointUrl(TAWEndpoint.aeLocations,
  2647.       'cities/geoposition/search')+'&q='+FLocation1+','+FLocation2;
  2648.     wlAutoIP:     U:= GetEndpointUrl(TAWEndpoint.aeLocations,
  2649.       'cities/ipaddress')+'&q='+FLocation1;
  2650.   end;
  2651.  
  2652.   S:= FWeb.Get(U);
  2653.   O:= SO(S);
  2654.   if Assigned(O) then begin
  2655.     FLocation:= O;
  2656.     FLocationKey:= O.S['Key'];
  2657.  
  2658.   end;
  2659.  
  2660. end;
  2661.  
  2662. procedure TAWWeatherThread.InvalidateLocation;
  2663. begin
  2664.   FLocationKey:= '';
  2665. end;
  2666.  
  2667. function TAWWeatherThread.Get(const U: String): ISuperObject;
  2668. var
  2669.   S: String;
  2670. begin
  2671.   Result:= nil;
  2672.   S:= FWeb.Get(U);
  2673.   Result:= SO(S);
  2674. end;
  2675.  
  2676. function TAWWeatherThread.DoAlerts(Alerts: TWeatherAlerts): Boolean;
  2677. var
  2678.   U: String;
  2679.   S1, S2: String;
  2680.   O: ISuperObject;
  2681. begin
  2682.   Result:= False;
  2683.   S1:= FOwner.FLocationDetail1;
  2684.   S2:= FOwner.FLocationDetail2;
  2685.   if FOwner.FLocationType <> FLocationType then begin
  2686.     FLocationType:= FOwner.FLocationType;
  2687.     InvalidateLocation;
  2688.   end;
  2689.   if S1 <> FLocation1 then begin
  2690.     FLocation1:= S1;
  2691.     InvalidateLocation;
  2692.   end;
  2693.   if S2 <> FLocation2 then begin
  2694.     FLocation2:= S2;
  2695.     InvalidateLocation;
  2696.   end;
  2697.   CheckLocation;
  2698.  
  2699.   U:= Self.GetEndpointUrl(TAWEndpoint.aeAlerts, FLocationKey);
  2700.   O:= Get(U);
  2701.  
  2702.   //TODO: Populate alerts structure
  2703.  
  2704. end;
  2705.  
  2706. function TAWWeatherThread.DoAll(Conditions: TWeatherConditions;
  2707.   Forecast: TWeatherForecast; Alerts: TWeatherAlerts;
  2708.   Maps: TWeatherMaps): Boolean;
  2709. begin
  2710.   Result:= False;
  2711.  
  2712. end;
  2713.  
  2714. function TAWWeatherThread.DoConditions(Conditions: TWeatherConditions): Boolean;
  2715. begin
  2716.   Result:= False;
  2717.  
  2718. end;
  2719.  
  2720. function TAWWeatherThread.DoForecast(Forecast: TWeatherForecast): Boolean;
  2721. begin
  2722.   Result:= False;
  2723.  
  2724. end;
  2725.  
  2726. function TAWWeatherThread.DoMaps(Maps: TWeatherMaps): Boolean;
  2727. begin
  2728.   Result:= False;
  2729.  
  2730. end;
  2731.  
  2732. {$ENDREGION}
  2733.  
  2734.  
  2735.  
  2736.  
  2737.  
  2738.  
  2739.  
  2740.  
  2741. //Foreca
  2742.  
  2743. {$REGION "Foreca Thread"}
  2744.  
  2745. { TForecaWeatherThread }
  2746.  
  2747. function TForecaWeatherThread.Support: TWeatherThreadFunctions;
  2748. begin
  2749.   Result:= [];
  2750. end;
  2751.  
  2752. function TForecaWeatherThread.GetUrl: String;
  2753. begin
  2754.   Result:= 'http://apitest.foreca.net/';
  2755.   Result:= Result + '?key='+FOwner.Key;
  2756.   Result:= Result + '&format=json';
  2757.   //http://apitest.foreca.net/?lon=24.934&lat=60.1755&key=yxDYDu3IIlRJzjBVaoje7jtLa4A&format=json
  2758. end;
  2759.  
  2760. function TForecaWeatherThread.DoAll(Conditions: TWeatherConditions;
  2761.   Forecast: TWeatherForecast; Alerts: TWeatherAlerts;
  2762.   Maps: TWeatherMaps): Boolean;
  2763. begin
  2764.   Result:= False;
  2765.  
  2766. end;
  2767.  
  2768. function TForecaWeatherThread.DoConditions(Conditions: TWeatherConditions): Boolean;
  2769. begin
  2770.   Result:= False;
  2771.  
  2772. end;
  2773.  
  2774. function TForecaWeatherThread.DoForecast(Forecast: TWeatherForecast): Boolean;
  2775. begin
  2776.   Result:= False;
  2777.  
  2778. end;
  2779.  
  2780. function TForecaWeatherThread.DoAlerts(Alerts: TWeatherAlerts): Boolean;
  2781. begin
  2782.   Result:= False;
  2783.  
  2784. end;
  2785.  
  2786. function TForecaWeatherThread.DoMaps(Maps: TWeatherMaps): Boolean;
  2787. begin
  2788.   Result:= False;
  2789.  
  2790. end;
  2791.  
  2792. {$ENDREGION}
  2793.  
  2794.  
  2795.  
  2796.  
  2797.  
  2798.  
  2799.  
  2800.  
  2801. //Main TJDWeather Component
  2802.  
  2803. {$REGION "Main TJDWeather Component"}
  2804.  
  2805. { TJDWeather }
  2806.  
  2807. constructor TJDWeather.Create(AOwner: TComponent);
  2808. begin
  2809.   inherited;
  2810.   FLocationType:= wlAutoIP;
  2811.   FService:= wsWUnderground;
  2812.   EnsureThread;
  2813.   FAllFreq:= 300;
  2814.   FConditionFreq:= 300;
  2815.   FForecastFreq:= 300;
  2816.   FAlertsFreq:= 300;
  2817.   FMapsFreq:= 300;
  2818.   FUnits:= wuImperial;
  2819. end;
  2820.  
  2821. destructor TJDWeather.Destroy;
  2822. begin
  2823.   DestroyThread;
  2824.   inherited;
  2825. end;
  2826.  
  2827. procedure TJDWeather.EnsureThread;
  2828. begin
  2829.   if csDesigning in ComponentState then Exit;
  2830.  
  2831.   //If thread is not already created, create it now.
  2832.   //Depending on the chosen service, it will create the
  2833.   //service-specific thread.
  2834.  
  2835.   if FThread = nil then begin
  2836.     case FService of
  2837.       wsOpenWeatherMap:   FThread:= TOWMWeatherThread.Create(Self);
  2838.       wsWUnderground:     FThread:= TWUWeatherThread.Create(Self);
  2839.       wsNWS:              FThread:= TNWSWeatherThread.Create(Self);
  2840.       wsAccuWeather:      FThread:= TAWWeatherThread.Create(Self);
  2841.       wsNOAA:             FThread:= TNOAAWeatherThread.Create(Self);
  2842.       wsForeca:           FThread:= TForecaWeatherThread.Create(Self);
  2843.     end;
  2844.     FThread.OnConditions:= ThreadConditions;
  2845.     FThread.OnForecast:= ThreadForecast;
  2846.     FThread.OnMaps:= ThreadMaps;
  2847.     FThread.OnAlerts:= ThreadAlerts;
  2848.     FThread.Start;
  2849.   end;
  2850. end;
  2851.  
  2852. procedure TJDWeather.DestroyThread;
  2853. begin
  2854.   if Assigned(FThread) then begin
  2855.     FThread.Terminate;
  2856.     FThread:= nil;
  2857.   end;
  2858. end;
  2859.  
  2860. procedure TJDWeather.ThreadConditions(Sender: TObject; const Conditions: IWeatherConditions);
  2861. begin
  2862.   if Assigned(FOnConditions) then
  2863.     FOnConditions(Self, Conditions);
  2864. end;
  2865.  
  2866. procedure TJDWeather.ThreadForecast(Sender: TObject; const Forecast: IWeatherForecast);
  2867. begin
  2868.   if Assigned(FOnForecast) then
  2869.     FOnForecast(Self, Forecast);
  2870. end;
  2871.  
  2872. procedure TJDWeather.ThreadMaps(Sender: TObject; const Maps: IWeatherMaps);
  2873. begin
  2874.   if Assigned(FOnMaps) then
  2875.     FOnMaps(Self, Maps);
  2876. end;
  2877.  
  2878. procedure TJDWeather.ThreadAlerts(Sender: TObject; const Alert: IWeatherAlerts);
  2879. begin
  2880.   if Assigned(FOnAlerts) then
  2881.     FOnAlerts(Self, Alert);
  2882. end;
  2883.  
  2884. procedure TJDWeather.SetActive(const Value: Boolean);
  2885. begin
  2886.   if Value then begin
  2887.     if not FActive then begin
  2888.       FActive:= True;
  2889.       EnsureThread;
  2890.     end;
  2891.   end else begin
  2892.     if FActive then begin
  2893.       FActive:= False;
  2894.       DestroyThread;
  2895.     end;
  2896.   end;
  2897. end;
  2898.  
  2899. procedure TJDWeather.SetAlertsFreq(const Value: Integer);
  2900. begin
  2901.   FAlertsFreq := Value;
  2902. end;
  2903.  
  2904. procedure TJDWeather.SetAllAtOnce(const Value: Boolean);
  2905. begin
  2906.   FAllAtOnce := Value;
  2907.   //TODO: Invalidate Thread
  2908. end;
  2909.  
  2910. procedure TJDWeather.SetAllFreq(const Value: Integer);
  2911. begin
  2912.   FAllFreq := Value;
  2913. end;
  2914.  
  2915. procedure TJDWeather.SetConditionFreq(const Value: Integer);
  2916. begin
  2917.   FConditionFreq := Value;
  2918. end;
  2919.  
  2920. procedure TJDWeather.SetForecastFreq(const Value: Integer);
  2921. begin
  2922.   FForecastFreq:= Value;
  2923. end;
  2924.  
  2925. procedure TJDWeather.SetKey(const Value: String);
  2926. begin
  2927.   FKey := Value;
  2928. end;
  2929.  
  2930. procedure TJDWeather.SetLocationDetail1(const Value: String);
  2931. begin
  2932.   FLocationDetail1 := Value;
  2933. end;
  2934.  
  2935. procedure TJDWeather.SetLocationDetail2(const Value: String);
  2936. begin
  2937.   FLocationDetail2 := Value;
  2938. end;
  2939.  
  2940. procedure TJDWeather.SetLocationType(const Value: TJDWeatherLocationType);
  2941. begin
  2942.   FLocationType := Value;
  2943. end;
  2944.  
  2945. procedure TJDWeather.SetMapsFreq(const Value: Integer);
  2946. begin
  2947.   FMapsFreq := Value;
  2948. end;
  2949.  
  2950. procedure TJDWeather.SetUnits(const Value: TWeatherUnits);
  2951. begin
  2952.   FUnits := Value;
  2953.   //TODO: Invalidate all info
  2954. end;
  2955.  
  2956. procedure TJDWeather.SetService(const Value: TWeatherService);
  2957. begin
  2958.   //Changing service requires swapping out thread class
  2959.   //This switching is the core of multiple services in a single common structure
  2960.   //Each inherited thread implementation must be specific to the chosen service
  2961.   if Value <> FService then begin
  2962.     if FActive then begin
  2963.       raise Exception.Create('Cannot change service while active.');
  2964.     end else begin
  2965.       DestroyThread;
  2966.       FService := Value;
  2967.       EnsureThread;
  2968.     end;
  2969.   end;
  2970. end;
  2971.  
  2972. {$ENDREGION}
  2973.  
  2974. end.
Advertisement
Add Comment
Please, Sign In to add comment