From 3c4b2686a87262df0f1128a79227451eff3ddfc2 Mon Sep 17 00:00:00 2001 From: Aaron Parecki Date: Mon, 15 Feb 2016 08:11:39 -0800 Subject: [PATCH] adds a weather API closes #2 --- controllers/weather.php | 27 +++++++ lib/config.template.php | 4 + p3k/Weather.php | 171 ++++++++++++++++++++++++++++++++++++++++ public/index.php | 1 + views/index.php | 10 +++ views/layout.php | 2 +- 6 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 controllers/weather.php create mode 100644 p3k/Weather.php diff --git a/controllers/weather.php b/controllers/weather.php new file mode 100644 index 0000000..ca06e76 --- /dev/null +++ b/controllers/weather.php @@ -0,0 +1,27 @@ +get('/api/weather', function() use($app) { + $params = $app->request()->params(); + + if(k($params, 'latitude') !== null && k($params, 'longitude') !== null) { + + $lat = (float)$params['latitude']; + $lng = (float)$params['longitude']; + + $weather = \p3k\Weather::weather_for_location($lat, $lng); + + if($weather) { + json_response($app, $weather); + } else { + json_response($app, [ + 'error' => 'not_found', + 'error_description' => 'No weather information was found for the requested location' + ]); + } + } else { + json_response($app, [ + 'error' => 'invalid_request', + 'error_description' => 'Request was missing parameters' + ], 400); + } +}); diff --git a/lib/config.template.php b/lib/config.template.php index e69de29..bc4bc88 100644 --- a/lib/config.template.php +++ b/lib/config.template.php @@ -0,0 +1,4 @@ +current_observation; + + $weather = [ + 'description' => null, + 'icon' => [ + 'url' => null, + 'name' => null + ], + 'temp' => null, + 'feelslike' => null, + 'humidity' => null, + 'wind' => null, + 'pressure' => null, + 'precip_today' => null, + 'timezone' => [ + 'offset' => null, + 'name' => null, + 'abbr' => null + ] + ]; + + if($current) { + + $loc = $current->display_location; + if($loc) { + $weather['location'] = [ + 'city' => $loc->city, + 'state' => $loc->state, + 'country' => $loc->country, + 'zip' => $loc->zip + ]; + $sunny = self::_sunny($current->display_location->latitude, $current->display_location->longitude); + } else { + $sunny = 'day'; + } + + $icon_name = self::_icon_name($current->icon, $sunny); + + $weather['description'] = $current->weather; + $weather['icon']['url'] = $current->icon_url; + $weather['icon']['name'] = $icon_name; + $weather['temp'] = [ + 'num' => (double)$current->temp_f, + 'unit' => '°F' + ]; + $weather['feelslike'] = [ + 'num' => (double)$current->feelslike_f, + 'unit' => '°F' + ]; + $weather['wind'] = [ + 'num' => $current->wind_mph, + 'unit' => 'mph' + ]; + $weather['pressure'] = [ + 'num' => (int)$current->pressure_mb, + 'unit' => 'mb' + ]; + $weather['precip_today'] = [ + 'num' => (double)$current->precip_today_in, + 'unit' => 'in' + ]; + $weather['humidity'] = [ + 'num' => (int)str_replace('%','',$current->relative_humidity), + 'unit' => '%' + ]; + + $weather['timezone']['offset'] = $current->local_tz_offset; + $weather['timezone']['name'] = $current->local_tz_long; + $weather['timezone']['abbr'] = $current->local_tz_short; + } + + #$weather['raw'] = $current; + + return $weather; + } + + private static function _fetch($lat, $lng) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, 'http://api.wunderground.com/api/'.Config::$wundergroundAPIKey.'/conditions/q/'.$lat.','.$lng.'.json'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); + // curl_setopt($ch, CURLOPT_USERAGENT, ''); + curl_setopt($ch, CURLOPT_TIMEOUT, 5); + $result = curl_exec($ch); + + if($result == FALSE) + return FALSE; + + return json_decode($result); + } + + // Returns "day" or "night" depending on whether the sun is up at the given location + private static function _sunny($lat, $lng) { + $now = time(); + if($lat !== null) { + $sunrise = date_sunrise($now, SUNFUNCS_RET_TIMESTAMP, $lat, $lng, 96); + $sunset = date_sunset($now, SUNFUNCS_RET_TIMESTAMP, $lat, $lng, 96); + if($sunrise < $now && $sunset > $now) { + return 'day'; + } else { + return 'night'; + } + } else { + return 'unknown'; + } + } + + private static function _icon_name($icon, $sunny) { + // This list is from http://www.wunderground.com/weather/api/d/docs?d=resources/icon-sets + // A mapping of wunderground to weather-icons is here https://erikflowers.github.io/weather-icons/api-list.html + $map = [ + 'day' => [ + 'chanceflurries' => 'snow-wind', + 'chancerain' => 'day-rain', + 'chancesleet' => 'sleet', + 'chancesnow' => 'snow', + 'chancetstorms' => 'thunderstorm', + 'clear' => 'day-sunny', + 'cloudy' => 'day-cloudy', + 'flurries' => 'snow-wind', + 'fog' => 'day-haze', + 'hazy' => 'day-haze', + 'mostlycloudy' => 'day-cloudy', + 'mostlysunny' => 'day-sunny-overcast', + 'partlycloudy' => 'day-cloudy', + 'partlysunny' => 'day-sunny-overcast', + 'sleet' => 'sleet', + 'rain' => 'rain', + 'snow' => 'snow', + 'sunny' => 'day-sunny', + 'tstorms' => 'thunderstorm', + ], + 'night' => [ + 'chanceflurries' => 'night-snow-wind', + 'chancerain' => 'night-rain', + 'chancesleet' => 'night-alt-sleet', + 'chancesnow' => 'night-snow', + 'chancetstorms' => 'night-thunderstorm', + 'clear' => 'night-clear', + 'cloudy' => 'night-alt-cloudy', + 'flurries' => 'night-alt-snow-wind', + 'fog' => 'night-fog', + 'hazy' => 'night-fog', + 'mostlycloudy' => 'night-cloudy', + 'mostlysunny' => 'night-clear', + 'partlycloudy' => 'night-partly-cloudy', + 'partlysunny' => 'night-partly-cloudy', + 'sleet' => 'night-alt-sleet', + 'rain' => 'night-alt-showers', + 'snow' => 'night-alt-snow', + 'sunny' => 'night-clear', + 'tstorms' => 'night-alt-thunderstorm', + ] + ]; + if(array_key_exists($icon, $map[$sunny])) { + return 'wi-'.$map[$sunny][$icon]; + } else { + return false; + } + } + +} diff --git a/public/index.php b/public/index.php index e4c02f3..6738126 100644 --- a/public/index.php +++ b/public/index.php @@ -7,5 +7,6 @@ require 'vendor/autoload.php'; require 'controllers/main.php'; require 'controllers/timezone.php'; require 'controllers/geocode.php'; +require 'controllers/weather.php'; $app->run(); diff --git a/views/index.php b/views/index.php index 33fee0e..2f11c7d 100644 --- a/views/index.php +++ b/views/index.php @@ -22,6 +22,16 @@
  • /api/geocode?latitude=45.5118&longitude=-122.6433
  • +

    Weather

    + +

    Retrieving the current weather for a lat/lng

    + + + +

    Icon names reference the weather-icons icon font.

    +

    Static Maps

    /map/img?marker[]=lat:45.5165;lng:-122.6764;icon:small-blue-cutout&basemap=gray&width=600&height=240&zoom=14

    diff --git a/views/layout.php b/views/layout.php index 872de08..b9aaa88 100644 --- a/views/layout.php +++ b/views/layout.php @@ -21,7 +21,7 @@
    Source Code
    - © 2015 by Aaron Parecki + © by Aaron Parecki