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 ORDER BY id ASC`; 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}`); });