You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
4.9 KiB

  1. <?php
  2. namespace p3k;
  3. use Config;
  4. class Weather {
  5. public static function weather_for_location($lat, $lng) {
  6. $data = self::_fetch($lat, $lng);
  7. if(!$data) return null;
  8. $current = $data->current_observation;
  9. $weather = [
  10. 'description' => null,
  11. 'icon' => [
  12. 'url' => null,
  13. 'name' => null
  14. ],
  15. 'temp' => null,
  16. 'feelslike' => null,
  17. 'humidity' => null,
  18. 'wind' => null,
  19. 'pressure' => null,
  20. 'precip_today' => null,
  21. 'timezone' => [
  22. 'offset' => null,
  23. 'name' => null,
  24. 'abbr' => null
  25. ]
  26. ];
  27. if($current) {
  28. $loc = $current->display_location;
  29. if($loc) {
  30. $weather['location'] = [
  31. 'city' => $loc->city,
  32. 'state' => $loc->state,
  33. 'country' => $loc->country,
  34. 'zip' => $loc->zip
  35. ];
  36. $sunny = self::_sunny($current->display_location->latitude, $current->display_location->longitude);
  37. } else {
  38. $sunny = 'day';
  39. }
  40. $icon_name = self::_icon_name($current->icon, $sunny);
  41. $weather['description'] = $current->weather;
  42. $weather['icon']['url'] = $current->icon_url;
  43. $weather['icon']['name'] = $icon_name;
  44. $weather['temp'] = [
  45. 'num' => (double)$current->temp_f,
  46. 'unit' => '°F'
  47. ];
  48. $weather['feelslike'] = [
  49. 'num' => (double)$current->feelslike_f,
  50. 'unit' => '°F'
  51. ];
  52. $weather['wind'] = [
  53. 'num' => $current->wind_mph,
  54. 'unit' => 'mph'
  55. ];
  56. $weather['pressure'] = [
  57. 'num' => (int)$current->pressure_mb,
  58. 'unit' => 'mb'
  59. ];
  60. $weather['precip_today'] = [
  61. 'num' => (double)$current->precip_today_in,
  62. 'unit' => 'in'
  63. ];
  64. $weather['humidity'] = [
  65. 'num' => (int)str_replace('%','',$current->relative_humidity),
  66. 'unit' => '%'
  67. ];
  68. $weather['timezone']['offset'] = $current->local_tz_offset;
  69. $weather['timezone']['name'] = $current->local_tz_long;
  70. $weather['timezone']['abbr'] = $current->local_tz_short;
  71. }
  72. #$weather['raw'] = $current;
  73. return $weather;
  74. }
  75. private static function _fetch($lat, $lng) {
  76. $ch = curl_init();
  77. curl_setopt($ch, CURLOPT_URL, 'http://api.wunderground.com/api/'.Config::$wundergroundAPIKey.'/conditions/q/'.$lat.','.$lng.'.json');
  78. curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  79. // curl_setopt($ch, CURLOPT_USERAGENT, '');
  80. curl_setopt($ch, CURLOPT_TIMEOUT, 5);
  81. $result = curl_exec($ch);
  82. if($result == FALSE)
  83. return FALSE;
  84. return json_decode($result);
  85. }
  86. // Returns "day" or "night" depending on whether the sun is up at the given location
  87. private static function _sunny($lat, $lng) {
  88. $now = time();
  89. if($lat !== null) {
  90. $sunrise = date_sunrise($now, SUNFUNCS_RET_TIMESTAMP, $lat, $lng, 96);
  91. $sunset = date_sunset($now, SUNFUNCS_RET_TIMESTAMP, $lat, $lng, 96);
  92. if($sunrise < $now && $sunset > $now) {
  93. return 'day';
  94. } else {
  95. return 'night';
  96. }
  97. } else {
  98. return 'unknown';
  99. }
  100. }
  101. private static function _icon_name($icon, $sunny) {
  102. // This list is from http://www.wunderground.com/weather/api/d/docs?d=resources/icon-sets
  103. // A mapping of wunderground to weather-icons is here https://erikflowers.github.io/weather-icons/api-list.html
  104. $map = [
  105. 'day' => [
  106. 'chanceflurries' => 'snow-wind',
  107. 'chancerain' => 'day-rain',
  108. 'chancesleet' => 'sleet',
  109. 'chancesnow' => 'snow',
  110. 'chancetstorms' => 'thunderstorm',
  111. 'clear' => 'day-sunny',
  112. 'cloudy' => 'day-cloudy',
  113. 'flurries' => 'snow-wind',
  114. 'fog' => 'day-haze',
  115. 'hazy' => 'day-haze',
  116. 'mostlycloudy' => 'day-cloudy',
  117. 'mostlysunny' => 'day-sunny-overcast',
  118. 'partlycloudy' => 'day-cloudy',
  119. 'partlysunny' => 'day-sunny-overcast',
  120. 'sleet' => 'sleet',
  121. 'rain' => 'rain',
  122. 'snow' => 'snow',
  123. 'sunny' => 'day-sunny',
  124. 'tstorms' => 'thunderstorm',
  125. ],
  126. 'night' => [
  127. 'chanceflurries' => 'night-snow-wind',
  128. 'chancerain' => 'night-rain',
  129. 'chancesleet' => 'night-alt-sleet',
  130. 'chancesnow' => 'night-snow',
  131. 'chancetstorms' => 'night-thunderstorm',
  132. 'clear' => 'night-clear',
  133. 'cloudy' => 'night-alt-cloudy',
  134. 'flurries' => 'night-alt-snow-wind',
  135. 'fog' => 'night-fog',
  136. 'hazy' => 'night-fog',
  137. 'mostlycloudy' => 'night-cloudy',
  138. 'mostlysunny' => 'night-clear',
  139. 'partlycloudy' => 'night-partly-cloudy',
  140. 'partlysunny' => 'night-partly-cloudy',
  141. 'sleet' => 'night-alt-sleet',
  142. 'rain' => 'night-alt-showers',
  143. 'snow' => 'night-alt-snow',
  144. 'sunny' => 'night-clear',
  145. 'tstorms' => 'night-alt-thunderstorm',
  146. ]
  147. ];
  148. if(array_key_exists($icon, $map[$sunny])) {
  149. return 'wi-'.$map[$sunny][$icon];
  150. } else {
  151. return false;
  152. }
  153. }
  154. }