From c4065c3f9c3fc1634b5c7df9ad591cba93c4eb9c Mon Sep 17 00:00:00 2001 From: rasta5man Date: Mon, 15 Apr 2024 19:46:51 +0200 Subject: [PATCH] Initial commit - express server, where citysys-terminal app is uploaded --- README-HOW-TO-DEPLOY.txt | 54 +++ bit.js | 43 +++ decodeValue.js | 746 +++++++++++++++++++++++++++++++++++++++ express.service | 13 + index.js | 647 +++++++++++++++++++++++++++++++++ package.json | 26 ++ pyunzip.py | 6 + readme.txt | 2 + serialport_helper.js | 86 +++++ 9 files changed, 1623 insertions(+) create mode 100644 README-HOW-TO-DEPLOY.txt create mode 100644 bit.js create mode 100644 decodeValue.js create mode 100644 express.service create mode 100644 index.js create mode 100644 package.json create mode 100644 pyunzip.py create mode 100644 readme.txt create mode 100644 serialport_helper.js diff --git a/README-HOW-TO-DEPLOY.txt b/README-HOW-TO-DEPLOY.txt new file mode 100644 index 0000000..7dcc23f --- /dev/null +++ b/README-HOW-TO-DEPLOY.txt @@ -0,0 +1,54 @@ +cd terminal + +if node js is running - kill process +ss -lntup +kill pid +kill -9 pid // force kill + +unzip terminal.zip -d destination_folder +alebo +python pyunzip.py terminal.zip +alebo python pyunzip.py node_modules.zip + + +---- +create service + +expres.service + +---------------- + +[Unit] +Description=ExpressJS Server Launcher +After=network.target + +[Service] +Type=simple +Restart=always +RestartSec=1 +ExecStart=/root/.nvm/versions/node/v12.18.2/bin/node /root/terminal/index.js +WorkingDirectory = /root/terminal + +[Install] +WantedBy=multi-user.target + + +--------------------- + +copy here: /etc/systemd/system/ + +--------------------- + + + + +autostart express– location je //etc/systemd/system +vytvorim novy subor “sudo nano expres.service” +whereis node – zistim cestu k node +do ExecStart napisem cestu – napr: “node homeuser/flowserver/index.js” mozno treba aj sudo +spravime ho spustitelnym s “sudo chmod +x expres.service” +aby sa sam spustal dam “sudo systemctl enable expres” +ked uz je nahodou enablenuty treba ho reloadnut s “sudo systemctl daemon-reload” +ked nejde, treba dat pod ExecStart “WorkingDirectory = cesta/na/flowserver” + +“sudo reboot” alebo “sudo systemctl reboot” \ No newline at end of file diff --git a/bit.js b/bit.js new file mode 100644 index 0000000..902d77d --- /dev/null +++ b/bit.js @@ -0,0 +1,43 @@ +//http://lua-users.org/wiki/BitwiseOperators +//https://basicer.com/lua2js/ + +class bit { + static lshift(x, n) + { + return x << n; + } + + static rshift(x, n) + { + return x >> n; + } + + //bit.bor(x1[,x2...]) -- bitwise or of x1, x2, ... + static bor(...args) + { + let v = args[0]; + if(args.length === 1) return v; + + for (var i = 1; i < args.length; i++) { + v = v | args[i]; + } + + return v; + } + + //bit.band(x1[,x2...]) -- bitwise and of x1, x2, ... + static band(...args) + { + + let v = args[0]; + if(args.length === 1) return v; + + for (var i = 1; i < args.length; i++) { + v = v & args[i]; + } + + return v; + } + } + + module.exports = bit diff --git a/decodeValue.js b/decodeValue.js new file mode 100644 index 0000000..9732765 --- /dev/null +++ b/decodeValue.js @@ -0,0 +1,746 @@ +const bit = require('./bit.js'); + +function numberToMonth(num) +{ + let month = "january"; + if (num == 2) + month = "february"; + else if (num == 3) + month = "march"; + else if (num == 4) + month = "april"; + else if (num == 5) + month = "may"; + else if (num == 6) + month = "june"; + else if (num == 7) + month = "july"; + else if (num == 8) + month = "august"; + else if (num == 9) + month = "september"; + else if (num == 10) + month = "october"; + else if (num == 11) + month = "november"; + else + month = "december"; +} + +function numberToDay(num) +{ + let day = "monday"; + if (num == 2) + day = "tuesday"; + else if (num == 3) + day = "wednessday"; + else if (num == 4) + day = "thursday"; + else if (num == 5) + day = "friday"; + else if (num == 6) + day = "saturday"; + else + day = "sunday"; + + return day +} + +function decodeValue(add, cmd, a, b, c, d){ + + var cmd_pure = bit.band(cmd, 0x7FFF) + var response = []; + + console.log("inside decodeValue", add, cmd, cmd_pure, a, b, c, d); + + if (cmd_pure == 0) { // Status + if (add == 0) { // Master + if (bit.band(d,1)>0) { + response.push( {type: "ERROR", message: "Comunication error"}); + } if (bit.band(d,2)>0) { + response.push( {type: "ERROR", message: "Init mode active"}); + } if (bit.band(d,4)>0) { + response.push( {type: "ERROR", message: "Hit detected by accelerometer"}); + } + }else{ // Slave + if (bit.band(a,1)>0) { + response.push( {type: "ERROR", message: "Unread critical event"}); + } if (bit.band(a,2)>0) { + response.push( {type: "ERROR", message: "Unread non-critical event"}); + } if (bit.band(a,4)>0) { + response.push( {type: "ERROR", message: "Event memory full"}); + } + if (bit.band(b,1)>0) { + response.push( {type: "ERROR", message: "Power meter error"}); + } if (bit.band(b,2)>0) { + response.push( {type: "ERROR", message: "Load status error"}); + } if (bit.band(b,4)>0) { + response.push( {type: "ERROR", message: "Inclination error"}); + } if (bit.band(b,8)>0) { + response.push( {type: "ERROR", message: "Time error"}); + } if (bit.band(b,16)>0) { + response.push( {type: "ERROR", message: "Hit detected"}); + } if (bit.band(b,32)>0) { + response.push( {type: "ERROR", message: "Max power cycle exceeded (input)"}); + } if (bit.band(b,64)>0) { + response.push( {type: "ERROR", message: "Max power cycle exceeded (relay)"}); + } if (bit.band(b,128)>0) { + response.push( {type: "ERROR", message: "Temperature error"}); + } + + if (bit.band(c,1)>0) { + response.push( {type: "ERROR", message: "No driver connection"}); + } if (bit.band(c,2)>0) { + response.push( {type: "ERROR", message: "Driver error"}); + } if (bit.band(c,4)>0) { + response.push( {type: "ERROR", message: "No external device connected"}); + } if (bit.band(c,8)>0) { + response.push( {type: "ERROR", message: "External device error"}); + } if (bit.band(c,16)>0) { + response.push( {type: "ERROR", message: "No external sensor connected"}); + } if (bit.band(c,32)>0) { + response.push( {type: "ERROR", message: "External sensor error"}); + } if (bit.band(c,64)>0) { + response.push( {type: "ERROR", message: "Dev. count exceeded"}); + } if (bit.band(c,128)>0) { + response.push( {type: "ERROR", message: "DALI short circuit"}); + } + + if (bit.band(d,1)>0) { + response.push( {type: "ERROR", message: "Node error"}); + } if (bit.band(d,2)>0) { + response.push( {type: "ERROR", message: "Node not init."}); + } if (bit.band(d,4)>0) { + response.push( {type: "ERROR", message: "Bootloader active"}); + } if (bit.band(d,8)>0) { + response.push( {type: "ERROR", message: "Lifetime exceeded"}); + } if (bit.band(d,16)>0) { + response.push( {type: "ERROR", message: "Hold reinit active"}); + } if (bit.band(d,32)>0) { + response.push( {type: "ERROR", message: "Dimming changed"}); + } if (bit.band(d,128)>0) { + response.push( {type: "ERROR", message: "LM marks node as innactive"}); + } + + if (response.length == 0) { + response.push( "No errors recognized"); + }else{ + // + //response.push( "" + response + ""); + //response.push({type: "ERROR", message: }); + } + } + }else if (cmd_pure == 1) { + if (add == 0) { // Master + if (bit.band(d,1)>0) { + response.push( "Init mode enabled"); + }else{ + response.push( "Init mode disabled"); + } + }else{ // Slave + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + } + }else if (cmd_pure == 2) { + if (add == 0) { // Master + if (d == 0) { + response.push( "PLC Master node"); + }else if (d == 1) { + response.push( "RF Master node"); + }else if (d == 2) { + response.push( "Mixed Master node"); + }else{ + response.push( "Unknown Master node (" + String(d) + ")"); + } + }else{ // Slave + var nodetype = "Luminaire 1 channel"; + if (d == 1) { + nodetype = "Luminaire 2 channels"; + }else if (d==2) { + nodetype = "Luminaire 3 channels"; + }else if (d==3) { + nodetype = "Luminaire 4 channels"; + }else if (d==4) { + nodetype = "Sensor node"; + }else{ + nodetype = "Unknown type"; + } + response.push( "External sensor DT : "); + response.push( "External device DT : " + String(b) ); + response.push( "Main driver DT : " + String(c) ); + response.push( "Node : " + nodetype ); + } + }else if (cmd_pure == 3) { + if (add == 0) { // Master + response.push( String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) ); + }else{ // Slave + response.push( "Group addresses : {" + String(a) + ", " + String(b) + ", " + String(c) + ", " + String(d) + "}"); + } + }else if (cmd_pure == 4) { + if (add == 0) { // Master + if (d < 255) { + var yearcount = Math.floor(d / 12); + var monthcount = (d - yearcount) + 1; + var month = numberToMonth(monthcount); + response.push( "HW Version : " + String(a) ); + response.push( "FW Version : " + String(b) + "." + String(c) ); + response.push( "Last update : " + month + " " + String(2018+yearcount) ); + }else{ + response.push( "HW Version : " + String(a) ); + response.push( "FW Version : " + String(b) + "." + String(c)); + response.push( "Last update : NEVER" ); + } + }else{ // Slave + response.push( "Group addresses : {" + String(a) + ", " + String(b) + ", " + String(c) + ", " + String(d) + "}"); + } + }else if (cmd_pure == 5) { + if (add == 0) { // Master + response.push( "Batch no. : " + String(bit.bor(bit.lshift(a,8), b)) ); + response.push( "Production date : " + numberToMonth(c) + " " + String(2000+d)); + }else{ // Slave + response.push( String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) ); + } + }else if (cmd_pure == 6) { + if (add == 0) { // Master + response.push( String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) ); + }else{ // Slave + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + } + }else if (cmd_pure == 7) { + if (add == 0) { // Master + response.push( "RS232 param : " + String(a) + ", " + String(b) ); + response.push( "Baudrate : " + String(bit.bor(bit.lshift(c,8), d)*100)); + }else{ // Slave + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + } + }else if (cmd_pure == 8) { + if (add == 0) { // Master + var x = bit.band(b,0x7F) + var y = bit.band(c,0x7F) + var z = bit.band(d,0x7F) + + if (bit.band(b,0x80) > 0) { + x = x * -1; + } + if (bit.band(c,0x80) > 0) { + y = y * -1; + } + if (bit.band(d,0x80) > 0) { + z = z * -1; + } + + response.push( "Temperature : " + String(a) ); + response.push( "X tilt : " + String(x) ); + response.push( "Y tilt : " + String(y) ); + response.push( "Z tilt : " + String(z) ); + + }else{ // Slave + if (bit.band(a,1)>0) { + response.push( "Standard register behaviour"); + } if (bit.band(a,2)>0) { + response.push( "TS activated without changing other settings"); + } if (bit.band(a,4)>0) { + response.push( "TS deactivated without changing other settings "); + } + + if (bit.band(b,1)>0) { + response.push( "DUSK control active"); + } if (bit.band(b,2)>0) { + response.push( "DAWN control active"); + } if (bit.band(b,4)>0) { + response.push( "Lux level source: in lamp"); + }else{ + response.push( "Lux level source: cabinet"); + } + + if (bit.band(c,1)>0) { + response.push( "movement control active"); + } + + if (bit.band(d,2)>0) { + response.push( "Default table: TS2"); + }else{ + response.push( "Default table: TS1"); + } if (bit.band(d,4)>0) { + response.push( "Active table: TS2"); + }else{ + response.push( "Active table: TS1"); + } + + if (bit.band(d,16)>0) { + response.push( "Twilight mode active"); + }else{ + response.push( "Twilight mode inactive"); + } if (bit.band(d,32)>0) { + response.push( "TS1 was resseted"); + } if (bit.band(d,64)>0) { + response.push( "TS2 was resseted"); + } + + if (bit.band(d,1)>0) { + response.push( "Timer ACTIVE"); + }else{ + response.push( "Timer INACTIVE"); + } + } + }else if (cmd_pure == 9) { + if (add == 0) { // Master + response.push( "Version : " + String(d) + "." + String(c) + "." + String(b) + "." + String(a) ); + }else{ // Slave + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + } + + }else if (cmd_pure == 10) { + if (add == 0) { // Master + response.push( "MAC_0: " + String(c) ); + response.push( "MAC_1: " + String(d) ); + }else{ // Slave + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + } + + }else if (cmd_pure == 11) { + if (add == 0) { // Master + response.push( "MAC_2: " + String(a) ); + response.push( "MAC_3: " + String(b) ); + response.push( "MAC_4: " + String(c) ); + response.push( "MAC_5: " + String(d) ); + + }else{ // Slave + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + } + }else if (cmd_pure == 12) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 13) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 14) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 15) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 16) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 17) { + }else if (cmd_pure == 18) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 19) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 20) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 21) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 22) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 23) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 24) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 25) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 26) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 27) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 28) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 29) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 30) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 31) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 32) { + if (add == 0) { // Master + response.push( ""); + }else{ // Slave + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + } + }else if (cmd_pure == 33) { + if (addd == 0) { // Master + response.push( ""); + }else{ // Slave + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + } + }else if (cmd_pure == 34) { + if (add == 0) { // Master + response.push( ""); + }else{ // Slave + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + } + }else if (cmd_pure == 35) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 36) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 37) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 38) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 39) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 40) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 41) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 42) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 43) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 44) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 45) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 46) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 47) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 48) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 49) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 50) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 51) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 52) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 53) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 54) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 55) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 56) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 57) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 58) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 59) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 60) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 61) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 62) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 63) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 64) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 65) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 66) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 67) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 68) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 69) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 70) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 71) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 72) { + if (bit.band(d,0x80) > 0) { + response.push( "Relay : ON"); + }else{ + response.push( "Relay : OFF"); + } + response.push( "Dimming : " + String(bit.band(d,0x7F)) + " %"); + }else if (cmd_pure == 73) { + response.push( ""); + }else if (cmd_pure == 74) { + response.push( (String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) / 10) + " V"); + }else if (cmd_pure == 75) { + response.push( String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) + " mA"); + }else if (cmd_pure == 76) { + response.push( (String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) / 10) + " W"); + }else if (cmd_pure == 77) { + var v = bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)/10 + response.push( String(Math.cos(math.rad(v))) ); + }else if (cmd_pure == 78) { + response.push( (String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) / 10) + " Hz"); + }else if (cmd_pure == 79) { + response.push( String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) + " Wh"); + }else if (cmd_pure == 80) { + var mins = bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d) + var hours = Math.floor(mins/60) + var rest_min = mins - (hours*60) + response.push( String(hours) + ":" + String(rest_min) ); + }else if (cmd_pure == 81) { + response.push( String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) ); + }else if (cmd_pure == 82) { + response.push( String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) ); + }else if (cmd_pure == 83) { + var mins = bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d) + var hours = Math.floor(mins/60); + var rest_min = mins - (hours*60); + response.push( String(hours) + ":" + String(rest_min) ); + }else if (cmd_pure == 84) { + var x = bit.band(b,0x7F); + var y = bit.band(c,0x7F); + var z = bit.band(d,0x7F); + + if (bit.band(b,0x80) > 0) { + x = x * -1; + } + if (bit.band(c,0x80) > 0) { + y = y * -1; + } + if (bit.band(d,0x80) > 0) { + z = z * -1; + } + + response.push( "Temperature : " + String(a) ); + response.push( "X tilt : " + String(x) ); + response.push( "Y tilt : " + String(y) ); + response.push( "Z tilt : " + String(z) ); + }else if (cmd_pure == 85) { + if (a > 0) { + response.push( "-"); + } + response.push( response + String(b) + "° " + String(c) + "’ " + String(d) + "’’"); + }else if (cmd_pure == 86) { + if (a > 0) { + response.push( "-"); + } + response.push( response + String(b) + "° " + String(c) + "’ " + String(d) + "’’"); + }else if (cmd_pure == 87) { + response.push( String(a) + ":" + String(b) + ":" + String(c) ); + }else if (cmd_pure == 88) { + response.push( numberToDay(a) + " " + String(b) + "." + String(c) + ". " + String(2000+d) ); + }else if (cmd_pure == 89) { + if (d < 255) { + var yearcount = Math.floor(d / 12); + var monthcount = (d - yearcount) + 1; + var month = numberToMonth(monthcount); + response.push( "HW Version : " + String(a) ); + response.push( "FW Version : " + String(b) + "." + String(c) ); + response.push( "Last update : " + month + " " + String(2018+yearcount) ); + }else{ + response.push( "HW Version : " + String(a) ); + response.push( "FW Version : " + String(b) + "." + String(c) ); + response.push( "Last update : NEVER" ); + } + }else if (cmd_pure == 90) { + response.push( "Batch no. : " + String(bit.bor(bit.lshift(a,8), b)) ); + response.push( "Production date : " + numberToMonth(c) + " " + String(2000+d) ); + }else if (cmd_pure == 91) { + response.push( String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) ); + }else if (cmd_pure == 92) { + response.push( ""); + }else if (cmd_pure == 93) { + response.push( ""); + }else if (cmd_pure == 94) { + response.push( ""); + }else if (cmd_pure == 95) { + response.push( String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) ); + }else if (cmd_pure == 96) { + response.push( "Dusk : " + String(bit.bor(bit.lshift(a,8),b)) ); + response.push( "Dawn : " + String(bit.bor(bit.lshift(c,8),d)) ); + }else if (cmd_pure == 97) { + response.push( "Dusk : " + String(bit.bor(bit.lshift(a,8),b)) ); + response.push( "Dawn : " + String(bit.bor(bit.lshift(c,8),d)) ); + }else if (cmd_pure == 98) { + response.push( "Dusk : " + String(c) ); + response.push( "Dawn : " + String(d) ); + }else if (cmd_pure == 99) { + response.push( "CCT max: " + String(bit.bor(bit.lshift(a,8), b)) ); + response.push( "CCT min: " + String(bit.bor(bit.lshift(c,8), d)) ); + }else if (cmd_pure == 100) { + var resid = "unknown (" + String(a) + ")"; + if (a == 0x80) { + resid = "OK"; + }else if (a == 0x81) { + resid = "timeout"; + }else if (a == 0x83) { + resid = "error"; + } + response.push( "Resp ID: " + resid ); + response.push( "Add: " + String(b) ); + response.push( "CMD: " + String(c) ); + response.push( "Resp: " + String(d) ); + }else if (cmd_pure == 101) { + response.push( "Version : " + String(d) + "." + String(c) + "." + String(b) + "." + String(a) ); + }else if (cmd_pure == 102) { + response.push( "MAC_0: " + String(c) ); + response.push( "MAC_1: " + String(d) ); + }else if (cmd_pure == 103) { + response.push( "MAC_2: " + String(a) ); + response.push( "MAC_3: " + String(b) ); + response.push( "MAC_4: " + String(c) ); + response.push( "MAC_5: " + String(d) ); + }else if (cmd_pure == 122) { + response.push( ""); + }else if (cmd_pure == 123) { + response.push( ""); + }else if (cmd_pure == 124) { + response.push( ""); + }else if ((cmd_pure > 127) && (cmd_pure < 0x100)) { + if (add == 0) { + response.push( "Serial nb. : " + String(bit.bor(bit.lshift(a,24),bit.lshift(b,16),bit.lshift(c,8),d)) ); + } + } + + return response; + } + + module.exports = decodeValue diff --git a/express.service b/express.service new file mode 100644 index 0000000..5b9231e --- /dev/null +++ b/express.service @@ -0,0 +1,13 @@ +[Unit] +Description=ExpressJS Server Launcher +After=network.target + +[Service] +Type=simple +Restart=always +RestartSec=1 +ExecStart=/root/.nvm/versions/node/v12.18.2/bin/node /root/terminal/index.js +WorkingDirectory = /root/terminal + +[Install] +WantedBy=multi-user.target diff --git a/index.js b/index.js new file mode 100644 index 0000000..75856bb --- /dev/null +++ b/index.js @@ -0,0 +1,647 @@ +//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"); +}); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..2c74186 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "server", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "nodemon index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "bitwise": "^2.1.0", + "cors": "^2.8.5", + "easy-crc": "0.0.2", + "express": "^4.17.1", + "http-status": "^1.5.0", + "nodemon": "^2.0.3", + "serialport": "^9.0.6", + "sqlite": "^4.0.19", + "sqlite3": "^5.0.2", + "ws": "^7.4.5" + }, + "devDependencies": {} +} diff --git a/pyunzip.py b/pyunzip.py new file mode 100644 index 0000000..800fb38 --- /dev/null +++ b/pyunzip.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 +import sys +from zipfile import PyZipFile +for zip_file in sys.argv[1:]: + pzf = PyZipFile(zip_file) + pzf.extractall() \ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..ab1b5bd --- /dev/null +++ b/readme.txt @@ -0,0 +1,2 @@ +https://levelup.gitconnected.com/how-to-render-react-app-using-express-server-in-node-js-a428ec4dfe2b +https://www.freecodecamp.org/news/how-to-make-create-react-app-work-with-a-node-backend-api-7c5c48acb1b0/ \ No newline at end of file diff --git a/serialport_helper.js b/serialport_helper.js new file mode 100644 index 0000000..7c6958f --- /dev/null +++ b/serialport_helper.js @@ -0,0 +1,86 @@ +const { exec } = require('child_process'); + +function openPort(port){ + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) + } + + function runSyncExec(command){ + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if(error == null) resolve(stdout); + reject(error); + }); + + }) + } + + async function writeData(port, data, readbytes, timeout){ + return new Promise((resolve, reject) => { + + if(readbytes == undefined) readbytes = 0; + if(timeout == undefined) timeout = 10000; + + var callback = function(data) { + rsPortReceivedData.push(...data); + let l = rsPortReceivedData.length; + + if(l >= readbytes) + { + port.removeListener('data', callback); + + clearTimeout(t); + resolve(rsPortReceivedData); + } + }; + + let t = setTimeout(() => { + port.removeListener('data', callback); + reject("TIMEOUT READING"); + }, timeout); + + let rsPortReceivedData = []; + + if(readbytes > 0) port.on('data', callback); + + port.write(Buffer.from(data), function(err) { + if (err) { + port.removeListener('data', callback); + reject(err.message); + } + + if(readbytes == 0) + { + resolve(rsPortReceivedData); + } + + }); + }) +} + +module.exports = { + openPort, + runSyncExec, + writeData +} \ No newline at end of file