djjd47130

Weather API Wrapper Unit - V2

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