diff --git a/API_DOCUMENTATION.md b/API_DOCUMENTATION.md index bb98e35..4652346 100644 --- a/API_DOCUMENTATION.md +++ b/API_DOCUMENTATION.md @@ -221,7 +221,44 @@ main.php?service={service_name}[¶meters] - Old: `update_field.php` - New: `main.php?service=update_field` (POST request) -### 19. mp4 +### 19. camobs +**Description**: Returns camera observations with radius and bbox filtering +**Usage**: `main.php?service=camobs[&camstatic={radius|bbox}&lat1={lat}&lon1={lon}&radius={radius}&lat2={lat}&lon2={lon}&elevbottom={elev}&elevtop={elev}]` +**Parameters**: +- `camstatic=radius` - Get cameras within radius (requires `lat1`, `lon1`, `radius`) +- `camstatic=bbox` - Get cameras within bounding box (requires `lat1`, `lon1`, `lat2`, `lon2`, `elevbottom`, `elevtop`) +**Migration**: +- Old: `camobs.php?camstatic=radius&lat1=...&lon1=...&radius=...` +- New: `main.php?service=camobs&camstatic=radius&lat1=...&lon1=...&radius=...` + +### 20. single +**Description**: Returns single camera information by camid +**Usage**: `main.php?service=single&camid={camid}` +**Parameters**: +- `camid` - Camera ID (required) +**Migration**: +- Old: `single.php?camid=...` +- New: `main.php?service=single&camid=...` + +### 21. powerapitest +**Description**: Returns extended power outage testing data +**Usage**: `main.php?service=powerapitest[&{various parameters}]` +**Parameters**: +- No parameters - Get current power outages +- `max` - Get max outages (requires `start` and `end`) +- `county` - Get county data +- `countyarchive` - Get archived county data (requires `start` and `end`) +- `archivepoint` - Get archived point data (requires `start` and `end`) +- `svr` - Get severe weather reports +- `svr=current` - Get current severe weather +- `svr=archive` - Get archived severe weather (optional `start` and `end`) +**Migration**: +- Old: `powerapitest.php` +- New: `main.php?service=powerapitest` +- Old: `powerapitest.php?max&start=...&end=...` +- New: `main.php?service=powerapitest&max&start=...&end=...` + +### 22. mp4 **Description**: Generates MP4/gif from images (POST only) **Usage**: POST to `main.php?service=mp4` **Parameters** (in POST body): diff --git a/camobs.html b/camobs.html index 4819b43..09dd720 100644 --- a/camobs.html +++ b/camobs.html @@ -69,11 +69,11 @@ var elevbottom = getUrlVars()["elevbottom"]; var elevtop = getUrlVars()["elevtop"]; if (querytype == "bbox") { -var camurl = "camobs.php?camstatic=bbox&lat1=" + lat1 + "&lon1=" + lon1 + "&lat2=" + lat2 + "&lon2=" + lon2 + "&elevbottom=" + elevbottom + "&elevtop=" + elevtop; +var camurl = "main.php?service=camobs&camstatic=bbox&lat1=" + lat1 + "&lon1=" + lon1 + "&lat2=" + lat2 + "&lon2=" + lon2 + "&elevbottom=" + elevbottom + "&elevtop=" + elevtop; } if (querytype == "radius") { -var camurl = "camobs.php?camstatic=radius&lat1=" + lat1 + "&lon1=" + lon1 + "&radius=" + radius; +var camurl = "main.php?service=camobs&camstatic=radius&lat1=" + lat1 + "&lon1=" + lon1 + "&radius=" + radius; } console.log(camurl); diff --git a/camobs.php b/camobs.php deleted file mode 100644 index f7a4769..0000000 --- a/camobs.php +++ /dev/null @@ -1,88 +0,0 @@ - %s and lat < %s and lon > %s and lon < %s order by lastsuccess desc limit 25 - - -//no gets, curent point outage info - -//error_reporting(-1); // reports all errors -//ini_set("display_errors", "1"); // shows all errors -//ini_set("log_errors", 1); -//ini_set("error_log", "php-error.log"); - - - - - -if($_GET['camstatic']) { -if ($_GET['camstatic'] == 'radius') { - - -if($_GET['lat1']) { -$lat1 = pg_escape_string($_GET['lat1']); -if($_GET['lon1']) { -$lon1 = pg_escape_string($_GET['lon1']); -if($_GET['radius']) { -$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()); - -while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) { - $array[] = $line; -} -echo json_encode($array); -pg_free_result($result); -pg_close($dbconn); -}}}}} - -if($_GET['camstatic']) { -if ($_GET['camstatic'] == 'bbox') { -if($_GET['lat1']) { -$lat1 = pg_escape_string($_GET['lat1']); -if($_GET['lon1']) { -$lon1 = pg_escape_string($_GET['lon1']); -if($_GET['lat2']) { -$lat2 = pg_escape_string($_GET['lat2']); -if($_GET['lon2']) { -$lon2 = pg_escape_string($_GET['lon2']); -if($_GET['elevbottom']) { -$elevbottom = pg_escape_string($_GET['elevbottom']); -if($_GET['elevtop']) { -$elevtop = pg_escape_string($_GET['elevtop']); - -//$lat1 = floatval($lat1); -//$lon1 = floatval($lon1); -//$lat2 = floatval($lat2); -//$lon2 = floatval($lon2); -//$elevbottom = floatval($elevbottom); -//$elevtop = floatval($elevtop); -//echo($lat1,$lat2,$lon1,$lon2,$elevbottom,$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()); -while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) { - $array[] = $line; -} -echo json_encode($array); -pg_free_result($result); -pg_close($dbconn); -}}}}}}}} - - - - - - - - -?> diff --git a/main.php b/main.php index ee6cb4b..3beea14 100644 --- a/main.php +++ b/main.php @@ -25,76 +25,88 @@ * - service=ver: Returns version information * - service=update_field: Updates table fields * - service=mp4: Returns MP4 video information - * + * - service=camobs: Returns camera observations with radius and bbox filtering + * - service=single: Returns single camera information by camid + * - service=powerapitest: Returns extended power outage testing data + * * Migration instructions: * To migrate from the old scripts to the new unified API: - * + * * Old endpoint: cam.php * New endpoint: main.php?service=cams - * + * * Old endpoint: camapi.php?cams&lat1=...&lon1=...&lat2=...&lon2=... * New endpoint: main.php?service=camapi&cams&lat1=...&lon1=...&lat2=...&lon2=... - * + * * Old endpoint: camlist.php * New endpoint: main.php?service=camlist - * + * * Old endpoint: admin.php?action=... * New endpoint: main.php?service=admin&action=... - * + * * Old endpoint: camcircle.php * New endpoint: main.php?service=camcircle - * + * + * Old endpoint: camobs.php + * New endpoint: main.php?service=camobs + * + * Old endpoint: single.php?camid=... + * New endpoint: main.php?service=single&camid=... + * + * Old endpoint: powerapitest.php + * New endpoint: main.php?service=powerapitest + * * Old endpoint: db.php * New endpoint: main.php?service=db - * + * * Old endpoint: db.php?outside * New endpoint: main.php?service=db&outside - * + * * Old endpoint: fire.php * New endpoint: main.php?service=fire - * + * * Old endpoint: individualcam.php?camid=... * New endpoint: main.php?service=individualcam&camid=... - * + * * Old endpoint: lsr.php * New endpoint: main.php?service=lsr - * + * * Old endpoint: lsr.php?ohgo * New endpoint: main.php?service=lsr&ohgo - * + * * Old endpoint: nws.php * New endpoint: main.php?service=nws - * + * * Old endpoint: nws.php?officestats * New endpoint: main.php?service=nws&officestats - * + * * Old endpoint: powerapi.php * New endpoint: main.php?service=powerapi - * + * * Old endpoint: powerapi.php?states * New endpoint: main.php?service=powerapi&states - * + * * Old endpoint: searchapi.php * New endpoint: main.php?service=searchapi - * + * * Old endpoint: ohgo.php * New endpoint: main.php?service=ohgo - * + * * Old endpoint: power.php * New endpoint: main.php?service=power - * + * * Old endpoint: stormdata.php * New endpoint: main.php?service=stormdata - * + * * Old endpoint: warntrack.php * New endpoint: main.php?service=warntrack - * + * * Old endpoint: ver.php * New endpoint: main.php?service=ver - * + * * Old endpoint: update_field.php?table=...&field=...&value=...&where=... * New endpoint: main.php?service=update_field&table=...&field=...&value=...&where=... - * + * * Old endpoint: mp4.php?camid=... * New endpoint: main.php?service=mp4&camid=... */ @@ -2730,6 +2742,253 @@ elseif ($service === 'mp4') { exit; } +// Service: camobs - Camera observation queries with radius and bbox filtering +elseif ($service === 'camobs') { + $dbconn = getDBConnection(); + + if($_GET['camstatic'] ?? null) { + if ($_GET['camstatic'] == 'radius') { + if($_GET['lat1'] ?? null) { + $lat1 = getParam('lat1'); + if($_GET['lon1'] ?? null) { + $lon1 = getParam('lon1'); + if($_GET['radius'] ?? null) { + $radius = getParam('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 = array(); + while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) { + $array[] = $line; + } + echo json_encode($array); + pg_free_result($result); + } + } + } + } + } + + if($_GET['camstatic'] ?? null) { + if ($_GET['camstatic'] == 'bbox') { + if($_GET['lat1'] ?? null) { + $lat1 = getParam('lat1'); + if($_GET['lon1'] ?? null) { + $lon1 = getParam('lon1'); + if($_GET['lat2'] ?? null) { + $lat2 = getParam('lat2'); + if($_GET['lon2'] ?? null) { + $lon2 = getParam('lon2'); + if($_GET['elevbottom'] ?? null) { + $elevbottom = getParam('elevbottom'); + if($_GET['elevtop'] ?? null) { + $elevtop = getParam('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 = array(); + while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) { + $array[] = $line; + } + echo json_encode($array); + pg_free_result($result); + } + } + } + } + } + } + } + } +} + +// Service: single - Returns single camera information by camid +elseif ($service === 'single') { + header('Content-Type: application/json'); + + $dbconn = getDBConnection(); + + // Check if camid is actually set to avoid warnings + if (!isset($_GET['camid'])) { + echo json_encode(array("error" => "No camid specified")); + exit; + } + + $camid = $_GET['camid']; + + // Performing SQL query + $query = "SELECT *, COALESCE(hydro, false) as hydro, COALESCE(airport, false) as airport FROM cams WHERE camid = $1"; + + // Use pg_query_params to safely bind the $camid variable + $result = pg_query_params($dbconn, $query, array($camid)) + or die('Query failed: ' . pg_last_error()); + + // Processing results + $array = array(); + while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) { + // Ensure hydro is a proper boolean + $line['hydro'] = ($line['hydro'] === 't' || $line['hydro'] === true); + // Ensure airport is a proper boolean + $line['airport'] = ($line['airport'] === 't' || $line['airport'] === true); + $array[] = $line; + } + + // Output the ORIGINAL full array (including errorcode) to the client + echo json_encode($array); + + // Free resultset + pg_free_result($result); +} + +// Service: powerapitest - Extended power outage testing API +elseif ($service === 'powerapitest') { + $dbconn = getDBConnection(); + + //no gets, current point outage info + if(empty(array_diff_key($_GET, array('service' => '')))) { + $result = pg_query_params($dbconn, + "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))order by startguess asc)) FROM power WHERE cwa = $1 and active = true", + array('RLX')) or die('Query failed: ' . pg_last_error()); + $resultArray = pg_fetch_all($result); + echo($resultArray[0]['json_build_object']); + } + + //county/state max + if($_GET['max'] ?? null) { + if($_GET['start'] ?? null) { + $starttime = pg_escape_string($_GET['start']); + if($_GET['end'] ?? null) { + $endtime = pg_escape_string($_GET['end']); + + $result = pg_query_params($dbconn, + "select distinct on (county,state) max(outage),county,state from (select distinct on (county,state,update) county,state,sum(outages) as outage, update as time, sum(served) as served from countyoutages where update > $2 and update < $3 and cwa = $1 group by county,state,update) as potato group by county,state", + array('RLX',$starttime,$endtime)) or die('Query failed: ' . pg_last_error()); + + $array = array(); + while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) { + $array[] = $line; + } + echo json_encode($array); + } + } + } + + if (isset($_GET['county'])) { + try { + $query = " + SELECT DISTINCT ON (county, state) + county, + state, + SUM(outages) as outage, + update as time, + SUM(served) as served, + ROUND( + CAST( + CASE + WHEN SUM(served) = 0 THEN NULL + ELSE (SUM(outages)::FLOAT / SUM(served)) * 100 + END AS NUMERIC + ), 2 + ) as perout + FROM countyoutages + WHERE update = (SELECT MAX(update) FROM countyoutages) + AND (cwa = $1 OR cwa = $2 OR cwa = $3 OR cwa = $4 OR cwa = $5 OR cwa = $6 OR cwa = $7) + GROUP BY county, state, update + "; + + $result = pg_query_params($dbconn, $query, ['RLX','JKL','ILN','PBZ','MRX','LWX','RNK']); + if ($result === false) { + throw new Exception('Query failed: ' . pg_last_error()); + } + + $results = []; + while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) { + $results[] = $line; + } + + header('Content-Type: application/json'); + echo json_encode($results); + + pg_free_result($result); + } catch (Exception $e) { + header('Content-Type: application/json'); + http_response_code(500); + echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]); + exit; + } + } + + //county archive + if($_GET['countyarchive'] ?? null) { + if($_GET['start'] ?? null) { + $starttime = pg_escape_string($_GET['start']); + if($_GET['end'] ?? null) { + $endtime = pg_escape_string($_GET['end']); + + $result = pg_query_params($dbconn, + "select distinct on (county,state,update) county,state,sum(outages) as outage, update as time, sum(served) as served from countyoutages where update > $9 and update < $10 and (cwa = $1 or cwa = $2 or cwa = $3 or cwa = $4 or cwa = $5 or cwa = $6 or cwa = $7 or cwa = $8) group by county,state,update", + array('RLX','JKL','ILN','PBZ','MRX','LWX','RNK','CTP',$starttime,$endtime)) or die('Query failed: ' . pg_last_error()); + + $array = array(); + while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) { + $array[] = $line; + } + echo json_encode($array); + } + } + } + + //Archive point data + if($_GET['archivepoint'] ?? null) { + $starttime = pg_escape_string($_GET['start']); + $endtime = pg_escape_string($_GET['end']); + $result = pg_query_params($dbconn, + "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))order by startguess asc)) FROM power WHERE cwa = $1 and startguess > $2 and lastchange < $3", + array('RLX',$starttime,$endtime)) or die('Query failed: ' . pg_last_error()); + $resultArray = pg_fetch_all($result); + echo($resultArray[0]['json_build_object']); + } + + // Svr related functionality + if($_GET['svr'] ?? null =='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); + echo($resultArray[0]['json_build_object']); + } + + if($_GET['svr'] ?? null == 'archive') { + if($_GET['start'] ?? null) { + $starttime = pg_escape_string($_GET['start']); + if($_GET['end'] ?? null) { + $endtime = pg_escape_string($_GET['end']); + + $result = pg_query_params($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 > $1 and endtime < $2" + ,array($starttime,$endtime)) or die('Query failed: ' . pg_last_error()); + $resultArray = pg_fetch_all($result); + echo($resultArray[0]['json_build_object']); + } + } + + if(!isset($_GET['start']) && !isset($_GET['end'])) { + $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() - interval '24 hours' and endtime > now() - interval '24 hours'") or die('Query failed: ' . pg_last_error()); + $resultArray = pg_fetch_all($result); + echo($resultArray[0]['json_build_object']); + } + } + + pg_free_result($result); +} + // Default behavior - show available services if no valid service provided else { header('Content-Type: application/json'); @@ -2740,7 +2999,8 @@ else { 'cams', 'camapi', 'camlist', 'admin', 'camcircle', 'db', 'fire', 'individualcam', 'lsr', 'nws', 'powerapi', 'searchapi', 'ohgo', 'power', - 'stormdata', 'warntrack', 'ver', 'update_field', 'mp4' + 'stormdata', 'warntrack', 'ver', 'update_field', 'mp4', + 'camobs', 'single', 'powerapitest' ], 'documentation' => 'See main.php file for detailed documentation on each service.' ]); diff --git a/one.php b/one.php index 82e19ac..fb5c2ea 100644 --- a/one.php +++ b/one.php @@ -167,9 +167,10 @@ function doTheInsert(label1, value1, label2, value2) { } function updatetable() { - $.getJSON("single.php?camid=" + camid, function(caminfo){ + $.getJSON("main.php?service=single&camid=" + camid, function(caminfo){ document.getElementById('camstats').innerHTML = ''; + // Add header row var headerRow = document.createElement('tr'); headerRow.innerHTML = '