1571 lines
54 KiB
PHP
1571 lines
54 KiB
PHP
<?php
|
|
// Main integrated PHP file containing all functions from separate scripts
|
|
// This file consolidates functionality from: admin.php, cam.php, camapi.php, camcircle.php,
|
|
// camlist.php, camobs.php, db.php, fire.php, individualcam.php, lsr.php, mp4.php,
|
|
// nws.php, ohgo.php, one.php, power.php, powerapi.php, powerapitest.php,
|
|
// searchapi.php, single.php, stormdata.php, update_field.php, ver.php, warntrack.php
|
|
|
|
// ============================================================================
|
|
// UTILITY FUNCTIONS (No GET/POST requests - keep at top for compatibility)
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Database connection function
|
|
*/
|
|
function connect_db() {
|
|
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
|
|
or die('Could not connect: ' . pg_last_error());
|
|
return $dbconn;
|
|
}
|
|
|
|
/**
|
|
* Send JSON error response
|
|
*/
|
|
function send_error($code, $message) {
|
|
http_response_code($code);
|
|
header('Content-Type: application/json');
|
|
echo json_encode(['error' => $message]);
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Send JSON success response
|
|
*/
|
|
function send_json($data) {
|
|
header('Content-Type: application/json');
|
|
echo json_encode($data);
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Send GeoJSON response
|
|
*/
|
|
function send_geojson($features) {
|
|
$geojson_output = ['type' => 'FeatureCollection', 'features' => $features];
|
|
header('Content-Type: application/geo+json');
|
|
echo json_encode($geojson_output);
|
|
exit;
|
|
}
|
|
|
|
// ============================================================================
|
|
// MAIN ROUTING AND REQUEST HANDLING
|
|
// ============================================================================
|
|
|
|
// Set common headers
|
|
header('Content-Type: application/json');
|
|
header('Access-Control-Allow-Origin: *');
|
|
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
|
|
header('Access-Control-Allow-Headers: Content-Type');
|
|
|
|
// Handle OPTIONS request for CORS
|
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
exit(0);
|
|
}
|
|
|
|
// Connect to database
|
|
$dbconn = connect_db();
|
|
|
|
// ============================================================================
|
|
// POST REQUEST HANDLING
|
|
// ============================================================================
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
|
// Handle mp4.php POST request for GIF creation
|
|
if (isset($_POST['data']) && isset($_POST['images'])) {
|
|
handle_mp4_request();
|
|
}
|
|
|
|
// Handle update_field.php POST request
|
|
if (isset($_POST['camid']) && isset($_POST['field'])) {
|
|
handle_update_field();
|
|
}
|
|
|
|
// Handle admin.php POST requests
|
|
if (isset($_POST['action'])) {
|
|
handle_admin_post();
|
|
}
|
|
|
|
// Handle stormdata.php POST requests
|
|
$input_data = json_decode(file_get_contents('php://input'), true);
|
|
if ($input_data && isset($input_data['request_type'])) {
|
|
handle_stormdata_post($input_data);
|
|
}
|
|
|
|
exit;
|
|
}
|
|
|
|
// ============================================================================
|
|
// GET REQUEST HANDLING
|
|
// ============================================================================
|
|
|
|
// Get all query parameters
|
|
$action = $_GET['action'] ?? '';
|
|
$camid = $_GET['camid'] ?? '';
|
|
$endpoint = $_GET;
|
|
|
|
// Route based on parameters
|
|
if (empty($_GET)) {
|
|
// Default behavior - could serve a basic API info
|
|
send_json([
|
|
'message' => 'NWS API Main Endpoint',
|
|
'version' => '1.0',
|
|
'endpoints' => [
|
|
'single' => '?camid={id}',
|
|
'cam' => 'Get active cameras',
|
|
'camlist' => 'Get camera list',
|
|
'power' => 'Get power outages',
|
|
'admin' => '?action={checkurl|newcam}',
|
|
// Add more endpoints as needed
|
|
]
|
|
]);
|
|
}
|
|
|
|
// ============================================================================
|
|
// SPECIFIC ENDPOINT HANDLERS
|
|
// ============================================================================
|
|
|
|
// single.php - Get single camera info
|
|
if (isset($_GET['camid']) && !isset($_GET['action'])) {
|
|
handle_single_camera();
|
|
}
|
|
|
|
// admin.php - Admin functions
|
|
if (isset($_GET['action'])) {
|
|
handle_admin_get();
|
|
}
|
|
|
|
// cam.php - Get active cameras
|
|
if (isset($_GET['cams']) || (empty($_GET) && count($_GET) === 0)) {
|
|
handle_active_cameras();
|
|
}
|
|
|
|
// camlist.php - Get camera list
|
|
if (isset($_GET['camlist'])) {
|
|
handle_camera_list();
|
|
}
|
|
|
|
// camapi.php - Camera API with various filters
|
|
if (isset($_GET['cams']) || isset($_GET['camstatic']) || isset($_GET['camdb'])) {
|
|
handle_camera_api();
|
|
}
|
|
|
|
// camcircle.php - Camera circles
|
|
if (isset($_GET['camcircle'])) {
|
|
handle_camera_circles();
|
|
}
|
|
|
|
// camobs.php - Camera observations
|
|
if (isset($_GET['camstatic'])) {
|
|
handle_camera_observations();
|
|
}
|
|
|
|
// db.php - Database queries
|
|
if (isset($_GET['outside']) || isset($_GET['outsideold'])) {
|
|
handle_db_queries();
|
|
}
|
|
|
|
// fire.php - Fire data
|
|
if (isset($_GET['fire']) || (empty($_GET) && in_array('fire.php', get_included_files()))) {
|
|
handle_fire_data();
|
|
}
|
|
|
|
// individualcam.php - Individual camera images
|
|
if (isset($_GET['camid']) && (isset($_GET['dtg']) || isset($_GET['camimages']))) {
|
|
handle_individual_camera();
|
|
}
|
|
|
|
// lsr.php - Local storm reports
|
|
if (isset($_GET['ohgo']) || isset($_GET['ohgotable']) || isset($_GET['vtec']) ||
|
|
isset($_GET['reports']) || isset($_GET['outages']) || isset($_GET['verify']) ||
|
|
isset($_GET['stats']) || isset($_GET['metars']) || isset($_GET['news']) ||
|
|
isset($_GET['news2']) || isset($_GET['news3']) || isset($_GET['newsarchive']) ||
|
|
isset($_GET['wv511']) || isset($_GET['ky511']) || isset($_GET['getCombinedTable']) ||
|
|
isset($_GET['updater'])) {
|
|
handle_lsr_requests();
|
|
}
|
|
|
|
// nws.php - NWS data
|
|
if (isset($_GET['officestats']) || isset($_GET['regionstats']) || isset($_GET['drilldown'])) {
|
|
handle_nws_data();
|
|
}
|
|
|
|
// ohgo.php - OHGO data
|
|
if (isset($_GET['ohgo']) && !isset($_GET['action'])) {
|
|
handle_ohgo_data();
|
|
}
|
|
|
|
// power.php - Power data
|
|
if (isset($_GET['power']) && !isset($_GET['action'])) {
|
|
handle_power_data();
|
|
}
|
|
|
|
// powerapi.php - Power API
|
|
if (isset($_GET['states']) || isset($_GET['max']) || isset($_GET['county']) ||
|
|
isset($_GET['countyarchive']) || isset($_GET['archivepoint']) || isset($_GET['svr']) ||
|
|
isset($_GET['svrpolys']) || isset($_GET['powerids']) || isset($_GET['poweridsgeojson']) ||
|
|
isset($_GET['polygongeojson'])) {
|
|
handle_power_api();
|
|
}
|
|
|
|
// searchapi.php - Search API
|
|
if (isset($_GET['county']) || isset($_GET['countyarchive']) || isset($_GET['archivepoint']) || isset($_GET['svr'])) {
|
|
handle_search_api();
|
|
}
|
|
|
|
// stormdata.php - Storm data (POST handled above)
|
|
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['storm'])) {
|
|
handle_stormdata_get();
|
|
}
|
|
|
|
// ver.php - Verification data
|
|
if (isset($_GET['lsrslist']) || isset($_GET['reset']) || isset($_GET['lsrs']) ||
|
|
isset($_GET['inc']) || isset($_GET['hide'])) {
|
|
handle_verification_data();
|
|
}
|
|
|
|
// warntrack.php - Warning tracking
|
|
if (isset($_GET['warntrack'])) {
|
|
handle_warning_tracking();
|
|
}
|
|
|
|
// Close database connection
|
|
pg_close($dbconn);
|
|
|
|
// ============================================================================
|
|
// FUNCTION IMPLEMENTATIONS
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Handle single camera request (from single.php)
|
|
*/
|
|
function handle_single_camera() {
|
|
global $dbconn;
|
|
|
|
$camid = $_GET['camid'];
|
|
|
|
$query = "SELECT *, COALESCE(hydro, false) as hydro, COALESCE(airport, false) as airport FROM cams WHERE camid = $1";
|
|
$result = pg_query_params($dbconn, $query, array($camid))
|
|
or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = array();
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$line['hydro'] = ($line['hydro'] === 't' || $line['hydro'] === true);
|
|
$line['airport'] = ($line['airport'] === 't' || $line['airport'] === true);
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
|
|
/**
|
|
* Handle active cameras request (from cam.php)
|
|
*/
|
|
function handle_active_cameras() {
|
|
global $dbconn;
|
|
|
|
$query = "SELECT cwa,lat,lon,lastimage,county,elevation,camid,state,description,hydro,airport FROM cams WHERE active <> false AND lastsuccess IS NOT NULL AND (EXTRACT(EPOCH FROM (current_timestamp - lastsuccess ))/60) < (interval + 20) order by elevation desc";
|
|
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = array();
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$line['hydro'] = ($line['hydro'] === 't' || $line['hydro'] === true);
|
|
$line['airport'] = ($line['airport'] === 't' || $line['airport'] === true);
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
|
|
/**
|
|
* Handle camera list request (from camlist.php)
|
|
*/
|
|
function handle_camera_list() {
|
|
global $dbconn;
|
|
|
|
$query = "SELECT url, lat, lon, elevation, county, state, active, aspect, bloomsky, source, method FROM cams where active = true";
|
|
$result = pg_query($dbconn, $query);
|
|
|
|
if (!$result) {
|
|
send_error(500, 'Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$data = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$line['lat'] = floatval($line['lat']);
|
|
$line['lon'] = floatval($line['lon']);
|
|
$line['elevation'] = floatval($line['elevation']);
|
|
$line['active'] = $line['active'] === 't' ? true : false;
|
|
$data[] = $line;
|
|
}
|
|
|
|
$response = [
|
|
'status' => 'success',
|
|
'data' => $data,
|
|
'count' => count($data)
|
|
];
|
|
|
|
pg_free_result($result);
|
|
send_json($response);
|
|
}
|
|
|
|
/**
|
|
* Handle camera API request (from camapi.php)
|
|
*/
|
|
function handle_camera_api() {
|
|
global $dbconn;
|
|
|
|
if (isset($_GET['cams'])) {
|
|
// Handle camera bounding box query
|
|
if(isset($_GET['lat1']) && isset($_GET['lon1']) && isset($_GET['lat2']) &&
|
|
isset($_GET['lon2']) && isset($_GET['elevbottom']) && isset($_GET['elevtop'])) {
|
|
|
|
$lat1 = pg_escape_string($_GET['lat1']);
|
|
$lon1 = pg_escape_string($_GET['lon1']);
|
|
$lat2 = pg_escape_string($_GET['lat2']);
|
|
$lon2 = pg_escape_string($_GET['lon2']);
|
|
$elevbottom = pg_escape_string($_GET['elevbottom']);
|
|
$elevtop = pg_escape_string($_GET['elevtop']);
|
|
|
|
$result = pg_query_params($dbconn,
|
|
"select camid,url,description from cams where method = 'rtsp' and active = true and cwa = 'RLX' and elevation > $5 and elevation < $6 and (EXTRACT(EPOCH FROM (current_timestamp - lastsuccess ))/60) < (interval + 20) and lat < $1 and lat > $2 and lon < $3 and lon > $4 order by elevation desc",
|
|
array($lat1,$lat2,$lon1,$lon2,$elevbottom,$elevtop)) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['camstatic'])) {
|
|
if(isset($_GET['lat1']) && isset($_GET['lon1']) && isset($_GET['radius'])) {
|
|
$lat1 = pg_escape_string($_GET['lat1']);
|
|
$lon1 = pg_escape_string($_GET['lon1']);
|
|
$radius = pg_escape_string($_GET['radius']);
|
|
$rad = $radius / 70;
|
|
|
|
$lat1 = floatval($lat1);
|
|
$lon1 = floatval($lon1);
|
|
$radius = floatval($rad);
|
|
$query = "select * from cams where method = 'rtsp' and active = true and cwa = 'RLX' and (EXTRACT(EPOCH FROM (current_timestamp - lastsuccess ))/60) < (interval + 20) and st_dwithin(geom, ST_SetSRID(ST_Point(" . strval($lon1) . ", " . strval($lat1) . "), 4326)," . strval($radius) . ") order by elevation desc";
|
|
|
|
$result = pg_query($dbconn,$query) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['camdb'])) {
|
|
$result = pg_query($dbconn, "SELECT COUNT(*) FROM camdb") or die('Query failed: ' . pg_last_error());
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle camera circles request (from camcircle.php)
|
|
*/
|
|
function handle_camera_circles() {
|
|
global $dbconn;
|
|
|
|
$query = "WITH subquery_points AS (
|
|
SELECT geom AS point_geometry
|
|
FROM cams
|
|
WHERE active = true and lastsuccess IS NOT NULL AND (EXTRACT(EPOCH FROM (current_timestamp - lastsuccess ))/60) < 60
|
|
)
|
|
SELECT jsonb_build_object(
|
|
'type', 'FeatureCollection',
|
|
'features', jsonb_agg(jsonb_build_object(
|
|
'type', 'Feature',
|
|
'geometry', ST_AsGeoJSON(ST_Buffer(point_geometry::geography, 8000))::jsonb
|
|
))
|
|
) AS feature_collection
|
|
FROM subquery_points";
|
|
|
|
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
if (isset($array[0]['feature_collection'])) {
|
|
echo $array[0]['feature_collection'];
|
|
} else {
|
|
send_json(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle camera observations request (from camobs.php)
|
|
*/
|
|
function handle_camera_observations() {
|
|
global $dbconn;
|
|
|
|
if($_GET['camstatic'] == 'radius') {
|
|
if(isset($_GET['lat1']) && isset($_GET['lon1']) && isset($_GET['radius'])) {
|
|
$lat1 = pg_escape_string($_GET['lat1']);
|
|
$lon1 = pg_escape_string($_GET['lon1']);
|
|
$radius = pg_escape_string($_GET['radius']);
|
|
$rad = $radius / 70;
|
|
|
|
$lat1 = floatval($lat1);
|
|
$lon1 = floatval($lon1);
|
|
$radius = floatval($rad);
|
|
$query = "select * from cams where active = true and cwa = 'RLX' and (EXTRACT(EPOCH FROM (current_timestamp - lastsuccess ))/60) < (interval + 20) and st_dwithin(geom, ST_SetSRID(ST_Point(" . strval($lon1) . ", " . strval($lat1) . "), 4326)," . strval($radius) . ") order by elevation desc";
|
|
|
|
$result = pg_query($dbconn,$query) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
}
|
|
|
|
if($_GET['camstatic'] == 'bbox') {
|
|
if(isset($_GET['lat1']) && isset($_GET['lon1']) && isset($_GET['lat2']) &&
|
|
isset($_GET['lon2']) && isset($_GET['elevbottom']) && isset($_GET['elevtop'])) {
|
|
|
|
$lat1 = pg_escape_string($_GET['lat1']);
|
|
$lon1 = pg_escape_string($_GET['lon1']);
|
|
$lat2 = pg_escape_string($_GET['lat2']);
|
|
$lon2 = pg_escape_string($_GET['lon2']);
|
|
$elevbottom = pg_escape_string($_GET['elevbottom']);
|
|
$elevtop = pg_escape_string($_GET['elevtop']);
|
|
|
|
$result = pg_query_params($dbconn,
|
|
"select * from cams where active = true and cwa = 'RLX' and elevation > $5 and elevation < $6 and (EXTRACT(EPOCH FROM (current_timestamp - lastsuccess ))/60) < (interval + 20) and lat < $1 and lat > $2 and lon < $3 and lon > $4 order by elevation desc",
|
|
array($lat1,$lat2,$lon1,$lon2,$elevbottom,$elevtop)) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle database queries (from db.php)
|
|
*/
|
|
function handle_db_queries() {
|
|
global $dbconn;
|
|
|
|
if (isset($_GET['outside'])) {
|
|
try {
|
|
$query = "
|
|
SELECT
|
|
stationid,
|
|
lat,
|
|
lon,
|
|
tempf,
|
|
dewpt,
|
|
preciptotal,
|
|
winddir,
|
|
windspd,
|
|
windgust,
|
|
elev,
|
|
adm1,
|
|
adm2,
|
|
neighborhood,
|
|
maxt,
|
|
mint,
|
|
pressure,
|
|
lastob,
|
|
county,
|
|
rain24,
|
|
rain3,
|
|
rain6,
|
|
windmax,
|
|
cwa
|
|
FROM (
|
|
SELECT DISTINCT ON (stationid) *
|
|
FROM wusites
|
|
WHERE active = TRUE
|
|
AND lastob BETWEEN timezone('utc', NOW()) - INTERVAL '0.5 hours'
|
|
AND timezone('utc', NOW())
|
|
) p
|
|
ORDER BY lastob DESC
|
|
";
|
|
|
|
$result = pg_query($dbconn, $query);
|
|
if ($result === false) {
|
|
throw new Exception('Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$results = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$results[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($results);
|
|
} catch (Exception $e) {
|
|
send_error(500, $e->getMessage());
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['outsideold'])) {
|
|
$query = "SELECT stationid, lat, lon, tempf, dewpt,preciptotal,winddir,windspd,windgust,elev,adm1,adm2,neighborhood,maxt,mint,pressure,lastob,county,rain24,rain3,rain6,windmax,cwa FROM (SELECT DISTINCT ON (stationid) * FROM wusites WHERE (active = TRUE) and lastob BETWEEN timezone('utc', now()) - INTERVAL '.5 HOURS'AND timezone('utc', now())) p ORDER BY lastob desc;";
|
|
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle fire data request (from fire.php)
|
|
*/
|
|
function handle_fire_data() {
|
|
global $dbconn;
|
|
|
|
$result = pg_query_params($dbconn,
|
|
"SELECT json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type','Feature', 'geometry', ST_AsGeoJSON(geom)::json,'properties',json_build_object('incname',incname,'discovery',discovery,'modified',modified,'age',age,'dailyacres',dailyacres,'type',type,'contained',contained,'personnel',personnel))order by modified asc)) FROM fire where type = $1 and contained <> 100 and modified > now() - interval '36 hours'",
|
|
array('WF')) or die('Query failed: ' . pg_last_error());
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
if (isset($resultArray[0]['json_build_object'])) {
|
|
echo($resultArray[0]['json_build_object']);
|
|
} else {
|
|
send_json(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle individual camera images request (from individualcam.php)
|
|
*/
|
|
function handle_individual_camera() {
|
|
global $dbconn;
|
|
|
|
$camid = pg_escape_string($_GET['camid'] ?? null);
|
|
$camimages = $_GET['camimages'] ?? 20;
|
|
|
|
if(isset($_GET['dtg'])) {
|
|
$endtime = pg_escape_string($_GET['dtg']);
|
|
$query = "SELECT camid, filepath, date_trunc('second', dateutc) as dateutc FROM camdb where camid = '{$camid}' and dateutc < '{$endtime}' order by dateutc desc limit '{$camimages}'";
|
|
} else {
|
|
$query = "SELECT camid, filepath, date_trunc('second', dateutc) as dateutc FROM camdb where camid = '{$camid}' order by dateutc desc limit '{$camimages}'";
|
|
}
|
|
|
|
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
|
|
/**
|
|
* Handle MP4/GIF creation request (from mp4.php)
|
|
*/
|
|
function handle_mp4_request() {
|
|
ini_set('display_errors', 'off');
|
|
|
|
$elements = $_POST['data'];
|
|
$numimages = $_POST['images'];
|
|
$delay = $_POST['delay'];
|
|
$lastdelay = $_POST['lastdelay'];
|
|
$maxh = $_POST['maxh'] ?? 500;
|
|
$maxv = $_POST['maxv'] ?? 400;
|
|
|
|
if (! is_numeric($maxh)) {
|
|
$maxh = 500;
|
|
}
|
|
|
|
if (! is_numeric($maxv)) {
|
|
$maxv = 400;
|
|
}
|
|
|
|
$numimages = $numimages - 1;
|
|
$inputfiles = "";
|
|
|
|
foreach ($elements as $value) {
|
|
if ($value != $elements[array_key_last($elements)]) {
|
|
$inputfiles = $inputfiles . " -delay {$delay} {$value}";
|
|
}
|
|
if ($value == $elements[array_key_last($elements)]) {
|
|
$inputfiles = $inputfiles . " -delay {$lastdelay} {$value}";
|
|
}
|
|
}
|
|
|
|
$gif = shell_exec("convert {$inputfiles} -resize {$maxh}x{$maxv}\> -layers Optimize gif:-");
|
|
echo base64_encode($gif);
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Handle update field request (from update_field.php)
|
|
*/
|
|
function handle_update_field() {
|
|
global $dbconn;
|
|
|
|
$camid = $_POST['camid'];
|
|
$field = $_POST['field'];
|
|
$value = $_POST['value'];
|
|
|
|
// Validate inputs
|
|
if (empty($camid) || empty($field)) {
|
|
send_json(['success' => false, 'message' => 'Invalid input']);
|
|
}
|
|
|
|
// Check if field is valid
|
|
if (!in_array($field, ['hydro', 'airport'])) {
|
|
send_json(['success' => false, 'message' => 'Invalid field']);
|
|
}
|
|
|
|
// Convert to proper boolean for PostgreSQL
|
|
$value_bool = ($value === 'true');
|
|
|
|
// Update field value in database
|
|
$query = "UPDATE cams SET $field = $1 WHERE camid = $2";
|
|
$result = pg_query_params($dbconn, $query, array($value_bool ? 't' : 'f', $camid));
|
|
|
|
if ($result) {
|
|
send_json(['success' => true]);
|
|
} else {
|
|
$error = pg_last_error($dbconn);
|
|
send_json(['success' => false, 'message' => $error]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle admin GET requests (from admin.php)
|
|
*/
|
|
function handle_admin_get() {
|
|
global $dbconn;
|
|
|
|
$action = $_GET['action'];
|
|
|
|
if ($action == 'checkurl') {
|
|
$url = $_POST['url'];
|
|
$query = "SELECT exists (SELECT 1 FROM cams WHERE url = '{$url}')";
|
|
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle admin POST requests (from admin.php)
|
|
*/
|
|
function handle_admin_post() {
|
|
global $dbconn;
|
|
|
|
$action = $_POST['action'];
|
|
|
|
if ($action == 'checkurl') {
|
|
$url = $_POST['url'];
|
|
$query = "SELECT exists (SELECT 1 FROM cams WHERE url = '{$url}')";
|
|
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
|
|
if ($action == 'newcam') {
|
|
$url = $_POST['url'];
|
|
$lat = $_POST['lat'];
|
|
$lon = $_POST['lon'];
|
|
$desc = $_POST['description'];
|
|
$method = $_POST['method'];
|
|
$permission = $_POST['permission'];
|
|
$owner = $_POST['owner'];
|
|
$email = $_POST['email'];
|
|
|
|
$query = "INSERT into cams (url,lat,lon,description,interval,method,active,permission,owner,email,keephours) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)";
|
|
$result = pg_query_params($query, Array($url,$lat,$lon,$desc,'10',$method,'t',$permission,$owner,$email,'240')) or die('Query failed: ' . pg_last_error());
|
|
|
|
$status = pg_result_status($result);
|
|
pg_free_result($result);
|
|
|
|
shell_exec('python3 /var/www/html/work/runallgeom.py');
|
|
|
|
send_json($status);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle LSR requests (from lsr.php) - simplified version
|
|
*/
|
|
function handle_lsr_requests() {
|
|
global $dbconn;
|
|
|
|
// Handle OHGO GeoJSON
|
|
if (isset($_GET['ohgo'])) {
|
|
$query = "SELECT jsonb_build_object(
|
|
'type', 'FeatureCollection',
|
|
'features', jsonb_agg(
|
|
jsonb_build_object(
|
|
'type', 'Feature',
|
|
'geometry', ST_AsGeoJSON(geom)::jsonb,
|
|
'properties', jsonb_build_object(
|
|
'lat', lat,
|
|
'lon', lon,
|
|
'description', description,
|
|
'roadstatus', roadstatus,
|
|
'start', start,
|
|
'lastupdate', lastupdate
|
|
)
|
|
)
|
|
)
|
|
) as geojson
|
|
FROM public.ohgo
|
|
WHERE endtime IS NULL
|
|
AND lastupdate > NOW() - INTERVAL '2 hours'";
|
|
|
|
$result = pg_query($dbconn);
|
|
if (!$result) {
|
|
send_error(500, 'Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
if ($resultArray && isset($resultArray[0]['geojson'])) {
|
|
echo $resultArray[0]['geojson'];
|
|
} else {
|
|
send_json(['error' => 'No results found']);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
exit;
|
|
}
|
|
|
|
// Handle OHGO table
|
|
if (isset($_GET['ohgotable'])) {
|
|
$query = "SELECT CASE WHEN COALESCE(lsr, FALSE) THEN 'true' ELSE 'false' END AS lsr,
|
|
CASE WHEN COALESCE(hide, FALSE) THEN 'true' ELSE 'false' END AS hide,
|
|
ROUND(ST_Y(geom)::numeric, 3) AS lat,
|
|
ROUND(ST_X(geom)::numeric, 3) AS lon,
|
|
id, category, roadstatus, cwa, county, state, location, routename,
|
|
description,
|
|
TO_CHAR(start, 'YYYY-MM-DD HH24:MI') AS start,
|
|
TO_CHAR(endtime, 'YYYY-MM-DD HH24:MI') AS endtime,
|
|
TO_CHAR(lastupdate, 'YYYY-MM-DD HH24:MI') AS lastupdate
|
|
FROM ohgo
|
|
WHERE (endtime IS NULL OR endtime > NOW() - INTERVAL '48 hours') and start > now() - interval '144 hours'
|
|
ORDER BY start ASC";
|
|
|
|
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
|
|
// Handle VTEC query
|
|
if (isset($_GET['vtec'])) {
|
|
$vtec = $_GET['vtec'];
|
|
|
|
$query = "
|
|
SELECT json_build_object(
|
|
'type', 'FeatureCollection',
|
|
'features', json_agg(
|
|
json_build_object(
|
|
'type', 'Feature',
|
|
'geometry', ST_AsGeoJSON(nwspoly)::json,
|
|
'properties', json_build_object(
|
|
'id', warnindex,
|
|
'issue', issue,
|
|
'endtime', endtime,
|
|
'warntype', warntype,
|
|
'issue', issue,
|
|
'outagesvalid', outagesvalid,
|
|
'outagesbuffer', outagesbuffer,
|
|
'polygonpop', polygonpop,
|
|
'lat', st_y(st_centroid(nwspoly)),
|
|
'lon', st_x(st_centroid(nwspoly)),
|
|
'vtec', vtec
|
|
)
|
|
)
|
|
)
|
|
)
|
|
FROM svr
|
|
WHERE vtec = $1;
|
|
";
|
|
|
|
$result = pg_query_params($dbconn, $query, array($vtec))
|
|
or die('Query failed: ' . pg_last_error());
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
if (isset($resultArray[0]['json_build_object'])) {
|
|
echo($resultArray[0]['json_build_object']);
|
|
} else {
|
|
send_json(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
exit;
|
|
}
|
|
|
|
// Handle reports query
|
|
if (isset($_GET['reports'])) {
|
|
$vtec = $_GET['reports'];
|
|
$hours = $_GET['hours'] ?? 6;
|
|
|
|
$query = "SELECT * from reports,svr where ST_Contains(svr.nwspoly, reports.geom) and vtec = $1 and reports.initialdtg AT TIME ZONE 'America/New_York' > svr.issue AND reports.initialdtg AT TIME ZONE 'America/New_York' < svr.issue + (INTERVAL '1 h' * $2)";
|
|
$result = pg_query_params($dbconn, $query, array($vtec,$hours)) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
|
|
// Handle current reports (no GET parameters)
|
|
if (empty($_GET) || (count($_GET) === 1 && isset($_GET['reports']))) {
|
|
$result = pg_query_params($dbconn,
|
|
"SELECT json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type','Feature', 'geometry', ST_AsGeoJSON(geom)::json,'properties',json_build_object('id',id,'time',initialdtg,'county',county,'state',state,'issue',issue,'rawemail',rawemail,'place',place,'comments',comments)) order by initialdtg desc)) FROM reports where initialdtg > $1 ",
|
|
array('2024-06-07')) or die('Query failed: ' . pg_last_error());
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
if (isset($resultArray[0]['json_build_object'])) {
|
|
echo($resultArray[0]['json_build_object']);
|
|
} else {
|
|
send_json(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle NWS data requests (from nws.php) - simplified version
|
|
*/
|
|
function handle_nws_data() {
|
|
global $dbconn;
|
|
|
|
if (isset($_GET['officestats'])) {
|
|
$query = "SELECT * FROM nws order by lastupdate asc";
|
|
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle OHGO data request (from ohgo.php)
|
|
*/
|
|
function handle_ohgo_data() {
|
|
global $dbconn;
|
|
|
|
$query = "SELECT lat,lon,id,category,roadstatus,cwa,county,state,location,routename,description,lsr,date_trunc('minute', start) as start, date_trunc('minute', endtime) as endtime,date_trunc('minute', lastupdate) as lastupdate from ohgo where endtime is null or endtime > now() - interval '48 hours' order by start asc;";
|
|
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
|
|
/**
|
|
* Handle power data request (from power.php)
|
|
*/
|
|
function handle_power_data() {
|
|
global $dbconn;
|
|
|
|
$query = "SELECT lat,lon,outagen FROM power WHERE active = true and cwa = 'RLX'";
|
|
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
|
|
/**
|
|
* Handle power API requests (from powerapi.php) - simplified version
|
|
*/
|
|
function handle_power_api() {
|
|
global $dbconn;
|
|
|
|
// Handle default power outage request
|
|
if (empty($_GET) || (count($_GET) === 1 && isset($_GET['power']))) {
|
|
$query = "
|
|
SELECT json_build_object(
|
|
'type', 'FeatureCollection',
|
|
'features', json_agg(
|
|
json_build_object(
|
|
'type', 'Feature',
|
|
'geometry', ST_AsGeoJSON(realgeom)::json,
|
|
'properties', json_build_object(
|
|
'time', startguess,
|
|
'county', county,
|
|
'state', state,
|
|
'outage', outagen,
|
|
'lastchange', lastchange,
|
|
'cause', cause,
|
|
'area_geometry', ST_AsGeoJSON(COALESCE(realareageom, realgeom))::json
|
|
)
|
|
)
|
|
ORDER BY startguess ASC
|
|
)
|
|
)
|
|
FROM power
|
|
WHERE cwa = $1 AND active = true
|
|
";
|
|
|
|
$result = pg_query_params($dbconn, $query, array('RLX'));
|
|
if ($result === false) {
|
|
send_error(500, 'Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
if ($resultArray && isset($resultArray[0]['json_build_object'])) {
|
|
echo $resultArray[0]['json_build_object'];
|
|
} else {
|
|
send_json(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
exit;
|
|
}
|
|
|
|
// Handle states request
|
|
if (isset($_GET['states'])) {
|
|
$query = "
|
|
SELECT jsonb_build_object(
|
|
'type', 'FeatureCollection',
|
|
'features', jsonb_agg(features.feature)
|
|
)
|
|
FROM (
|
|
SELECT jsonb_build_object(
|
|
'type', 'Feature',
|
|
'geometry', ST_AsGeoJSON(ST_Transform(geom, 4326))::jsonb,
|
|
'properties', to_jsonb(properties) - 'geom'
|
|
) AS feature
|
|
FROM (
|
|
SELECT *
|
|
FROM states
|
|
WHERE state IN ('WV', 'VA', 'KY', 'MD', 'PA', 'OH')
|
|
) AS properties
|
|
) AS features
|
|
";
|
|
|
|
$result = pg_query($dbconn);
|
|
if ($result === false) {
|
|
send_error(500, 'Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
if ($resultArray && isset($resultArray[0]['jsonb_build_object'])) {
|
|
echo $resultArray[0]['jsonb_build_object'];
|
|
} else {
|
|
send_json(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
exit;
|
|
}
|
|
|
|
// Handle county request
|
|
if (isset($_GET['county'])) {
|
|
$query = "
|
|
SELECT DISTINCT ON (county, state)
|
|
county,
|
|
state,
|
|
SUM(outages) as outage,
|
|
update as time,
|
|
SUM(served) as served,
|
|
ROUND(CAST((SUM(outages)::FLOAT / SUM(served)) * 100 AS NUMERIC), 2) as perout
|
|
FROM countyoutages
|
|
WHERE update = (SELECT MAX(update) FROM countyoutages)
|
|
AND cwa = $1
|
|
GROUP BY county, state, update
|
|
";
|
|
|
|
$result = pg_query_params($dbconn, $query, ['RLX']);
|
|
if ($result === false) {
|
|
send_error(500, 'Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$results = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$results[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($results);
|
|
}
|
|
|
|
// Handle current SVR warnings
|
|
if (isset($_GET['svr']) && $_GET['svr'] == 'current') {
|
|
$result = pg_query($dbconn,
|
|
"SELECT json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type','Feature', 'geometry', ST_AsGeoJSON(nwspoly)::json,'properties',json_build_object('issue',issue,'end',endtime,'vtec',vtec,'type',warntype)))) FROM svr where issue < now() and endtime > now()") or die('Query failed: ' . pg_last_error());
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
if (isset($resultArray[0]['json_build_object'])) {
|
|
echo($resultArray[0]['json_build_object']);
|
|
} else {
|
|
send_json(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle search API requests (from searchapi.php)
|
|
*/
|
|
function handle_search_api() {
|
|
global $dbconn;
|
|
|
|
// Handle county current
|
|
if(isset($_GET['county'])) {
|
|
$result = pg_query_params($dbconn,
|
|
"SELECT distinct on (county,state) update as time, county, state, outages as outage,served FROM countyoutages where cwa = $1 order by county,state,update desc",
|
|
array('RLX')) or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
|
|
// Handle SVR current
|
|
if(isset($_GET['svr']) && $_GET['svr'] == 'current') {
|
|
$result = pg_query($dbconn,
|
|
"SELECT json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type','Feature', 'geometry', ST_AsGeoJSON(nwspoly)::json,'properties',json_build_object('issue',issue,'end',endtime,'vtec',vtec,'type',warntype)))) FROM svr where issue < now() and endtime > now()") or die('Query failed: ' . pg_last_error());
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
if (isset($resultArray[0]['json_build_object'])) {
|
|
echo($resultArray[0]['json_build_object']);
|
|
} else {
|
|
send_json(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle storm data POST requests (from stormdata.php)
|
|
*/
|
|
function handle_stormdata_post($input_data) {
|
|
global $dbconn;
|
|
|
|
$request_type = $input_data['request_type'];
|
|
|
|
switch ($request_type) {
|
|
case 'ohgo':
|
|
handle_ohgo_request($dbconn, $input_data);
|
|
break;
|
|
case 'ohgonopoly':
|
|
handle_ohgo_request_no_poly($dbconn, $input_data);
|
|
break;
|
|
case 'power':
|
|
handle_power_request($dbconn, $input_data);
|
|
break;
|
|
case 'powernopoly':
|
|
handle_power_request_no_poly($dbconn, $input_data);
|
|
break;
|
|
case 'wupoly':
|
|
handle_wu_request_poly($dbconn, $input_data);
|
|
break;
|
|
case 'campoly':
|
|
handle_cam_request($dbconn, $input_data);
|
|
break;
|
|
default:
|
|
send_error(400, 'Invalid request_type specified: ' . htmlspecialchars($request_type));
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle verification data requests (from ver.php)
|
|
*/
|
|
function handle_verification_data() {
|
|
global $dbconn;
|
|
|
|
// Handle default request
|
|
if (empty($_GET) || (count($_GET) === 1 && isset($_GET['ver']))) {
|
|
$result = pg_query($dbconn,
|
|
"SELECT jsonb_build_object('type', 'FeatureCollection','features', jsonb_agg(features.feature)) FROM (SELECT jsonb_build_object('type', 'Feature','geometry', ST_AsGeoJSON(ST_Transform(geom, 4326))::jsonb,'properties', to_jsonb(properties) - 'geom') AS feature FROM (SELECT *FROM pzone where cwa ='RLX') AS properties) AS features") or die('Query failed: ' . pg_last_error());
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
if (isset($resultArray[0]['jsonb_build_object'])) {
|
|
echo($resultArray[0]['jsonb_build_object']);
|
|
} else {
|
|
send_json(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
exit;
|
|
}
|
|
|
|
// Handle lsrslist
|
|
if (isset($_GET['lsrslist'])) {
|
|
$result = pg_query($dbconn,"SELECT * from simplever") or die('Query failed: ' . pg_last_error());
|
|
|
|
$array = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$array[] = $line;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($array);
|
|
}
|
|
|
|
// Handle reset
|
|
if (isset($_GET['reset'])) {
|
|
$result = pg_query($dbconn,"truncate simplever") or die('Query failed: ' . pg_last_error());
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
send_json($resultArray);
|
|
}
|
|
|
|
// Handle lsrs
|
|
if (isset($_GET['lsrs'])) {
|
|
if (isset($_GET['zone'])) {
|
|
$zone = $_GET['zone'];
|
|
$lsr = isset($_GET['lsr']) ? (int) $_GET['lsr'] : 1;
|
|
$dir = $_GET['dir'] ?? 1;
|
|
|
|
if ($dir == 1) {
|
|
$result = pg_query_params($dbconn,"INSERT into simplever (zone,lsr) values ($1,$2) on conflict (zone) do update set lsr = (simplever.lsr + 1) where simplever.zone = $1", array($zone,$lsr)) or die('Query failed: ' . pg_last_error());
|
|
} else {
|
|
$result = pg_query_params($dbconn,"INSERT into simplever (zone,lsr) values ($1,$2) on conflict (zone) do update set lsr = 0 where simplever.zone = $1", array($zone,$lsr)) or die('Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
send_json($resultArray);
|
|
}
|
|
}
|
|
|
|
// Handle inc/hide
|
|
if (isset($_GET['inc']) || isset($_GET['hide'])) {
|
|
$field = isset($_GET['inc']) ? 'inc' : 'hide';
|
|
$value = $_GET[$field] ?? 'false';
|
|
$hideflag = ($value == 'true') ? 'true' : 'false';
|
|
$id = (int) $_GET['id'];
|
|
$query = "UPDATE reports SET $field = $1 WHERE id = $2";
|
|
$result = pg_query_params($dbconn, $query, array($hideflag, $id)) or die('Query failed: ' . pg_last_error());
|
|
|
|
pg_free_result($result);
|
|
send_json(['success' => true]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle warning tracking requests (from warntrack.php)
|
|
*/
|
|
function handle_warning_tracking() {
|
|
global $dbconn;
|
|
|
|
$result = pg_query($dbconn,
|
|
"SELECT json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type','Feature', 'geometry', ST_AsGeoJSON(nwspoly)::json,'properties',json_build_object('issue',issue,'endtime',endtime,'warntype',warntype,'etin',etin,'followups',followups,'followup',followup,'canexp',canexp,'warnexpired',warnexpired,'vtectext',vtectext,'office',office))order by issue desc)) FROM warntracker WHERE office = 'KRLX' and svstype = 'NEW' and EXTRACT(EPOCH FROM (current_timestamp - endtime ))/60 < 2400") or die('Query failed: ' . pg_last_error());
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
if (isset($resultArray[0]['json_build_object'])) {
|
|
echo($resultArray[0]['json_build_object']);
|
|
} else {
|
|
send_json(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
}
|
|
|
|
// ============================================================================
|
|
// STORMDATA HELPER FUNCTIONS (from stormdata.php)
|
|
// ============================================================================
|
|
|
|
function handle_ohgo_request($dbconn, array $data): void {
|
|
$start = $data['start_time'] ?? null;
|
|
$geojson_str = $data['area_geojson'] ?? null;
|
|
$end = $data['end_time'] ?? null;
|
|
|
|
if ($start === null || $geojson_str === null || $end === null) {
|
|
send_error(400, 'Missing required parameters for ohgo request: start, geojson, end');
|
|
}
|
|
|
|
$geojson_obj = json_decode($geojson_str);
|
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
send_error(400, 'Invalid GeoJSON provided: Not valid JSON.');
|
|
}
|
|
|
|
if (!isset($geojson_obj->type) || !in_array($geojson_obj->type, ['Polygon', 'MultiPolygon'])) {
|
|
send_error(400, 'Invalid GeoJSON provided: Type must be Polygon or MultiPolygon.');
|
|
}
|
|
|
|
$query = "SELECT ST_AsGeoJSON(geom) AS geometry, category, roadstatus, county, state, location, routename, description, start AS start_timestamp, endtime AS end_timestamp, lastupdate FROM ohgo WHERE start > $1::timestamp AND start < $3::timestamp AND ST_Within(geom, ST_GeomFromGeoJSON($2)) ORDER BY start ASC";
|
|
$params = array($start, $geojson_str, $end);
|
|
$result = pg_query_params($dbconn, $query, $params);
|
|
if (!$result) {
|
|
send_error(500, 'Database query failed for ohgo data.');
|
|
}
|
|
|
|
$features = [];
|
|
while ($line = pg_fetch_assoc($result)) {
|
|
$geometry = json_decode($line['geometry']);
|
|
if (json_last_error() !== JSON_ERROR_NONE) { continue; }
|
|
$properties = $line; unset($properties['geometry']);
|
|
$features[] = ['type' => 'Feature', 'geometry' => $geometry, 'properties' => $properties];
|
|
}
|
|
pg_free_result($result);
|
|
|
|
send_geojson($features);
|
|
}
|
|
|
|
function handle_ohgo_request_no_poly($dbconn, array $data): void {
|
|
$start = $data['start_time'] ?? null;
|
|
$end = $data['end_time'] ?? null;
|
|
|
|
if ($start === null || $end === null) {
|
|
send_error(400, 'Missing required parameters for ohgo request: start, end');
|
|
}
|
|
|
|
$query = "SELECT ST_AsGeoJSON(geom) AS geometry, county, state AS st, location, routename AS city, upper(cwa) AS wfo, 'FLOOD' AS typetext, 'Department of Highways' AS source, description AS remark,
|
|
TO_CHAR(start, 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') AS valid
|
|
FROM ohgo
|
|
WHERE start > $1::timestamp
|
|
AND start < $2::timestamp
|
|
AND cwa = 'RLX'
|
|
ORDER BY start ASC";
|
|
$params = array($start, $end);
|
|
$result = pg_query_params($dbconn, $query, $params);
|
|
if (!$result) {
|
|
send_error(500, 'Database query failed for ohgo data.');
|
|
}
|
|
|
|
$features = [];
|
|
while ($line = pg_fetch_assoc($result)) {
|
|
$geometry = json_decode($line['geometry']);
|
|
if (json_last_error() !== JSON_ERROR_NONE) { continue; }
|
|
$properties = $line; unset($properties['geometry']);
|
|
$features[] = ['type' => 'Feature', 'geometry' => $geometry, 'properties' => $properties];
|
|
}
|
|
pg_free_result($result);
|
|
|
|
send_geojson($features);
|
|
}
|
|
|
|
function handle_power_request($dbconn, array $data): void {
|
|
$start = $data['start_time'] ?? null;
|
|
$geojson_str = $data['area_geojson'] ?? null;
|
|
$end = $data['end_time'] ?? null;
|
|
$buffer_hours = $data['buffer'] ?? 0;
|
|
|
|
if ($start === null || $geojson_str === null || $end === null || $buffer_hours === null) {
|
|
send_error(400, 'Missing required parameters for power request: start_time, area_geojson, end_time, buffer_hours');
|
|
}
|
|
|
|
if (!is_numeric($buffer_hours) || ($buffer_hours_float = floatval($buffer_hours)) < 0) {
|
|
send_error(400, 'Invalid buffer_hours provided: Must be a non-negative number.');
|
|
}
|
|
|
|
$buffer_hours_int = (int)$buffer_hours_float;
|
|
$geojson_obj = json_decode($geojson_str);
|
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
send_error(400, 'Invalid area_geojson provided: Contains invalid JSON string.');
|
|
}
|
|
|
|
if (!is_object($geojson_obj) || !isset($geojson_obj->type) || !in_array($geojson_obj->type, ['Polygon', 'MultiPolygon'])) {
|
|
send_error(400, 'Invalid area_geojson provided: Decoded JSON must be a Polygon or MultiPolygon object.');
|
|
}
|
|
|
|
$query = "SELECT ST_AsGeoJSON(realgeom) AS geometry, derivedstart AS start_timestamp, cause, peakoutage, lastchange AS end_timestamp FROM power WHERE derivedstart >= $1::timestamp AND derivedstart < ($3::timestamp + make_interval(hours => $4::integer)) AND ST_Within(realgeom, ST_GeomFromGeoJSON($2)) ORDER BY derivedstart ASC";
|
|
$params = array(
|
|
$start,
|
|
$geojson_str,
|
|
$end,
|
|
$buffer_hours_int
|
|
);
|
|
$result = pg_query_params($dbconn, $query, $params);
|
|
if (!$result) {
|
|
send_error(500, 'Database query failed for power data.');
|
|
}
|
|
|
|
$features = [];
|
|
while ($line = pg_fetch_assoc($result)) {
|
|
$geometry = json_decode($line['geometry']);
|
|
if (json_last_error() !== JSON_ERROR_NONE) { continue; }
|
|
$properties = $line; unset($properties['geometry']);
|
|
$features[] = ['type' => 'Feature', 'geometry' => $geometry, 'properties' => $properties];
|
|
}
|
|
pg_free_result($result);
|
|
|
|
send_geojson($features);
|
|
}
|
|
|
|
function handle_power_request_no_poly($dbconn, array $data): void {
|
|
$start = $data['start_time'] ?? null;
|
|
$end = $data['end_time'] ?? null;
|
|
$outage_threshold = $data['outage_threshold'] ?? 9;
|
|
$buffer_hours = $data['buffer'] ?? 0;
|
|
|
|
if ($start === null || $end === null || $buffer_hours === null) {
|
|
send_error(400, 'Missing required parameters for power request: start_time, end_time, buffer_hours');
|
|
}
|
|
|
|
if (!is_numeric($buffer_hours) || ($buffer_hours_float = floatval($buffer_hours)) < 0) {
|
|
send_error(400, 'Invalid buffer_hours provided: Must be a non-negative number.');
|
|
}
|
|
|
|
$buffer_hours_int = (int)$buffer_hours_float;
|
|
$outage_thresh = (float)$outage_threshold;
|
|
|
|
$query = "SELECT ST_AsGeoJSON(realgeom) AS geometry,
|
|
TO_CHAR(derivedstart, 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') AS valid,
|
|
('Power Outage affecting ' || peakoutage || ' customers caused by ' || COALESCE(cause, 'unknown')) AS remark,
|
|
'Utility Company' as source,
|
|
'POWER OUTAGE' as typetext,
|
|
'U' as type,
|
|
(ROUND(ST_Y(realgeom)::numeric, 3) || ', ' || ROUND(ST_X(realgeom)::numeric, 3)) AS city,
|
|
county as county,
|
|
state as state,
|
|
state as st
|
|
FROM power
|
|
WHERE derivedstart >= $1::timestamp
|
|
AND derivedstart < ($2::timestamp + make_interval(hours => $3::integer))
|
|
and peakoutage > $4
|
|
AND ST_Within(realgeom, (SELECT geom FROM public.cwa WHERE cwa = 'RLX'))
|
|
ORDER BY derivedstart ASC";
|
|
|
|
$params = array(
|
|
$start,
|
|
$end,
|
|
$buffer_hours_int,
|
|
$outage_thresh
|
|
);
|
|
$result = pg_query_params($dbconn, $query, $params);
|
|
if (!$result) {
|
|
send_error(500, 'Database query failed for power data.');
|
|
}
|
|
|
|
$features = [];
|
|
while ($line = pg_fetch_assoc($result)) {
|
|
$geometry = json_decode($line['geometry']);
|
|
if (json_last_error() !== JSON_ERROR_NONE) { continue; }
|
|
$properties = $line; unset($properties['geometry']);
|
|
$features[] = ['type' => 'Feature', 'geometry' => $geometry, 'properties' => $properties];
|
|
}
|
|
pg_free_result($result);
|
|
|
|
send_geojson($features);
|
|
}
|
|
|
|
function handle_wu_request_poly($dbconn, array $data): void {
|
|
$polygons = $data['polygons'] ?? [];
|
|
$start_time = $data['start_time'] ?? '2025-01-01 00:00:00';
|
|
$end_time = $data['end_time'] ?? '2025-01-02 00:00:00';
|
|
|
|
if (empty($polygons)) {
|
|
send_error(500, 'No polygons provided');
|
|
}
|
|
|
|
$polygon_placeholders = [];
|
|
$params = [];
|
|
$param_index = 1;
|
|
|
|
foreach ($polygons as $polygon) {
|
|
$polygon_placeholders[] = "ST_GeomFromText(\$$param_index, 4326)";
|
|
$params[] = $polygon;
|
|
$param_index++;
|
|
}
|
|
|
|
$params[] = $start_time;
|
|
$params[] = $end_time;
|
|
$start_time_placeholder = "\$$param_index";
|
|
$param_index++;
|
|
$end_time_placeholder = "\$$param_index";
|
|
|
|
$polygon_sql = implode(', ', $polygon_placeholders);
|
|
|
|
$sql = "
|
|
SELECT wo.*
|
|
FROM wuobs wo
|
|
JOIN wusites ws ON wo.stationid = ws.stationid
|
|
WHERE ws.geom && ST_Union(ARRAY[$polygon_sql])::geometry
|
|
AND ST_Within(ws.geom, ST_Union(ARRAY[$polygon_sql])::geometry)
|
|
AND wo.observation_time BETWEEN $start_time_placeholder AND $end_time_placeholder
|
|
";
|
|
|
|
$result = pg_query_params($dbconn, $sql, $params);
|
|
|
|
if ($result === false) {
|
|
send_error(500, pg_last_error($dbconn));
|
|
}
|
|
|
|
$results = [];
|
|
while ($row = pg_fetch_assoc($result)) {
|
|
$results[] = $row;
|
|
}
|
|
|
|
pg_free_result($result);
|
|
send_json($results);
|
|
}
|
|
|
|
function handle_cam_request($dbconn, array $data): void {
|
|
$start_time_str = $data['start_time'] ?? null;
|
|
$end_time_str = $data['end_time'] ?? null;
|
|
$geojson_str = $data['area_geojson'] ?? null;
|
|
|
|
if ($start_time_str === null || $end_time_str === null || $geojson_str === null) {
|
|
send_error(400, 'Missing required parameters for camera request: start_time, end_time, area_geojson');
|
|
}
|
|
|
|
if (strtotime($start_time_str) === false) {
|
|
send_error(400, 'Invalid start_time format.');
|
|
}
|
|
|
|
if (strtotime($end_time_str) === false) {
|
|
send_error(400, 'Invalid end_time format.');
|
|
}
|
|
|
|
$geojson_obj = json_decode($geojson_str);
|
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
send_error(400, 'Invalid area_geojson provided: Contains invalid JSON string.');
|
|
}
|
|
|
|
if (!is_object($geojson_obj) || !isset($geojson_obj->type) || !in_array($geojson_obj->type, ['Polygon', 'MultiPolygon'])) {
|
|
send_error(400, 'Invalid area_geojson provided: Decoded JSON must be a Polygon or MultiPolygon object.');
|
|
}
|
|
|
|
$query = "
|
|
SELECT
|
|
c.*,
|
|
ST_AsGeoJSON(c.geom) as geometry_geojson,
|
|
COALESCE(img_agg.images, '[]'::jsonb) AS images
|
|
FROM
|
|
cams c
|
|
LEFT JOIN (
|
|
SELECT
|
|
camid,
|
|
jsonb_agg(
|
|
jsonb_build_object(
|
|
'timestamp', dateutc,
|
|
'url', filepath
|
|
) ORDER BY dateutc ASC
|
|
) AS images
|
|
FROM
|
|
camdb
|
|
WHERE
|
|
dateutc >= $1::timestamp
|
|
AND dateutc <= $2::timestamp
|
|
GROUP BY
|
|
camid
|
|
) AS img_agg ON c.camid = img_agg.camid
|
|
WHERE
|
|
c.active = TRUE
|
|
AND ST_Within(c.geom, ST_GeomFromGeoJSON($3))
|
|
ORDER BY
|
|
c.camid;
|
|
";
|
|
|
|
$params = array(
|
|
$start_time_str,
|
|
$end_time_str,
|
|
$geojson_str
|
|
);
|
|
|
|
$result = pg_query_params($dbconn, $query, $params);
|
|
|
|
if (!$result) {
|
|
send_error(500, 'Database query failed for camera data.');
|
|
}
|
|
|
|
$cameras_output = [];
|
|
while ($row = pg_fetch_assoc($result)) {
|
|
$geometry = json_decode($row['geometry_geojson']);
|
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
$geometry = null;
|
|
}
|
|
|
|
$images = json_decode($row['images']);
|
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
$images = [];
|
|
}
|
|
|
|
$camera_data = $row;
|
|
unset($camera_data['geometry_geojson']);
|
|
unset($camera_data['geom']);
|
|
$camera_data['geometry'] = $geometry;
|
|
$camera_data['images'] = $images;
|
|
|
|
$cameras_output[] = $camera_data;
|
|
}
|
|
pg_free_result($result);
|
|
|
|
header('Content-Type: application/json');
|
|
echo json_encode($cameras_output, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
|
exit;
|
|
}
|
|
|
|
?>
|