Compare commits

..

10 Commits

Author SHA1 Message Date
e50c132676 backup 2025-12-11 03:27:46 +00:00
5fdb7e1808 clean comments 2025-12-11 02:36:27 +00:00
7f8881a600 migrate summary.html 2025-12-11 02:34:10 +00:00
d05dfa7503 initial transition 2025-12-10 18:20:30 +00:00
0310e0ea8e mark for removal 2025-12-10 05:51:17 +00:00
b9763e60fb fixes 2025-12-10 04:03:33 +00:00
3f3e743139 fix issues 2025-12-10 03:06:19 +00:00
dfb2a3ba6e fix empty get 2025-12-10 02:49:07 +00:00
5e7d2f9a77 current 2025-12-10 02:21:15 +00:00
4aba2c4273 new php 2025-12-10 02:18:45 +00:00
12 changed files with 3268 additions and 30 deletions

144
main2.php Normal file
View File

@@ -0,0 +1,144 @@
<?php
/**
* Unified API Gateway
*
* This file serves as a single entry point for all API services.
* Each route is identified by the 'service' parameter.
*
* Available routes:
* - service=cams: Returns active camera information
* - service=camapi: Returns camera API endpoints with filtering
* - service=camlist: Returns camera list with active status
* - service=admin: Admin operations for cameras
* - service=camcircle: Returns camera coverage circles
* - service=db: Returns weather station data
* - service=fire: Returns fire information
* - service=individualcam: Returns individual camera images
* - service=lsr: Returns local storm reports
* - service=nws: Returns NWS personnel stats
* - service=powerapi: Returns power outage information
* - service=searchapi: Returns search results for power outages
* - service=ohgo: Returns Ohio traffic information
* - service=newpower: Returns power outage information from the new schema
* - service=newpowerapi: Returns power outage information from the new schema
* - service=newpowerapitest: Returns extended power outage testing data from the new schema
* - service=newsearchapi: Returns search results for power outages from the new schema
* - service=newstormdata: Returns storm data from the new schema
* - service=power: Returns power outage information
* - service=stormdata: Returns storm data
* - service=warntrack: Returns warning tracking data
* - 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=...
*/
// Get the service parameter to determine which function to execute
$service = $_GET['service'] ?? 'default';
// Route to the appropriate service file
$serviceFile = __DIR__ . '/php/' . $service . '.php';
if (file_exists($serviceFile)) {
require_once $serviceFile;
} else {
// Default behavior - show available services if no valid service provided
header('Content-Type: application/json');
http_response_code(400);
echo json_encode([
'error' => 'Invalid service parameter. Please provide a valid service.',
'available_services' => [
'cams', 'camapi', 'camlist', 'admin', 'camcircle',
'db', 'fire', 'individualcam', 'lsr', 'nws',
'powerapi', 'searchapi', 'ohgo', 'power', 'newpower',
'newpowerapi', 'newpowerapitest', 'newsearchapi', 'newstormdata',
'stormdata', 'warntrack', 'ver', 'update_field', 'mp4',
'camobs', 'single', 'powerapitest'
],
'documentation' => 'See main.php file for detailed documentation on each service.'
]);
}
?>

1100
outage2.html Normal file

File diff suppressed because it is too large Load Diff

1100
outage3.html Normal file

File diff suppressed because it is too large Load Diff

25
php/newpower.php Normal file
View File

@@ -0,0 +1,25 @@
<?php
require_once __DIR__ . '/common.php';
// Think this is depreciated
header('Content-Type: application/json');
$dbconn = getDBConnection();
try {
$query = "SELECT lat, lon, outagen FROM newpower WHERE active = true AND cwa = 'RLX'";
$result = pg_query($dbconn, $query);
if ($result === false) {
throw new Exception('Query failed: ' . pg_last_error());
}
$data = pg_fetch_all($result) ?: [];
echo json_encode($data);
pg_free_result($result);
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
} finally {
pg_close($dbconn);
}
?>

519
php/newpowerapi.php Normal file
View File

