overhaul ble.py, move all async calls there
This commit is contained in:
1 parent
87cd24234a
commit
0d975a15a8
8 files changed
+712
-135
No files matched your search
+74
-33
@@ -1,33 +1,35 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
# ---------- Settings ----------
|
||||
date_default_timezone_set('America/Los_Angeles');
|
||||
/* ---------- Settings ----------
|
||||
* Adjust if your API lives somewhere else.
|
||||
*/
|
||||
$api_host = 'http://172.20.20.51';
|
||||
$api_port = 5001; // drive‑health API
|
||||
$api_path = '/details'; // endpoint that returns the JSON you showed
|
||||
|
||||
# ---------- Helper: JSON fetch ----------
|
||||
/* ---------- Helper: JSON fetch ----------
|
||||
*/
|
||||
function fetch_json(string $url): ?array
|
||||
{
|
||||
$ctx = stream_context_create([
|
||||
'http' => ['timeout' => 2]
|
||||
]);
|
||||
$ctx = stream_context_create(['http' => ['timeout' => 2]]);
|
||||
$raw = @file_get_contents($url, false, $ctx);
|
||||
if ($raw === false) {
|
||||
return null;
|
||||
}
|
||||
$data = json_decode($raw, true);
|
||||
return is_array($data) ? $data : null;
|
||||
return ($raw !== false) ? json_decode($raw, true) : null;
|
||||
}
|
||||
/* ---------- Helper: format epoch to Pacific time ----------
|
||||
*/
|
||||
function fmt_ts(int $epoch): string
|
||||
{
|
||||
$dt = new DateTime("@$epoch");
|
||||
$dt->setTimezone(new DateTimeZone('America/Los_Angeles'));
|
||||
// 1:30:30 pm 10-14-2026
|
||||
return $dt->format('g:i:s a m-d-Y');
|
||||
}
|
||||
|
||||
# ---------- Load data ----------
|
||||
$api_url = "$api_host:$api_port$api_path";
|
||||
$payload = fetch_json($api_url);
|
||||
foreach ($payload['sensors'] as $s){
|
||||
echo $s;
|
||||
}
|
||||
# ---------- Render ----------
|
||||
/* ---------- Load data ----------
|
||||
*/
|
||||
$api_url = "$api_host:$api_port$api_path";
|
||||
$payload = fetch_json($api_url);
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
@@ -36,43 +38,66 @@ foreach ($payload['sensors'] as $s){
|
||||
<title>Sensor Dashboard</title>
|
||||
<link rel="stylesheet" href="src/styles.css">
|
||||
<style>
|
||||
.card { max-width: 550px;}
|
||||
.card { max-width: 750px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<center>
|
||||
<h1>Sensor Dashboard</h1>
|
||||
|
||||
<?php if ($payload === null): ?>
|
||||
<p style="color:red;">⚠️ Could not fetch data from the API.</p>
|
||||
<?php else: ?>
|
||||
<table id="sensor-table">
|
||||
<table id="sensor-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Device</th>
|
||||
<th>Comment</th>
|
||||
<th>Sensor Time</th>
|
||||
<th>Temp (°C)</th>
|
||||
<th>Humidity %</th>
|
||||
<?php //<th>Humidity %</th> ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($payload['sensors'] as $s): ?>
|
||||
<?php
|
||||
$temp = $hum = '';
|
||||
foreach ($s['data']['data'] as $d) {
|
||||
if ($d['name'] === 'temp') $temp = $d['value'];
|
||||
if ($d['name'] === 'humidity') $hum = $d['value'];
|
||||
// sensor‑level timestamps
|
||||
$sensorFirst = fmt_ts($s['first_seen']);
|
||||
$sensorLast = fmt_ts($s['last_seen']);
|
||||
|
||||
// value‑level timestamps
|
||||
$temp = $hum = '';
|
||||
$tFirst = $tLast = $hFirst = $hLast = '';
|
||||
foreach ($s['data'] as $d) {
|
||||
if ($d['name'] === 'temp') {
|
||||
$temp = $d['value'] ;
|
||||
$tFirst = fmt_ts($d['first_seen']);
|
||||
$tLast = fmt_ts($d['last_seen']);
|
||||
} elseif ($d['name'] === 'humidity') {
|
||||
$hum = $d['value'];
|
||||
$hFirst = fmt_ts($d['first_seen']);
|
||||
$hLast = fmt_ts($d['last_seen']);
|
||||
}
|
||||
}
|
||||
|
||||
// cast values to string for htmlspecialchars
|
||||
$tempStr = htmlspecialchars((string)$temp);
|
||||
$tempF = (intval($tempStr) * 1.8) + 32;
|
||||
$humStr = htmlspecialchars((string)$hum);
|
||||
$comment = htmlspecialchars($s['comment'] ?? '');
|
||||
?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($s['name']) ?></td>
|
||||
<td><?= htmlspecialchars($s['comment'] ?? '') ?></td>
|
||||
<td><?= htmlspecialchars($temp) ?></td>
|
||||
<td><?= htmlspecialchars($hum) ?></td>
|
||||
<td><?= $comment ?></td>
|
||||
<td><small>First seen:<br><?= $sensorFirst ?><br>Last seen:<br> <?= $sensorLast ?></small></td>
|
||||
<td><?= $tempF.'°F' ?><br><small>First seen: <?= $tFirst ?><br>Last seen: <?= $tLast ?></small></td>
|
||||
<?php /*<td><?= $humStr.'%' ?><br><small>First seen: <?= $hFirst ?><br>Last seen: <?= $hLast ?></small></td>*/ ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</center>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<!-- Socket.io client -->
|
||||
@@ -82,17 +107,33 @@ foreach ($payload['sensors'] as $s){
|
||||
|
||||
// Receive updated rows from Redis
|
||||
socket.on('temp_hum', data => {
|
||||
// `data` has the same structure as the API response
|
||||
const tbody = document.querySelector('#sensor-table tbody');
|
||||
tbody.innerHTML = ''; // clear existing rows
|
||||
tbody.innerHTML = '';
|
||||
data.sensors.forEach(s => {
|
||||
const temp = s.data.data.find(d => d.name==='temp')?.value ?? '';
|
||||
const hum = s.data.data.find(d => d.name==='humidity')?.value ?? '';
|
||||
const temp = s.data.find(d => d.name==='temp')?.value ?? '';
|
||||
const hum = s.data.find(d => d.name==='humidity')?.value ?? '';
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `<td>${s.name}</td><td>${s.comment}</td><td>${temp}</td><td>${hum}</td>`;
|
||||
row.innerHTML = `
|
||||
<td>${s.name}</td>
|
||||
<td>${s.comment}</td>
|
||||
<td>${fmt_ts(s.first_seen)}<br>Last: ${fmt_ts(s.last_seen)}</td>
|
||||
<td>${temp}<br>First: ${s.data.find(d=>d.name==='temp')?.first_seen ?? ''}<br>Last: ${s.data.find(d=>d.name==='temp')?.last_seen ?? ''}</td>
|
||||
<td>${hum}<br>First: ${s.data.find(d=>d.name==='humidity')?.first_seen ?? ''}<br>Last: ${s.data.find(d=>d.name==='humidity')?.last_seen ?? ''}</td>
|
||||
`;
|
||||
tbody.appendChild(row);
|
||||
});
|
||||
});
|
||||
|
||||
// Helper for JS timestamp formatting (same as PHP)
|
||||
function fmt_ts(epoch) {
|
||||
const dt = new Date(epoch * 1000);
|
||||
const options = { hour12: true, hour: 'numeric', minute: '2-digit', second: '2-digit', month: '2-digit', day: '2-digit', year: 'numeric' };
|
||||
const formatter = new Intl.DateTimeFormat('en-US', options);
|
||||
// Convert to Pacific time by applying offset -7/ -8 depending on DST
|
||||
const pacificOffset = (dt.getTimezoneOffset() + (new Date().getTimezoneOffset() - 0)) * 60 * 1000;
|
||||
const pacific = new Date(dt.getTime() + pacificOffset);
|
||||
return pacific.toLocaleString('en-US', options).replace(',', '');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/* ---------- Settings ---------- */
|
||||
date_default_timezone_set('America/Los_Angeles');
|
||||
$api_host = 'http://172.20.20.51';
|
||||
$api_port = 5001; // drive‑health API
|
||||
$api_path = '/details'; // endpoint that returns the JSON you showed
|
||||
|
||||
/* ---------- Helper: JSON fetch ---------- */
|
||||
function fetch_json(string $url): ?array
|
||||
{
|
||||
$ctx = stream_context_create(['http' => ['timeout' => 2]]);
|
||||
$raw = @file_get_contents($url, false, $ctx);
|
||||
return ($raw !== false) ? json_decode($raw, true) : null;
|
||||
}
|
||||
|
||||
/* ---------- Load data ---------- */
|
||||
$api_url = "$api_host:$api_port$api_path";
|
||||
$payload = fetch_json($api_url);
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Sensor Dashboard</title>
|
||||
<link rel="stylesheet" href="src/styles.css">
|
||||
<style>
|
||||
.card { max-width: 550px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<h1>Sensor Dashboard</h1>
|
||||
|
||||
<?php if ($payload === null): ?>
|
||||
<p style="color:red;">Could not fetch data from the API.</p>
|
||||
<?php else: ?>
|
||||
<table id="sensor-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Device</th>
|
||||
<th>Comment</th>
|
||||
<th>Temp (°C)</th>
|
||||
<th>Humidity %</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($payload['sensors'] as $s): ?>
|
||||
<?php
|
||||
// In the new format, $s['data'] is already an array of readings
|
||||
$temp = $hum = '';
|
||||
foreach ($s['data'] as $d) {
|
||||
if ($d['name'] === 'temp') $temp = $d['value'];
|
||||
if ($d['name'] === 'humidity')$hum = $d['value'];
|
||||
}
|
||||
$tempStr = htmlspecialchars((string)$temp);
|
||||
$humStr = htmlspecialchars((string)$hum);
|
||||
?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($s['name']) ?></td>
|
||||
<td><?= htmlspecialchars($s['comment'] ?? '') ?></td>
|
||||
<td><?= htmlspecialchars($temp) ?></td>
|
||||
<td><?= htmlspecialchars($hum) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<!-- Socket.io client -->
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script>
|
||||
const socket = io();
|
||||
|
||||
// Receive updated rows from Redis
|
||||
socket.on('temp_hum', data => {
|
||||
// `data` has the same structure as the API response
|
||||
const tbody = document.querySelector('#sensor-table tbody');
|
||||
tbody.innerHTML = ''; // clear existing rows
|
||||
data.sensors.forEach(s => {
|
||||
const temp = s.data.find(d => d.name==='temp')?.value ?? '';
|
||||
const hum = s.data.find(d => d.name==='humidity')?.value ?? '';
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `<td>${s.name}</td><td>${s.comment}</td><td>${temp}</td><td>${hum}</td>`;
|
||||
tbody.appendChild(row);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user