예제 #1
0
        // -------- Functions --------

        /// <summary>
        /// Queries the weather service in the background and returns
        /// what should be send over IRC.
        /// </summary>
        /// <param name="zip">Zip code.</param>
        /// <returns>
        /// The string that should go out over IRC.
        /// Can be report or an error message.
        /// </returns>
        public async Task <string> QueryWeather(string zip)
        {
            string returnString = string.Empty;

            try
            {
                if (reportCache.ContainsKey(zip))
                {
                    // If our cache reports a null, its an invalid zip code.  Print error message.
                    if (reportCache[zip] == null)
                    {
                        returnString = "Error with one or more zip codes: Error: Zip code \"" + zip + "\" is not a valid US zip code";
                    }
                    // Otherwise, if the value in our cache is old, get updated info.
                    else if ((DateTime.UtcNow - reportCache[zip].ConstructionTime).TotalSeconds >= this.weatherQuery.Cooldown)
                    {
                        // Get the weather report in the background.
                        WeatherReport report = await this.weatherQuery.QueryForWeather(zip);

                        returnString     = report.ToString();
                        reportCache[zip] = report;
                    }
                    // Otherwise, our cache is still new, do not query NOAA, just return our cache.
                    else
                    {
                        returnString = reportCache[zip].ToString();
                    }
                }
                else
                {
                    // Get the weather report in the background.
                    WeatherReport report = await this.weatherQuery.QueryForWeather(zip);

                    returnString     = report.ToString();
                    reportCache[zip] = report;
                }
            }
            catch (QueryException err)
            {
                // Only fill our cache if an invalid zip.  Its possible we timed out
                // or the service is just having a tough time at the moment.  We don't
                // want to fill the cache with a zip code that may be okay in the future,
                // just not now.
                if (err.ErrorCode == QueryErrors.InvalidZip)
                {
                    reportCache[zip] = null; // Invalid zip, no sense wasting our time querying the SOAP service next time around.
                }

                returnString = err.Message;
            }
            catch (Exception err)
            {
                returnString = err.Message;
            }

            return(returnString);
        }
예제 #2
0
        // -------- Functions --------

        /// <summary>
        /// Queries NOAA in the backgroud.
        /// </summary>
        /// <param name="zip">The ZIP code to get weather information from.</param>
        /// <returns>The weather report from NOAA.</returns>
        public Task <WeatherReport> QueryForWeather(string zip)
        {
            return(Task.Run(
                       delegate()
            {
                // First, get the Lat/Long of the zip code.
                Tuple <string, string> latLon;
                using (WebClient client = new WebClient())
                {
                    client.QueryString.Add("whichClient", "LatLonListZipCode");
                    client.QueryString.Add("listZipCodeList", zip);
                    client.QueryString.Add("Submit", "Submit");

                    // Per http://stackoverflow.com/questions/32641072/current-observation-feed-from-weather-gov-forbidden-403,
                    // Weather.gov now requires a user agent when querying their API.

                    client.Headers.Add("user-agent", userAgent);

                    string response = client.DownloadString("https://graphical.weather.gov/xml/SOAP_server/ndfdXMLclient.php");
                    latLon = XmlLoader.ParseLatitudeLongitude(response, zip);
                }

                // Next, get the weather report.
                WeatherReport report = null;
                using (WebClient client = new WebClient())
                {
                    client.QueryString.Add("whichClient", "GmlLatLonList");
                    client.QueryString.Add("gmlListLatLon", Uri.EscapeDataString(latLon.Item1 + "," + latLon.Item2));
                    client.QueryString.Add("featureType", "Forecast_Gml2Point");
                    client.QueryString.Add("product", "glance");
                    client.QueryString.Add("Unit", "e");
                    client.QueryString.Add("maxt", "maxt");   // High Temp
                    client.QueryString.Add("mint", "mint");   // Low Temp
                    client.QueryString.Add("pop12", "pop12"); // Precipitation chance
                    client.QueryString.Add("wx", "wx");       // Current Conditations
                    client.QueryString.Add("appt", "appt");   // Apparent Temp
                    client.QueryString.Add("temp", "temp");   // Current Temp
                    client.QueryString.Add("Submit", "Submit");

                    client.Headers.Add("user-agent", userAgent);

                    string response = client.DownloadString("https://graphical.weather.gov/xml/SOAP_server/ndfdXMLclient.php");
                    report = XmlLoader.ParseWeatherReport(response, zip);
                }
                return report;
            }
                       ));
        }