@@ -0,0 +1,519 @@
<?php
require_once __DIR__ . '/common.php';
header('Content-Type: application/json');
$dbconn = getDBConnection();
// Default endpoint: Get current point outages
if (empty(array_diff_key($_GET, array('service' => '')))) {
try {
$query = "
SELECT json_build_object(
'type', 'FeatureCollection',
'features', COALESCE(json_agg(
json_build_object(
'type', 'Feature',
'geometry', ST_AsGeoJSON(geom)::json,
'properties', json_build_object(
'time', start_time,
'county', county,
'state', state,
'outage', outagen,
'lastchange', last_change,
'cause', COALESCE(cause, ''),
'area_geometry', ST_AsGeoJSON(COALESCE(realareageom, geom))::json
)
)
ORDER BY start_time ASC
), '[]'::json)
) as geojson
FROM newpower
WHERE cwa = $1 AND active = true AND geom IS NOT NULL
";
$result = pg_query_params($dbconn, $query, array('RLX'));
if ($result === false) {
throw new Exception('Query failed: ' . pg_last_error());
}
$resultArray = pg_fetch_assoc($result);
if ($resultArray && $resultArray['geojson']) {
echo $resultArray['geojson'];
} else {
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
}
pg_free_result($result);
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]);
}
}
// Get states boundaries
if (isset($_GET['states'])) {
try {
$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, $query);
if ($result === false) {
throw new Exception('Query failed: ' . pg_last_error());
}
$resultArray = pg_fetch_all($result);
// Set proper JSON header and handle output
header('Content-Type: application/json');
if ($resultArray && isset($resultArray[0]['jsonb_build_object'])) {
echo $resultArray[0]['jsonb_build_object'];
} else {
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
}
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;
}
}
// Get current county outages
if (isset($_GET['county'])) {
try {
$query = "
WITH latest_fetch AS (
SELECT MAX(fetch_time) as max_fetch_time FROM newcountyoutages
)
SELECT
n.county,
n.state,
SUM(n.outages) as outage,
MAX(n.fetch_time) as time,
SUM(n.served) as served,
CASE
WHEN SUM(n.served) > 0 THEN ROUND(CAST((SUM(n.outages)::FLOAT / SUM(n.served)) * 100 AS NUMERIC), 2)
ELSE 0
END as perout
FROM newcountyoutages n, latest_fetch
WHERE n.fetch_time = latest_fetch.max_fetch_time
AND n.cwa = $1
GROUP BY n.county, n.state
";
$result = pg_query_params($dbconn, $query, ['RLX']);
if ($result === false) {
throw new Exception('Query failed: ' . pg_last_error());
}
$results = pg_fetch_all($result) ?: [];
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()]);
}
}
// Max county outages for a time range
if (isset($_GET['max'])) {
if (isset($_GET['start']) && isset($_GET['end'])) {
try {
$starttime = getParam('start');
$endtime = getParam('end');
$query = "
SELECT DISTINCT ON (county, state)
max(outage) as max_outage,
county,
state
FROM (
SELECT DISTINCT ON (county, state, fetch_time)
county,
state,
SUM(outages) as outage,
fetch_time as time,
SUM(served) as served
FROM newcountyoutages
WHERE fetch_time > $2
AND fetch_time < $3
AND cwa = $1
GROUP BY county, state, fetch_time
) as subquery
GROUP BY county, state
";
$result = pg_query_params(
$dbconn,
$query,
['RLX', $starttime, $endtime]
);
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;
}
} else {
header('Content-Type: application/json');
http_response_code(400);
echo json_encode(['error' => 'Both start and end parameters are required']);
}
}
// Archive county outages for a time range
if (isset($_GET['countyarchive'])) {
if (isset($_GET['start']) && isset($_GET['end'])) {
try {
$starttime = getParam('start');
$endtime = getParam('end');
$query = "
SELECT DISTINCT ON (county, state, fetch_time)
county,
state,
SUM(outages) as outage,
fetch_time as time,
SUM(served) as served
FROM newcountyoutages
WHERE fetch_time > $9
AND fetch_time < $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, fetch_time
";
$result = pg_query_params($dbconn, $query, ['RLX','JKL','ILN','PBZ','MRX','LWX','RNK','CTP',$starttime,$endtime]);
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()]);
if (isset($result)) {
pg_free_result($result);
}
exit;
}
} else {
header('Content-Type: application/json');
http_response_code(400);
echo json_encode(['error' => 'Both start and end parameters are required']);
}
}
// Archive point data for a time range
if (isset($_GET['archivepoint'])) {
try {
if (!isset($_GET['start']) || !isset($_GET['end'])) {
throw new Exception('Both start and end parameters are required');
}
$starttime = getParam('start');
$endtime = getParam('end');
$query = "
SELECT json_build_object(
'type', 'FeatureCollection',
'features', json_agg(
json_build_object(
'type', 'Feature',
'geometry', ST_AsGeoJSON(geom)::json,
'properties', json_build_object(
'time', start_time,
'county', county,
'state', state,
'outage', outagen,
'lastchange', last_change,
'cause', cause
)
)
ORDER BY start_time ASC
)
)
FROM newpower
WHERE cwa = $1
AND start_time > $2
AND last_change < $3
AND geom IS NOT NULL
";
$result = pg_query_params($dbconn, $query, ['RLX', $starttime, $endtime]);
if ($result === false) {
throw new Exception('Query failed: ' . pg_last_error());
}
$resultArray = pg_fetch_all($result);
header('Content-Type: application/json');
if ($resultArray && isset($resultArray[0]['json_build_object'])) {
echo $resultArray[0]['json_build_object'];
} else {
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
}
pg_free_result($result);
} catch (Exception $e) {
header('Content-Type: application/json');
$statusCode = strpos($e->getMessage(), 'required') !== false ? 400 : 500;
http_response_code($statusCode);
echo json_encode(['error' => $e->getMessage()]);
if (isset($result)) {
pg_free_result($result);
}
exit;
}
}
// Current severe weather warnings
if (@$_GET['svr'] == 'current') {
try {
$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);
header('Content-Type: application/json');
if ($resultArray && isset($resultArray[0]['json_build_object'])) {
echo $resultArray[0]['json_build_object'];
} else {
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
}
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()]);
}
}
// Archive severe weather warnings
if (isset($_GET['svr']) && $_GET['svr'] === 'archive') {
try {
$result = null;
if (isset($_GET['start']) && isset($_GET['end'])) {
$starttime = getParam('start');
$endtime = getParam('end');
$query = "
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
";
$result = pg_query_params($dbconn, $query, [$starttime, $endtime]);
} elseif (!isset($_GET['start']) && !isset($_GET['end'])) {
$query = "
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'
";
$result = pg_query($dbconn, $query);
} else {
throw new Exception('Both start and end parameters are required together');
}
if ($result === false) {
throw new Exception('Query failed: ' . pg_last_error());
}
$resultArray = pg_fetch_all($result);
header('Content-Type: application/json');
if ($resultArray && isset($resultArray[0]['json_build_object'])) {
echo $resultArray[0]['json_build_object'];
} else {
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
}
pg_free_result($result);
} catch (Exception $e) {
if (isset($result)) {
pg_free_result($result);
}
header('Content-Type: application/json');
$statusCode = strpos($e->getMessage(), 'required') !== false ? 400 : 500;
http_response_code($statusCode);
echo json_encode(['error' => $e->getMessage()]);
exit;
}
}
// Severe weather warning polygons
if (isset($_GET['svrpolys'])) {
try {
$query = "
SELECT
vtec,
outagesvalid,
polygonpop,
outagesbuffer,
lsrids
FROM svr
WHERE EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - endtime)) / 60 / 60 / 24 < 60
";
$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;
}
header('Content-Type: application/json');
echo json_encode($results);
pg_free_result($result);
} catch (Exception $e) {
if (isset($result)) {
pg_free_result($result);
}
header('Content-Type: application/json');
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
exit;
}
}
// Power outage details by IDs
if (isset($_GET['powerids'])) {
try {
$powerids = $_GET['powerids'];
// Validate input exists and isn't empty
if (empty($powerids)) {
throw new Exception('No power IDs provided');
}
// Convert comma-separated string to array and sanitize
$poweridArray = explode(',', $powerids);
$sanitizedIds = array_filter(array_map('intval', $poweridArray));
if (empty($sanitizedIds)) {
throw new Exception('Invalid power ID format');
}
// Prepare placeholders for the query
$placeholders = implode(',', array_map(function($i) { return '$' . $i; }, range(1, count($sanitizedIds))));
$query = "
SELECT
lat,
lon,
last_change,
start_time,
peakoutage,
cause,
lsrtime,
lsrref,
(lsrtime AT TIME ZONE 'America/New_York')::timestamp as lsrlocal
FROM newpower
WHERE id IN ($placeholders)
";
$result = pg_query_params($dbconn, $query, $sanitizedIds);
if ($result === false) {
throw new Exception('Query failed: ' . pg_last_error());
}
$results = pg_fetch_all($result) ?: [];
header('Content-Type: application/json');
echo json_encode($results);
pg_free_result($result);
} catch (Exception $e) {
if (isset($result)) {
pg_free_result($result);
}
header('Content-Type: application/json');
$statusCode = strpos($e->getMessage(), 'Invalid') !== false ? 400 : 500;
http_response_code($statusCode);
echo json_encode(['error' => $e->getMessage()]);
exit;
}
}
pg_close($dbconn);
?>

