325 lines
8.5 KiB
HTML
325 lines
8.5 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Sistem Monitoring Kualitas Udara</title>
|
|
|
|
<link rel="stylesheet" href="assets/styles/style-horizontal.min.css">
|
|
<link rel="stylesheet" href="assets/plugin/mCustomScrollbar/jquery.mCustomScrollbar.min.css">
|
|
<link rel="stylesheet" href="assets/plugin/waves/waves.min.css">
|
|
<link rel="stylesheet" href="assets/plugin/sweet-alert/sweetalert.css">
|
|
</head>
|
|
|
|
<body>
|
|
<header class="fixed-header">
|
|
<div class="header-top">
|
|
<div class="container">
|
|
<div class="pull-left">
|
|
<a href="index.html" class="logo">Monitor Kualitas Udara</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="nav-horizontal">
|
|
<div class="container">
|
|
<ul class="menu">
|
|
<li class="current">
|
|
<a href="index.html">
|
|
<i class="ico fa fa-home"></i>
|
|
<span>Halaman Utama</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="list.html">
|
|
<i class="ico fa fa-list"></i>
|
|
<span>List Sensor</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
</header>
|
|
|
|
<div id="wrapper">
|
|
<div class="main-content container">
|
|
<div class="row small-spacing" id="ini_dia"></div>
|
|
|
|
<div style="margin-top:20px;">
|
|
<button class="btn btn-primary" onclick="openDialog()">Add Sensor</button>
|
|
</div>
|
|
|
|
<footer class="footer">
|
|
<ul class="list-inline">
|
|
<li>2026 © SULAIMAN, Universitas Muhammadiyah Parepare.</li>
|
|
</ul>
|
|
</footer>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal -->
|
|
<div id="dialog"
|
|
style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,.6); z-index:9999;">
|
|
<div style="background:#fff; padding:20px; width:350px; margin:100px auto; border-radius:10px;">
|
|
<h4>Tambah Sensor</h4>
|
|
|
|
<label>Alamat:</label>
|
|
<select id="alamat-select" class="form-control" onchange="gambar_preview()">
|
|
<option value="">-- Pilih Alamat --</option>
|
|
</select>
|
|
|
|
<div id="preview-container" style="margin-top:15px;"></div>
|
|
<hr>
|
|
|
|
|
|
|
|
<button class="btn btn-success" onclick="addSensor()">Simpan</button>
|
|
<button class="btn btn-default" onclick="closeDialog()">Batal</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="assets/scripts/jquery.min.js"></script>
|
|
<script src="assets/plugin/bootstrap/js/bootstrap.min.js"></script>
|
|
<script src="assets/plugin/nprogress/nprogress.js"></script>
|
|
<script src="assets/scripts/main.js"></script>
|
|
|
|
<script>
|
|
function getStatus(aq) {
|
|
if (aq >= 90) return "Sangat Baik";
|
|
if (aq >= 70) return "Baik";
|
|
if (aq >= 50) return "Sedang";
|
|
if (aq > 30) return "Buruk";
|
|
return "Sangat Buruk";
|
|
}
|
|
|
|
async function fetchAllSensors() {
|
|
const res = await fetch("/api/sensors");
|
|
return await res.json();
|
|
}
|
|
|
|
async function fetchSensorData(id) {
|
|
const res = await fetch(`/api/sensordata/${id}`);
|
|
return await res.json();
|
|
}
|
|
|
|
async function initSensors() {
|
|
const container = document.getElementById("ini_dia");
|
|
container.innerHTML = "";
|
|
|
|
const sensors = await fetchAllSensors();
|
|
|
|
for (const sensor of sensors) {
|
|
const data = await fetchSensorData(sensor.id);
|
|
|
|
const card = document.createElement("div");
|
|
card.className = "col-lg-6 col-xs-12";
|
|
|
|
if (!data || data.error) {
|
|
card.innerHTML = `
|
|
<div class="box-content card white">
|
|
<h4 class="box-title">Sensor ID: ${sensor.id}</h4>
|
|
<div class="card-content">
|
|
<p style="color: orange;">Belum Ada Data</p>
|
|
</div>
|
|
</div>
|
|
`;
|
|
} else {
|
|
card.innerHTML = `
|
|
<div class="box-content card white">
|
|
<h4 class="box-title">Sensor ID: ${sensor.id}</h4>
|
|
<div class="card-content">
|
|
<form class="form-horizontal">
|
|
|
|
|
|
<div class="form-group">
|
|
<label class="col-sm-4 control-label">Alamat</label>
|
|
<div class="col-sm-8">
|
|
<p class="form-control-static">${data.alamat}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="col-sm-4 control-label">Karbon Monoksida</label>
|
|
<div class="col-sm-8">
|
|
<p class="form-control-static">
|
|
<span id="co2-${sensor.id}">-</span> ppm
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="col-sm-4 control-label">Karbon Oksida</label>
|
|
<div class="col-sm-8">
|
|
<p class="form-control-static">
|
|
<span id="co-${sensor.id}">-</span> ppm
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="col-sm-4 control-label">Benzena</label>
|
|
<div class="col-sm-8">
|
|
<p class="form-control-static">
|
|
<span id="bz-${sensor.id}">-</span> ppm
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="col-sm-4 control-label">Kualitas</label>
|
|
<div class="col-sm-8">
|
|
<p class="form-control-static">
|
|
<span id="aq-${sensor.id}">-</span> %
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="col-sm-4 control-label">Status</label>
|
|
<div class="col-sm-8">
|
|
<p class="form-control-static">
|
|
<span id="qa-${sensor.id}">-</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
</form>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
container.appendChild(card);
|
|
}
|
|
}
|
|
|
|
async function updateSensorValues() {
|
|
const sensors = await fetchAllSensors();
|
|
|
|
for (const sensor of sensors) {
|
|
const data = await fetchSensorData(sensor.id);
|
|
|
|
if (!data || data.error) continue;
|
|
|
|
const co2 = document.getElementById(`co2-${sensor.id}`);
|
|
if (!co2) continue;
|
|
|
|
document.getElementById(`co2-${sensor.id}`).textContent = data.co2;
|
|
document.getElementById(`co-${sensor.id}`).textContent = data.co;
|
|
document.getElementById(`bz-${sensor.id}`).textContent = data.bz;
|
|
document.getElementById(`aq-${sensor.id}`).textContent = data.aq;
|
|
document.getElementById(`qa-${sensor.id}`).textContent = getStatus(data.aq);
|
|
}
|
|
}
|
|
|
|
function openDialog() {
|
|
document.getElementById("dialog").style.display = "block";
|
|
// reset dropdown
|
|
document.getElementById("alamat-select").value = "";
|
|
$("#preview-gambar").html("");
|
|
loadAlamat();
|
|
}
|
|
|
|
function closeDialog() {
|
|
document.getElementById("dialog").style.display = "none";
|
|
}
|
|
|
|
async function addSensor() {
|
|
const id = document.getElementById("alamat-select").value;
|
|
|
|
if (!id) {
|
|
alert("Pilih alamat terlebih dahulu!");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const res = await fetch("/api/addSensor", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json"
|
|
},
|
|
body: JSON.stringify({ id })
|
|
});
|
|
|
|
const result = await res.json();
|
|
|
|
if (!res.ok) {
|
|
alert(result.error || "Gagal menambah sensor");
|
|
return;
|
|
}
|
|
|
|
alert("Sensor berhasil ditambahkan");
|
|
|
|
closeDialog();
|
|
|
|
// reset dropdown
|
|
document.getElementById("alamat-select").value = "";
|
|
$("#preview-gambar").html("");
|
|
|
|
// rebuild cards
|
|
await initSensors();
|
|
updateSensorValues();
|
|
|
|
} catch (err) {
|
|
console.error(err);
|
|
alert("Terjadi kesalahan");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
initSensors();
|
|
updateSensorValues();
|
|
setInterval(updateSensorValues, 5000);
|
|
|
|
async function loadAlamat() {
|
|
const res = await fetch("/api/alamat");
|
|
const data = await res.json();
|
|
|
|
const select = document.getElementById("alamat-select");
|
|
select.innerHTML = `<option value="">-- Pilih Alamat --</option>`;
|
|
|
|
data.forEach(item => {
|
|
select.innerHTML += `<option value="${item.id}">${item.alamat}</option>`;
|
|
});
|
|
}
|
|
|
|
function gambar_preview() {
|
|
const alamatId = document.getElementById("alamat-select").value;
|
|
const container = document.getElementById("preview-container");
|
|
|
|
container.innerHTML = "";
|
|
|
|
if (!alamatId) return;
|
|
|
|
const maxImages = 5; // try up to 5 images
|
|
|
|
for (let i = 1; i <= maxImages; i++) {
|
|
const path = `assets/images/${alamatId}/${i}.png`;
|
|
|
|
const img = new Image();
|
|
|
|
img.onload = function () {
|
|
img.style.width = "100%";
|
|
img.style.marginBottom = "10px";
|
|
img.style.borderRadius = "8px";
|
|
img.style.border = "1px solid #ddd";
|
|
|
|
container.appendChild(img);
|
|
};
|
|
|
|
img.onerror = function () {
|
|
// image doesn't exist → ignore
|
|
};
|
|
|
|
img.src = path;
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
|
|
</html> |