diff --git a/._.DS_Store b/._.DS_Store new file mode 100755 index 0000000..cda2de7 Binary files /dev/null and b/._.DS_Store differ diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000..e61dc75 Binary files /dev/null and b/bun.lockb differ diff --git a/conn.js b/conn.js new file mode 100755 index 0000000..fc83a40 --- /dev/null +++ b/conn.js @@ -0,0 +1,22 @@ +const mysql = require('mysql'); +const dotenv = require('dotenv'); + +dotenv.config(); + +// Connect to the MySQL database +const connection = mysql.createConnection({ + host: process.env.DB_HOST, + user: process.env.DB_USER, + password: process.env.DB_PASS, + database: process.env.DB_NAME +}); + +// connection.connect((err) => { +// if (err) { +// console.error('Error connecting to MySQL database: ' + err.stack); +// return; +// } +// console.log('Connected to MySQL database as id ' + connection.threadId); +// }) + +module.exports = {connection} \ No newline at end of file diff --git a/index.js b/index.js index bf738fa..d5260c0 100755 --- a/index.js +++ b/index.js @@ -1,31 +1,198 @@ const express = require('express'); -const bodyParser = require('body-parser'); - +const http = require('http'); +const cors = require('cors'); +const dotenv = require('dotenv'); +const socket = require('./socket'); const app = express(); -const port = 3001; +const server = http.createServer(app); +const io = socket.init(server); +const iosend = socket.getIO(); +const conn = require('./conn.js'); +const connection = conn.connection; -// Parse JSON bodies -app.use(bodyParser.json()); +dotenv.config(); + +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); +// app.use(fileUpload()); +app.options('*', cors()); +app.use(cors()); + +function timeStringToDate(timeStr) { + const [hours, minutes, seconds] = timeStr.split(':').map(Number); + const date = new Date(); + date.setHours(hours, minutes, seconds, 0); + return date; +} // Handle POST requests to '/post' -app.post('/post', (req, res) => { +app.post('/', async (req, res) => { // Access the POST data sent in the request body - const postData = req.body; + var postData = req.body; + const query_search = 'Select * from tb_data where fase=?'; + + const result_search = await new Promise((resolve, reject) => { + connection.query(query_search, [postData.fase], (err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }); + }) + var now = new Date(); + var hours = now.getHours(); + var minutes = now.getMinutes(); + var seconds = now.getSeconds(); + + // Pad single digits with leading zeros + hours = hours < 10 ? '0' + hours : hours; + minutes = minutes < 10 ? '0' + minutes : minutes; + seconds = seconds < 10 ? '0' + seconds : seconds; + // change the time to 24 h format with no AM/PM . example 12:00:01, li + time = hours + ':' + minutes + ':' + seconds; + // if time only 12:00 add :00 + + // console.log(result_search); + if (result_search.length > 0) { + // get the last data + const data_seach = result_search[result_search.length - 1]; + const time_last = data_seach.time; + console.log("ini current time: " + time) + // console.log("ini last time: " + time_last) + const converted_time_last = timeStringToDate(time_last); + const converted_time = timeStringToDate(time); + console.log('Converted time:', converted_time); + console.log('Converted time last:', converted_time_last); + + // Calculate the difference in seconds + const differenceInSeconds = (converted_time - converted_time_last) / 1000; + + console.log('Difference in seconds:', differenceInSeconds); + + // Check if the difference is exactly 30 seconds + // const isThirtySecondsApart = differenceInSeconds === 30; + + + // check if time_last is 30 second ago from time + // if (differenceInSeconds < 10800) { + if (differenceInSeconds < 3600) { + console.log('data is not new'); + postData.time = time; + console.log('Received data:', postData); + iosend.emit('datanya', postData); + + + // Respond with a simple message + res.send('Received your POST request!'); + return; + } + const query_insert = 'INSERT INTO tb_data (fase, voltage, current, power, energy, pf, time) VALUES (?, ?, ?, ?, ?, ?, ?)'; + const result_insert = await new Promise((resolve, reject) => { + connection.query(query_insert, [postData.fase, postData.voltage, postData.current, postData.power, postData.energy, postData.pf, time], (err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }); + }) + } else { + const query_insert = 'INSERT INTO tb_data (fase, voltage, current, power, energy, pf, time) VALUES (?, ?, ?, ?, ?, ?, ?)'; + const result_insert = await new Promise((resolve, reject) => { + connection.query(query_insert, [postData.fase, postData.voltage, postData.current, postData.power, postData.energy, postData.pf, time], (err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }); + }) + } // Process the received data + + // get timge by hh:mm + + + + + + postData.time = time; console.log('Received data:', postData); + iosend.emit('datanya', postData); + // Respond with a simple message res.send('Received your POST request!'); }); -app.get('/get', (req, res) => { - // Respond with a simple message - console.log('Received GET request'); - res.status(200).send({ message: 'Hello World!' }); +app.get('/', async (req, res) => { + // only show 10 last data + const query_fase_r = 'Select * from tb_data where fase="Fase R" order by id desc limit 10'; + const query_fase_s = 'Select * from tb_data where fase="Fase S" order by id desc limit 10'; + const query_fase_t = 'Select * from tb_data where fase="Fase T" order by id desc limit 10'; + + const result_fase_r = await new Promise((resolve, reject) => { + connection.query(query_fase_r, (err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }); + }) + const result_fase_s = await new Promise((resolve, reject) => { + connection.query(query_fase_s, (err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }); + }) + const result_fase_t =await new Promise((resolve, reject) => { + connection.query(query_fase_t, (err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }) + }) + + return res.json({ "result_fase_r": result_fase_r, "result_fase_s": result_fase_s, "result_fase_t": result_fase_t }); + }) +// app error handler +app.use((err, req, res, next) => { + console.log(err); + res.status(500).send('Something broke!'); +}); + +io.on('connection', (socket) => { + let userID = socket.id; + console.log('A user connected: ' + userID); + + socket.on('scan_dia', (data) => { + console.log('Received scan_dia event: ' + data); + }); + + socket.on('disconnect', () => { + console.log('User disconnected: ' + userID); + }); +}); + +module.exports = { + app, + server, + io +}; + +const port = process.env.PORT || 3001; + // Start the server -app.listen(port, () => { +server.listen(port, () => { console.log(`Server is running on http://localhost:${port}`); }); diff --git a/package-lock.json b/package-lock.json index 5b113cb..bbc7f5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,37 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "dotenv": "^16.4.5", "express": "^4.19.2", "express-form-data": "^2.0.23", - "nodemon": "^3.1.0" + "nodemon": "^3.1.0", + "socket.io": "^4.7.5" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.12.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.8.tgz", + "integrity": "sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==", + "dependencies": { + "undici-types": "~5.26.4" } }, "node_modules/abbrev": { @@ -61,6 +89,14 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -279,6 +315,18 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -320,6 +368,17 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -333,6 +392,63 @@ "node": ">= 0.8" } }, + "node_modules/engine.io": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -888,6 +1004,14 @@ "node": ">=0.10.0" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -1137,6 +1261,107 @@ "node": ">=10" } }, + "node_modules/socket.io": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", + "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", + "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-adapter/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -1214,6 +1439,11 @@ "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -1246,6 +1476,26 @@ "node": ">= 0.8" } }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index 761fd80..bf94bc3 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,11 @@ "author": "kicap", "license": "ISC", "dependencies": { + "dotenv": "^16.4.5", "express": "^4.19.2", "express-form-data": "^2.0.23", - "nodemon": "^3.1.0" + "mysql": "^2.18.1", + "nodemon": "^3.1.0", + "socket.io": "^4.7.5" } } diff --git a/socket.js b/socket.js new file mode 100755 index 0000000..c0d73f3 --- /dev/null +++ b/socket.js @@ -0,0 +1,29 @@ +const socketio = require('socket.io'); +// const socketio_client = require('socket.io-client'); +const dotenv = require('dotenv'); + +dotenv.config(); + +// const socket_client = socketio_client("http://localhost:"+process.env.PORT); + +let io; + +function init(server) { + io = socketio(server); + return io; +} + +function getIO() { + if (!io) { + throw new Error('Socket.io not initialized'); + } + return io; +} + + + +module.exports = { + init, + getIO, + // socket_client +}; \ No newline at end of file