get("gis.weather.$lat,$lon"); if ($cacheresp !== false) { exitWithJson(json_decode($cacheresp, true)); } } $json = file_get_contents("https://api.openweathermap.org/data/2.5/onecall?lat=$lat&lon=$lon&units=imperial&appid=" . env("openweathermap_appid", "")); $weather = json_decode($json, TRUE); $minutely = []; foreach ($weather["minutely"] as $m) { $minutely[] = [ "time" => $m["dt"], "precip" => round($m["precipitation"] / 25.4, 3) ]; } $hourly = []; $mintemp = false; $maxtemp = false; $maxwind = false; $precipchance = false; $preciptype = ""; $maxcloudcover = false; $cloudcovers = []; // For calculating average $summaryicon = "clear"; $oldicon = "clear"; $nowicon = "clear"; $lasttimestamp = time(); foreach ($weather["hourly"] as $w) { if ($w["dt"] > strtotime("now + " . env("weather_summary_hours", 8) . " hours")) { continue; } $hourly[] = [ "time" => $w["dt"], "temp" => $w["temp"], "feelslike" => $w["feels_like"], "windspeed" => $w["wind_speed"], "winddirection" => $w["wind_deg"], "precipchance" => $w["pop"] ]; if ($mintemp === false) { $mintemp = $w["temp"]; } if ($maxtemp === false) { $maxtemp = $w["temp"]; } if ($maxwind === false) { $maxwind = $w["wind_speed"]; } if ($precipchance === false) { $precipchance = $w["pop"]; } if ($maxcloudcover === false) { $maxcloudcover = $w["clouds"]; } $mintemp = min($w["temp"], $mintemp); $maxtemp = max($w["temp"], $maxtemp); $maxwind = max($w["wind_speed"], $maxwind); $precipchance = max($w["pop"], $precipchance); $maxcloudcover = max($w["clouds"], $maxcloudcover); $cloudcovers[] = $w["clouds"]; $lasttimestamp = max($w["dt"], $lasttimestamp); } $avgcloudcover = array_sum($cloudcovers) / count($cloudcovers); if ($precipchance > 0.2) { $summaryicon = "rain"; $oldicon = "rain"; if ($maxtemp < 28) { $summaryicon = "snow"; $oldicon = "snow"; } } else if ($mintemp > 55 && $maxtemp > 85 && $avgcloudcover <= 25) { $summaryicon = "heat"; } else if ($maxwind >= 20) { $summaryicon = "windy"; $oldicon = "windy"; } else if ($avgcloudcover >= 75 || $maxcloudcover >= 90) { $summaryicon = "cloudy"; $oldicon = "cloudy"; } else if ($avgcloudcover <= 15) { $summaryicon = "mostly-sunny"; $oldicon = "partly-cloudy"; } else if ($maxcloudcover >= 33) { $summaryicon = "partly-cloudy"; $oldicon = "partly-cloudy"; } if (((string) $weather["current"]["weather"][0]["id"])[0] == "2") { $nowicon = "rain"; } else if (((string) $weather["current"]["weather"][0]["id"])[0] == "3") { $nowicon = "rain"; } else if (((string) $weather["current"]["weather"][0]["id"])[0] == "5") { $nowicon = "rain"; } else if (((string) $weather["current"]["weather"][0]["id"])[0] == "6") { $nowicon = "snow"; } else if (((string) $weather["current"]["weather"][0]["id"])[0] == "7") { $nowicon = "fog"; if ($weather["current"]["weather"][0]["id"] == 781) { // Tornado!!! $nowicon = "hazard"; } } else if ($weather["current"]["weather"][0]["id"] == 801) { $nowicon = "mostly-sunny"; } else if ($weather["current"]["weather"][0]["id"] == 802) { $nowicon = "partly-cloudy"; } else if ($weather["current"]["weather"][0]["id"] >= 803) { $nowicon = "cloudy"; } if (($nowicon == "mostly-sunny" || $nowicon == "clear" || $nowicon == "partly-cloudy") && $weather["current"]["feels_like"] > 80) { $nowicon = "heat"; } $dailyforecast = []; foreach ($weather["daily"] as $w) { $dailyforecast[] = [ "date" => $w["dt"], "temp" => [ "min" => $w["temp"]["min"], "max" => $w["temp"]["max"] ], "precipitation" => [ "chance" => empty($w["pop"]) ? 0 : $w["pop"] ], "windspeed" => $w["wind_speed"], "uv_index" => round($w["uvi"], 1) ]; } $reverse_geocode_url = ($_SERVER['SERVER_PORT'] == 443 ? "https://" : "http://") . $_SERVER['HTTP_HOST'] . str_replace("/gis/weather/", "/gis/geocode/reverse/", $_SERVER['REQUEST_URI']); $geocode = json_decode(file_get_contents($reverse_geocode_url), TRUE); $location_name = ""; $epa_uv_index = null; if ($geocode["status"] == "OK") { $location_name = implode(", ", [$geocode["address"]["city"], $geocode["address"]["state"]]); $city = $geocode["address"]["city"]; $state = $geocode["address"]["state"]; try { $epa_url = "https://enviro.epa.gov/enviro/efservice/getEnvirofactsUVHOURLY/CITY/$city/STATE/$state/JSON"; $epa_data = json_decode(ApiFetcher::get($epa_url), true); // Find which returned result is closest to the current date and time $closest = $epa_data[0]; foreach ($epa_data as $entry) { if (abs(time() - strtotime(str_replace("/", " ", $entry["DATE_TIME"]))) < abs(time() - strtotime(str_replace("/", " ", $closest["DATE_TIME"])))) { $closest = $entry; } } $epa_uv_index = min($closest["UV_VALUE"], 11); } catch (Exception $ex) { $epa_uv_index = null; } } else { $location_name = "Unknown"; } $output = [ "status" => "OK", "summary" => [ "icon" => $summaryicon, "temp" => [ "min" => $mintemp, "max" => $maxtemp ], "precipitation" => [ "type" => $preciptype, "chance" => $precipchance ], "windspeed" => $maxwind, "cloudcover" => $maxcloudcover, "cloudcover_avg" => $avgcloudcover, "forecast_hours" => env("weather_summary_hours", 8), "forecast_until" => $lasttimestamp ], "now" => [ "icon" => $nowicon, "temp" => $weather["current"]["temp"], "feelslike" => $weather["current"]["feels_like"], "uv_index" => (is_null($epa_uv_index) ? min(round($weather["current"]["uvi"], 1), 11) : $epa_uv_index), "windspeed" => $weather["current"]["wind_speed"], "winddirection" => $weather["current"]["wind_deg"] ], "today" => [ "minutely" => $minutely, "hourly" => $hourly ], "forecast" => $dailyforecast, // From here to the next comment is deprecated "icon" => $oldicon, "temp" => [ "min" => $mintemp, "max" => $maxtemp ], "precipitation" => [ "type" => $preciptype, "chance" => $precipchance ], "windspeed" => $maxwind, "cloudcover" => $maxcloudcover, "cloudcover_avg" => $avgcloudcover, "forecast_hours" => env("weather_summary_hours", 8), "forecast_until" => $lasttimestamp, // the next comment "location_name" => $location_name, "latitude" => $lat, "longitude" => $lon, "source" => [ "text" => "Data: OpenWeatherMap.org" . (is_null($epa_uv_index) ? "" : ", EPA"), "url" => "https://openweathermap.org" ] ]; $memcache->set("gis.weather.$lat,$lon", json_encode($output), 60 * 10); exitWithJson($output);