commit c4065c3f9c3fc1634b5c7df9ad591cba93c4eb9c Author: rasta5man Date: Mon Apr 15 19:46:51 2024 +0200 Initial commit - express server, where citysys-terminal app is uploaded 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