Browse Source

adds a weather API

closes #2
main
Aaron Parecki 8 years ago
parent
commit
3c4b2686a8
6 changed files with 214 additions and 1 deletions
  1. +27
    -0
      controllers/weather.php
  2. +4
    -0
      lib/config.template.php
  3. +171
    -0
      p3k/Weather.php
  4. +1
    -0
      public/index.php
  5. +10
    -0
      views/index.php
  6. +1
    -1
      views/layout.php

+ 27
- 0
controllers/weather.php View File

@ -0,0 +1,27 @@
<?php
$app->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);
}
});

+ 4
- 0
lib/config.template.php View File

@ -0,0 +1,4 @@
<?php
class Config {
public static $wundergroundAPIKey = '';
}

+ 171
- 0
p3k/Weather.php View File

@ -0,0 +1,171 @@
<?php
namespace p3k;
use Config;
class Weather {
public static function weather_for_location($lat, $lng) {
$data = self::_fetch($lat, $lng);
if(!$data) return null;
$current = $data->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;
}
}
}

+ 1
- 0
public/index.php View File

@ -7,5 +7,6 @@ require 'vendor/autoload.php';
require 'controllers/main.php'; require 'controllers/main.php';
require 'controllers/timezone.php'; require 'controllers/timezone.php';
require 'controllers/geocode.php'; require 'controllers/geocode.php';
require 'controllers/weather.php';
$app->run(); $app->run();

+ 10
- 0
views/index.php View File

@ -22,6 +22,16 @@
<li><a href="/api/geocode?latitude=45.5118&amp;longitude=-122.6433">/api/geocode?latitude=45.5118&amp;longitude=-122.6433</a></li> <li><a href="/api/geocode?latitude=45.5118&amp;longitude=-122.6433">/api/geocode?latitude=45.5118&amp;longitude=-122.6433</a></li>
</ul> </ul>
<h2><i class="fa fa-sun-o"></i> Weather</h2>
<h3>Retrieving the current weather for a lat/lng</h3>
<ul>
<li><a href="/api/weather?latitude=45.5118&amp;longitude=-122.6433">/api/weather?latitude=45.5118&amp;longitude=-122.6433</a></li>
</ul>
<p>Icon names reference the <a href="https://erikflowers.github.io/weather-icons/">weather-icons</a> icon font.</p>
<h2><i class="fa fa-map"></i> Static Maps</h2> <h2><i class="fa fa-map"></i> Static Maps</h2>
<p><a href="/map/img?marker[]=lat:45.5165;lng:-122.6764;icon:small-blue-cutout&amp;basemap=gray&amp;width=600&amp;height=240&amp;zoom=14">/map/img?marker[]=lat:45.5165;lng:-122.6764;icon:small-blue-cutout&amp;basemap=gray&amp;width=600&amp;height=240&amp;zoom=14</a></p> <p><a href="/map/img?marker[]=lat:45.5165;lng:-122.6764;icon:small-blue-cutout&amp;basemap=gray&amp;width=600&amp;height=240&amp;zoom=14">/map/img?marker[]=lat:45.5165;lng:-122.6764;icon:small-blue-cutout&amp;basemap=gray&amp;width=600&amp;height=240&amp;zoom=14</a></p>

+ 1
- 1
views/layout.php View File

@ -21,7 +21,7 @@
<div class="right"> <div class="right">
<a href="https://github.com/aaronpk/Atlas">Source Code</a> <a href="https://github.com/aaronpk/Atlas">Source Code</a>
</div> </div>
&copy; 2015 by Aaron Parecki
&copy; <?= date('Y') ?> by Aaron Parecki
</footer> </footer>
</body> </body>
</html> </html>

Loading…
Cancel
Save