151
php/newpowerapitest.php Normal file
View File

@@ -0,0 +1,151 @@
<?php
require_once __DIR__ . '/common.php';
$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(geom)::json,'properties',json_build_object('time',start_time,'county',county,'state',state,'outage',outagen,'lastchange',last_change,'cause',cause))order by start_time asc)) FROM newpower WHERE cwa = $1 and active = true AND geom IS NOT NULL",
array('RLX')) or die('Query failed: ' . pg_last_error());
$resultArray = pg_fetch_all($result);
header('Content-Type: application/json');
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(outages),county,state from (select distinct on (county,state,fetch_time) county,state,sum(outages) as outages, fetch_time as time, sum(served) as served from newcountyoutages where fetch_time > $2 and fetch_time < $3 and cwa = $1 group by county,state,fetch_time) 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;
}
header('Content-Type: application/json');
echo json_encode($array);
}
}
}
if (isset($_GET['county'])) {
try {
$cwas = ['RLX','JKL','ILN','PBZ','MRX','LWX','RNK'];
$placeholders = implode(',', array_map(function($i) { return '$' . $i; }, range(1, count($cwas))));
$query = "
WITH latest_fetch AS (
SELECT MAX(fetch_time) as max_fetch_time FROM newcountyoutages
)
SELECT
n.county,
n.state,
n.outages as outage,
n.fetch_time as time,
n.served,
CASE
WHEN n.served > 0 THEN ROUND(CAST((n.outages::FLOAT / n.served) * 100 AS NUMERIC), 2)
ELSE 0
END as perout
FROM newcountyoutages n, latest_fetch
WHERE n.fetch_time = latest_fetch.max_fetch_time
AND n.cwa IN ($placeholders)
";
$result = pg_query_params($dbconn, $query, $cwas);
if ($result === false) {
throw new Exception('Query failed: ' . pg_last_error());
}
$results = pg_fetch_all($result) ?: [];
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,fetch_time) county,state,sum(outages) as outage, fetch_time as time, sum(served) as served from newcountyoutages where fetch_time > $9 and fetch_time < $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,fetch_time",
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;
}
header('Content-Type: application/json');
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(geom)::json,'properties',json_build_object('time',start_time,'county',county,'state',state,'outage',outagen,'lastchange',last_change,'cause',cause))order by start_time asc)) FROM newpower WHERE cwa = $1 and start_time > $2 and last_change < $3 AND geom IS NOT NULL",
array('RLX',$starttime,$endtime)) or die('Query failed: ' . pg_last_error());
$resultArray = pg_fetch_all($result);
header('Content-Type: application/json');
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);
header('Content-Type: application/json');
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);
header('Content-Type: application/json');
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);
header('Content-Type: application/json');
echo($resultArray[0]['json_build_object']);
}
}
pg_free_result($result);
// Close database connection when needed
if (isset($dbconn)) {
pg_close($dbconn);
}
?>

