306 lines
6.2 KiB
JavaScript
306 lines
6.2 KiB
JavaScript
const express = require("express");
|
|
const mysql = require("mysql2");
|
|
|
|
const app = express();
|
|
const PORT = 3000;
|
|
app.use(express.json());
|
|
|
|
// ============================
|
|
// DB CONFIG
|
|
// ============================
|
|
const dbConfig = {
|
|
host: "db", // docker service name
|
|
user: "leman",
|
|
password: "leman123",
|
|
database: "air_quality"
|
|
};
|
|
|
|
let db;
|
|
|
|
// ============================
|
|
// CONNECT WITH RETRY
|
|
// ============================
|
|
function connectDB() {
|
|
db = mysql.createConnection(dbConfig);
|
|
|
|
db.connect(err => {
|
|
if (err) {
|
|
console.error("❌ DB connection failed:", err.message);
|
|
console.log("🔄 Retrying in 5 seconds...");
|
|
setTimeout(connectDB, 5000);
|
|
} else {
|
|
console.log("✅ Connected to MariaDB");
|
|
}
|
|
});
|
|
|
|
db.on("error", err => {
|
|
console.error("⚠️ DB error:", err.message);
|
|
|
|
if (err.code === "PROTOCOL_CONNECTION_LOST") {
|
|
console.log("🔄 Reconnecting...");
|
|
connectDB();
|
|
} else {
|
|
throw err;
|
|
}
|
|
});
|
|
}
|
|
|
|
connectDB();
|
|
|
|
// ============================
|
|
// ROOT CHECK
|
|
// ============================
|
|
app.get("/", (req, res) => {
|
|
res.send("API is running 🚀");
|
|
});
|
|
|
|
// ============================
|
|
// GET LATEST DATA
|
|
// ============================
|
|
app.get("/data", (req, res) => {
|
|
const sql = `
|
|
SELECT * FROM air_data
|
|
ORDER BY updated_at DESC
|
|
LIMIT 1
|
|
`;
|
|
|
|
db.query(sql, (err, results) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return res.status(500).json({ error: "DB error" });
|
|
}
|
|
|
|
res.json(results[0] || {});
|
|
});
|
|
});
|
|
|
|
// ============================
|
|
// INSERT DATA
|
|
// ============================
|
|
app.get("/update", (req, res) => {
|
|
const { co2, co, bz, aq, id } = req.query;
|
|
|
|
if (!co2 || !co || !bz || !aq || !id) {
|
|
return res.status(400).json({
|
|
error: "Parameter wajib: co2, co, bz, aq, id"
|
|
});
|
|
}
|
|
|
|
const sql = `
|
|
INSERT INTO air_data (co2, co, bz, aq, id)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
`;
|
|
|
|
db.query(
|
|
sql,
|
|
[
|
|
Number(co2),
|
|
Number(co),
|
|
Number(bz),
|
|
Number(aq),
|
|
String(id) // sensor id
|
|
],
|
|
(err, result) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return res.status(500).json({ error: "DB error" });
|
|
}
|
|
|
|
res.json({
|
|
message: "Data berhasil disimpan",
|
|
insertId: result.insertId
|
|
});
|
|
}
|
|
);
|
|
});
|
|
|
|
app.get("/sensordata/:id", (req, res) => {
|
|
const sensorId = req.params.id;
|
|
|
|
const sql = `
|
|
SELECT
|
|
air_data.co2,
|
|
air_data.co,
|
|
air_data.bz,
|
|
air_data.aq,
|
|
air_data.updated_at,
|
|
|
|
sensor_data.alamat,
|
|
|
|
kelurahan.nama AS kelurahan,
|
|
kecamatan.nama AS kecamatan
|
|
|
|
FROM air_data
|
|
|
|
JOIN sensor_data
|
|
ON air_data.id = sensor_data.id
|
|
|
|
JOIN kelurahan
|
|
ON sensor_data.kelurahan = kelurahan.id
|
|
|
|
JOIN kecamatan
|
|
ON kelurahan.kecamatan_id = kecamatan.id
|
|
|
|
WHERE air_data.id = ?
|
|
ORDER BY air_data.updated_at DESC
|
|
LIMIT 1
|
|
`;
|
|
|
|
db.query(sql, [sensorId], (err, results) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return res.status(500).json({ error: "DB error" });
|
|
}
|
|
|
|
if (results.length === 0) {
|
|
return res.status(404).json({
|
|
error: "Sensor not found"
|
|
});
|
|
}
|
|
|
|
res.json(results[0]);
|
|
});
|
|
});
|
|
|
|
app.get("/sensors", (req, res) => {
|
|
const sql = `SELECT id FROM sensor_data`;
|
|
|
|
db.query(sql, (err, results) => {
|
|
if (err) {
|
|
return res.status(500).json({ error: "DB error" });
|
|
}
|
|
|
|
res.json(results);
|
|
});
|
|
});
|
|
|
|
// ============================
|
|
// ADD SENSOR
|
|
// ============================
|
|
app.post("/addSensor", (req, res) => {
|
|
const { kelurahan, alamat } = req.body;
|
|
|
|
// ============================
|
|
// VALIDATION
|
|
// ============================
|
|
if (!kelurahan || !alamat) {
|
|
return res.status(400).json({
|
|
error: "kelurahan dan alamat wajib diisi"
|
|
});
|
|
}
|
|
|
|
// ============================
|
|
// VALIDATE KELURAHAN EXISTS
|
|
// ============================
|
|
const checkSql = `SELECT id FROM kelurahan WHERE id = ?`;
|
|
|
|
db.query(checkSql, [kelurahan], (err, rows) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return res.status(500).json({ error: "DB error" });
|
|
}
|
|
|
|
if (rows.length === 0) {
|
|
return res.status(400).json({
|
|
error: "Kelurahan tidak valid"
|
|
});
|
|
}
|
|
|
|
// ============================
|
|
// INSERT SENSOR
|
|
// ============================
|
|
const insertSql = `
|
|
INSERT INTO sensor_data (kelurahan, alamat)
|
|
VALUES (?, ?)
|
|
`;
|
|
|
|
db.query(insertSql, [kelurahan, alamat], (err, result) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return res.status(500).json({
|
|
error: "DB error saat insert"
|
|
});
|
|
}
|
|
|
|
res.json({
|
|
message: "Sensor berhasil ditambahkan",
|
|
sensor_id: result.insertId
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
// ============================
|
|
// GET ALL DATA (OPTIONAL)
|
|
// ============================
|
|
app.get("/history", (req, res) => {
|
|
const sql = `
|
|
SELECT * FROM air_data
|
|
ORDER BY updated_at DESC
|
|
LIMIT 100
|
|
`;
|
|
|
|
db.query(sql, (err, results) => {
|
|
if (err) {
|
|
return res.status(500).json({ error: "DB error" });
|
|
}
|
|
|
|
res.json(results);
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// get kecamatan
|
|
app.get("/kecamatan", (req, res) => {
|
|
const sql = `SELECT id, nama FROM kecamatan ORDER BY nama ASC`;
|
|
|
|
db.query(sql, (err, results) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return res.status(500).json({ error: "DB error" });
|
|
}
|
|
|
|
res.json(results);
|
|
});
|
|
});
|
|
|
|
|
|
// get kelurahan by kecamatan_id
|
|
app.get("/kelurahan", (req, res) => {
|
|
const { kecamatan_id } = req.query;
|
|
|
|
let sql = `
|
|
SELECT
|
|
kelurahan.id,
|
|
kelurahan.nama,
|
|
kecamatan.nama AS kecamatan
|
|
FROM kelurahan
|
|
JOIN kecamatan ON kelurahan.kecamatan_id = kecamatan.id
|
|
`;
|
|
|
|
let params = [];
|
|
|
|
if (kecamatan_id) {
|
|
sql += ` WHERE kelurahan.kecamatan_id = ?`;
|
|
params.push(kecamatan_id);
|
|
}
|
|
|
|
sql += ` ORDER BY kelurahan.nama ASC`;
|
|
|
|
db.query(sql, params, (err, results) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return res.status(500).json({ error: "DB error" });
|
|
}
|
|
|
|
res.json(results);
|
|
});
|
|
});
|
|
|
|
// ============================
|
|
// START SERVER
|
|
// ============================
|
|
app.listen(PORT, () => {
|
|
console.log(`🚀 API running on port ${PORT}`);
|
|
}); |