//https://www.dontpanicblog.co.uk/2016/04/17/websocket-push-notifications-with-node-js/ //!!!!!!!!!!!!!!!! //!!! if express server is running, but it's not servig pages - try to unblock PORT //!!!!!!!!!!!!!!!! let wss = undefined; let startWebSocketServer = false; //startWebSocketServer = false;//KONSBERG if(startWebSocketServer) { var WebSocketServer = require('ws').Server; wss = new WebSocketServer({ port: 9090 }); } const express = require("express"); const bodyParser = require('body-parser'); const app = express(); // create express app //const SerialPort = require('serialport'); const { exec } = require('child_process'); const { crc8, crc16, crc32 } = require('easy-crc'); const http = require('http'); const status = require('http-status'); const username = "admin"; const password = "admin"; const decodeValue = require('./decodeValue.js'); const { openPort, runSyncExec, writeData } = require('./serialport_helper.js'); //const hostname = "10.0.0.5"; const hostname = "localhost"; process.on('uncaughtException', function(error) { // do something clever here //TODO send message to services!!! console.log("errors", error); // do NOT do this for real! }); function httpRequest(params, postData) { return new Promise(function(resolve, reject) { console.log(params); var req = http.request(params, function(res) { // reject on bad status if (res.statusCode < 200 || res.statusCode >= 300) { return reject(new Error(res.statusCode + " " + status[res.statusCode])); } // cumulate data var body = []; res.on('data', function(chunk) { body.push(chunk); }); // resolve on end res.on('end', function() { try { console.log("body", body); body = JSON.parse(Buffer.concat(body).toString()); } catch(e) { reject(e); } resolve(body); }); }); // reject on request error req.on('error', function(err) { // This is not a "Second reject", just a different sort of failure reject(err); }); if (postData) { req.write(postData); } // IMPORTANT req.end(); }); } //terminal---------------------------------- function detectIfResponseIsValid(bytes) { let type = "RESPONSE"; if(bytes[4] == 0) type = "RESPONSE"; else if(bytes[4] == 1) type = "ERROR"; else if(bytes[4] == 2) type = "EVENT"; else type = "UNKNOWN"; let crc = crc16('ARC', bytes.slice(0, 9)); let c1 = (crc >> 8) & 0xFF; let c2 = crc & 0xFF; let message = "OK"; let error = ""; if(c1 != bytes[9]) { //CRC_ERROR message = "NOK"; error = "CRC_ERROR c1"; } if(c2 != bytes[10]) { //CRC_ERROR message = "NOK"; error = "CRC_ERROR c2"; } //crc error if(type != "RESPONSE") { message = "NOK"; } return {message: message, type: type, error: error}; } handleResponse = (bytes, cmd) => { console.log("handleResponse"); let result = detectIfResponseIsValid(bytes); let message = result.message; let type = result.type; let error = result.error; if(message != "OK") { return {type: type, message: message + " " + error + " " + bytes.join(", "), 'date': (new Date()).getTime()}; } let add = (bytes[0] >> 24) | (bytes[1] >> 16) | (bytes[2] >> 8) | bytes[3]; let decodedValue = "cmd: " + cmd; if(cmd >= 0x8000) { return decodeValue(add, cmd, bytes[5],bytes[6],bytes[7],bytes[8]); } return {type: type, message: message + " " + bytes.join(", "), 'date': (new Date()).getTime()}; } com_generic = (adresa, rec, rw, register, name, byte1, byte2, byte3, byte4) =>{ let resp = []; let cmd = register; if (rw === 0) { cmd = cmd + 0x8000; } if (rec === 3) { resp.push(0xFF); resp.push(0xFF); resp.push(0xFF); resp.push(0xFF); resp.push( adresa & 0xFF );//band } else { resp.push( (adresa >> 24) & 0xFF);//rshift resp.push( (adresa >> 16) & 0xFF); resp.push( (adresa >> 8) & 0xFF); resp.push( adresa & 0xFF ); if (rec === 2) { resp.push(0xFF); } else resp.push(0); } resp.push( (cmd >> 8) & 0xFF);//rshift resp.push( cmd & 0xFF );//band resp.push( byte1 & 0xFF );//band resp.push( byte2 & 0xFF );//band resp.push( byte3 & 0xFF );//band resp.push( byte4 & 0xFF );//band //let data = '12345'; let crc = crc16('ARC', resp); let c1 = (crc >> 8) & 0xFF; let c2 = crc & 0xFF; resp.push(c1); resp.push(c2); console.log("checksum", crc); console.log("resp", resp); return resp; } //------------- //https://expressjs.com/en/resources/middleware/cors.html var cors = require('cors'); const { report } = require("process"); app.use(cors()); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); // add middleware //app.use(express.static("public")); app.use(express.static(__dirname + "/public")); app.get('/restart', function (req, res) { console.log('restart'); exec(`service nodejs restart`, (err, stdout, stderr) => { if (err || stderr) { console.log("failed to restart nodejs"); console.error(err); console.log(stderr); let response = {"message": "failed to restart nodejs " + err}; res.json(response); } else { console.log(stdout); console.log(`Successfully restarted service nodejs ${stdout}`); let response = {"message": "restarted"}; res.json(response); } }); //res.sendStatus(200); }); //KONBERG // Broadcast updates to all WebSocketServer clients //app.post('/notify', function (req, res) { app.get('/notify', function (req, res) { if(wss == undefined) { res.sendStatus(200); return; } console.log('Event: notify'); wss.clients.forEach(function each(client) { client.send("broadcast: updated"); //console.log('broadcast', client); }); res.sendStatus(200); }); //---general app.get('/db', function(req, res) { //res.sendStatus(404); let params = {table: "settings", action: "read"}; const data = JSON.stringify(params); let h = hostname; const httpRequestParams = { hostname: h, port: 12345, path: '/db_connector', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': data.length } } httpRequest(httpRequestParams, data).then(function(body) { console.log("response", body); let response = {"data": body.data}; res.json(response); }).catch(function (e) { //console.log(e); //messages.push({type: "ERROR", message: e.message}); let response = {"message": e.message, "type": "ERROR"}; res.json(response); // and so on }); }); app.post('/db', function(req, res) { //res.sendStatus(404); console.log("request", req.body); //let params = {table: req.body.table, action: req.body.action}; let params = req.body; const data = JSON.stringify(params); let h = hostname; if(req.body.hostname !== undefined) h = req.body.hostname; const httpRequestParams = { hostname: h, port: 12345, path: '/db_connector', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': data.length } } httpRequest(httpRequestParams, data).then(function(body) { console.log("response", body.data); //let response = {"data": body.data}; let response = body.data; //res.sendStatus(200); res.json(response); return; }).catch(function (e) { //console.log(e); let response = {"message": e.message, "type": "ERROR"}; res.json(response); // and so on }); }); app.post('/validate', function(req, res) { let response = {"valid": false}; if(username === req.body.username && password === req.body.password) { response.valid = true; } res.json(response); }); //--terminal app.get('/cmd', function(req, res) { //console.log('GET: Got body:', req.body); //res.send("error: use POST request instead"); res.sendStatus(501); }); //https://zellwk.com/blog/async-await-express/ app.post('/cmd', async(req, res, next) => { console.log('POST: Got body:', req.body); if(username != req.body.username && password != req.body.password) { res.sendStatus(501); return; } let message = "";//TODO remove let messages = []; let makeHttpRequest = true; //make http request let params = req.body.command; let cmd = params.register; //hostname: req.body.hostname, let h = hostname; if(req.body.hostname !== undefined) h = req.body.hostname; if(makeHttpRequest) { const data = JSON.stringify(params); const httpRequestParams = { hostname: h, port: 12345, path: '/terminal', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': data.length } } await httpRequest(httpRequestParams, data).then(function(body) { if (params.rw === 0) { cmd = cmd + 0x8000; } let bytes = body.bytes; console.log("body", body, bytes, typeof body); let type = "RESPONSE"; if(bytes === undefined) { if(typeof body === 'object') { type = body.type; messages.push({type: "ERROR", message: body.message}); } } else { if(bytes[4] == 0) type = "RESPONSE"; else if(bytes[4] == 1) type = "ERROR"; else if(bytes[4] == 2) type = "EVENT"; else type = "UNKNOWN"; //ake data sme zapisali? message = bytes.join(", "); messages.push({type: type, message: "RESP: " + message}); let result = handleResponse(bytes, cmd); if(result == undefined) messages.push({type: "ERROR", message: "ERROR: handleResponse undefined", 'date': (new Date()).getTime()}); if(Array.isArray(result)) { messages = messages.concat(result); } else { messages.push({type: "RESPONSE", message: result}); //messages.push(result); } } if(cmd >= 0x8000) { console.log("params.register", params.register); } let response = {"message": message, messages: messages, hostname: h, "type": "SUCESS"}; res.json(response); }).catch(function (e) { console.log(e, new Date()); messages.push({type: "ERROR", message: "express exception: " + e.message}); let response = {"message": message, messages: messages, hostname: h, "type": "ERROR"}; res.json(response); // and so on }); return; } //if we want to use serial port directly let portOpened = false; let error = false; let port = "/dev/ttymxc4"; try { const rsPort = new SerialPort(port, { autoOpen: false }); /* await runSyncExec("ping localhost").then(function (status) { console.log("Promise Resolved:", status); message = status; }).catch(function (reason) { console.log("Promise Rejected:", reason); error = true; message = reason; }); */ messages.push({type: "INFO", message: "trying to open port directly (express.js): " + port, 'date': (new Date()).getTime()}); await openPort(rsPort).then(function (status) { console.log("Promise Resolved:", status, new Date()); portOpened = true; message = status; //messages.push(message); }).catch(function (reason) { console.log("Promise Rejected:", reason); error = true; message = reason; messages.push({type: "ERROR", message: message, 'date': (new Date()).getTime()}); }); if(!error) { await runSyncExec("stty -F /dev/ttymxc4 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke").then(function (status) { console.log("Promise Resolved:", status, new Date()); //message = status; }).catch(function (reason) { console.log("Promise Rejected:", reason); error = true; //message = escapeSpecialChars(reason); if(typeof reason == "object") { message = JSON.stringify(reason); messages.push({type: "ERROR", message: message, 'date': (new Date()).getTime()}); } }); } //WRITE DATA & READ RESPONSE /* if(error) { //print(P.decodeValue(add, L.last_cmd, bytes[6],bytes[7],bytes[8],bytes[9]).."
") let decodedValue = decodeValue(1, 5,0, 0, 0, 0 ); console.log(decodedValue); let params = req.body.command; let resp = com_generic(params.address, params.recipient, params.rw, params.register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); //messages.push("WRITE: " + resp.join(", ")); messages.push({type: "INFO", message: "TEST WRITE " + resp.join(", "), 'date': (new Date()).getTime()}); } */ if(!error) { let params = req.body.command; let cmd = params.register; if (params.rw === 0) { //cmd = cmd + 0x8000; } let resp = com_generic(params.address, params.recipient, params.rw, cmd, params.name, params.byte1, params.byte2, params.byte3, params.byte4); //messages.push({type: "WRITE", message: "WRITE " + resp.join(", "), 'date': (new Date()).getTime()}); await writeData(rsPort, resp, 11).then(function (data) { console.log("Promise Resolved:", data, new Date()); //process data /* RESPONSE = 0, ERROR = 1, EVENT = 2, TIMEOUT = 3, CRC_ERROR = 4 */ let bytes = data.slice(0); let type = "RESPONSE"; if(bytes[4] == 0) type = "RESPONSE"; else if(bytes[4] == 1) type = "ERROR"; else if(bytes[4] == 2) type = "EVENT"; else type = "UNKNOWN"; //ake data sme zapisali? message = data.join(", "); messages.push({type: type, message: "RESP: " + message}); if(cmd >= 0x8000) { console.log("params.register", params.register); } let result = handleResponse(bytes, cmd); if(result == undefined) messages.push({type: "ERROR", message: "ERROR: handleResponse undefined", 'date': (new Date()).getTime()}); console.log("handleResponse: ", result); if(Array.isArray(result)) { messages = messages.concat(result); } else { messages.push({type: "RESPONSE", message: result}); //messages.push(result); } }).catch(function (reason) { console.log("Promise Rejected:", reason, new Date()); error = true; message = reason; messages.push({type: "ERROR", message: message, 'date': (new Date()).getTime()}); }); } if(portOpened) rsPort.close(); } catch(err) { console.log("Exception", err.message); error = true; message = err.message; messages.push({type: "ERROR", message: message, 'date': (new Date()).getTime()}); } console.log("END", new Date()); if(!error) { //let response = {"message": "OK" + JSON.stringify(req.body)}; let response = {"message": message, messages: messages, "type": "SUCESS"}; res.json(response); return; } else { let response = {"message": message, messages: messages, "type": "ERROR"}; res.json(response); } }); // start express server on port 5000 app.listen(5000, () => { console.log("server started on port 5000"); });