95
php/newsearchapi.php Normal file
View File

@@ -0,0 +1,95 @@
<?php
require_once __DIR__ . '/common.php';
// Think this is depreciated
header('Content-Type: application/json');
$dbconn = getDBConnection();
// Default endpoint: Get current point outages from newpower table
if (empty(array_diff_key($_GET, array('service' => '')))) {
try {
$query = "
SELECT json_build_object(
'type', 'FeatureCollection',
'features', json_agg(
json_build_object(
'type', 'Feature',
'geometry', ST_AsGeoJSON(geom)::json,
'properties', json_build_object(
'time', start_time,
'county', county,
'state', state,
'outage', outagen,
'lastchange', last_change,
'cause', cause
)
)
ORDER BY start_time ASC
)
) as geojson
FROM newpower
WHERE cwa = $1 AND active = true
";
$result = pg_query_params($dbconn, $query, array('RLX'));
if ($result === false) {
throw new Exception('Query failed: ' . pg_last_error());
}
$resultArray = pg_fetch_assoc($result);
if ($resultArray && $resultArray['geojson']) {
echo $resultArray['geojson'];
} else {
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
}
pg_free_result($result);
} catch (Exception $e) {
http_response_code(500);
die(json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]));
}
}
// Get current county outages from newcountyoutages table
if (isset($_GET['county'])) {
try {
$query = "
WITH latest_fetch AS (
SELECT MAX(fetch_time) as max_fetch_time FROM newcountyoutages
)
SELECT
n.fetch_time as time,
n.county,
n.state,
n.outages as outage,
n.served
FROM newcountyoutages n, latest_fetch
WHERE n.fetch_time = latest_fetch.max_fetch_time
AND n.cwa = $1
ORDER BY n.county, n.state
";
$result = pg_query_params($dbconn, $query, ['RLX']);
if ($result === false) {
throw new Exception('Query failed: ' . pg_last_error());
}
$results = pg_fetch_all($result) ?: [];
echo json_encode($results);
pg_free_result($result);
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]);
}
}
// Note: The 'countyarchive', 'archivepoint', and 'svr' endpoints from the original
// searchapi.php can be migrated here. The queries would need to be updated to use
// the 'newpower' and 'newcountyoutages' tables and their corresponding columns
// (e.g., start_time, geom, fetch_time).
pg_close($dbconn);
?>

