djjd47130

Weather API Wrapper Unit - V3

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