first commit
This commit is contained in:
366
templates/dashboard.html
Normal file
366
templates/dashboard.html
Normal file
@@ -0,0 +1,366 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Lab Weather Dashboard</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="{{ url_for('static', filename='style.css') }}"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<h1>MBTECH Binglab Envoro Dashboard</h1>
|
||||
<p class="subtitle">Environmental Monitoring System</p>
|
||||
</header>
|
||||
|
||||
<div class="current-readings">
|
||||
<h2>Current Conditions</h2>
|
||||
<div class="reading-cards">
|
||||
<div class="card temperature-card">
|
||||
<div class="card-icon">🌡️</div>
|
||||
<div class="card-content">
|
||||
<div class="card-value" id="current-temp">--</div>
|
||||
<div class="card-label">Temperature (°C)</div>
|
||||
<div class="card-sublabel" id="temp-raw" style="font-size: 0.85em; color: #888; margin-top: 4px;">Raw: --°C</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card pressure-card">
|
||||
<div class="card-icon">🔽</div>
|
||||
<div class="card-content">
|
||||
<div class="card-value" id="current-pressure">
|
||||
--
|
||||
</div>
|
||||
<div class="card-label">Pressure (hPa)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card light-card">
|
||||
<div class="card-icon">💡</div>
|
||||
<div class="card-content">
|
||||
<div class="card-value" id="current-light">--</div>
|
||||
<div class="card-label">Light (lux)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card color-card">
|
||||
<div class="card-icon">🎨</div>
|
||||
<div class="card-content">
|
||||
<div class="color-swatch" id="color-swatch"></div>
|
||||
<div class="card-label">Detected Color</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="last-update">
|
||||
Last update: <span id="last-update">--</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stats-section">
|
||||
<h2>Today's Statistics</h2>
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-title">Temperature</div>
|
||||
<div class="stat-values">
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Min:</span>
|
||||
<span class="stat-value" id="temp-min">--</span
|
||||
>°C
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Max:</span>
|
||||
<span class="stat-value" id="temp-max">--</span
|
||||
>°C
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Avg:</span>
|
||||
<span class="stat-value" id="temp-avg">--</span
|
||||
>°C
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<div class="stat-title">Pressure</div>
|
||||
<div class="stat-values">
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Min:</span>
|
||||
<span class="stat-value" id="pressure-min"
|
||||
>--</span
|
||||
>
|
||||
hPa
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Max:</span>
|
||||
<span class="stat-value" id="pressure-max"
|
||||
>--</span
|
||||
>
|
||||
hPa
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Avg:</span>
|
||||
<span class="stat-value" id="pressure-avg"
|
||||
>--</span
|
||||
>
|
||||
hPa
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<div class="stat-title">Light</div>
|
||||
<div class="stat-values">
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Min:</span>
|
||||
<span class="stat-value" id="light-min"
|
||||
>--</span
|
||||
>
|
||||
lux
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Max:</span>
|
||||
<span class="stat-value" id="light-max"
|
||||
>--</span
|
||||
>
|
||||
lux
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Avg:</span>
|
||||
<span class="stat-value" id="light-avg"
|
||||
>--</span
|
||||
>
|
||||
lux
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="charts-section">
|
||||
<h2>Historical Data</h2>
|
||||
<div class="chart-container">
|
||||
<canvas id="temperatureChart"></canvas>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<canvas id="pressureChart"></canvas>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<canvas id="lightChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let tempChart, pressureChart, lightChart;
|
||||
|
||||
// Initialize charts
|
||||
function initCharts() {
|
||||
const commonOptions = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
aspectRatio: 3,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
type: "category",
|
||||
ticks: {
|
||||
maxTicksLimit: 10,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
beginAtZero: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
tempChart = new Chart(
|
||||
document.getElementById("temperatureChart"),
|
||||
{
|
||||
type: "line",
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [
|
||||
{
|
||||
label: "Temperature (°C)",
|
||||
data: [],
|
||||
borderColor: "#ff6b6b",
|
||||
backgroundColor: "rgba(255, 107, 107, 0.1)",
|
||||
tension: 0.4,
|
||||
fill: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: commonOptions,
|
||||
},
|
||||
);
|
||||
|
||||
pressureChart = new Chart(
|
||||
document.getElementById("pressureChart"),
|
||||
{
|
||||
type: "line",
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [
|
||||
{
|
||||
label: "Pressure (hPa)",
|
||||
data: [],
|
||||
borderColor: "#4ecdc4",
|
||||
backgroundColor: "rgba(78, 205, 196, 0.1)",
|
||||
tension: 0.4,
|
||||
fill: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: commonOptions,
|
||||
},
|
||||
);
|
||||
|
||||
lightChart = new Chart(document.getElementById("lightChart"), {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [
|
||||
{
|
||||
label: "Light (lux)",
|
||||
data: [],
|
||||
borderColor: "#ffe66d",
|
||||
backgroundColor: "rgba(255, 230, 109, 0.1)",
|
||||
tension: 0.4,
|
||||
fill: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: commonOptions,
|
||||
});
|
||||
}
|
||||
|
||||
// Update current readings
|
||||
async function updateCurrent() {
|
||||
try {
|
||||
const response = await fetch("/api/current");
|
||||
const data = await response.json();
|
||||
|
||||
document.getElementById("current-temp").textContent =
|
||||
data.temperature;
|
||||
|
||||
// Update raw temperature if available
|
||||
if (data.temperature_raw !== undefined) {
|
||||
document.getElementById("temp-raw").textContent =
|
||||
`Raw: ${data.temperature_raw}°C`;
|
||||
}
|
||||
|
||||
document.getElementById("current-pressure").textContent =
|
||||
data.pressure;
|
||||
document.getElementById("current-light").textContent =
|
||||
data.light;
|
||||
document.getElementById("last-update").textContent =
|
||||
data.timestamp;
|
||||
|
||||
// Update color swatch if RGB data is available
|
||||
if (data.rgb) {
|
||||
const colorSwatch = document.getElementById("color-swatch");
|
||||
colorSwatch.style.backgroundColor = `rgb(${data.rgb.r}, ${data.rgb.g}, ${data.rgb.b})`;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching current data:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Update statistics
|
||||
async function updateStats() {
|
||||
try {
|
||||
const response = await fetch("/api/stats");
|
||||
const data = await response.json();
|
||||
|
||||
if (data.temperature) {
|
||||
document.getElementById("temp-min").textContent =
|
||||
data.temperature.min;
|
||||
document.getElementById("temp-max").textContent =
|
||||
data.temperature.max;
|
||||
document.getElementById("temp-avg").textContent =
|
||||
data.temperature.avg;
|
||||
}
|
||||
|
||||
if (data.pressure) {
|
||||
document.getElementById("pressure-min").textContent =
|
||||
data.pressure.min;
|
||||
document.getElementById("pressure-max").textContent =
|
||||
data.pressure.max;
|
||||
document.getElementById("pressure-avg").textContent =
|
||||
data.pressure.avg;
|
||||
}
|
||||
|
||||
if (data.light) {
|
||||
document.getElementById("light-min").textContent =
|
||||
data.light.min;
|
||||
document.getElementById("light-max").textContent =
|
||||
data.light.max;
|
||||
document.getElementById("light-avg").textContent =
|
||||
data.light.avg;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching stats:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Update historical charts
|
||||
async function updateHistory() {
|
||||
try {
|
||||
const response = await fetch("/api/history");
|
||||
const data = await response.json();
|
||||
|
||||
if (data.length === 0) return;
|
||||
|
||||
const labels = data.map((d) => {
|
||||
const date = new Date(d.timestamp);
|
||||
return date.toLocaleTimeString("en-US", {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
});
|
||||
|
||||
const temps = data.map((d) => d.temperature);
|
||||
const pressures = data.map((d) => d.pressure);
|
||||
const lights = data.map((d) => d.light);
|
||||
|
||||
tempChart.data.labels = labels;
|
||||
tempChart.data.datasets[0].data = temps;
|
||||
tempChart.update();
|
||||
|
||||
pressureChart.data.labels = labels;
|
||||
pressureChart.data.datasets[0].data = pressures;
|
||||
pressureChart.update();
|
||||
|
||||
lightChart.data.labels = labels;
|
||||
lightChart.data.datasets[0].data = lights;
|
||||
lightChart.update();
|
||||
} catch (error) {
|
||||
console.error("Error fetching history:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize and start auto-refresh
|
||||
initCharts();
|
||||
updateCurrent();
|
||||
updateStats();
|
||||
updateHistory();
|
||||
|
||||
// Refresh current readings every 10 seconds
|
||||
setInterval(updateCurrent, 10000);
|
||||
|
||||
// Refresh stats and history every 60 seconds
|
||||
setInterval(() => {
|
||||
updateStats();
|
||||
updateHistory();
|
||||
}, 60000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user