126
php/newstormdata.php Normal file
View File

@@ -0,0 +1,126 @@
<?php
require_once __DIR__ . '/common.php';
/**
* Handles power outage requests for the new schema.
* @param resource $dbconn The database connection.
* @param array $input_data The decoded JSON input data.
*/
function handle_new_power_request($dbconn, $input_data) {
$poly = $input_data['poly'] ?? null;
$start = $input_data['start'] ?? null;
$end = $input_data['end'] ?? null;
if (!$poly || !$start || !$end) {
send_error(400, 'Missing required fields: poly, start, and end are required for power requests.');
}
$query = "
SELECT
SUM(p.outagen) as total_outages,
COUNT(p.id) as outage_events,
SUM(p.peakoutage) as peak_outages
FROM newpower p
WHERE ST_Within(p.geom, ST_GeomFromText($1, 4326))
AND p.start_time >= $2
AND p.start_time <= $3
";
try {
$result = pg_query_params($dbconn, $query, [$poly, $start, $end]);
if ($result === false) {
throw new Exception('Database query failed: ' . pg_last_error($dbconn));
}
$data = pg_fetch_assoc($result);
pg_free_result($result);
header('Content-Type: application/json');
echo json_encode($data ?: new stdClass()); // Return empty JSON object if no results
} catch (Exception $e) {
send_error(500, 'An error occurred while processing the power request.', $e->getMessage());
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input_data = null;
$request_type = null;
$contentType = trim(strtolower($_SERVER['HTTP_CONTENT_TYPE'] ?? $_SERVER['CONTENT_TYPE'] ?? ''));
if (strpos($contentType, 'application/json') === 0) {
$raw_post_data = file_get_contents('php://input');
if ($raw_post_data === false || $raw_post_data === '') {
send_error(400, 'Received empty request body or could not read input.', "Error: Could not read php://input or it was empty.");
}
$input_data = json_decode($raw_post_data, true);
if (json_last_error() !== JSON_ERROR_NONE) {
send_error(400, 'Invalid JSON payload received.', 'JSON Decode Error: ' . json_last_error_msg() . " | Raw data snippet: " . substr($raw_post_data, 0, 100));
} elseif (!is_array($input_data)) {
send_error(400, 'Invalid JSON payload: Expected a JSON object.', "JSON Decode Warning: Result is not an array. Data: " . print_r($input_data, true));
} else {
$request_type = $input_data['request_type'] ?? null;
}
} else {
send_error(415, 'Unsupported Media Type. This endpoint requires application/json.', "Unsupported Media Type Received: " . $contentType);
}
if ($request_type === null) {
if (is_array($input_data) && !isset($input_data['request_type'])) {
send_error(400, 'Missing "request_type" field within the request payload.');
} else {
send_error(400, 'Missing required parameter: request_type (or processing error).');
}
}
$dbconn = getDBConnection();
switch ($request_type) {
// Retaining legacy endpoints from stormdata.php but pointing to new handlers if needed
// For now, only implementing the 'power' endpoint for the new schema
case 'power':
handle_new_power_request($dbconn, $input_data);
break;
// The 'powernopoly' case from the original file can be implemented here if needed.
// It would be similar to handle_new_power_request but without the ST_Within clause.
/*
// Legacy endpoints can be added here if they need to be migrated.
case 'ohgo':
// handle_ohgo_request($dbconn, $input_data);
send_error(501, 'The "ohgo" request type is not yet implemented for newstormdata.');
break;
case 'ohgonopoly':
// handle_ohgo_request_no_poly($dbconn, $input_data);
send_error(501, 'The "ohgonopoly" request type is not yet implemented for newstormdata.');
break;
case 'wupoly':
// handle_wu_request_poly($dbconn, $input_data);
send_error(501, 'The "wupoly" request type is not yet implemented for newstormdata.');
break;
case 'campoly':
// handle_cam_request($dbconn, $input_data);
send_error(501, 'The "campoly" request type is not yet implemented for newstormdata.');
break;
*/
default:
send_error(400, 'Invalid request_type specified: ' . htmlspecialchars($request_type));
break;
}
pg_close($dbconn);
} else {
http_response_code(405);
header('Allow: POST');
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['error' => 'Invalid request method. Only POST is allowed.']);
exit;
}
?>