예제 #3
0
        // -------- Functions --------

        /// <summary>
        /// Queries NOAA in the backgroud.
        /// </summary>
        /// <param name="zip">The ZIP code to get weather information from.</param>
        /// <returns>The weather report from NOAA.</returns>
        public Task <WeatherReport> QueryForWeather(string zip)
        {
            return(Task.Run(
                       delegate()
            {
                // First, get the Lat/Long of the zip code.
                Tuple <string, string> latLon;
                using (WebClient client = new WebClient())
                {
                    client.QueryString.Add("whichClient", "LatLonListZipCode");
                    client.QueryString.Add("listZipCodeList", zip);
                    client.QueryString.Add("Submit", "Submit");

                    string response = client.DownloadString("http://graphical.weather.gov/xml/SOAP_server/ndfdXMLclient.php");
                    latLon = XmlLoader.ParseLatitudeLongitude(response, zip);
                }

                // Next, get the weather report.
                WeatherReport report = null;
                using (WebClient client = new WebClient())
                {
                    client.QueryString.Add("whichClient", "GmlLatLonList");
                    client.QueryString.Add("gmlListLatLon", Uri.EscapeDataString(latLon.Item1 + "," + latLon.Item2));
                    client.QueryString.Add("featureType", "Forecast_Gml2Point");
                    client.QueryString.Add("product", "glance");
                    client.QueryString.Add("Unit", "e");
                    client.QueryString.Add("maxt", "maxt");   // High Temp
                    client.QueryString.Add("mint", "mint");   // Low Temp
                    client.QueryString.Add("pop12", "pop12"); // Precipitation chance
                    client.QueryString.Add("wx", "wx");       // Current Conditations
                    client.QueryString.Add("appt", "appt");   // Apparent Temp
                    client.QueryString.Add("temp", "temp");   // Current Temp
                    client.QueryString.Add("Submit", "Submit");

                    string response = client.DownloadString("http://graphical.weather.gov/xml/SOAP_server/ndfdXMLclient.php");
                    report = XmlLoader.ParseWeatherReport(response, zip);
                }
                return report;
            }
                       ));
        }
예제 #4
0
        /// <summary>
        /// Parses the given XML from NOAA to a WeatherReport our plugin can use.
        /// </summary>
        /// <exception cref="ApplicationException">XML from NOAA is invalid.</exception>
        /// <param name="noaaXml">The XML from NOAA's SOAP service.</param>
        /// <param name="zipCode">The zip code we are getting the information from.</param>
        /// <returns>A Weather Report object.</returns>
        public static WeatherReport ParseWeatherReport(string noaaXml, string zipCode)
        {
            XmlDocument doc = new XmlDocument();

            doc.LoadXml(noaaXml);

            XmlNodeList forecastNodes = doc.GetElementsByTagName("app:Forecast_Gml2Point");

            if (forecastNodes.Count == 0)
            {
                CheckForErrorResponse(noaaXml);

                throw new QueryException(
                          QueryErrors.MissingForecast,
                          "Got invalid XML from NOAA.  Could not get weather report from zip code " + zipCode
                          );
            }

            WeatherReport report = new WeatherReport();

            report.ZipCode = zipCode;

            XmlNode forecastNode = forecastNodes[0];

            foreach (XmlNode childNode in forecastNode.ChildNodes)
            {
                switch (childNode.Name)
                {
                // High Temperature:
                case "app:maximumTemperature":
                    report.HighTemp = childNode.InnerText;
                    break;

                // Low Temperature:
                case "app:minimumTemperature":
                    report.LowTemp = childNode.InnerText;
                    break;

                // Current Temperature:
                case "app:temperature":
                    report.CurrentTemp = childNode.InnerText;
                    break;

                // Apparent Temperature:
                case "app:apparentTemperature":
                    report.ApparentTemp = childNode.InnerText;
                    break;

                // Chance of Precipitation:
                case "app:probOfPrecip12hourly":
                    report.ChanceOfPrecipitation = childNode.InnerText;
                    break;

                // Current Conditions:
                case "app:weatherPhrase":
                    report.CurrentConditions = childNode.InnerText;
                    break;
                }
            }

            return(report);
        }