added phpmyadmin and mysql database, change the html so dont flickering and load container only once
This commit is contained in:
@ -2,7 +2,7 @@ FROM node:20-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN npm init -y && npm install express
|
||||
RUN npm init -y && npm install express mysql2
|
||||
|
||||
COPY server.js .
|
||||
COPY data.json .
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"CO2": 2.43,
|
||||
"CO": 0.56,
|
||||
"BZ": 3.11,
|
||||
"CO2": 2.78,
|
||||
"CO": 0.62,
|
||||
"BZ": 3.7,
|
||||
"AQ": 100,
|
||||
"updated_at": "2026-01-30T03:48:16.033Z"
|
||||
"updated_at": "2026-03-11T12:46:55.233Z"
|
||||
}
|
||||
98
api/server copy.js
Normal file
98
api/server copy.js
Normal file
@ -0,0 +1,98 @@
|
||||
const express = require("express");
|
||||
const fs = require("fs");
|
||||
|
||||
const app = express();
|
||||
const PORT = 3000;
|
||||
const DATA_FILE = "./data.json";
|
||||
|
||||
// Helper: read data
|
||||
function readData() {
|
||||
return JSON.parse(fs.readFileSync(DATA_FILE, "utf8"));
|
||||
}
|
||||
|
||||
// Helper: write data
|
||||
function writeData(data) {
|
||||
fs.writeFileSync(DATA_FILE, JSON.stringify(data, null, 2));
|
||||
}
|
||||
|
||||
// ============================
|
||||
// GET /api/data → read values
|
||||
// ============================
|
||||
app.get("/data", (req, res) => {
|
||||
try {
|
||||
const data = readData();
|
||||
res.json(data);
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: "Gagal membaca data" });
|
||||
}
|
||||
});
|
||||
|
||||
// ============================
|
||||
// ADD SENSOR
|
||||
// ============================
|
||||
app.post("/addSensor", (req, res) => {
|
||||
const { id } = req.body;
|
||||
|
||||
if (!id) {
|
||||
return res.status(400).json({
|
||||
error: "Sensor ID is required"
|
||||
});
|
||||
}
|
||||
|
||||
const sql = `INSERT INTO sensor_data (id) VALUES (?)`;
|
||||
|
||||
db.query(sql, [id], (err, result) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
|
||||
// handle duplicate ID (optional but nice)
|
||||
if (err.code === "ER_DUP_ENTRY") {
|
||||
return res.status(400).json({
|
||||
error: "Sensor already exists"
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(500).json({ error: "DB error" });
|
||||
}
|
||||
|
||||
res.json({
|
||||
message: "Sensor added successfully",
|
||||
id: id
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// ===========================================
|
||||
// GET /api/update?co2=&co=&bz=&aq=
|
||||
// ===========================================
|
||||
app.get("/update", (req, res) => {
|
||||
const { co2, co, bz, aq } = req.query;
|
||||
|
||||
if (!co2 || !co || !bz || !aq) {
|
||||
return res.status(400).json({
|
||||
error: "Parameter wajib: co2, co, bz, aq"
|
||||
});
|
||||
}
|
||||
|
||||
const newData = {
|
||||
CO2: Number(co2),
|
||||
CO: Number(co),
|
||||
BZ: Number(bz),
|
||||
AQ: Number(aq),
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
|
||||
try {
|
||||
writeData(newData);
|
||||
res.json({
|
||||
message: "Data berhasil diperbarui",
|
||||
data: newData
|
||||
});
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: "Gagal menyimpan data" });
|
||||
}
|
||||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`API berjalan di port ${PORT}`);
|
||||
});
|
||||
329
api/server.js
329
api/server.js
@ -1,63 +1,306 @@
|
||||
const express = require("express");
|
||||
const fs = require("fs");
|
||||
const mysql = require("mysql2");
|
||||
|
||||
const app = express();
|
||||
const PORT = 3000;
|
||||
const DATA_FILE = "./data.json";
|
||||
|
||||
// Helper: read data
|
||||
function readData() {
|
||||
return JSON.parse(fs.readFileSync(DATA_FILE, "utf8"));
|
||||
}
|
||||
|
||||
// Helper: write data
|
||||
function writeData(data) {
|
||||
fs.writeFileSync(DATA_FILE, JSON.stringify(data, null, 2));
|
||||
}
|
||||
app.use(express.json());
|
||||
|
||||
// ============================
|
||||
// GET /api/data → read values
|
||||
// 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) => {
|
||||
try {
|
||||
const data = readData();
|
||||
res.json(data);
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: "Gagal membaca data" });
|
||||
}
|
||||
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] || {});
|
||||
});
|
||||
});
|
||||
|
||||
// ===========================================
|
||||
// GET /api/update?co2=&co=&bz=&aq=
|
||||
// ===========================================
|
||||
// ============================
|
||||
// INSERT DATA
|
||||
// ============================
|
||||
app.get("/update", (req, res) => {
|
||||
const { co2, co, bz, aq } = req.query;
|
||||
const { co2, co, bz, aq, id } = req.query;
|
||||
|
||||
if (!co2 || !co || !bz || !aq) {
|
||||
if (!co2 || !co || !bz || !aq || !id) {
|
||||
return res.status(400).json({
|
||||
error: "Parameter wajib: co2, co, bz, aq"
|
||||
error: "Parameter wajib: co2, co, bz, aq, id"
|
||||
});
|
||||
}
|
||||
|
||||
const newData = {
|
||||
CO2: Number(co2),
|
||||
CO: Number(co),
|
||||
BZ: Number(bz),
|
||||
AQ: Number(aq),
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
const sql = `
|
||||
INSERT INTO air_data (co2, co, bz, aq, id)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`;
|
||||
|
||||
try {
|
||||
writeData(newData);
|
||||
res.json({
|
||||
message: "Data berhasil diperbarui",
|
||||
data: newData
|
||||
});
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: "Gagal menyimpan data" });
|
||||
}
|
||||
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 berjalan di port ${PORT}`);
|
||||
});
|
||||
console.log(`🚀 API running on port ${PORT}`);
|
||||
});
|
||||
Reference in New Issue
Block a user