View File

@@ -1,6 +1,6 @@
<?php
require_once __DIR__ . '/common.php';
// Think this is depreciated
$dbconn = getDBConnection();
// Performing SQL query

View File

@@ -2,7 +2,7 @@
require_once __DIR__ . '/common.php';
$dbconn = getDBConnection();
// Think this is depreciated
//no gets, current point outage info
if(empty(array_diff_key($_GET, array('service' => '')))) {
$result = pg_query_params($dbconn,

View File

@@ -42,9 +42,9 @@ function rackandstack() {
var start = document.getElementById("start").value;
var end = document.getElementById("end").value;
$.getJSON(`main.php?service=powerapi&max=potato&start=${start}&end=${end}`, function(data) {
$.getJSON(`main.php?service=newpowerapi&max=potato&start=${start}&end=${end}`, function(data) {
$.getJSON('main.php?service=powerapi&county=r', function(data1) {
$.getJSON('main.php?service=newpowerapi&county=r', function(data1) {
countylist(data,data1);
});
@@ -62,8 +62,9 @@ function countylist(data,data1) {
for (i=0; i< data.length; i++) {
for (j=0; j<data1.length;j++){
if (data[i].county == data1[j].county && data[i].state == data1[j].state) {
console.log(data[i]);
data[i]['served'] = data1[j]['served'];
data[i]['percent'] = Math.round(data[i]['max']/data[i]['served']*1000)/10;
data[i]['percent'] = Math.round(data[i]['max_outage']/data[i]['served']*1000)/10;
}
}
}
@@ -75,7 +76,7 @@ statepercent = 0;
for (k=0; k<data.length; k++) {
if (states[l] == data[k]['state']) {
stateout = stateout + parseFloat(data[k]['max']);
stateout = stateout + parseFloat(data[k]['max_outage']);
stateserved = stateserved + parseFloat(data[k]['served']);
statepercent = Math.round(stateout/stateserved*1000)/10;
if (states[l] == 'WV') {
@@ -154,7 +155,7 @@ var table = new Tabulator("#countysum", {
columns:[
{title:"County", field:"county"},
{title:"State", field:"state"},
{title:"Max Outages", field:"max"},
{title:"Max Outages", field:"max_outage"},
{title:"Served", field:"served"},
{title:"Max % Out", field:"percent"},
{title:"State Total Out", field:"stateout"},

View File

@@ -114,30 +114,7 @@
</div>
<script>
/*
always EST
create (static?) map for each product in leaflet
instead of point in polygon just plot all lsrs that fall within the bounding box of map around polygon
find hydrographs in non river point warnings and plot
color lsrs by time, red before product, yellow 30 min to 15hrs depending, green inside product
could also color by criteria
filter lsr by product type
take arguments for time and distance buffer for LSR
create hydrograph as static image for flood Points
find hydrographs in areals and plot
Link for hydrographs
Link to severe polygon on power outage
https://wx.stoat.org/main.php?service=powerapi&svrpolys=potato
https://waterservices.usgs.gov/nwis/iv/?format=json&bBox=-83.254395,36.932330,-78.508301,40.145289&parameterCd=00065&siteType=ST
-83.254395,36.932330,-78.508301,40.145289
https://api.water.noaa.gov/nwps/v1/gauges?bbox.xmin=-83.254395&bbox.ymin=36.932330&bbox.xmax=-78.508301&bbox.ymax=40.145289&srid=EPSG_4326&catfim=false
time info flood and crest time
below flood
impacts
*/