consolidate php

This commit is contained in:
2025-12-09 00:20:32 +00:00
parent a7b6c529a9
commit eba6536050
44 changed files with 3458 additions and 4911 deletions

View File

@@ -83,7 +83,7 @@
var table = new Tabulator("#wunderobs", { var table = new Tabulator("#wunderobs", {
virtualDom: true, virtualDom: true,
virtualDomBuffer: 300, virtualDomBuffer: 300,
ajaxURL: "lsr.php?getCombinedTable=p", ajaxURL: "main.php?service=lsr&getCombinedTable=p",
ajaxConfig: "GET", ajaxConfig: "GET",
autoResize: true, autoResize: true,
initialSort: [{ column: "start", dir: "desc" }], initialSort: [{ column: "start", dir: "desc" }],
@@ -181,7 +181,7 @@
function lsr(lsr, id, source) { function lsr(lsr, id, source) {
$.get({ $.get({
url: 'lsr.php?updater=true&lsr=' + lsr + "&id=" + id + "&table="+source, url: 'main.php?service=lsr&updater=true&lsr=' + lsr + "&id=" + id + "&table="+source,
error: function(xhr, error) { error: function(xhr, error) {
alert('Unable to update, please refresh page'); alert('Unable to update, please refresh page');
} }
@@ -195,7 +195,7 @@
function hide(hide, id, source) { function hide(hide, id, source) {
$.get({ $.get({
url: 'lsr.php?updater=true&hide=' + hide + "&id=" + id + "&table="+source, url: 'main.php?service=lsr&updater=true&hide=' + hide + "&id=" + id + "&table="+source,
error: function(xhr, error) { error: function(xhr, error) {
alert('Unable to update, please refresh page'); alert('Unable to update, please refresh page');
} }

278
API_DOCUMENTATION.md Normal file
View File

@@ -0,0 +1,278 @@
# Unified API Gateway Documentation
## Overview
This API gateway serves as a single entry point for all API services that were previously separate PHP scripts. Each service is accessed via a `service` parameter that routes the request to the appropriate functionality.
## Base URL
```
main.php?service={service_name}[&parameters]
```
## Available Services
### 1. cams
**Description**: Returns active camera information
**Usage**: `main.php?service=cams`
**Parameters**: None required
**Migration**:
- Old: `cam.php`
- New: `main.php?service=cams`
### 2. camapi
**Description**: Returns camera API endpoints with filtering
**Usage**: `main.php?service=camapi[&cams&lat1={lat}&lon1={lon}&lat2={lat}&lon2={lon}&elevbottom={elev}&elevtop={elev}]`
**Parameters**:
- `cams` - Get RTSP cameras
- `lat1, lon1, lat2, lon2` - Bounding box coordinates
- `elevbottom, elevtop` - Elevation range
- `camstatic` - Get cameras near a point (requires `lat1`, `lon1`, `radius`)
- `camdb` - Get camera count
**Migration**:
- Old: `camapi.php?cams&lat1=...&lon1=...&lat2=...&lon2=...`
- New: `main.php?service=camapi&cams&lat1=...&lon1=...&lat2=...&lon2=...`
### 3. camlist
**Description**: Returns camera list with active status
**Usage**: `main.php?service=camlist`
**Parameters**: None required
**Migration**:
- Old: `camlist.php`
- New: `main.php?service=camlist`
### 4. admin
**Description**: Admin operations for cameras
**Usage**: `main.php?service=admin&action={action}`
**Parameters**:
- `action='checkurl'` - Check if URL exists (POST required)
- `action='newcam'` - Add new camera (POST required)
**Migration**:
- Old: `admin.php?action=checkurl`
- New: `main.php?service=admin&action=checkurl`
### 5. camcircle
**Description**: Returns camera coverage circles
**Usage**: `main.php?service=camcircle`
**Parameters**: None required
**Migration**:
- Old: `camcircle.php`
- New: `main.php?service=camcircle`
### 6. db
**Description**: Returns weather station data
**Usage**: `main.php?service=db[&outside]`
**Parameters**:
- `outside` - Get outside weather data
**Migration**:
- Old: `db.php`
- New: `main.php?service=db`
- Old: `db.php?outside`
- New: `main.php?service=db&outside`
### 7. fire
**Description**: Returns fire information
**Usage**: `main.php?service=fire`
**Parameters**: None required
**Migration**:
- Old: `fire.php`
- New: `main.php?service=fire`
### 8. individualcam
**Description**: Returns individual camera images
**Usage**: `main.php?service=individualcam&camid={camid}[&dtg={datetime}&camimages={count}]`
**Parameters**:
- `camid` - Camera ID (required)
- `dtg` - Date/time to get images before
- `camimages` - Number of images to return (default: 20)
**Migration**:
- Old: `individualcam.php?camid=...`
- New: `main.php?service=individualcam&camid=...`
### 9. lsr
**Description**: Returns local storm reports and related data
**Usage**: `main.php?service=lsr[&{various parameters}]`
**Parameters**:
- No parameters - Get all reports
- `ohgo` - Get Ohio traffic data
- `ohgotable` - Get Ohio traffic table data
- `lsrohgo`, `ohgohide` - Update records
- `vtec` - Get data for specific VTEC code
- `preflagreports` - Get pre-flagged reports
- `reports` - Get reports within polygon
- `outages` - Get power outages within polygon
- `rtcad` - Get real-time CAD reports
- `verify` - Get verification reports
- `stats` - Get statistics
- `metars` - Get METARs
- `news` - Get news data
- `news2` - Get news data (version 2)
- `news3` - Get news data (version 3)
- `wv511`, `ky511` - Get state traffic data
- `getCombinedTable` - Get combined traffic data
- `updater` - Update records
**Migration**:
- Old: `lsr.php`
- New: `main.php?service=lsr`
- Old: `lsr.php?ohgo`
- New: `main.php?service=lsr&ohgo`
### 10. nws
**Description**: Returns NWS personnel stats
**Usage**: `main.php?service=nws[&{various parameters}]`
**Parameters**:
- No parameters - Get all NWS data
- `officestats`, `officestats11`, `regionstats`, `drilldown` - Various statistics
- `datetime` - Date for statistics
**Migration**:
- Old: `nws.php`
- New: `main.php?service=nws`
### 11. powerapi
**Description**: Returns power outage information
**Usage**: `main.php?service=powerapi[&{various parameters}]`
**Parameters**:
- No parameters - Get current power outages
- `states` - Get state boundaries
- `max` - Get max outages (requires `start` and `end`)
- `county` - Get county power outages
- `countyarchive` - Get archived county outages (requires `start` and `end`)
- `archivepoint` - Get archived point outages (requires `start` and `end`)
- `svr` - Severe weather reports
- `svrpolys` - Get severe weather polygons
- `powerids` - Get specific power outages (requires comma-separated IDs)
- `poweridsgeojson` - Get specific power outages as GeoJSON
- `polygongeojson` - Get power outages in polygon (requires GeoJSON string)
**Migration**:
- Old: `powerapi.php`
- New: `main.php?service=powerapi`
- Old: `powerapi.php?states`
- New: `main.php?service=powerapi&states`
### 12. searchapi
**Description**: Returns search results for power outages
**Usage**: `main.php?service=searchapi[&{various parameters}]`
**Parameters**:
- No parameters - Get current power outages
- `county` - Get county data
- `countyarchive` - Get archived county data
- `archivepoint` - Get archived point data
- `svr` - Get severe weather data
**Migration**:
- Old: `searchapi.php`
- New: `main.php?service=searchapi`
### 13. ohgo
**Description**: Returns Ohio traffic information
**Usage**: `main.php?service=ohgo`
**Parameters**: None required
**Migration**:
- Old: `ohgo.php`
- New: `main.php?service=ohgo`
### 14. power
**Description**: Returns power outage information (simplified)
**Usage**: `main.php?service=power`
**Parameters**: None required
**Migration**:
- Old: `power.php`
- New: `main.php?service=power`
### 15. stormdata
**Description**: Returns storm data (POST only)
**Usage**: POST to `main.php?service=stormdata`
**Parameters** (in POST body as JSON):
- `request_type` - Type of request (ohgo, ohgonopoly, power, powernopoly, wupoly, campoly)
- `start_time`, `end_time` - Time range
- `area_geojson` - Area as GeoJSON
- `buffer` - Buffer time in hours
**Migration**:
- Old: `stormdata.php`
- New: `main.php?service=stormdata` (POST request)
### 16. warntrack
**Description**: Returns warning tracking data
**Usage**: `main.php?service=warntrack`
**Parameters**: None required
**Migration**:
- Old: `warntrack.php`
- New: `main.php?service=warntrack`
### 17. ver
**Description**: Returns version information
**Usage**: `main.php?service=ver[&{various parameters}]`
**Parameters**:
- No parameters - Get version polygons
- `lsrslist` - Get LSRs list
- `reset` - Reset LSRs
- `lsrs` - Update LSRs
- `inc` - Update increment
- `hide` - Update hide status
**Migration**:
- Old: `ver.php`
- New: `main.php?service=ver`
### 18. update_field
**Description**: Updates table fields (POST only)
**Usage**: POST to `main.php?service=update_field`
**Parameters** (in POST body):
- `camid` - Camera ID
- `field` - Field to update (hydro, airport)
- `value` - Value to set
**Migration**:
- Old: `update_field.php`
- New: `main.php?service=update_field` (POST request)
### 19. mp4
**Description**: Generates MP4/gif from images (POST only)
**Usage**: POST to `main.php?service=mp4`
**Parameters** (in POST body):
- `data` - Array of image paths
- `images` - Number of images
- `delay` - Delay between images
- `lastdelay` - Delay for last image
- `maxh`, `maxv` - Max dimensions
**Migration**:
- Old: `mp4.php`
- New: `main.php?service=mp4` (POST request)
## Error Handling
- Invalid service parameters return HTTP 400 with available services
- Database errors return appropriate error messages
- Missing required parameters return HTTP 400 with descriptive error messages
## Security Considerations
- All user-provided input is properly escaped using `pg_escape_string()`
- SQL injection prevention through parameterized queries
- Input validation for numeric and boolean values
## Migration Guide
### For Web Applications
1. Update all API calls to use the new endpoint format
2. Replace direct script calls with `main.php?service={service_name}`
3. Ensure all existing parameters are preserved
4. Test all functionality to verify compatibility
### For JavaScript Applications
```javascript
// Old approach
fetch('cam.php')
.then(response => response.json())
// New approach
fetch('main.php?service=cams')
.then(response => response.json())
```
### For Server-to-Server Communication
```php
// Old approach
$result = file_get_contents('http://yourserver/camapi.php?cams&lat1=...&lon1=...');
// New approach
$result = file_get_contents('http://yourserver/main.php?service=camapi&cams&lat1=...&lon1=...');
```
## Testing
- All services maintain the same output format as the original scripts
- Backwards compatibility is preserved for parameter usage
- JSON output remains consistent with previous implementations

View File

@@ -167,7 +167,7 @@ padding-horizontal: 15px;
function isValidUrl(string) { function isValidUrl(string) {
$.ajax({ $.ajax({
url: 'admin.php?action=checkurl', url: 'main.php?service=admin&action=checkurl',
type: 'POST', type: 'POST',
dataType: "json", dataType: "json",
data: {url:string}, data: {url:string},
@@ -191,7 +191,7 @@ function isValidUrl(string) {
$('#newcam').submit(function(e){ $('#newcam').submit(function(e){
e.preventDefault(); e.preventDefault();
$.ajax({ $.ajax({
url: 'admin.php?action=newcam', url: 'main.php?service=admin&action=newcam',
type: 'post', type: 'post',
data:$('#newcam').serialize(), data:$('#newcam').serialize(),
success:function(data){ success:function(data){

View File

@@ -1,61 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
$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());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
pg_free_result($result);
pg_close($dbconn);
}
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);
echo json_encode($status);
pg_free_result($result);
pg_close($dbconn);
shell_exec('python3 /var/www/html/work/runallgeom.py');
}

26
cam.php
View File

@@ -1,26 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
// Performing SQL query
$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());
// Printing results in HTML
$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;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
// Closing connection
pg_close($dbconn);
?>

View File

@@ -1,102 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
//select camid,url,description from cams where cwa = 'RLX' and method = 'rtsp' and active = true AND (EXTRACT(EPOCH FROM (current_timestamp - lastsuccess ))/60) < (interval + 20) and lat > %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");
//county/state max
if (isset($_GET['cams'])) {
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']);
$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());
//$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 > '2023-04-01' and update < '2023-04-02' and cwa = 'RLX' group by county,state,update) as potato group by county,state;
//"select camid,url,description from cams where method = 'rtsp' and active = true $1 '162.210.14.137' and (EXTRACT(EPOCH FROM (current_timestamp - lastsuccess ))/60) < (interval + 20) and lat < $2 and lat > $3 and lon < $4 and lon > $5",
//array($res,$lat1,$lat2,$lon1,$lon2)) 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 (isset($_GET['camstatic'])) {
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 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());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
pg_free_result($result);
pg_close($dbconn);
}}}}
if (isset($_GET['camdb'])) {
$result = pg_query($dbconn,
"SELECT COUNT(*) FROM camdb") 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);
}
?>

View File

@@ -1,43 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
// Performing SQL query
//$query = "SELECT distinct on (camid) camid, filepath FROM camdb order by camid,dateutc desc";
//$query = "SELECT * FROM cams WHERE active <> false AND lastsuccess IS NOT NULL AND (EXTRACT(EPOCH FROM (current_timestamp - lastsuccess ))/60) < (interval + 20) order by elevation desc";
//$query = "SELECT cwa,lat,lon,lastimage,county,elevation,camid,state,description FROM cams WHERE active <> false AND lastsuccess IS NOT NULL AND (EXTRACT(EPOCH FROM (current_timestamp - lastsuccess ))/60) < (interval + 20) order by elevation desc";
//$query = "SELECT json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type','Feature', 'geometry', ST_AsGeoJSON(WITH subquery_points AS (SELECT geom AS point_geometry FROM cams WHERE active = true and totalfails < 50) SELECT ST_Buffer(point_geometry::geography, 8000) AS circle_geometry FROM subquery_points)))";
//"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"
$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());
// Printing results in HTML
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
print_r($array[0]['feature_collection']);
// Free resultset
pg_free_result($result);
// Closing connection
pg_close($dbconn);
?>

View File

@@ -1,56 +0,0 @@
<?php
header('Content-Type: application/json; charset=utf-8');
// Initialize response array
$response = [];
// Database connection
try {
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws");
if (!$dbconn) {
throw new Exception('Could not connect to database');
}
// Performing SQL query
$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) {
throw new Exception('Query failed: ' . pg_last_error());
}
// Fetch results
$data = [];
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
// Ensure numeric values are properly typed
$line['lat'] = floatval($line['lat']);
$line['lon'] = floatval($line['lon']);
$line['elevation'] = floatval($line['elevation']);
$line['active'] = $line['active'] === 't' ? true : false; // Convert PostgreSQL boolean
$data[] = $line;
}
$response = [
'status' => 'success',
'data' => $data,
'count' => count($data)
];
// Free resultset
pg_free_result($result);
// Close connection
pg_close($dbconn);
} catch (Exception $e) {
http_response_code(500);
$response = [
'status' => 'error',
'message' => $e->getMessage()
];
}
// Output JSON
echo json_encode($response, JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK);
?>

View File

@@ -501,7 +501,7 @@ for (var ii in sortcams) {
// Load settings when the page loads // Load settings when the page loads
window.onload = function() { window.onload = function() {
loadSettings(); loadSettings();
$.getJSON('cam.php', function(data) { $.getJSON('main.php?service=cams', function(data) {
var wild = Math.random(); var wild = Math.random();
allcams = data; allcams = data;
console.log('Camera data:', data); // Debug: log camera data console.log('Camera data:', data); // Debug: log camera data
@@ -535,7 +535,7 @@ for (var ii in sortcams) {
} }
filter(); filter();
sortcams(); // Apply saved sort sortcams(); // Apply saved sort
$.getJSON('camapi.php?camdb', function(data){ $.getJSON('main.php?service=camapi&camdb', function(data){
document.getElementById("camcount").textContent = "Total Images: " + data[0].count; document.getElementById("camcount").textContent = "Total Images: " + data[0].count;
}); });
}); });
@@ -544,7 +544,7 @@ for (var ii in sortcams) {
function refreshcams() { function refreshcams() {
$.getJSON('cam.php', function(data){ $.getJSON('main.php?service=cams', function(data){
var wild = Math.random(); var wild = Math.random();
//console.log(data); //console.log(data);
for(var i in data){ for(var i in data){
@@ -565,7 +565,7 @@ $.getJSON('cam.php', function(data){
} }
}} }}
}); });
$.getJSON('camapi.php?camdb', function(data){ $.getJSON('main.php?service=camapi&camdb', function(data){
document.getElementById("camcount").textContent = "Total Images: " + data[0].count; document.getElementById("camcount").textContent = "Total Images: " + data[0].count;
}); });

View File

@@ -204,7 +204,7 @@ style: function (feature) {
}).addTo(mymap); }).addTo(mymap);
$.getJSON('camcircle.php', function(data) { $.getJSON('main.php?service=camcircle', function(data) {
var geojsonFeature = data; var geojsonFeature = data;
geoJSONcircle.addData(geojsonFeature); geoJSONcircle.addData(geojsonFeature);

View File

@@ -19,7 +19,7 @@
<div id="wunderobs"></div> <div id="wunderobs"></div>
<script> <script>
var dataurl = 'db.php' var dataurl = 'main.php?service=db'
function googleMap(cell, formatterParams){ function googleMap(cell, formatterParams){
@@ -126,13 +126,13 @@ table.setData(dataurl);
function filters() { function filters() {
var y = document.getElementById("cwa").checked; var y = document.getElementById("cwa").checked;
if (y) { if (y) {
dataurl = 'db.php' dataurl = 'main.php?service=db'
table.replaceData(dataurl) table.replaceData(dataurl)
table.addFilter("cwa", "=", 'RLX'); table.addFilter("cwa", "=", 'RLX');
} }
if (!y) { if (!y) {
dataurl = 'db.php?outside=yes' dataurl = 'main.php?service=db&outside=yes'
table.replaceData(dataurl) table.replaceData(dataurl)
table.removeFilter("cwa", "=", 'RLX'); table.removeFilter("cwa", "=", 'RLX');
} }

179
db.php
View File

@@ -1,179 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
//no gets, curent point outage info
if (empty($_GET)) {
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 cwa = 'RLX'
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;
}
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;
}
}
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());
// Printing results in HTML
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
// Closing connection
}
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;
}
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;
}
}
pg_close($dbconn);
/*
// Performing SQL query
$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());
// Printing results in HTML
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
// Closing connection
pg_close($dbconn);
?>
*/

View File

@@ -1,16 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
//no gets, curent point outage info
if(empty($_GET)) {
$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);
echo($resultArray[0]['json_build_object']);
}

View File

@@ -1,53 +0,0 @@
<?php
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
$camid = pg_escape_string($_GET['camid'] ?? null);
if($_GET['dtg'] ?? null){
$endtime = pg_escape_string($_GET['dtg']);
if($_GET['camimages']){
$camimages = $_GET['camimages'];
}
if(!$_GET['camimages'] ?? null){
$camimages = 20;
}
$query = "SELECT camid, filepath, date_trunc('second', dateutc) as dateutc FROM camdb where camid = '{$camid}' and dateutc < '{$endtime}' order by dateutc desc limit '{$camimages}'";
}
$camimages = 20;
//if(!$_GET['dtg'] ?? null){
//if ($_GET['dtg'] == null) {
if (!isset($_GET['dtg'])) {
if($_GET['camimages'] ?? null){
$camimages = $_GET['camimages'];
}
$query = "SELECT camid, filepath, date_trunc('second', dateutc) as dateutc FROM camdb where camid = '{$camid}' order by dateutc desc limit '{$camimages}'";
}
//$query = "SELECT camid, filepath, date_trunc('second', dateutc) as dateutc FROM camdb where camid = '{$camid}' order by dateutc desc limit 20";
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
// Closing connection
pg_close($dbconn);
?>

825
lsr.php
View File

@@ -1,825 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
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'";
// Prepare and execute the query
$result = pg_query($dbconn, $query);
if (!$result) {
header('Content-Type: application/json');
echo json_encode(['error' => 'Query failed: ' . pg_last_error()]);
exit;
}
// Fetch the result
$resultArray = pg_fetch_all($result);
// Check if we got results
if ($resultArray && isset($resultArray[0]['geojson'])) {
header('Content-Type: application/json');
echo $resultArray[0]['geojson']; // Direct output since it's already JSON from jsonb_build_object
} else {
header('Content-Type: application/json');
echo json_encode(['error' => 'No results found']);
}
// Free result and close connection
pg_free_result($result);
// pg_close($dbconn); // Uncomment if you want to close the connection
}
if (isset($_GET['ohgotable'])) {
// Performing SQL query
$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());
// Printing results in JSON
$array = [];
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
}
if (isset($_GET['lsrohgo'])) {
if ($_GET['lsrohgo'] == 'true') {
$lsrflag = 'true';
} else {
$lsrflag = 'false';
}
$id = (int) $_GET['id'];
$query = "UPDATE ohgo SET lsr = $1 WHERE id = $2";
$result = pg_query_params($dbconn, $query, array($lsrflag, $id)) or die('Query failed: ' . pg_last_error());
pg_free_result($result);
}
if (isset($_GET['ohgohide'])) {
if ($_GET['ohgohide'] == 'true') {
$lsrflag = 'true';
} else {
$lsrflag = 'false';
}
$id = (int) $_GET['id'];
$query = "UPDATE ohgo SET hide = $1 WHERE id = $2";
$result = pg_query_params($dbconn, $query, array($lsrflag, $id)) or die('Query failed: ' . pg_last_error());
pg_free_result($result);
}
//take vtec, return start, end, polygon, outages in polygon, outages in buffer, warntype, polygon pop
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;
";
// Prepare and execute the query using pg_query_params
$result = pg_query_params($dbconn, $query, array($vtec))
or die('Query failed: ' . pg_last_error());
// Fetch the result
$resultArray = pg_fetch_all($result);
// Output the JSON object
echo($resultArray[0]['json_build_object']);
// Free result
pg_free_result($result);
}
//Get reports pre-flagged with the vtec
if (isset($_GET['preflagreports'])) {
$vtec = $_GET['preflagreports'];
$query = "SELECT * from reports WHERE severe = $1";
$result = pg_query_params($dbconn, $query, array($vtec)) 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);
}
//Get reports within polygon for arbitary time after end time
if (isset($_GET['reports'])) {
$vtec = $_GET['reports'];
if (isset($_GET['hours'])) {
$hours = $_GET['hours'];
} else {
$hours = 6;
}
//echo $hours;
$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());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
pg_free_result($result);
}
//Get point power outages within polygon + arb time, default 60 minutes
if (isset($_GET['outages'])) {
$vtec = $_GET['outages'];
if (isset($_GET['hours'])) {
$hours = $_GET['hours'];
} else {
$hours = 1;
}
//echo $hours;
$query = "SELECT power.lat,power.lon,power.peakoutage,power.cause,power.derivedstart,power.lastchange from power,svr where ST_Contains(svr.nwspoly, power.realgeom) and vtec = $1 and derivedstart > svr.issue AND derivedstart < svr.issue + (INTERVAL '1 h' * $2)";
$result = pg_query_params($dbconn, $query, array($vtec,$hours)) 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);
}
//no gets, curent point outage info
if(empty($_GET)) {
$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);
echo($resultArray[0]['json_build_object']);
pg_free_result($result);
}
//For real time mapping
if($_GET['verify'] ?? null) {
$query = "select id, lat::Numeric(16,3), lon::Numeric(16,3),issue,to_char(initialdtg, 'yyyy/mm/dd hh24:mi') as initialdtg,rawemail,concat(county,' ',state,'\n',place) as place,comments,lsr::text,severe from reports where severe is not null and processed = true order by initialdtg desc";
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
}
//no gets, curent point outage info
if (isset($_GET['rtcad'])) {
if (isset($_GET['hours'])) {
$hours = $_GET['hours'];
}
else {
$hours = 6;
}
$query = "
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', utcinitialdtg,
'county', county,
'state', state,
'issue', issue,
'rawemail', rawemail,
'place', place,
'comments', comments
)
) ORDER BY initialdtg DESC
)
)
FROM reports
WHERE lat is not null and utcinitialdtg >= NOW() - INTERVAL '1 hour' * $1;
";
// Prepare and execute the query using pg_query_params
$result = pg_query_params($dbconn, $query, array($hours))
or die('Query failed: ' . pg_last_error());
// Fetch the result
$resultArray = pg_fetch_all($result);
// Output the JSON object
echo($resultArray[0]['json_build_object']);
// Free result
pg_free_result($result);
}
//Stats
if (isset($_GET['stats'])) {
$query = "SELECT county, state, MAX(emailtime), count(*) FROM reports where county is not null and (state = 'WV' or state = 'VA' or state = 'KY' or state = 'OH') GROUP BY county, state";
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
}
//Get METAR Array for Jelly Bean
if (isset($_GET['metars'])) {
if (isset($_GET['start'])) {
$start = $_GET['start'];
}
if (isset($_GET['end'])) {
$end = $_GET['end'];
}
$query = "SELECT icao,temp,dewp,wx,precip1,precip3,precip6,raw,obtime,stationname,lat,lon from metars where obtime - interval '45 minutes' > $1 and obtime < $2 order by lon asc";
$result = pg_query_params($dbconn, $query, array($start,$end)) or die('Query failed: ' . pg_last_error());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
} //echo($array);
echo json_encode($array);
pg_free_result($result);
}
if (isset($_GET['news'])) {
//$query = "SELECT headline, summary, imageurl, source, storylink, updated from news where notrelevant is not true";
$query = "
SELECT
*,
CASE
WHEN concat(summary, ' ', headline) ILIKE ANY (ARRAY[
'%weather%', '%flood%', '%fire%', '%fog%', '%snow%', '%emergency%'
'%wind%', '%ice%', '%rain%', '%power%', '%explosion%',
'%drown%', '%stream%', '%river%', '%air%', '%wind%',
'%river%', '%ice%', '%creek%', '%crash%', '%thunder%',
'%fog%', '%spill%', '%pileup%', '%pile-up%', '%gust%',
'%fatal%', '%injury%', '%sleet%', '%injured%', '%frost%',
'%culvert%', '%slippery%', '%wildfire%', '%tornado%',
'%thunderstorm%', '%downburst%', '%microburst%', '%crash%', '%heatstroke%', '%derecho%'
'%lightning%', '%hypothermia%', '%slide%', '%flow%', '%ski%', '%water%', '%innundation%'
]) THEN 2
WHEN concat(summary, ' ', headline) ILIKE ANY (ARRAY[
'%legislative%','%history%','%budget%','%birthday%','%banning%','%academic%','%tuna%','%Service Forecast%', '%DOGE%','%demonstrators%','%forum%','%health%','%fraud%','%birthday%', '%egg%', '%eggs%', '%collector%', '%church%', ' %crypto%'
]) THEN 0
ELSE 1
END AS relevance_level
FROM news WHERE timeutc > NOW() - INTERVAL '18 hours'
ORDER BY relevance_level DESC, timeutc DESC
";
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
}
if (isset($_GET['news2'])) {
$query = "
SELECT
*,
(SELECT COUNT(*)
FROM unnest(ARRAY[
'weather', 'flood', 'fire', 'fog', 'snow', 'emergency',
'wind', 'ice', 'rain', 'power', 'explosion', 'warmer', 'colder',
'drown', 'stream', 'river', 'air', 'wind', 'destroyed', 'rime', 'glaze',
'river', 'ice', 'creek', 'crash', 'thunder', 'spinup', 'black ice', 'aircraft',
'fog', 'spill', 'pileup', 'pile-up', 'gust', 'frozen', 'funnel', 'rainfall',
'fatal', 'injury', 'sleet', 'injured', 'frost', 'dead', 'death', 'landslide',
'culvert', 'slippery', 'wildfire', 'tornado', 'blizzard', 'creek', 'hail',
'thunderstorm', 'downburst', 'microburst', 'crash', 'heatstroke', 'derecho',
'lightning', 'hypothermia', 'slide', 'flow', 'ski', 'water', 'inundation', 'victim',
'victims', 'flooding','flooded','snowing','freezing rain','clouds','cloud','storm'
]) AS pattern
WHERE concat(summary, ' ', headline) ~* ('\y' || pattern || '\y')) AS match_count
FROM news
WHERE timeutc > NOW() - INTERVAL '18 hours'
ORDER BY nlpscore DESC, timeutc DESC
";
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
}
if (isset($_GET['news3old'])) {
$query = "
SELECT * FROM news WHERE (timeutc > NOW() - INTERVAL '24 hours' and nlpscore > 0.1) or (timeutc > NOW() - INTERVAL '6 hours') ORDER BY nlpscore DESC, timeutc DESC";
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
}
if (isset($_GET['news3'])) {
// Corrected query with NULLS LAST
$query = "
SELECT * FROM news
WHERE (timeutc > NOW() - INTERVAL '24 hours' AND impact_score > 25)
OR (timeutc > NOW() - INTERVAL '6 hours' and impact_score > 0)
ORDER BY impact_score DESC NULLS LAST, timeutc DESC limit 50";
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
$array = []; // It's good practice to initialize the array
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
}
// --- FIXED SECTION: newsarchive ---
if (isset($_GET['newsarchive'])) {
// Initialize variables
$start = isset($_GET['start']) ? $_GET['start'] : null;
$end = isset($_GET['end']) ? $_GET['end'] : null;
$keys = isset($_GET['key']) ? $_GET['key'] : [];
// Convert keys to an array if it's a string
if (is_string($keys)) {
$keys = explode(',', $keys);
}
$patterns = array_map(function($term) {
return trim($term);
}, $keys);
// Handle case with no search terms
if (empty($patterns)) {
$query = "SELECT * FROM news";
$params = [];
} else {
// Build parameter placeholders
$placeholders = [];
for ($i = 1; $i <= count($patterns); $i++) {
// FIXED: Use concatenation to create "$1::text"
$placeholders[] = '$' . $i . '::text';
}
$placeholder_string = implode(',', $placeholders);
$query = "
SELECT
n.*,
(
SELECT COUNT(*)
FROM unnest(ARRAY[{$placeholder_string}]::text[]) AS pattern
WHERE concat(n.summary, ' ', n.headline) ILIKE pattern
) AS match_count
FROM news n
WHERE concat(summary, ' ', headline) ILIKE ANY (ARRAY[{$placeholder_string}]::text[])
";
$params = array_map(function($term) { return "%{$term}%"; }, $patterns);
}
// Add date filters if provided
$param_count = count($patterns);
if ($start) {
$param_count++;
// FIXED: Use concatenation instead of deprecated interpolation
$query .= " AND timeutc >= $" . $param_count;
$params[] = $start;
}
if ($end) {
$param_count++;
// FIXED: Use concatenation instead of deprecated interpolation
$query .= " AND timeutc <= $" . $param_count;
$params[] = $end;
}
$query .= " ORDER BY match_count DESC, timeutc desc";
// Execute query
$result = pg_query_params($query, $params) or die('Query failed: ' . pg_last_error());
$array = [];
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
}
if (isset($_GET['wv511'])) {
$query = "SELECT jsonb_build_object(
'type', 'FeatureCollection',
'features', jsonb_agg(
jsonb_build_object(
'type', 'Feature',
'geometry', ST_AsGeoJSON(geom)::jsonb,
'properties', jsonb_build_object(
'type', name,
'reported', first_seen,
'end', last_seen_in_feed,
'county', county,
'state', st,
'remark', latest_description,
'lat', st_y(st_centroid(geom)),
'lon', st_x(st_centroid(geom))
)
)
)
) as geojson
FROM public.wv511
WHERE last_updated > NOW() - INTERVAL '2 hours'";
// Prepare and execute the query
$result = pg_query($dbconn, $query);
if (!$result) {
header('Content-Type: application/json');
echo json_encode(['error' => 'Query failed: ' . pg_last_error()]);
exit;
}
// Fetch the result
$resultArray = pg_fetch_all($result);
// Check if we got results
if ($resultArray && isset($resultArray[0]['geojson'])) {
header('Content-Type: application/json');
echo $resultArray[0]['geojson']; // Direct output since it's already JSON from jsonb_build_object
} else {
header('Content-Type: application/json');
echo json_encode(['error' => 'No results found']);
}
// Free result and close connection
pg_free_result($result);
// pg_close($dbconn); // Uncomment if you want to close the connection
}
if (isset($_GET['ky511'])) {
$query = "SELECT jsonb_build_object(
'type', 'FeatureCollection',
'features', jsonb_agg(
jsonb_build_object(
'type', 'Feature',
'geometry', ST_AsGeoJSON(geom)::jsonb,
'properties', jsonb_build_object(
'reported', first_seen,
'end', last_seen_in_feed,
'county', county,
'state', st,
'remark', latest_description,
'lat', st_y(st_centroid(geom)),
'lon', st_x(st_centroid(geom))
)
)
)
) as geojson
FROM ky511.ky511
WHERE last_updated > NOW() - INTERVAL '2 hours'";
// Prepare and execute the query
$result = pg_query($dbconn, $query);
if (!$result) {
header('Content-Type: application/json');
echo json_encode(['error' => 'Query failed: ' . pg_last_error()]);
exit;
}
// Fetch the result
$resultArray = pg_fetch_all($result);
// Check if we got results
if ($resultArray && isset($resultArray[0]['geojson'])) {
header('Content-Type: application/json');
echo $resultArray[0]['geojson']; // Direct output since it's already JSON from jsonb_build_object
} else {
header('Content-Type: application/json');
echo json_encode(['error' => 'No results found']);
}
// Free result and close connection
pg_free_result($result);
// pg_close($dbconn); // Uncomment if you want to close the connection
}
if (isset($_GET['getCombinedTable'])) {
// Combined SQL query using UNION ALL with CAST for 'id'
$query = "
SELECT * FROM (
-- OHGO Query
SELECT
'ohgo' AS source,
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,
CAST(id AS TEXT) AS id, -- Cast id to TEXT
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 '24 hours') AND start > now() - interval '144 hours'
UNION ALL
-- WV511 Query
SELECT
'wv511' AS source,
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,
CAST(id AS TEXT) AS id, -- Cast id to TEXT
wv511.name as category,
NULL AS roadstatus,
cwa,
county,
st as state,
'Map Link' AS location,
NULL AS routename,
latest_description as description,
TO_CHAR(first_seen, 'YYYY-MM-DD HH24:MI') AS start,
TO_CHAR(last_seen_in_feed, 'YYYY-MM-DD HH24:MI') AS endtime,
TO_CHAR(last_updated, 'YYYY-MM-DD HH24:MI') AS lastupdate
FROM wv511
WHERE (last_seen_in_feed IS NULL OR last_seen_in_feed > NOW() - INTERVAL '24 hours') AND first_seen > now() - interval '144 hours'
and wv511.name !~ 'Crash' and
wv511.name !~ 'Vehicle' and wv511.name !~ 'Dead Animal' and wv511.name !~ 'Debris in Roadway' and wv511.name !~ 'Congestion-Delay' and
wv511.name !~ 'Pot hole' and wv511.name !~ 'Debris On Bridge' and wv511.name !~ 'Attenuator' and wv511.name !~ 'Pedestrian' and
wv511.name !~ 'Bridge Closed' and wv511.name !~ 'Truck on escape' and wv511.name !~ 'Bridge Incident' and wv511.name !~ 'Escape Ramp' AND
wv511.name !~ 'Signal'
UNION ALL
-- KY511 Query
SELECT
'ky511.ky511' AS source,
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,
CAST(id AS TEXT) AS id, -- Cast id to TEXT
'Weather' as category,
NULL AS roadstatus,
cwa,
county,
st as state,
'Map Link' AS location,
NULL AS routename,
latest_description as description,
TO_CHAR(first_seen, 'YYYY-MM-DD HH24:MI') AS start,
TO_CHAR(last_seen_in_feed, 'YYYY-MM-DD HH24:MI') AS endtime,
TO_CHAR(last_updated, 'YYYY-MM-DD HH24:MI') AS lastupdate
FROM ky511.ky511
WHERE (last_seen_in_feed IS NULL OR last_seen_in_feed > NOW() - INTERVAL '24 hours') AND first_seen > now() - interval '144 hours'
) AS combined_data
ORDER BY start ASC;
";
// Execute the query
$result = pg_query($dbconn, $query);
// Set header before any output
header('Content-Type: application/json');
if (!$result) {
// Output error as JSON
echo json_encode(['error' => 'Combined query failed: ' . pg_last_error($dbconn)]);
// Close connection if needed
// pg_close($dbconn);
exit;
}
// Fetch results into an array
$dataArray = [];
while ($row = pg_fetch_assoc($result)) {
$dataArray[] = $row;
}
if ($dataArray === false) {
echo json_encode(['error' => 'Failed to fetch results.']);
pg_free_result($result);
// pg_close($dbconn);
exit;
}
// Output the combined results as JSON
echo json_encode($dataArray);
// Free result memory
pg_free_result($result);
// Optionally close the connection
// pg_close($dbconn);
exit; // Stop script execution
}
if (isset($_GET['updater'])) {
$allowedTables = ['wv511', 'ky511.ky511', 'ohgo'];
if (isset($_GET['lsr']) && isset($_GET['id']) && isset($_GET['table'])) {
// --- Handle LSR Update ---
$requestedTable = $_GET['table'];
$lsrInput = $_GET['lsr'];
$idInput = $_GET['id']; // ID validation missing here, see note below
if (!in_array($requestedTable, $allowedTables)) {
http_response_code(400);
die('Error (LSR): Invalid table specified.');
}
$lsrflag = ($lsrInput === 'true') ? 'true' : 'false';
$id = $idInput; // WARNING: ID is not validated/sanitized here for LSR!
$tableNameEscaped = $requestedTable;
// Note: {$tableNameEscaped} is VALID complex syntax. The issue was with ${var}
$query = "UPDATE {$tableNameEscaped} SET lsr = $1 WHERE id = $2";
$result = pg_query_params($dbconn, $query, array($lsrflag, $id));
if ($result) {
$affectedRows = pg_affected_rows($result);
echo "LSR Update successful for table '{$requestedTable}'. {$affectedRows} row(s) affected for ID {$id}.";
} else {
http_response_code(500);
error_log("LSR Query failed for table '{$requestedTable}', ID {$id}: " . pg_last_error($dbconn));
die('Error: The LSR update query failed.');
}
} else if (isset($_GET['hide']) && isset($_GET['id']) && isset($_GET['table'])) {
// --- Handle Hide Update ---
$requestedTable = $_GET['table'];
$hideInput = $_GET['hide'];
$idInput = $_GET['id'];
if (!in_array($requestedTable, $allowedTables)) {
http_response_code(400);
die('Error (Hide): Invalid table specified.');
}
$hideflag = ($hideInput === 'true') ? 'true' : 'false';
// Use INT validation for ID here - make sure this matches your DB column type
$id = $idInput;
$tableNameEscaped = $requestedTable;
$query = "UPDATE {$tableNameEscaped} SET hide = $1 WHERE id = $2";
$result = pg_query_params($dbconn, $query, array($hideflag, $id));
if ($result) {
$affectedRows = pg_affected_rows($result);
echo "Hide Update successful for table '{$requestedTable}'. {$affectedRows} row(s) affected for ID {$id}.";
} else {
http_response_code(500);
error_log("Hide Query failed for table '{$requestedTable}', ID {$id}: " . pg_last_error($dbconn));
die('Error: The Hide update query failed.');
}
} else {
// --- Handle Missing Parameters Error ---
// Neither 'lsr' nor 'hide' (along with id and table) were provided correctly.
http_response_code(400); // Bad Request
// Check which parameters *are* present to give a potentially more helpful error
$missing = [];
if (!isset($_GET['id'])) $missing[] = '"id"';
if (!isset($_GET['table'])) $missing[] = '"table"';
if (!isset($_GET['lsr']) && !isset($_GET['hide'])) {
$missing[] = 'action ("lsr" or "hide")';
} else if (isset($_GET['lsr']) && (!isset($_GET['id']) || !isset($_GET['table']))) {
// LSR was specified, but others missing
} else if (isset($_GET['hide']) && (!isset($_GET['id']) || !isset($_GET['table']))) {
// Hide was specified, but others missing
}
if (!empty($missing)) {
die('Error: Missing required parameter(s): ' . implode(', ', $missing) . '. Please provide a valid action ("lsr" or "hide"), "id", and "table".');
} else {
// Should ideally not happen with the logic above, but as a fallback:
die('Error: Invalid request parameters. Please provide action ("lsr" or "hide"), "id", and "table".');
}
}
}
pg_close($dbconn);
?>

View File

@@ -239,7 +239,7 @@
const ids = urlParams.get('id'); const ids = urlParams.get('id');
try { try {
const svrResponse = await fetch(`lsr.php?vtec=${vtec}`); const svrResponse = await fetch(`main.php?service=lsr&vtec=${vtec}`);
const geojsonsvr = await svrResponse.json(); const geojsonsvr = await svrResponse.json();
geoJSONsvr.clearLayers().addData(geojsonsvr); geoJSONsvr.clearLayers().addData(geojsonsvr);
@@ -250,7 +250,7 @@
} }
if (ids) { if (ids) {
const powerResponse = await fetch(`powerapi.php?poweridsgeojson=${ids}`); const powerResponse = await fetch(`main.php?service=powerapi&poweridsgeojson=${ids}`);
const geojsonPoint = await powerResponse.json(); const geojsonPoint = await powerResponse.json();
geoJSONPoint.clearLayers().addData(geojsonPoint); geoJSONPoint.clearLayers().addData(geojsonPoint);
} }

3119
main.php Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -235,7 +235,7 @@ camlayer = L.layerGroup();
$.getJSON('cam.php', function(data){ $.getJSON('main.php?service=cams', function(data){
var wild = Math.random(); var wild = Math.random();
for(var i in data){ for(var i in data){
//var greenIcon = new LeafIcon({iconUrl: 'camdata/' + data[i].lastimage}) //var greenIcon = new LeafIcon({iconUrl: 'camdata/' + data[i].lastimage})
@@ -274,7 +274,7 @@ function onMarkerNotHover(itemsID){
function updateIcon() { function updateIcon() {
var wild = Math.random(); var wild = Math.random();
$.getJSON('cam.php', function(data){ $.getJSON('main.php?service=cams', function(data){
for(var i in data){ for(var i in data){
//var greenIcon = new LeafIcon({iconUrl: 'camdata/' + data[i].lastimage}); //var greenIcon = new LeafIcon({iconUrl: 'camdata/' + data[i].lastimage});
var greenIcon = new LeafIcon({iconUrl: 'camdata/' + data[i].camid + "/latest.jpg"}) var greenIcon = new LeafIcon({iconUrl: 'camdata/' + data[i].camid + "/latest.jpg"})

View File

@@ -182,7 +182,7 @@ function getmetars(startDateStr, endDateStr, startZulu, endZulu) {
} }
// --- Fetch Data --- // --- Fetch Data ---
$.getJSON(`lsr.php?metars=true&start=${startDateStr}&end=${endDateStr}`, function(weatherdata) { $.getJSON(`main.php?service=lsr&metars=true&start=${startDateStr}&end=${endDateStr}`, function(weatherdata) {
// Ensure weatherdata is an array // Ensure weatherdata is an array
weatherdata = weatherdata || []; weatherdata = weatherdata || [];

73
mp4.php
View File

@@ -1,73 +0,0 @@
<?php
//error_reporting(E_ALL);
ini_set('display_errors', 'off');
// Create an array containing file paths, resource var (initialized with imagecreatefromXXX),
// image URLs or even binary code from image files.
// All sorted in order to appear.
//$array=json_decode($_POST['camarray']);
// Use an array containing file paths, resource vars (initialized with imagecreatefromXXX),
// image URLs or binary image data.
//$elements = $_POST['data'];
$elements = $_POST['data'];
$numimages = $_POST['images'];
$delay = $_POST['delay'];
$lastdelay = $_POST['lastdelay'];
$maxh = $_POST['maxh'];
$maxv = $_POST['maxv'];
if (! is_numeric($maxh)) {
$maxh = 500;
}
if (! is_numeric($maxv)) {
$maxv = 400;
}
$numimages = $numimages - 1;
//$elements = json_decode($elements);
$inputfiles = "";
//foreach ($elements as &$value) {
// $newin = $value. ":";
// $inputfiles = $inputfiles.$newin;
//}
//$inputfiles = rtrim($inputfiles, ":");
//echo $inputfiles;
//echo "ffmpeg -i concat:{$inputfiles} output.avi 2>&1";
//echo shell_exec("ffmpeg -i concat:{$inputfiles} output.avi 2>&1");
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}";
}
}
//echo "convert -delay 20 {$inputfiles} output.gif 2>&1";
$gif = shell_exec("convert {$inputfiles} -resize {$maxh}x{$maxv}\> -layers Optimize gif:-");
echo base64_encode($gif);
exit;
?>

View File

@@ -195,7 +195,7 @@
const PIXELS_PER_SECOND_SPEED = 150; // Adjust this value to control scroll speed. Higher is faster. const PIXELS_PER_SECOND_SPEED = 150; // Adjust this value to control scroll speed. Higher is faster.
let lastTickerUpdateTime = Date.now(); let lastTickerUpdateTime = Date.now();
let lastNewsData = null; let lastNewsData = null;
let currentNewsUrl = 'https://wx.stoat.org/lsr.php?news3=potato'; let currentNewsUrl = 'https://wx.stoat.org/main.php?service=lsr&news3=potato';
let nextTickerHtml = null; let nextTickerHtml = null;
let animationId = null; let animationId = null;
@@ -229,7 +229,7 @@
} }
} }
function fetchAndDisplayNews(url = 'https://wx.stoat.org/lsr.php?news3=potato') { function fetchAndDisplayNews(url = 'https://wx.stoat.org/main.php?service=lsr&news3=potato') {
// Update the current URL if provided // Update the current URL if provided
if (url) { if (url) {
currentNewsUrl = url; currentNewsUrl = url;
@@ -369,7 +369,7 @@
const keyTerms = document.getElementById("keyTerms").value; const keyTerms = document.getElementById("keyTerms").value;
const terms = keyTerms.split(','); const terms = keyTerms.split(',');
let arrayterms = terms.map(term => `key[]=${encodeURIComponent(term)}`).join('&'); let arrayterms = terms.map(term => `key[]=${encodeURIComponent(term)}`).join('&');
url = `lsr.php?newsarchive=true&start=${start}&end=${end}&${arrayterms}`; url = `main.php?service=lsr&newsarchive=true&start=${start}&end=${end}&${arrayterms}`;
// Clear the cache to force an update // Clear the cache to force an update
lastNewsData = null; lastNewsData = null;
fetchAndDisplayNews(url); fetchAndDisplayNews(url);

View File

@@ -195,7 +195,7 @@
const PIXELS_PER_SECOND_SPEED = 150; // Adjust this value to control scroll speed. Higher is faster. const PIXELS_PER_SECOND_SPEED = 150; // Adjust this value to control scroll speed. Higher is faster.
let lastTickerUpdateTime = Date.now(); let lastTickerUpdateTime = Date.now();
let lastNewsData = null; let lastNewsData = null;
let currentNewsUrl = 'https://wx.stoat.org/lsr.php?news3=potato'; let currentNewsUrl = 'https://wx.stoat.org/main.php?service=lsr&news3=potato';
let nextTickerHtml = null; let nextTickerHtml = null;
let animationId = null; let animationId = null;
@@ -229,7 +229,7 @@
} }
} }
function fetchAndDisplayNews(url = 'https://wx.stoat.org/lsr.php?news3=potato') { function fetchAndDisplayNews(url = 'https://wx.stoat.org/main.php?service=lsr&news3=potato') {
// Update the current URL if provided // Update the current URL if provided
if (url) { if (url) {
currentNewsUrl = url; currentNewsUrl = url;
@@ -369,7 +369,7 @@
const keyTerms = document.getElementById("keyTerms").value; const keyTerms = document.getElementById("keyTerms").value;
const terms = keyTerms.split(','); const terms = keyTerms.split(',');
let arrayterms = terms.map(term => `key[]=${encodeURIComponent(term)}`).join('&'); let arrayterms = terms.map(term => `key[]=${encodeURIComponent(term)}`).join('&');
url = `lsr.php?newsarchive=true&start=${start}&end=${end}&${arrayterms}`; url = `main.php?service=lsr&newsarchive=true&start=${start}&end=${end}&${arrayterms}`;
// Clear the cache to force an update // Clear the cache to force an update
lastNewsData = null; lastNewsData = null;
fetchAndDisplayNews(url); fetchAndDisplayNews(url);

411
nws.php
View File

@@ -1,411 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
//no gets, curent point outage info
if(empty($_GET)) {
$query = "SELECT * FROM nws order by lastupdate asc";
$result = pg_query($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);
}
if (isset($_GET['officestats11'])) {
// Get all unique lastupdate dates from the database
$date_query = "SELECT DISTINCT DATE(lastupdate) as unique_date
FROM nws
WHERE status = 'active'
AND office ~ 'WFO'
ORDER BY unique_date ASC"; // Changed from DESC to ASC
$date_result = pg_query($dbconn, $date_query)
or die('Date query failed: ' . pg_last_error());
$datetime_points = [];
while ($row = pg_fetch_array($date_result, null, PGSQL_ASSOC)) {
$dt = DateTime::createFromFormat('Y-m-d', $row['unique_date']);
$dt->setTime(23, 59, 59);
$datetime_points[] = $dt->format('Y-m-d H:i:s');
}
pg_free_result($date_result);
if (empty($datetime_points)) {
echo json_encode(['error' => 'No valid datetime points found in database']);
exit;
}
// Debug: Log the datetime points
error_log("Processed datetime points: " . implode(', ', $datetime_points));
$query = "WITH latest_records AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY personid ORDER BY ABS(EXTRACT(EPOCH FROM (lastupdate - CAST($1 AS TIMESTAMP)))) ASC) AS rn
FROM nws
WHERE status = 'active'
AND lastupdate <= CAST($1 AS TIMESTAMP) + INTERVAL '1 day'
AND lastupdate >= CAST($1 AS TIMESTAMP) - INTERVAL '3 days'
AND office ~ 'WFO'
),
otitle_counts AS (
SELECT
office,
otitle,
COUNT(*) AS otitle_count
FROM latest_records
WHERE rn = 1
GROUP BY office, otitle
)
SELECT
lr.office,
COUNT(DISTINCT lr.personid) AS unique_person_count,
(SELECT ARRAY_AGG(json_obj ORDER BY json_obj->>'otitle' ASC)
FROM (SELECT DISTINCT jsonb_build_object(
'otitle', tc2.otitle,
'count', tc2.otitle_count
) AS json_obj
FROM otitle_counts tc2
WHERE tc2.office = lr.office) AS subquery
) AS title_counts_array
FROM latest_records lr
WHERE lr.rn = 1
GROUP BY lr.office
ORDER BY unique_person_count DESC";
$results_array = [];
// Execute query for each unique datetime
foreach ($datetime_points as $datetime) {
$result = pg_query_params($dbconn, $query, array($datetime))
or die('Query failed: ' . pg_last_error());
$office_data = [];
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$office_data[] = $line;
}
// Store results with the datetime used
$results_array[] = [
'provided_datetime' => $datetime,
'data' => $office_data
];
pg_free_result($result);
}
// Debug: Log before output
error_log("Final results: " . json_encode($results_array));
// Return JSON encoded results
echo json_encode($results_array);
}
if (isset($_GET['officestats'])) {
if (isset($_GET['datetime'])) {
// Expecting datetime as comma-separated dates or JSON array
$input_dates = is_array($_GET['datetime'])
? $_GET['datetime']
: explode(',', $_GET['datetime']);
// Process each date and set to end of day
$input_dates = array_unique($input_dates);
$input_dates = array_values($input_dates);
$datetime_points = [];
foreach ($input_dates as $date) {
$dt = DateTime::createFromFormat('m-d-Y', trim($date));
if ($dt === false) {
error_log("Invalid date skipped: " . trim($date));
continue;
}
$dt->setTime(23, 59, 59);
$datetime_points[] = $dt->format('Y-m-d H:i:s');
}
// Ensure uniqueness and reindex
$datetime_points = array_unique($datetime_points);
$datetime_points = array_values($datetime_points);
// Debug: Log the datetime points
error_log("Processed datetime points: " . implode(', ', $datetime_points));
if (empty($datetime_points)) {
echo json_encode(['error' => 'No valid datetime points provided']);
exit;
}
$query = "WITH latest_records AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY personid ORDER BY ABS(EXTRACT(EPOCH FROM (lastupdate - CAST($1 AS TIMESTAMP)))) ASC) AS rn
FROM nws
WHERE status = 'active'
AND lastupdate <= CAST($1 AS TIMESTAMP) + INTERVAL '1 day'
AND lastupdate >= CAST($1 AS TIMESTAMP) - INTERVAL '3 days'
AND office ~ 'WFO'
),
otitle_counts AS (
SELECT
office,
otitle,
COUNT(*) AS otitle_count
FROM latest_records
WHERE rn = 1
GROUP BY office, otitle
)
SELECT
lr.office,
COUNT(DISTINCT lr.personid) AS unique_person_count,
(SELECT ARRAY_AGG(json_obj ORDER BY json_obj->>'otitle' ASC)
FROM (SELECT DISTINCT jsonb_build_object(
'otitle', tc2.otitle,
'count', tc2.otitle_count
) AS json_obj
FROM otitle_counts tc2
WHERE tc2.office = lr.office) AS subquery
) AS title_counts_array
FROM latest_records lr
WHERE lr.rn = 1
GROUP BY lr.office
ORDER BY unique_person_count DESC";
$results_array = [];
// Execute query for each provided datetime
foreach ($datetime_points as $datetime) {
$result = pg_query_params($dbconn, $query, array($datetime))
or die('Query failed: ' . pg_last_error());
$office_data = [];
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$office_data[] = $line;
}
// Store results with the datetime used
$results_array[] = [
'provided_datetime' => $datetime,
'data' => $office_data
];
pg_free_result($result);
}
// Debug: Log before output
error_log("Final results: " . json_encode($results_array));
// Return JSON encoded results
echo json_encode($results_array);
}
}
if (isset($_GET['regionstats'])) {
if (isset($_GET['datetime'])) {
// Expecting datetime as comma-separated dates or JSON array
$input_dates = is_array($_GET['datetime'])
? $_GET['datetime']
: explode(',', $_GET['datetime']);
// Process each date and set to end of day
$input_dates = array_unique($input_dates);
$input_dates = array_values($input_dates);
$datetime_points = [];
foreach ($input_dates as $date) {
$dt = DateTime::createFromFormat('m-d-Y', trim($date));
if ($dt === false) {
error_log("Invalid date skipped: " . trim($date));
continue;
}
$dt->setTime(23, 59, 59);
$datetime_points[] = $dt->format('Y-m-d H:i:s');
}
// Ensure uniqueness and reindex
$datetime_points = array_unique($datetime_points);
$datetime_points = array_values($datetime_points);
// Debug: Log the datetime points
error_log("Processed datetime points: " . implode(', ', $datetime_points));
if (empty($datetime_points)) {
echo json_encode(['error' => 'No valid datetime points provided']);
exit;
}
$query = "WITH latest_records AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY personid ORDER BY ABS(EXTRACT(EPOCH FROM (lastupdate - CAST($1 AS TIMESTAMP)))) ASC) AS rn,
SUBSTRING(office FROM 'NWS/([EWPASC]R)') AS region
FROM nws
WHERE lastupdate <= CAST($1 AS TIMESTAMP) + INTERVAL '1 day' - INTERVAL '1 second'
AND lastupdate >= CAST($1 AS TIMESTAMP) - INTERVAL '3 days'
AND office ~ 'NWS/[EWPASC]R'
and status = 'active'
),
otitle_counts AS (
SELECT
region,
otitle,
COUNT(*) AS otitle_count
FROM latest_records
WHERE rn = 1
GROUP BY region, otitle
)
SELECT
lr.region,
COUNT(DISTINCT lr.personid) AS unique_person_count,
(SELECT ARRAY_AGG(json_obj ORDER BY json_obj->>'otitle' ASC)
FROM (SELECT DISTINCT jsonb_build_object(
'otitle', tc2.otitle,
'count', tc2.otitle_count
) AS json_obj
FROM otitle_counts tc2
WHERE tc2.region = lr.region) AS subquery
) AS title_counts_array
FROM latest_records lr
WHERE lr.rn = 1
GROUP BY lr.region
ORDER BY unique_person_count DESC";
$results_array = [];
// Execute query for each provided datetime
foreach ($datetime_points as $datetime) {
$result = pg_query_params($dbconn, $query, array($datetime))
or die('Query failed: ' . pg_last_error());
$office_data = [];
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$office_data[] = $line;
}
// Store results with the datetime used
$results_array[] = [
'provided_datetime' => $datetime,
'data' => $office_data
];
pg_free_result($result);
}
// Debug: Log before output
//error_log("Final results: " . json_encode($results_array));
// Return JSON encoded results
echo json_encode($results_array);
}
}
if (isset($_GET['drilldown'])) {
if (isset($_GET['datetime'])) {
// Expecting datetime as comma-separated dates or JSON array
$input_dates = is_array($_GET['datetime'])
? $_GET['datetime']
: explode(',', $_GET['datetime']);
// Process each date and set to end of day
$datetime_points = [];
foreach ($input_dates as $date) {
// Specify the exact format of your input date string
$dt = DateTime::createFromFormat('m-d-Y', trim($date)); // Adjust format as needed
if ($dt === false) {
// Handle invalid date
continue;
}
$dt->setTime(23, 59, 59);
$datetime_points[] = $dt->format('Y-m-d H:i:s');
}
$datetime_points = array_unique($datetime_points);
$datetime_points = array_values($datetime_points);
$query = "WITH latest_records AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY personid ORDER BY lastupdate DESC) AS rn
FROM nws
WHERE status = 'active'
AND lastupdate <= $1
),
otitle_counts AS (
SELECT
office,
otitle,
COUNT(*) AS otitle_count
FROM latest_records
WHERE rn = 1
GROUP BY office, otitle
)
SELECT
lr.office,
COUNT(DISTINCT lr.personid) AS unique_person_count,
(SELECT ARRAY_AGG(json_obj ORDER BY json_obj->>'otitle' ASC)
FROM (SELECT DISTINCT jsonb_build_object(
'otitle', tc2.otitle,
'count', tc2.otitle_count
) AS json_obj
FROM otitle_counts tc2
WHERE tc2.office = lr.office) AS subquery
) AS title_counts_array
FROM latest_records lr
WHERE lr.rn = 1
GROUP BY lr.office
ORDER BY unique_person_count DESC";
$results_array = [];
// Execute query for each provided datetime
foreach ($datetime_points as $datetime) {
$result = pg_query_params($dbconn, $query, array($datetime))
or die('Query failed: ' . pg_last_error());
$office_data = [];
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$office_data[] = $line;
}
// Store results with the datetime used
$results_array[] = [
'provided_datetime' => $datetime,
'data' => $office_data
];
pg_free_result($result);
}
// Return JSON encoded results
echo json_encode($results_array);
}
}
pg_close($dbconn);
?>

View File

@@ -83,7 +83,7 @@
var table = new Tabulator("#wunderobs", { var table = new Tabulator("#wunderobs", {
virtualDom: true, virtualDom: true,
virtualDomBuffer: 300, virtualDomBuffer: 300,
ajaxURL: "lsr.php?getCombinedTable=p", ajaxURL: "main.php?service=lsr&getCombinedTable=p",
ajaxConfig: "GET", ajaxConfig: "GET",
autoResize: true, autoResize: true,
initialSort: [{ column: "start", dir: "desc" }], initialSort: [{ column: "start", dir: "desc" }],
@@ -181,7 +181,7 @@
function lsr(lsr, id, source) { function lsr(lsr, id, source) {
$.get({ $.get({
url: 'lsr.php?updater=true&lsr=' + lsr + "&id=" + id + "&table="+source, url: 'main.php?service=lsr&updater=true&lsr=' + lsr + "&id=" + id + "&table="+source,
error: function(xhr, error) { error: function(xhr, error) {
alert('Unable to update, please refresh page'); alert('Unable to update, please refresh page');
} }
@@ -195,7 +195,7 @@
function hide(hide, id, source) { function hide(hide, id, source) {
$.get({ $.get({
url: 'lsr.php?updater=true&hide=' + hide + "&id=" + id + "&table="+source, url: 'main.php?service=lsr&updater=true&hide=' + hide + "&id=" + id + "&table="+source,
error: function(xhr, error) { error: function(xhr, error) {
alert('Unable to update, please refresh page'); alert('Unable to update, please refresh page');
} }

View File

@@ -1,26 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
// Performing SQL query
$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());
// Printing results in HTML
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
// Closing connection
pg_close($dbconn);
?>

12
one.php
View File

@@ -227,14 +227,14 @@ function googleMap(lat, lon){
function getcam() { function getcam() {
if (typeof camtime !== 'undefined') { if (typeof camtime !== 'undefined') {
var reqstring = "individualcam.php?camid=" + camid + '&camimages=' + camimages + '&dtg=' + camtime; var reqstring = "main.php?service=individualcam&camid=" + camid + '&camimages=' + camimages + '&dtg=' + camtime;
} else { } else {
var reqstring = "individualcam.php?camid=" + camid + '&camimages=' + camimages; var reqstring = "main.php?service=individualcam&camid=" + camid + '&camimages=' + camimages;
} }
//$.getJSON("individualcam.php?camid=" + camid + '&camimages=' + camimages, function(data){ //$.getJSON("main.php?service=individualcam&camid=" + camid + '&camimages=' + camimages, function(data){
$.getJSON(reqstring, function(data){ $.getJSON(reqstring, function(data){
var camlist = []; var camlist = [];
var filetimes = []; var filetimes = [];
@@ -291,7 +291,7 @@ function toggleHydro(camid, currentValue) {
// Send AJAX request to update the hydro value // Send AJAX request to update the hydro value
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: 'update_field.php', url: 'main.php?service=update_field',
data: {camid: camid, field: 'hydro', value: newValue}, data: {camid: camid, field: 'hydro', value: newValue},
dataType: 'json', dataType: 'json',
success: function(response) { success: function(response) {
@@ -318,7 +318,7 @@ function toggleAirport(camid, currentValue) {
// Send AJAX request to update the airport value // Send AJAX request to update the airport value
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: 'update_field.php', url: 'main.php?service=update_field',
data: {camid: camid, field: 'airport', value: newValue}, data: {camid: camid, field: 'airport', value: newValue},
dataType: 'json', dataType: 'json',
success: function(response) { success: function(response) {
@@ -344,7 +344,7 @@ function makemp4() {
var maxv = document.getElementById("maxv").value; var maxv = document.getElementById("maxv").value;
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: 'mp4.php', url: 'main.php?service=mp4',
data: {data: externalcam, images: camimages, delay: delay, lastdelay: lastdelay, maxh: maxh, maxv: maxv}, data: {data: externalcam, images: camimages, delay: delay, lastdelay: lastdelay, maxh: maxh, maxv: maxv},
success: function(data) { success: function(data) {
var giffy = document.createElement('img'); var giffy = document.createElement('img');

View File

@@ -54,12 +54,12 @@ Note: move the map slightly after loading data if you want to capture</div>
.tabulator { .tabulator {
font-size: 26px; // change font size font-size: 26px; /* change font size */
padding:4px 4px; padding:4px 4px;
} }
//#mapid { height: 800px; } /*#mapid { height: 800px; }*/
body { body {
padding: 0; padding: 0;
margin: 0; margin: 0;
@@ -75,9 +75,7 @@ Note: move the map slightly after loading data if you want to capture</div>
background: none !important; background: none !important;
} }
#bottombar {
// height: 98%;
}
.box{ .box{
position: absolute; position: absolute;
@@ -173,7 +171,6 @@ input[type=text] {
top: 0px; top: 0px;
position: fixed; position: fixed;
} }
}
</style> </style>
@@ -339,7 +336,7 @@ bufferlink.innerHTML = "Outages Without Buffer";
} else { } else {
var powerapi = 'powerapi.php' var powerapi = 'main.php?service=powerapi'
var countiesjson = 'rlxtest.json' var countiesjson = 'rlxtest.json'
var states = 'states.geojson' var states = 'states.geojson'
} }
@@ -697,7 +694,7 @@ function county_archive_play(start,end) {
$.getJSON(powerapi + `?svr=archive&start=${start}&end=${end}`, function(data3) { $.getJSON(powerapi + `&svr=archive&start=${start}&end=${end}`, function(data3) {
var geojsonsvr = data3; var geojsonsvr = data3;
geoJSONsvr.clearLayers(); geoJSONsvr.clearLayers();
geoJSONsvr.addData(geojsonsvr); geoJSONsvr.addData(geojsonsvr);
@@ -848,7 +845,7 @@ function countyTable(data) {
function update_position() { function update_position() {
$.getJSON(powerapi + '?county=r', function(data) { $.getJSON(powerapi + '&county=r', function(data) {
console.log(data); console.log(data);
const dataMap = {}; const dataMap = {};
@@ -895,7 +892,7 @@ function update_position() {
geoJSONPoint.bringToFront(); geoJSONPoint.bringToFront();
}); });
$.getJSON(powerapi + '?svr=current', function(data2) { $.getJSON(powerapi + '&svr=current', function(data2) {
var geojsonsvr = data2; var geojsonsvr = data2;
geoJSONsvr.clearLayers(); geoJSONsvr.clearLayers();
geoJSONsvr.addData(geojsonsvr); geoJSONsvr.addData(geojsonsvr);
@@ -904,7 +901,7 @@ function update_position() {
}); });
$.getJSON('fire.php', function(data2) { $.getJSON('main.php?service=fire', function(data2) {
var fire = data2; var fire = data2;
geoJSONfire.clearLayers(); geoJSONfire.clearLayers();
geoJSONfire.addData(fire); geoJSONfire.addData(fire);
@@ -912,7 +909,7 @@ function update_position() {
geoJSONfire.removeEventListener('click'); geoJSONfire.removeEventListener('click');
}); });
$.getJSON('lsr.php?ohgo=p', function(data3) { $.getJSON('main.php?service=lsr&ohgo=p', function(data3) {
var flood = data3; var flood = data3;
geoJSONflood.clearLayers(); geoJSONflood.clearLayers();
geoJSONflood.addData(flood); geoJSONflood.addData(flood);

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
// Performing SQL query
//$query = "SELECT distinct on (camid) camid, filepath FROM camdb order by camid,dateutc desc";
$query = "SELECT lat,lon,outagen FROM power WHERE active = true and cwa = 'RLX'";
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
// Printing results in HTML
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
// Closing connection
pg_close($dbconn);
?>

View File

@@ -1,967 +0,0 @@
<?php
// Connecting, selecting database
//$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
// or die('Could not connect: ' . pg_last_error());
try {
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws");
if ($dbconn === false) {
throw new Exception('Could not connect: ' . pg_last_error());
}
} catch (Exception $e) {
http_response_code(500);
die('Database connection failed: ' . $e->getMessage());
}
//no gets, curent point outage info
//if(empty($_GET)) {
//$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,'area_geometry', ST_AsGeoJSON(COALESCE(realareageom, realgeom))::json))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']);
//pg_free_result($result);
//}
if (empty($_GET)) {
try {
$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) {
throw new Exception('Query failed: ' . pg_last_error());
}
$resultArray = pg_fetch_all($result);
// Check if we got results
if ($resultArray && isset($resultArray[0]['json_build_object'])) {
header('Content-Type: application/json');
echo $resultArray[0]['json_build_object'];
} else {
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
}
pg_free_result($result);
} catch (Exception $e) {
http_response_code(500);
die('Query execution failed: ' . $e->getMessage());
}
}
//if (isset($_GET['states'])) {
//$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 states where state = 'WV' or state = 'VA' or state = 'KY' or state ='VA' or state = 'MD' or state = 'PA' or state = 'OH') AS properties) AS features") or die('Query failed: ' . pg_last_error());
// $resultArray = pg_fetch_all($result);
//echo($resultArray[0]['jsonb_build_object']);
//pg_free_result($result);
//}
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) {
http_response_code(500);
header('Content-Type: application/json');
echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]);
exit;
}
}
//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 > '2023-04-01' and update < '2023-04-02' and cwa = 'RLX' group by county,state,update) as potato group by county,state;
////"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",
//"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());
//
//while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
// $array[] = $line;
//}
//echo json_encode($array);
//pg_free_result($result);
//}}}
if (isset($_GET['max'])) {
if (isset($_GET['start']) && isset($_GET['end'])) {
try {
$starttime = pg_escape_string($_GET['start']);
$endtime = pg_escape_string($_GET['end']);
$query = "
SELECT DISTINCT ON (county, state)
max(outage) as 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 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']);
}
}
//county current
//"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",
//if($_GET['county'] ?? null) {
//$result = pg_query_params($dbconn,
//"SELECT DISTINCT ON (county, state) county, state, SUM(outages) as outage, update as time, SUM(served) as served, round((SUM(outages) / SUM(served))*100,2) as perout FROM countyoutages WHERE update = (SELECT MAX(update) FROM countyoutages) AND cwa = $1 GROUP BY county, state, update",
//array('RLX')) or die('Query failed: ' . pg_last_error());
//while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
//$array[] = $line;
//}
//echo json_encode($array ?? null);
//pg_free_result($result);
//}
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((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) {
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 delete after testing
if($_GET['countyarchiveold'] ?? 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 > $2 and update < $3 and cwa = $1 group by county,state,update",
array('RLX',$starttime,$endtime)) 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);
}
if (isset($_GET['countyarchive'])) {
if (isset($_GET['start']) && isset($_GET['end'])) {
try {
$starttime = pg_escape_string($_GET['start']);
$endtime = pg_escape_string($_GET['end']);
$query = "
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
";
$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()]);
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
if($_GET['archivepointold'] ?? 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']);
pg_free_result($result);
}
if (isset($_GET['archivepoint'])) {
try {
if (!isset($_GET['start']) || !isset($_GET['end'])) {
throw new Exception('Both start and end parameters are required');
}
$starttime = pg_escape_string($_GET['start']);
$endtime = pg_escape_string($_GET['end']);
$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
)
)
ORDER BY startguess ASC
)
)
FROM power
WHERE cwa = $1
AND startguess > $2
AND lastchange < $3
";
$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;
}
}
//if($_GET['svr']=='current') {
//$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 < now() and endtime > now()"
//,array('2023-01-01 01:00','2023-02-12 10:00')) or die('Query failed: ' . pg_last_error());
//$resultArray = pg_fetch_all($result);
//echo($resultArray[0]['json_build_object']);
//}
if(@$_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);
echo($resultArray[0]['json_build_object']);
pg_free_result($result);
}
if(@$_GET['svr'] == 'archiveold') {
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 '<pre>'; print_r($resultAarray); echo '</pre>';
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);
}
if (isset($_GET['svr']) && $_GET['svr'] === 'archive') {
try {
$result = null;
if (isset($_GET['start']) && isset($_GET['end'])) {
$starttime = pg_escape_string($_GET['start']);
$endtime = pg_escape_string($_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 > $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;
}
}
if($_GET['svrpolysold'] ?? null) {
$query = "select vtec,outagesvalid,polygonpop,outagesbuffer,lsrids from svr where EXTRACT(EPOCH FROM (current_timestamp - endtime ))/60/60/24 < 60";
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
// Free resultset
pg_free_result($result);
}
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;
}
}
if (isset($_GET['poweridsold'])) {
$powerids = $_GET['powerids'];
// Convert the comma-separated string to an array
$poweridArray = explode(',', $powerids);
// Sanitize and prepare array values for SQL query
$sanitizedIds = array_map('intval', $poweridArray);
// Prepare placeholders for the query
$placeholders = implode(',', array_map(function($i) { return '$' . $i; }, range(1, count($sanitizedIds))));
// Set up your database connection here
// Prepare and execute the query with pg_query_params
$sql = "SELECT lat,lon,lastchange,startguess,peakoutage,cause,lsrtime,lsrref,(lsrtime AT TIME ZONE 'America/New_York')::timestamp as lsrlocal FROM power WHERE id IN ($placeholders)";
$result = pg_query_params($dbconn, $sql, $sanitizedIds);
if (!$result) {
echo 'Query failed: ' . pg_last_error();
exit;
}
// Fetch and output the results
$results = pg_fetch_all($result);
echo json_encode($results);
// Free resultset
// Close the connection
pg_free_result($result);
}
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,
lastchange,
startguess,
peakoutage,
cause,
lsrtime,
lsrref,
(lsrtime AT TIME ZONE 'America/New_York')::timestamp as lsrlocal
FROM power
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;
}
}
if (isset($_GET['poweridsgeojsonold'])) {
$powerids = $_GET['poweridsgeojson'];
$poweridArray = explode(',', $powerids);
$sanitizedIds = array_map('intval', $poweridArray);
$placeholders = implode(',', array_map(function($i) { return '$' . $i; }, range(1, count($sanitizedIds))));
$sql = "
SELECT json_build_object(
'type', 'FeatureCollection',
'features', json_agg(
json_build_object(
'type', 'Feature',
'geometry', ST_AsGeoJSON(realgeom)::json,
'properties', json_build_object(
'id', id,
'time', (startguess AT TIME ZONE 'UTC')::timestamp,
'county', county,
'state', state,
'cause', cause,
'outage', peakoutage,
'lsrtime', (lsrtime AT TIME ZONE 'UTC')::timestamp
)
) ORDER BY startguess ASC
)
)
FROM power
WHERE id IN ($placeholders);";
// $sql = "SELECT lat,lon,lastchange,startguess,peakoutage,cause,lsrtime,lsrref,(lsrtime AT TIME ZONE 'America/New_York')::timestamp as lsrlocal FROM power WHERE id IN ($placeholders)";
$result = pg_query_params($dbconn, $sql, $sanitizedIds);
if (!$result) {
echo 'Query failed: ' . pg_last_error();
exit;
}
$resultArray = pg_fetch_all($result);
// Output the JSON object
echo($resultArray[0]['json_build_object']);
pg_free_result($result);
}
if (isset($_GET['poweridsgeojson'])) {
try {
$powerids = $_GET['poweridsgeojson'];
if (empty($powerids)) {
throw new Exception('No power IDs provided');
}
// Convert and sanitize power IDs
$poweridArray = explode(',', $powerids);
$sanitizedIds = array_filter(array_map('intval', $poweridArray));
if (empty($sanitizedIds)) {
throw new Exception('Invalid power ID format');
}
// Prepare placeholders
$placeholders = implode(',', array_map(function($i) { return '$' . $i; }, range(1, count($sanitizedIds))));
$query = "
SELECT json_build_object(
'type', 'FeatureCollection',
'features', json_agg(
json_build_object(
'type', 'Feature',
'geometry', ST_AsGeoJSON(realgeom)::json,
'properties', json_build_object(
'id', id,
'time', (startguess AT TIME ZONE 'UTC')::timestamp,
'county', county,
'state', state,
'cause', cause,
'outage', peakoutage,
'lsrtime', (lsrtime AT TIME ZONE 'UTC')::timestamp
)
) ORDER BY startguess ASC
)
)
FROM power
WHERE id IN ($placeholders)
";
$result = pg_query_params($dbconn, $query, $sanitizedIds);
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(), 'Invalid') !== false ? 400 : 500;
http_response_code($statusCode);
echo json_encode(['error' => $e->getMessage()]);
exit;
}
}
// Assume $dbconn is your established PostgreSQL connection handle
// Example: $dbconn = pg_connect("host=localhost dbname=yourdb user=youruser password=yourpass");
// if (!$dbconn) { die("Connection failed"); }
if (isset($_GET['polygongeojson'])) {
$result = null; // Initialize result to null for catch block safety
try {
$polygonGeoJsonString = $_GET['polygongeojson'];
if (empty($polygonGeoJsonString)) {
throw new Exception('No GeoJSON polygon provided', 400); // Use exception code for status
}
// 1. Validate if the input is valid JSON
// We decode here primarily to check JSON validity.
// We'll pass the *original string* to PostGIS's ST_GeomFromGeoJSON for robustness.
$polygonGeoJson = json_decode($polygonGeoJsonString);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('Invalid JSON format: ' . json_last_error_msg(), 400);
}
// 2. Optional: Basic structural validation (can rely on PostGIS for full validation)
if (!is_object($polygonGeoJson) || !isset($polygonGeoJson->type) || !in_array($polygonGeoJson->type, ['MultiPolygon', 'Polygon'])) {
// Allow both Polygon and MultiPolygon for flexibility? Or stick to MultiPolygon?
// Let's allow Polygon too, as ST_Within works with both.
// If you strictly need *only* MultiPolygon, change the check.
throw new Exception('Input GeoJSON must be of type Polygon or MultiPolygon.', 400);
}
if (!isset($polygonGeoJson->coordinates) || !is_array($polygonGeoJson->coordinates)) {
throw new Exception('Input GeoJSON must have a coordinates array.', 400);
}
// 3. Prepare the PostgreSQL Query using PostGIS functions
// - ST_GeomFromGeoJSON($1): Parses the input GeoJSON string.
// - ST_SetSRID(..., 4326): Assigns the WGS84 SRID (standard for GeoJSON). Adjust if your data uses a different SRID.
// - ST_Within(realgeom, ...): Checks if the power outage geometry is within the provided polygon geometry.
// - Ensure your 'realgeom' column has a spatial index for performance!
$query = "
SELECT json_build_object(
'type', 'FeatureCollection',
'features', json_agg(
json_build_object(
'type', 'Feature',
'geometry', ST_AsGeoJSON(realgeom)::json,
'properties', json_build_object(
'id', id,
'time', (startguess AT TIME ZONE 'UTC')::timestamp,
'county', county,
'state', state,
'cause', cause,
'outage', peakoutage,
'lsrtime', (lsrtime AT TIME ZONE 'UTC')::timestamp
)
) ORDER BY startguess ASC -- Optional ordering
)
)
FROM power
WHERE ST_Within(realgeom, ST_SetSRID(ST_GeomFromGeoJSON($1), 4326))
";
// Note: If 'realgeom' might be NULL, you might add "AND realgeom IS NOT NULL"
// 4. Execute the query with the GeoJSON string as a parameter
$params = [$polygonGeoJsonString];
$result = pg_query_params($dbconn, $query, $params);
if ($result === false) {
// Check for specific PostGIS errors related to invalid GeoJSON input
$pgError = pg_last_error($dbconn);
if (strpos($pgError, 'invalid GeoJSON representation') !== false || strpos($pgError, 'ParseException') !== false || strpos($pgError, 'Invalid polygon') !== false) {
throw new Exception('Invalid GeoJSON geometry data provided: ' . $pgError, 400);
} else {
// Throw a generic server error for other query failures
throw new Exception('Query failed: ' . $pgError, 500);
}
}
// 5. Fetch and Output Results
$resultArray = pg_fetch_all($result);
header('Content-Type: application/json');
if ($resultArray && isset($resultArray[0]['json_build_object'])) {
// Ensure null result from json_agg (no features found) returns empty array
$outputJson = $resultArray[0]['json_build_object'];
$outputData = json_decode($outputJson, true);
if (isset($outputData['features']) && $outputData['features'] === null) {
$outputData['features'] = [];
echo json_encode($outputData);
} else {
echo $outputJson; // Output the JSON directly from Postgres
}
} else {
// Should ideally be handled by the check above, but as a fallback
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
}
pg_free_result($result);
} catch (Exception $e) {
// 6. Error Handling
if (isset($result) && is_resource($result)) { // Check if $result is a valid resource before freeing
pg_free_result($result);
}
header('Content-Type: application/json');
// Use exception code for status if provided (>=400), default to 500
$statusCode = ($e->getCode() >= 400 && $e->getCode() < 600) ? $e->getCode() : 500;
http_response_code($statusCode);
echo json_encode(['error' => $e->getMessage()]);
exit; // Stop script execution after error
}
}
// Add else block if needed for when the parameter is not set
// else {
// // Handle case where $_GET['polygongeojson'] is not present
// header('Content-Type: application/json');
// http_response_code(400); // Bad Request
// echo json_encode(['error' => 'Required parameter "polygongeojson" is missing.']);
// exit;
// }
pg_close($dbconn);
?>

View File

@@ -1,110 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
//no gets, curent point outage info
if(empty($_GET)) {
$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 current
if($_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());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
}
//county archive
if($_GET['countyarchive']) {
if($_GET['start']) {
$starttime = pg_escape_string($_GET['start']);
if($_GET['end']) {
$endtime = pg_escape_string($_GET['end']);
$result = pg_query_params($dbconn,
"SELECT county,state, update as time, county, state, outages as outage,served FROM countyoutages where cwa = $1 and update > $2 and update < $3 order by update asc",
array('RLX',$starttime,$endtime)) or die('Query failed: ' . pg_last_error());
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
$array[] = $line;
}
echo json_encode($array);
}}}
//Archive point data
if($_GET['archivepoint']) {
if($_GET['start']) {
$starttime = pg_escape_string($_GET['start']);
if($_GET['end']) {
$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']);
}}}
//if($_GET['svr']=='current') {
//$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 < now() and endtime > now()"
//,array('2023-01-01 01:00','2023-02-12 10:00')) or die('Query failed: ' . pg_last_error());
//$resultArray = pg_fetch_all($result);
//echo($resultArray[0]['json_build_object']);
//}
if($_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);
echo($resultArray[0]['json_build_object']);
}
if($_GET['svr'] == 'archive') {
if($_GET['start']) {
$starttime = pg_escape_string($_GET['start']);
if($_GET['end']) {
$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);
pg_close($dbconn);
?>

View File

@@ -255,7 +255,7 @@
} }
function main() { function main() {
fetchWeatherData('https://wx.stoat.org/nws.php?officestats11', function(weatherdata) { fetchWeatherData('https://wx.stoat.org/main.php?service=nws&officestats', function(weatherdata) {
if (weatherdata) { if (weatherdata) {
const jsonData = weatherdata; const jsonData = weatherdata;
const { dates, offices, officeDateMap, titleBreakdownMap } = processData(jsonData); const { dates, offices, officeDateMap, titleBreakdownMap } = processData(jsonData);

View File

@@ -1,572 +0,0 @@
<?php
// --- Error Reporting (Recommended for Development) ---
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// In production, turn display_errors off and configure log_errors.
// ini_set('display_errors', 0);
// ini_set('log_errors', 1);
// ini_set('error_log', '/path/to/your/php_error.log');
// --- Database Connection ---
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws");
if (!$dbconn) {
error_log('Database connection failed: ' . pg_last_error());
http_response_code(503);
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['error' => 'Service temporarily unavailable due to database connection issue.']);
exit;
}
// --- Helper Functions ---
/**
* Sends a JSON error response and terminates the script.
* @param int $http_code The HTTP status code.
* @param string $message The error message for the client.
* @param ?string $log_message Optional detailed message for the server error log.
*/
function send_error(int $http_code, string $message, ?string $log_message = null): void {
if ($log_message) { error_log($log_message); }
elseif ($http_code >= 500) { error_log("Server Error (" . $http_code . "): " . $message); }
http_response_code($http_code);
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['error' => $message]);
exit;
}
/**
* Sends a GeoJSON FeatureCollection response and terminates the script.
* @param array $features An array of GeoJSON Feature objects.
*/
function send_geojson(array $features): void {
$geojson_output = ['type' => 'FeatureCollection', 'features' => $features];
header('Content-Type: application/geo+json; charset=utf-8');
echo json_encode($geojson_output);
exit;
}
// --- Main Request Handling ---
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
error_log("--- New POST Request Received ---");
$input_data = null;
$request_type = null;
$contentType = trim(strtolower($_SERVER['HTTP_CONTENT_TYPE'] ?? $_SERVER['CONTENT_TYPE'] ?? ''));
error_log("Received Content-Type: " . $contentType);
// ***********************************************************
// ***** START: CRUCIAL JSON INPUT HANDLING BLOCK *****
// ***********************************************************
if (strpos($contentType, 'application/json') === 0) {
error_log("Content-Type identified as JSON.");
$raw_post_data = file_get_contents('php://input');
error_log("Raw php://input length: " . strlen($raw_post_data));
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.");
}
// Decode JSON into an associative array
$input_data = json_decode($raw_post_data, true); // Use 'true' for array
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 {
error_log("JSON Decode Successful.");
// ** GET request_type FROM THE DECODED ARRAY **
$request_type = $input_data['request_type'] ?? null;
error_log("Extracted request_type from JSON: " . ($request_type ?? 'null'));
}
} else {
// If JSON is strictly required, reject other types
send_error(415, 'Unsupported Media Type. This endpoint requires application/json.', "Unsupported Media Type Received: " . $contentType);
}
// ***********************************************************
// ***** END: CRUCIAL JSON INPUT HANDLING BLOCK *****
// ***********************************************************
// --- Final Check and Routing ---
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 {
error_log("Routing check reached but request_type is null without prior exit.");
send_error(400, 'Missing required parameter: request_type (or processing error).');
}
}
error_log("Routing request for type: " . $request_type);
switch ($request_type) {
case 'ohgo':
// ** Pass the $input_data array **
handle_ohgo_request($dbconn, $input_data);
break;
case 'ohgonopoly':
// ** Pass the $input_data array **
handle_ohgo_request_no_poly($dbconn, $input_data);
break;
case 'power':
// ** Pass the $input_data array **
handle_power_request($dbconn, $input_data);
break;
case 'powernopoly':
// ** Pass the $input_data array **
handle_power_request_no_poly($dbconn, $input_data);
break;
case 'wupoly':
// ** Pass the $input_data array **
handle_wu_request_poly($dbconn, $input_data);
break;
case 'campoly':
// ** Pass the $input_data array **
handle_cam_request($dbconn, $input_data);
break;
default:
send_error(400, 'Invalid request_type specified: ' . htmlspecialchars($request_type));
break;
}
} 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;
}
// --- Request Handler Functions ---
function handle_cam_request($dbconn, array $data): void {
error_log("Handling 'camera image' request.");
// --- 1. Get Data from the $data array ---
$start_time_str = $data['start_time'] ?? null;
$end_time_str = $data['end_time'] ?? null;
$geojson_str = $data['area_geojson'] ?? null;
// --- 2. Validation ---
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');
}
// Validate Timestamps (basic check, can be more robust)
// Consider using DateTime objects for more rigorous validation if needed
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.');
}
// Ensure start is before end? Optional, depends on requirements.
// if (strtotime($start_time_str) >= strtotime($end_time_str)) {
// send_error(400, 'start_time must be before end_time.');
// }
// Validate GeoJSON
$geojson_obj = json_decode($geojson_str);
if (json_last_error() !== JSON_ERROR_NONE) {
send_error(400, 'Invalid area_geojson provided: Contains invalid JSON string.', 'GeoJSON Decode Error: ' . json_last_error_msg());
}
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.');
}
// --- 3. Prepare and Execute Query ---
// This query finds active cameras within the GeoJSON area,
// then LEFT JOINs aggregated image data from camdb within the time range.
// We use jsonb_agg for efficiency and COALESCE to return an empty array []
// for cameras with no images in the range, instead of NULL.
// NOTE: Selecting c.* assumes 'geom' is not excessively large or problematic
// when fetched directly. If it is, list all columns except 'geom'.
// We explicitly fetch ST_AsGeoJSON for the geometry representation.
$query = "
SELECT
c.*, -- Select all columns from cams
ST_AsGeoJSON(c.geom) as geometry_geojson, -- Get geometry as GeoJSON string
COALESCE(img_agg.images, '[]'::jsonb) AS images -- Get aggregated images or empty JSON array
FROM
cams c
LEFT JOIN (
SELECT
camid,
jsonb_agg(
jsonb_build_object(
'timestamp', dateutc,
'url', filepath -- Assuming filepath is the relative URL path
) ORDER BY dateutc ASC -- Order images chronologically
) AS images
FROM
camdb
WHERE
dateutc >= $1::timestamp -- start_time
AND dateutc <= $2::timestamp -- end_time
GROUP BY
camid
) AS img_agg ON c.camid = img_agg.camid
WHERE
c.active = TRUE -- Only active cameras
AND ST_Within(c.geom, ST_GeomFromGeoJSON($3)) -- Camera location within area
ORDER BY
c.camid; -- Optional: Order cameras by ID
";
$params = array(
$start_time_str, // $1: start_time
$end_time_str, // $2: end_time
$geojson_str // $3: area_geojson string
);
$result = pg_query_params($dbconn, $query, $params);
if (!$result) {
send_error(500, 'Database query failed for camera data.', 'Camera Query Failed: ' . pg_last_error($dbconn) . " | Query: " . $query . " | Params: " . print_r($params, true));
}
// --- 4. Process Results ---
$cameras_output = [];
while ($row = pg_fetch_assoc($result)) {
// Decode the geometry GeoJSON string into a PHP object/array
$geometry = json_decode($row['geometry_geojson']);
if (json_last_error() !== JSON_ERROR_NONE) {
error_log('Failed to decode geometry for camid ' . ($row['camid'] ?? 'N/A') . ': ' . json_last_error_msg());
// Decide how to handle: skip camera, set geometry to null, etc.
$geometry = null; // Example: Set to null on error
}
// Decode the images JSON string (from jsonb_agg) into a PHP array
$images = json_decode($row['images']);
if (json_last_error() !== JSON_ERROR_NONE) {
error_log('Failed to decode images JSON for camid ' . ($row['camid'] ?? 'N/A') . ': ' . json_last_error_msg());
// Decide how to handle: skip camera, set images to empty array, etc.
$images = []; // Example: Set to empty array on error
}
// Prepare the output structure for this camera
$camera_data = $row; // Start with all columns fetched via c.*
// Replace/remove raw JSON strings and potentially the original binary geom
unset($camera_data['geometry_geojson']); // Remove the raw GeoJSON string
unset($camera_data['geom']); // Remove the raw binary geometry if it was fetched by c.*
$camera_data['geometry'] = $geometry; // Add the decoded geometry object/array
$camera_data['images'] = $images; // Add the decoded images array
$cameras_output[] = $camera_data;
}
pg_free_result($result);
error_log("Found " . count($cameras_output) . " cameras matching criteria.");
// --- 5. Send Response ---
// Use a function like send_json defined above, or inline the logic:
header('Content-Type: application/json');
echo json_encode($cameras_output, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
exit; // Important to stop script execution here
// Alternatively, if you have the helper:
// send_json($cameras_output);
}
function handle_wu_request_poly($dbconn, array $data): void { // Takes $data array
$polygons = $data['polygons'] ?? []; // Array of WKT polygons, e.g., ['POLYGON((...))', 'POLYGON((...))']
$start_time = $data['start_time'] ?? '2025-01-01 00:00:00'; // e.g., '2025-01-01 00:00:00'
$end_time = $data['end_time'] ?? '2025-01-02 00:00:00'; // e.g., '2025-01-02 00:00:00'
if (empty($polygons)) {
http_response_code(500);
echo json_encode(['error' => 'No polygons provided']);
pg_close($dbconn);
exit;
}
$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) {
http_response_code(500);
echo json_encode(['error' => pg_last_error($dbconn)]);
pg_close($dbconn);
exit;
}
// Fetch results
$results = [];
while ($row = pg_fetch_assoc($result)) {
$results[] = $row;
}
// Free result and close connection
pg_free_result($result);
// Output results as JSON
header('Content-Type: application/json');
echo json_encode($results);
}
/**
* Handles the 'ohgo' data request.
* @param resource $dbconn The active database connection resource.
* @param array $data The associative array of input parameters (from JSON).
*/
function handle_ohgo_request($dbconn, array $data): void { // Takes $data array
error_log("Handling 'ohgo' request.");
// --- 1. Get Data from the $data array ---
$start = $data['start_time'] ?? null; // Use $data, use correct key
$geojson_str = $data['area_geojson'] ?? null; // Use $data, not $_POST
$end = $data['end_time'] ?? null; // Use $data, use correct key
// --- 2. Validation ---
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.', 'GeoJSON Decode Error: ' . json_last_error_msg()); }
if (!isset($geojson_obj->type) || !in_array($geojson_obj->type, ['Polygon', 'MultiPolygon'])) { send_error(400, 'Invalid GeoJSON provided: Type must be Polygon or MultiPolygon.'); }
// --- 3. Prepare and Execute Query ---
$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.', 'OHGO Query Failed: ' . pg_last_error($dbconn)); }
// --- 4. Process Results ---
$features = [];
while ($line = pg_fetch_assoc($result)) {
$geometry = json_decode($line['geometry']);
if (json_last_error() !== JSON_ERROR_NONE) { error_log('Failed to decode geometry for ohgo row: ' . json_last_error_msg()); continue; }
$properties = $line; unset($properties['geometry']);
$features[] = ['type' => 'Feature', 'geometry' => $geometry, 'properties' => $properties];
}
pg_free_result($result);
error_log("Found " . count($features) . " features for ohgo request.");
// --- 5. Send Response ---
send_geojson($features);
}
/**
* Handles the 'power' data request.
* @param resource $dbconn The active database connection resource.
* @param array $data The associative array of input parameters (from JSON).
*/
function handle_power_request($dbconn, array $data): void { // Takes $data array
error_log("Handling 'power' request.");
// --- 1. Get Data from the $data array ---
// ** Match keys from your fetch request body: start_time, area_geojson, etc. **
$start = $data['start_time'] ?? null; // Use $data, use correct key
$geojson_str = $data['area_geojson'] ?? null; // Use $data, use correct key
$end = $data['end_time'] ?? null; // Use $data, use correct key
$buffer_hours = $data['buffer'] ?? 0;// Use $data, use correct key
// --- 2. Validation ---
if ($start === null || $geojson_str === null || $end === null || $buffer_hours === null) {
// Update error message to reflect the actual keys expected from JSON
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); // Decode the *string* value from the JSON input
if (json_last_error() !== JSON_ERROR_NONE) { send_error(400, 'Invalid area_geojson provided: Contains invalid JSON string.', 'GeoJSON Decode Error: ' . json_last_error_msg()); }
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.'); }
// ** Crucial Fix: Use the decoded $geojson_str for the query parameter, not $geojson_obj **
// --- 3. Prepare and Execute Query ---
// ** VERIFY TABLE/COLUMN NAMES FOR POWER TABLE **
$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, // $1: start_time from JSON
$geojson_str, // $2: area_geojson STRING from JSON
$end, // $3: end_time from JSON
$buffer_hours_int // $4: buffer_hours from JSON (as integer)
);
$result = pg_query_params($dbconn, $query, $params);
if (!$result) { send_error(500, 'Database query failed for power data.', 'Power Query Failed: ' . pg_last_error($dbconn) . " | Query: " . $query . " | Params: " . print_r($params, true)); }
// --- 4. Process Results ---
$features = [];
while ($line = pg_fetch_assoc($result)) {
$geometry = json_decode($line['geometry']);
if (json_last_error() !== JSON_ERROR_NONE) { error_log('Failed to decode geometry for power row: ' . json_last_error_msg()); continue; }
$properties = $line; unset($properties['geometry']);
$features[] = ['type' => 'Feature', 'geometry' => $geometry, 'properties' => $properties];
}
pg_free_result($result);
error_log("Found " . count($features) . " features for power request.");
// --- 5. Send Response ---
send_geojson($features);
}
/**
* Handles the 'ohgo' data request.
* @param resource $dbconn The active database connection resource.
* @param array $data The associative array of input parameters (from JSON).
*/
function handle_ohgo_request_no_poly($dbconn, array $data): void { // Takes $data array
error_log("Handling 'ohgo' request.");
// --- 1. Get Data from the $data array ---
$start = $data['start_time'] ?? null; // Use $data, use correct key
$end = $data['end_time'] ?? null; // Use $data, use correct key
// --- 2. Validation ---
if ($start === null || $end === null) { send_error(400, 'Missing required parameters for ohgo request: start, geojson, end'); }
// --- 3. Prepare and Execute Query ---
$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.', 'OHGO Query Failed: ' . pg_last_error($dbconn)); }
// --- 4. Process Results ---
$features = [];
while ($line = pg_fetch_assoc($result)) {
$geometry = json_decode($line['geometry']);
if (json_last_error() !== JSON_ERROR_NONE) { error_log('Failed to decode geometry for ohgo row: ' . json_last_error_msg()); continue; }
$properties = $line; unset($properties['geometry']);
$features[] = ['type' => 'Feature', 'geometry' => $geometry, 'properties' => $properties];
}
pg_free_result($result);
error_log("Found " . count($features) . " features for ohgo request.");
// --- 5. Send Response ---
send_geojson($features);
}
/**
* Handles the 'power' data request.
* @param resource $dbconn The active database connection resource.
* @param array $data The associative array of input parameters (from JSON).
*/
function handle_power_request_no_poly($dbconn, array $data): void { // Takes $data array
error_log("Handling 'power' request.");
// --- 1. Get Data from the $data array ---
// ** Match keys from your fetch request body: start_time, area_geojson, etc. **
$start = $data['start_time'] ?? null; // Use $data, use correct key
$end = $data['end_time'] ?? null; // Use $data, use correct key
$outage_threshold = $data['outage_threshold'] ?? 9;
$buffer_hours = $data['buffer'] ?? 0;// Use $data, use correct key
// --- 2. Validation ---
if ($start === null || $end === null || $buffer_hours === null) {
// Update error message to reflect the actual keys expected from JSON
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;
$outage_thresh = (float)$outage_threshold;
// --- 3. Prepare and Execute Query ---
// ** VERIFY TABLE/COLUMN NAMES FOR POWER TABLE **
$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, // $1: start_time from JSON
$end, // $2: end_time from JSON
$buffer_hours_int, // $3: buffer_hours from JSON (as integer)
$outage_thresh // $4
);
$result = pg_query_params($dbconn, $query, $params);
if (!$result) { send_error(500, 'Database query failed for power data.', 'Power Query Failed: ' . pg_last_error($dbconn) . " | Query: " . $query . " | Params: " . print_r($params, true)); }
// --- 4. Process Results ---
$features = [];
while ($line = pg_fetch_assoc($result)) {
$geometry = json_decode($line['geometry']);
if (json_last_error() !== JSON_ERROR_NONE) { error_log('Failed to decode geometry for power row: ' . json_last_error_msg()); continue; }
$properties = $line; unset($properties['geometry']);
$features[] = ['type' => 'Feature', 'geometry' => $geometry, 'properties' => $properties];
}
pg_free_result($result);
error_log("Found " . count($features) . " features for power request.");
// --- 5. Send Response ---
send_geojson($features);
}
// --- Close Database Connection ---
if ($dbconn) {
pg_close($dbconn);
error_log("Database connection closed.");
}
?>

View File

@@ -1030,7 +1030,7 @@ function formatDate_MMDD_HHMM(dateString) {
$(document).ready(function() { $(document).ready(function() {
// Ensure map initialization and initial data load happen first // Ensure map initialization and initial data load happen first
initializeMap(); initializeMap();
loadCountyLayer('https://wx.stoat.org/ver.php'); loadCountyLayer('https://wx.stoat.org/main.php?service=ver');
}); // End $(document).ready() }); // End $(document).ready()

View File

@@ -2685,7 +2685,7 @@ function generateLsrCsv() {
// --- Event Listener for Filtering the Event List --- // --- Event Listener for Filtering the Event List ---
$(document).ready(function() { $(document).ready(function() {
initializeMap(); initializeMap();
loadCountyLayer('ver.php'); // URL providing county/zone GeoJSON loadCountyLayer('main.php?service=ver'); // URL providing county/zone GeoJSON
getwwas(); // Initial load for VTEC events getwwas(); // Initial load for VTEC events
disableExportButtons(); // Start with export buttons disabled disableExportButtons(); // Start with export buttons disabled
// Attach the input event listener to the filter box // Attach the input event listener to the filter box

View File

@@ -42,9 +42,9 @@ function rackandstack() {
var start = document.getElementById("start").value; var start = document.getElementById("start").value;
var end = document.getElementById("end").value; var end = document.getElementById("end").value;
$.getJSON(`powerapi.php?max=potato&start=${start}&end=${end}`, function(data) { $.getJSON(`main.php?service=powerapi&max=potato&start=${start}&end=${end}`, function(data) {
$.getJSON('powerapi.php?county=r', function(data1) { $.getJSON('main.php?service=powerapi&county=r', function(data1) {
countylist(data,data1); countylist(data,data1);
}); });

View File

@@ -44,7 +44,7 @@ $.getJSON(url, function(json) {
lsrdata = json; lsrdata = json;
console.log("LSR Data Loaded:", lsrdata.events.features.length, "events"); console.log("LSR Data Loaded:", lsrdata.events.features.length, "events");
}).done(function() { }).done(function() {
table.setData("powerapi.php?svrpolys=potato"); table.setData("main.php?service=powerapi&svrpolys=potato");
table.setSort([ table.setSort([
{column:"vtec", dir: "desc"}, {column:"vtec", dir: "desc"},
]); ]);
@@ -82,7 +82,7 @@ function findFeatureById(featureCollection, id) {
} }
function reloadData() { function reloadData() {
table.replaceData("powerapi.php?svrpolys=potato"); table.replaceData("main.php?service=powerapi&svrpolys=potato");
table.setSort([ table.setSort([
{column:"vtec", dir: "desc"}, {column:"vtec", dir: "desc"},
]); ]);

View File

@@ -888,7 +888,7 @@ var geoJSONcounties = L.geoJSON(false, {
//var countiesjson = 'rlxtest.json' //var countiesjson = 'rlxtest.json'
var countiesjson = 'https://wx.stoat.org/ver.php' var countiesjson = 'https://wx.stoat.org/main.php?service=ver'
@@ -1270,7 +1270,7 @@ var geoJSONwwa1 = L.geoJSON(false, {
}).addTo(mymap); }).addTo(mymap);
$.getJSON('https://wx.stoat.org/ver.php', function(data) { $.getJSON('https://wx.stoat.org/main.php?service=verp', function(data) {
var geojsonFeature = data; var geojsonFeature = data;
geoJSONwwa1.addData(geojsonFeature); geoJSONwwa1.addData(geojsonFeature);

View File

@@ -128,7 +128,7 @@ create hydrograph as static image for flood Points
find hydrographs in areals and plot find hydrographs in areals and plot
Link for hydrographs Link for hydrographs
Link to severe polygon on power outage Link to severe polygon on power outage
https://wx.stoat.org/powerapi.php?svrpolys=potato 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 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 -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 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
@@ -203,7 +203,7 @@ var mymap = L.map('mapid', {zoomDelta: 0.25, zoomSnap: 0}).setView([38.508, -82.
var countiesjson = 'https://wx.stoat.org/ver.php' var countiesjson = 'https://wx.stoat.org/main.php?service=ver'

View File

@@ -1,41 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
// Get POST data
$camid = $_POST['camid'];
$field = $_POST['field'];
$value = $_POST['value'];
// Validate inputs
if (empty($camid) || empty($field)) {
echo json_encode(['success' => false, 'message' => 'Invalid input']);
exit;
}
// Check if the field is valid
if (!in_array($field, ['hydro', 'airport'])) {
echo json_encode(['success' => false, 'message' => 'Invalid field']);
exit;
}
// Convert to proper boolean for PostgreSQL
// JavaScript sends true/false as strings 'true' or 'false'
$value_bool = ($value === 'true');
// Update the field value in the database - use boolean directly
// PostgreSQL accepts 't'/'f' for boolean values
$query = "UPDATE cams SET $field = $1 WHERE camid = $2";
$result = pg_query_params($dbconn, $query, array($value_bool ? 't' : 'f', $camid));
if ($result) {
echo json_encode(['success' => true]);
} else {
$error = pg_last_error($dbconn);
echo json_encode(['success' => false, 'message' => $error]);
}
// Closing connection
pg_close($dbconn);
?>

140
ver.php
View File

@@ -1,140 +0,0 @@
<?php
header("Access-Control-Allow-Origin: *");
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
//no gets, curent point outage info
if(empty($_GET)) {
$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);
header('Content-Type: application/json; charset=utf-8');
echo($resultArray[0]['jsonb_build_object']);
pg_free_result($result);
}
if (isset($_GET['lsrslist'])) {
$result = pg_query($dbconn,"SELECT * from simplever") 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);
}
if (isset($_GET['reset'])) {
$result = pg_query($dbconn,"truncate simplever") or die('Query failed: ' . pg_last_error());
$resultArray = pg_fetch_all($result);
echo($resultArray);
}
if (isset($_GET['lsrs'])) {
if (isset($_GET['zone'])) {
$zone = $_GET['zone'];
if (isset($_GET['lsr'])) {
$lsr = (int) $_GET['lsr'];
} else {
$lsr = 1;
}
if (isset($_GET['lsrs'])) {
$dir = $_GET['dir'];
}
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());
$resultArray = pg_fetch_all($result);
}
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);
}
//echo($resultArray[0]);
pg_free_result($result);
}
}
if (isset($_GET['inc'])) {
if ($_GET['inc'] == 'true') {
$hideflag = 'true';
} else {
$hideflag = 'false';
}
$id = (int) $_GET['id'];
$query = "UPDATE reports SET hide = $1 WHERE id = $2";
$result = pg_query_params($dbconn, $query, array($hideflag, $id)) or die('Query failed: ' . pg_last_error());
pg_free_result($result);
}
if (isset($_GET['hide'])) {
if ($_GET['hide'] == 'true') {
$hideflag = 'true';
} else {
$hideflag = 'false';
}
$id = (int) $_GET['id'];
$query = "UPDATE reports SET hide = $1 WHERE id = $2";
$result = pg_query_params($dbconn, $query, array($hideflag, $id)) or die('Query failed: ' . pg_last_error());
pg_free_result($result);
}
pg_close($dbconn);
?>

View File

@@ -140,7 +140,7 @@
function resetmap() { function resetmap() {
$.get({ $.get({
url: 'ver.php?reset=potato', url: 'main.php?service=ver&reset=potato',
success: function () { success: function () {
geoJSONcounties.setStyle({ fillColor: 'red' }); // Reset visually immediately geoJSONcounties.setStyle({ fillColor: 'red' }); // Reset visually immediately
loadlsr(); // Reload data from server loadlsr(); // Reload data from server
@@ -211,7 +211,7 @@
// Optional: Add logic to cap the max value if needed (e.g., if (newLsr > 2) newLsr = 2;) // Optional: Add logic to cap the max value if needed (e.g., if (newLsr > 2) newLsr = 2;)
$.get({ $.get({
url: `ver.php?lsrs=potato&zone=${zone}&lsr=${newLsr}&dir=1`, // dir=1 seems specific to 'up' url: `main.php?service=ver&lsrs=potato&zone=${zone}&lsr=${newLsr}&dir=1`, // dir=1 seems specific to 'up'
success: function () { success: function () {
layer.setStyle({ fillColor: vercolor(newLsr) }); layer.setStyle({ fillColor: vercolor(newLsr) });
// No need to call loadlsr() here, the server state is updated, // No need to call loadlsr() here, the server state is updated,
@@ -232,7 +232,7 @@
var newLsr = 0; // Reset to red var newLsr = 0; // Reset to red
$.get({ $.get({
url: `ver.php?lsrs=potato&zone=${zone}&lsr=${newLsr}`, // No dir needed? Or specific dir for reset? url: `main.php?service=ver&lsrs=potato&zone=${zone}&lsr=${newLsr}`, // No dir needed? Or specific dir for reset?
success: function () { success: function () {
layer.setStyle({ fillColor: vercolor(newLsr) }); layer.setStyle({ fillColor: vercolor(newLsr) });
// No need to call loadlsr() here // No need to call loadlsr() here
@@ -254,7 +254,7 @@
update_position_timeout = null; // Best practice to nullify after clearing update_position_timeout = null; // Best practice to nullify after clearing
} }
$.getJSON('https://wx.stoat.org/ver.php?lsrslist=potato') $.getJSON('https://wx.stoat.org/main.php?service=ver&lsrslist=potato')
.done(function (data) { .done(function (data) {
if (data && data.length > 0) { if (data && data.length > 0) {
var zoneData = {}; var zoneData = {};
@@ -293,7 +293,7 @@
// var countiesjson = 'rlxtest.json'; // Local testing // var countiesjson = 'rlxtest.json'; // Local testing
var countiesjson = 'https://wx.stoat.org/ver.php'; // Production endpoint var countiesjson = 'https://wx.stoat.org/main.php?service=ver'; // Production endpoint
function initial_county_load() { function initial_county_load() {
geoJSONcounties.clearLayers(); geoJSONcounties.clearLayers();

View File

@@ -151,7 +151,7 @@ olddiv.innerHTML = '';
$.getJSON('warntrack.php', function(data){ $.getJSON('main.php?service=warntrack', function(data){
// console.log(data); // console.log(data);
//check if data has no data //check if data has no data
if (data.features != null) { if (data.features != null) {
@@ -176,7 +176,7 @@ function refresh_data() {
//{ //{
// elem.parentNode.removeChild(elem); // elem.parentNode.removeChild(elem);
//} //}
$.getJSON('warntrack.php', function(data){ $.getJSON('main.php?service=warntrack', function(data){
// console.log(data); // console.log(data);
//check if data has no data //check if data has no data
if (data.features != null) { if (data.features != null) {
@@ -338,7 +338,7 @@ return color
function update_position() { function update_position() {
//initial_county_load(); //initial_county_load();
$.getJSON('warntrack.php', function(data2) { $.getJSON('main.php?service=warntrack', function(data2) {
var geojsonsvr = data2; var geojsonsvr = data2;
geoJSONsvr.clearLayers(); geoJSONsvr.clearLayers();
geoJSONsvr.addData(geojsonsvr); geoJSONsvr.addData(geojsonsvr);

View File

@@ -1,19 +0,0 @@
<?php
// Connecting, selecting database
$dbconn = pg_connect("host=localhost dbname=nws user=nws password=nws")
or die('Could not connect: ' . pg_last_error());
//no gets, curent point outage info
if(empty($_GET)) {
$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);
echo($resultArray[0]['json_build_object']);
}
pg_free_result($result);
pg_close($dbconn);
?>