Add full-screen alarm acknowledgement overlay
This commit is contained in:
@@ -155,3 +155,54 @@ nav button {
|
||||
font-size: 0.9rem;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
|
||||
.alarm-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: #200;
|
||||
color: white;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.alarm-overlay.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.alarm-box {
|
||||
width: min(720px, 100%);
|
||||
background: #3a0000;
|
||||
border: 4px solid #ffdddd;
|
||||
border-radius: 24px;
|
||||
padding: 36px;
|
||||
text-align: center;
|
||||
box-shadow: 0 0 40px rgba(0,0,0,0.7);
|
||||
}
|
||||
|
||||
.alarm-icon {
|
||||
font-size: 5rem;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.alarm-box h1 {
|
||||
font-size: 2.4rem;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.alarm-box p {
|
||||
font-size: 1.8rem;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.alarm-box button {
|
||||
width: 100%;
|
||||
font-size: 1.5rem;
|
||||
padding: 24px;
|
||||
background: white;
|
||||
color: #300;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,15 @@
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="alarmOverlay" class="alarm-overlay hidden">
|
||||
<div class="alarm-box">
|
||||
<div class="alarm-icon">⚠</div>
|
||||
<h1 id="alarmTitle">ALARM</h1>
|
||||
<p id="alarmMessage">--</p>
|
||||
<button onclick="acknowledgeAlarm()">Acknowledge</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<main>
|
||||
<header>
|
||||
<h1>Xterra Dashboard</h1>
|
||||
@@ -80,6 +89,8 @@
|
||||
|
||||
<script>
|
||||
let relayState = {};
|
||||
let activeAlarmKey = null;
|
||||
let acknowledgedAlarms = new Set();
|
||||
|
||||
function showScreen(id) {
|
||||
document.querySelectorAll('.screen').forEach(screen => {
|
||||
@@ -92,6 +103,70 @@ function onOff(value) {
|
||||
return value ? 'ON' : 'OFF';
|
||||
}
|
||||
|
||||
function checkAlarms(data) {
|
||||
const alarms = [];
|
||||
|
||||
if (data.temps.rear_seat >= 95) {
|
||||
alarms.push({
|
||||
key: 'rear_seat_critical',
|
||||
title: 'REAR SEAT TEMP CRITICAL',
|
||||
message: `${data.temps.rear_seat}°F detected near car seat area`
|
||||
});
|
||||
} else if (data.temps.rear_seat >= 85) {
|
||||
alarms.push({
|
||||
key: 'rear_seat_warning',
|
||||
title: 'REAR SEAT TEMP HIGH',
|
||||
message: `${data.temps.rear_seat}°F detected near car seat area`
|
||||
});
|
||||
}
|
||||
|
||||
if (data.temps.fridge_zone_1 >= 45) {
|
||||
alarms.push({
|
||||
key: 'fridge_zone_1_warm',
|
||||
title: 'FRIDGE ZONE 1 WARM',
|
||||
message: `${data.temps.fridge_zone_1}°F`
|
||||
});
|
||||
}
|
||||
|
||||
if (data.temps.fridge_zone_2 >= 45) {
|
||||
alarms.push({
|
||||
key: 'fridge_zone_2_warm',
|
||||
title: 'FRIDGE ZONE 2 WARM',
|
||||
message: `${data.temps.fridge_zone_2}°F`
|
||||
});
|
||||
}
|
||||
|
||||
if (data.battery.soc <= 20) {
|
||||
alarms.push({
|
||||
key: 'battery_low',
|
||||
title: 'BATTERY LOW',
|
||||
message: `${data.battery.soc}% remaining`
|
||||
});
|
||||
}
|
||||
|
||||
const unacked = alarms.find(alarm => !acknowledgedAlarms.has(alarm.key));
|
||||
|
||||
if (unacked) {
|
||||
showAlarm(unacked);
|
||||
}
|
||||
}
|
||||
|
||||
function showAlarm(alarm) {
|
||||
activeAlarmKey = alarm.key;
|
||||
document.getElementById('alarmTitle').textContent = alarm.title;
|
||||
document.getElementById('alarmMessage').textContent = alarm.message;
|
||||
document.getElementById('alarmOverlay').classList.remove('hidden');
|
||||
}
|
||||
|
||||
function acknowledgeAlarm() {
|
||||
if (activeAlarmKey) {
|
||||
acknowledgedAlarms.add(activeAlarmKey);
|
||||
}
|
||||
|
||||
activeAlarmKey = null;
|
||||
document.getElementById('alarmOverlay').classList.add('hidden');
|
||||
}
|
||||
|
||||
async function loadStatus() {
|
||||
const res = await fetch('/status');
|
||||
const data = await res.json();
|
||||
@@ -128,6 +203,8 @@ async function loadStatus() {
|
||||
document.getElementById('sysRs485').textContent = data.network.rs485_connected ? 'Connected' : 'Disconnected';
|
||||
document.getElementById('sysWifi').textContent = data.network.wifi_enabled ? 'Enabled' : 'Disabled';
|
||||
document.getElementById('sysWifiOverride').textContent = data.network.wifi_override_active ? 'Active' : 'Inactive';
|
||||
|
||||
checkAlarms(data);
|
||||
}
|
||||
|
||||
async function toggleRelay(name) {
|
||||
|
||||
Reference in New Issue
Block a user