104 lines
4.0 KiB
JavaScript
104 lines
4.0 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
|
// A map to keep track of Chart instances to prevent memory leaks
|
|
const chartInstances = {};
|
|
|
|
const createGauge = (canvasId, label, value, max, unit, thresholds) => {
|
|
const ctx = document.getElementById(canvasId);
|
|
if (!ctx) return;
|
|
|
|
const parentCard = ctx.closest('.gauge-card');
|
|
if (!parentCard) return;
|
|
|
|
const valueEl = parentCard.querySelector('.gauge-value');
|
|
const labelEl = parentCard.querySelector('.card-footer');
|
|
|
|
const normalColor = '#34A853'; // Green
|
|
const warningColor = '#F9AB00'; // Orange
|
|
const alertColor = '#EA4335'; // Red
|
|
const bgColor = '#e9ecef';
|
|
|
|
let activeColor = normalColor;
|
|
if (value >= thresholds.warning && value < thresholds.critical) {
|
|
activeColor = warningColor;
|
|
} else if (value >= thresholds.critical) {
|
|
activeColor = alertColor;
|
|
}
|
|
|
|
// Update text content
|
|
if(labelEl) labelEl.textContent = label;
|
|
if(valueEl) {
|
|
valueEl.textContent = `${value}${unit}`;
|
|
valueEl.style.color = activeColor;
|
|
}
|
|
|
|
|
|
const percentage = Math.min(Math.max((value / max) * 100, 0), 100);
|
|
|
|
// If a chart already exists for this canvas, destroy it before creating a new one.
|
|
if (chartInstances[canvasId]) {
|
|
chartInstances[canvasId].destroy();
|
|
}
|
|
|
|
chartInstances[canvasId] = new Chart(ctx, {
|
|
type: 'doughnut',
|
|
data: {
|
|
datasets: [{
|
|
data: [percentage, 100 - percentage],
|
|
backgroundColor: [activeColor, bgColor],
|
|
borderColor: [activeColor, bgColor],
|
|
borderWidth: 1,
|
|
circumference: 270,
|
|
rotation: 225,
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
cutout: '80%',
|
|
plugins: {
|
|
legend: { display: false },
|
|
tooltip: { enabled: false }
|
|
},
|
|
events: []
|
|
}
|
|
});
|
|
};
|
|
|
|
const fetchSensorData = async () => {
|
|
try {
|
|
// Append a cache-busting query parameter
|
|
const response = await fetch('api/sensor-data.php?v=' + new Date().getTime());
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
const { data, thresholds } = await response.json();
|
|
|
|
// Update gauges with the new data
|
|
createGauge('gauge1', 'Temperature', data.temperature, thresholds.temperature.max, '°C', thresholds.temperature);
|
|
createGauge('gauge2', 'Humidity', data.humidity, thresholds.humidity.max, '%', thresholds.humidity);
|
|
createGauge('gauge3', 'CO2 Level', data.co2, thresholds.co2.max, 'ppm', thresholds.co2);
|
|
createGauge('gauge4', 'Gas Detection', data.gas_level, thresholds.gas_level.max, 'ppm', thresholds.gas_level);
|
|
createGauge('gauge5', 'Pressure', data.pressure, thresholds.pressure.max, 'hPa', thresholds.pressure);
|
|
createGauge('gauge6', 'Light Intensity', data.light_level, thresholds.light_level.max, 'lux', thresholds.light_level);
|
|
|
|
} catch (error) {
|
|
console.error("Could not fetch sensor data:", error);
|
|
// Find the main row and display an error
|
|
const mainRow = document.querySelector('.row');
|
|
if (mainRow) {
|
|
mainRow.innerHTML = `
|
|
<div class="col-12">
|
|
<div class="alert alert-danger" role="alert">
|
|
<strong>Error:</strong> Could not load live sensor data. The backend might be offline. Please check the console for details.
|
|
</div>
|
|
</div>`;
|
|
}
|
|
}
|
|
};
|
|
|
|
// Initial data load
|
|
fetchSensorData();
|
|
|
|
// Refresh data every 15 seconds
|
|
setInterval(fetchSensorData, 15000);
|
|
}); |