You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
4.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Air Quality Monitor</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400&display=swap" rel="stylesheet">
<style>
/* General Styles */
* { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Roboto', sans-serif; }
body { display: flex; flex-direction: column; align-items: center; justify-content: center; background: #f5f5f5; color: #333; height: 100vh; }
h1 { font-size: 2em; color: #444; margin-bottom: 20px; }
/* Container for Sensors */
.sensor-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 20px;
width: 100%;
max-width: 800px;
padding: 10px;
}
/* Sensor Box */
.sensor {
background: #fff;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 10px;
width: 180px;
padding: 20px;
text-align: center;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.sensor:hover { transform: scale(1.05); box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15); }
/* Sensor Titles */
.sensor-title {
font-weight: 400;
color: #555;
font-size: 1.2em;
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: center;
}
/* Sensor Value */
.sensor-value {
font-size: 2.5em;
font-weight: 300;
color: #333;
margin-bottom: 5px;
animation: fadeIn 0.5s ease;
}
.unit { font-size: 0.8em; color: #777; }
/* Icon Styles */
.sensor-icon {
width: 30px;
height: 30px;
margin-right: 8px;
filter: grayscale(50%);
}
/* Keyframes for Smooth Animations */
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
</style>
</head>
<body>
<h1>Room Air Quality Monitor</h1>
<div class="sensor-container">
<div id="temperature" class="sensor">
<div class="sensor-title">
<img src="./images/thermometer-outline.svg" class="sensor-icon" alt="Temperature Icon">
Temperature
</div>
<div class="sensor-value" id="temp-value">--</div>
<div class="unit"></div>
</div>
<div id="humidity" class="sensor">
<div class="sensor-title">
<img src="./images/water-outline.svg" class="sensor-icon" alt="Humidity Icon">
Humidity
</div>
<div class="sensor-value" id="humidity-value">--</div>
<div class="unit">%</div>
</div>
<div id="co2" class="sensor">
<div class="sensor-title">
<img src="./images/cloud-outline.svg" class="sensor-icon" alt="CO2 Icon">
CO₂
</div>
<div class="sensor-value" id="co2-value">--</div>
<div class="unit">ppm</div>
</div>
<div id="pressure" class="sensor">
<div class="sensor-title">
<img src="./images/sunny-outline.svg" class="sensor-icon" alt="Pressure Icon">
Pressure
</div>
<div class="sensor-value" id="pressure-value">--</div>
<div class="unit">hPa</div>
</div>
</div>
<script>
async function fetchData() {
try {
const res = await Promise.all([
//fetch("./data/BH1750.json"),
//fetch("./data/BMP180.json"),
fetch("./data/HTU21D.json"),
//fetch("./data/MH_Z19.json")
]);
const data = (await Promise.all(res.map(r => r.json()))).reduce((acc, item) => ({ ...acc, ...item }), {});
return data;
} catch (error) {
console.error("Failed to fetch sensor data:", error);
return {};
}
}
function updateUI(data) {
document.getElementById("temp-value").textContent = data.temperature ? data.temperature.toFixed(1) : "--";
document.getElementById("humidity-value").textContent = data.humidity ? data.humidity.toFixed(1) : "--";
document.getElementById("co2-value").textContent = data.co2 ? data.co2 : "--";
document.getElementById("pressure-value").textContent = data.pressure ? data.pressure.toFixed(1) : "--";
}
async function refreshData() {
const data = await fetchData();
updateUI(data);
}
setInterval(refreshData, 6000); // Refresh every 60 seconds
refreshData(); // Initial fetch
</script>
</body>
</html>