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.

152 lines
3.9 KiB

  1. <?php
  2. namespace p3k;
  3. use Config;
  4. use DateTime, DateTimeZone;
  5. class Weather {
  6. public static function weather_for_location($lat, $lng, $key) {
  7. if($key == 'XXX') {
  8. return ['error' => 'Please provide an api key from openweathermap.org'];
  9. }
  10. $data = self::_fetch($lat, $lng, $key);
  11. if(!$data) return null;
  12. if(!property_exists($data, 'weather'))
  13. return null;
  14. $weather = [
  15. 'description' => null,
  16. 'icon' => [
  17. 'name' => null
  18. ],
  19. 'temp' => null,
  20. 'feelslike' => null,
  21. 'humidity' => null,
  22. 'wind' => null,
  23. 'pressure' => null,
  24. 'precip_today' => null,
  25. 'timezone' => [
  26. 'offset' => null,
  27. 'name' => null,
  28. 'abbr' => null
  29. ]
  30. ];
  31. $sunny = self::_sunny($data->coord->lat, $data->coord->lon);
  32. $icon_name = self::_icon_name($data->weather[0]->id);
  33. $weather['sun'] = $sunny;
  34. $weather['description'] = $data->weather[0]->description;
  35. $weather['icon']['name'] = $icon_name;
  36. $weather['temp'] = [
  37. 'num' => (double)$data->main->temp,
  38. 'unit' => '°F'
  39. ];
  40. $weather['feelslike'] = [
  41. 'num' => (double)$data->main->feels_like,
  42. 'unit' => '°F'
  43. ];
  44. $weather['wind'] = [
  45. 'num' => $data->wind->speed,
  46. 'unit' => 'mph'
  47. ];
  48. $weather['pressure'] = [
  49. 'num' => (int)$data->main->pressure,
  50. 'unit' => 'mb'
  51. ];
  52. $weather['humidity'] = [
  53. 'num' => round($data->main->humidity),
  54. 'unit' => '%'
  55. ];
  56. $tz = new DateTimeZone($data->timezone);
  57. $now = new DateTime();
  58. $now->setTimeZone($tz);
  59. $offset = $now->format('Z')/3600;
  60. $weather['timezone']['name'] = $sunny['timezone'];
  61. $weather['timezone']['offset'] = $offset;
  62. #$weather['raw'] = $current;
  63. return $weather;
  64. }
  65. private static function _fetch($lat, $lng, $key) {
  66. $params = [
  67. 'units' => 'imperial',
  68. 'lat' => $lat,
  69. 'lon' => $lng,
  70. 'appid' => $key,
  71. ];
  72. $ch = curl_init();
  73. curl_setopt($ch, CURLOPT_URL, 'https://api.openweathermap.org/data/2.5/weather?'.http_build_query($params));
  74. curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  75. // curl_setopt($ch, CURLOPT_USERAGENT, '');
  76. curl_setopt($ch, CURLOPT_TIMEOUT, 5);
  77. $result = curl_exec($ch);
  78. if($result == FALSE)
  79. return FALSE;
  80. return json_decode($result);
  81. }
  82. // Returns "day" or "night" depending on whether the sun is up at the given location
  83. private static function _sunny($lat, $lng, $timezone=null) {
  84. // Get the beginning of the current day
  85. $now = new DateTime();
  86. if(!$timezone) {
  87. $timezone = \p3k\Timezone::timezone_for_location($lat, $lng);
  88. }
  89. $tz = new DateTimeZone($timezone);
  90. $now->setTimeZone($tz);
  91. $offset = $now->format('Z')/3600;
  92. $now = $now->format('H') + ($now->format('i')/60);
  93. $sunrise = date_sunrise($now, SUNFUNCS_RET_DOUBLE, $lat, $lng, 90, $offset);
  94. $sunset = date_sunset($now, SUNFUNCS_RET_DOUBLE, $lat, $lng, 90, $offset);
  95. return [
  96. 'sunrise' => round($sunrise,2),
  97. 'sunset' => round($sunset,2),
  98. 'now' => round($now,2),
  99. 'light' => ($sunrise < $now && $now < $sunset) ? 'day' : 'night',
  100. 'timezone' => $timezone,
  101. ];
  102. }
  103. private static function _icon_name($icon) {
  104. return 'wi-owm-'.$icon;
  105. /*
  106. // A mapping of darksky to weather-icons is here https://erikflowers.github.io/weather-icons/api-list.html
  107. $map = [
  108. 'clear-day' => 'day-sunny',
  109. 'clear-night' => 'night-clear',
  110. 'rain' => 'rain',
  111. 'snow' => 'snow',
  112. 'sleet' => 'sleet',
  113. 'wind' => 'strong-wind',
  114. 'fog' => 'day-haze',
  115. 'cloudy' => 'cloudy',
  116. 'partly-cloudy-day' => 'day-cloudy',
  117. 'partly-cloudy-night' => 'night-cloudy',
  118. 'hail' => 'day-hail',
  119. 'thunderstorm' => 'thunderstorm',
  120. 'tornado' => 'tornado',
  121. ];
  122. if(array_key_exists($icon, $map)) {
  123. return 'wi-'.$map[$icon];
  124. } else {
  125. return false;
  126. }
  127. */
  128. }
  129. }