diff --git a/databases/notifications.table b/databases/notifications.table index 9dbe047..f7c96cb 100644 --- a/databases/notifications.table +++ b/databases/notifications.table @@ -20,9 +20,12 @@ key:string|weight:string|sk:string|en:string +|power_supply_works_correctly|NOTICE|Napájací zdroj pracuje správne|Power supply works correctly|............... +|battery_level_is_low|ERROR|Batéria má nízku úroveň napätia|Battery level is low|............... +|battery_level_is_ok|NOTICE|Batéria má správnu úroveň napätia|Battery level is OK|............... -+|door_opened|NOTICE|Dvere boli otvorené|Door has been opeed|............... -+|door_closed|NOTICE|Dvere boli zatvorené|Door has been closed|............... -+|door_opened_without_permission|WARNING|Dvere boli otvorené bez povolenia - zapnutá siréna|Door opened without permision - alarm is on|............... ++|door_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... +|state_of_contactor_for_line|INFORMATIONAL|Stav stýkača pre líniu č. ${line} je ${value}|State of contactor for line no. ${line} is ${value}|............... +|local_database_is_corrupted|CRITICAL|||............... +|electrometer_nok|ERROR|Elektromer neodpovedá|Electrometer is not responding|............... @@ -34,5 +37,5 @@ key:string|weight:string|sk:string|en:string +|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... +|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... +|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... -+|flow_restart|NOTICE|Restart flowu|Flow has been restarted|............... -+|nodes_db_changed|NOTICE|Zmena v node databaze|Node db has changed|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/flow/cmd_manager.js b/flow/cmd_manager.js index 8c7543d..18807f9 100644 --- a/flow/cmd_manager.js +++ b/flow/cmd_manager.js @@ -39,7 +39,7 @@ exports.install = function(instance) { var SunCalc = require('./helper/suncalc'); const DataToTbHandler = require('./helper/DataToTbHandler'); - const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); const { sendNotification } = require('./helper/notification_reporter'); const process = require('process'); const { errLogger, logger, monitor } = require('./helper/logger'); @@ -127,8 +127,6 @@ exports.install = function(instance) { //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; - const errorHandler = new ErrorToServiceHandler(); - let rotary_switch_state; let lux_sensor; let state_of_breaker = {};//key is line, value is On/Off @@ -165,8 +163,6 @@ exports.install = function(instance) { tbHandler = new DataToTbHandler(SEND_TO.tb); tbHandler.setSender(exports.title); - errorHandler.setProjectsId(SETTINGS.project_id); - let now = new Date(); console.log("CMD Manager installed", now.toLocaleString("sk-SK")); @@ -186,7 +182,6 @@ exports.install = function(instance) { }, 120000); reportEdgeDateTimeAndNumberOfLuminaires(); - setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour setCorrectPlcTimeOnceADay(); @@ -1155,7 +1150,7 @@ exports.install = function(instance) { params.type = "cmd-master"; params.register = 4; params.address = 0; - params.timestamp = Date.now() + 60000; + params.timestamp = 0; params.addMinutesToTimestamp = 5; params.tbname = SETTINGS.rvoTbName; params.info = "Master node FW verzia"; @@ -1579,6 +1574,7 @@ exports.install = function(instance) { let readBytes = 11; let timeout = 4000; + // await keyword is important, otherwise incorrect data is returned! await writeData(rsPort, resp, readBytes, timeout).then(function(data) { @@ -1592,7 +1588,6 @@ exports.install = function(instance) { //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK let message = result.message; // OK, NOK let message_type = result.type; - let error = result.error; if (params.hasOwnProperty("debug")) { if (params.debug) { @@ -1643,11 +1638,6 @@ exports.install = function(instance) { if (register == 4) values["edge_fw_version"] = SETTINGS.edge_fw_version; } - //odoslanie príkazu z terminálu - dáta - if (type == "cmd-terminal") { - sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "command_was_sent_from_terminal_interface", {}, params, SEND_TO.tb, instance); - } - if (params.debug) { //logger.debug("saveToTb", saveToTb, tbname, values); } @@ -1879,16 +1869,6 @@ exports.install = function(instance) { logger.debug(0, "RPC runSyncExec - Promise Resolved:" + status); - //APP START - let dataToInfoSender = { id: SETTINGS.project_id, name: SETTINGS.rvo_name }; - dataToInfoSender.fw_version = SETTINGS.edge_fw_version; - dataToInfoSender.startdate = new Date().toISOString().slice(0, 19).replace('T', ' '); - dataToInfoSender.__force__ = true; - - instance.send(SEND_TO.infoSender, dataToInfoSender); - - logger.debug(0, "---------------------------->START message send to service", dataToInfoSender); - }).catch(function(reason) { instance.send(SEND_TO.debug, "CMD manager - RPC runSyncExec - promise rejected:" + reason); }); @@ -1986,7 +1966,7 @@ exports.install = function(instance) { //logger.debug(tasks); logger.debug("-->CMD MANAGER - RUN TASKS"); - interval = setInterval(runTasks, LONG_INTERVAL); + interval = setInterval(runTasks, 5000); } else if (cmd == "reload_relays") { loadRelaysData(flowdata.data.line); @@ -2627,7 +2607,7 @@ exports.install = function(instance) { } //Dimming, CCT - if (register == 1) { + else if (register == 1) { let brightness = 0; let dimming = byte0; if (dimming > 128) { @@ -2648,125 +2628,87 @@ exports.install = function(instance) { } // - if (register == 4) { + else if (register == 4) { values["master_node_version"] = bytes[1] + "." + bytes[2]; //logger.debug("FW Version", register, bytes); } //Napätie - if (register == 74) { + else if (register == 74) { let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); values["voltage"] = Number(voltage); } //Prúd - if (register == 75) { + else if (register == 75) { let current = bytesToInt(bytes); values["current"] = current; } //výkon - if (register == 76) { + else if (register == 76) { let power = (bytesToInt(bytes) * 0.1).toFixed(2); values["power"] = Number(power); } //účinník - if (register == 77) { + else if (register == 77) { let power_factor = Math.cos(bytesToInt(bytes) * 0.1).toFixed(2); values["power_factor"] = Number(power_factor); } //frekvencia - if (register == 78) { + else if (register == 78) { let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); values["frequency"] = Number(frequency); } //energia - if (register == 79) { + else if (register == 79) { let energy = bytesToInt(bytes); - - //Energiu treba reportovať v kWh. Teda číslo, ktoré príde treba podeliť 1000. Toto som ti možno zle napísal. - + //Energiu treba reportovať v kWh -> delit 1000 values["energy"] = energy / 1000; } //doba života - if (register == 80) { + else if (register == 80) { let lifetime = (bytesToInt(bytes) / 60).toFixed(2); values["lifetime"] = Number(lifetime); } //nastavenie profilu - if (register == 8) { + else if (register == 8) { let time_schedule_settings = bytesToInt(bytes); values["time_schedule_settings"] = time_schedule_settings; } //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() - if (register == 84) { - const temp = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; - const inclination_x = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; - const inclination_y = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; - const inclination_z = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; - - if (temp === undefined) temp = 999; - if (inclination_x === undefined) inclination_x = 999; - if (inclination_y === undefined) inclination_y = 999; - if (inclination_z === undefined) inclination_z = 999; - - values["temperature"] = temp; - values["inclination_x"] = inclination_x; - values["inclination_y"] = inclination_y; - values["inclination_z"] = inclination_z; - } - - let h = byte3; - let m = byte2; - - let timestamp; - - if (register == 87 || register == 6 || register == 7) { - //if(byte3 < 10) h = "0" + byte3; - //if(byte2 < 10) m = "0" + byte2; - //if(byte1 < 10) s = "0" + byte1; - - var d = new Date(); - d.setHours(h, m, 0, 0); - timestamp = d.getTime(); - } - - //aktuálny čas - if (register == 87) { - //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek. - //values["actual_time"] = h + ":" + m + ":" + s; - - values["actual_time"] = timestamp; - } - - //čas súmraku - if (register == 6) { - //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek. - //values["dusk_time"] = h + ":" + m + ":" + s; - - values["dusk_time"] = timestamp; - } - - //čas úsvitu - if (register == 7) { - //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek. - //values["dawn_time"] = h + ":" + m + ":" + s; - - values["dawn_time"] = timestamp; + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; } //FW verzia nodu - if (register == 89) { + else if (register == 89) { //formát: "Byte3: Byte2.Byte1 (Byte0)" values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; } + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + return values; } @@ -2850,9 +2792,13 @@ exports.install = function(instance) { if (temperatureInSenica === null) return; - for (const key in relaysData) { + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); - const lineData = relaysData[key]; + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; const lineNumber = lineData.line; const contactor = lineData.contactor; @@ -2862,17 +2808,21 @@ exports.install = function(instance) { let date = Date.now(); - Object.keys(nodesData).forEach((node, index) => { + Object.keys(nodesData_clone).forEach((node, index) => { setTimeout(function() { - if (nodesData[node].line === lineNumber) { + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; let x = null; if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; if (x === null) x = 0; - sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData[node].tbname, date); + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); } }, (index + 1) * 500); diff --git a/flow/db_init.js b/flow/db_init.js index 5b3d589..2a5caf9 100644 --- a/flow/db_init.js +++ b/flow/db_init.js @@ -4,8 +4,7 @@ exports.group = 'Worksys'; exports.color = '#888600'; exports.version = '1.0.2'; exports.icon = 'sign-out'; -exports.input = 1; -exports.output = ["blue"]; +exports.output = 2; exports.html = `
@@ -33,6 +32,12 @@ exports.readme = ` const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; exports.install = async function(instance) { @@ -94,15 +99,26 @@ exports.install = async function(instance) { } FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); initNotification(); + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + setTimeout(() => { console.log("DB_INIT - data loaded"); - instance.send(0, "_") + instance.send(SEND_TO.db_init, "_") }, 5000) }; - - - diff --git a/flow/designer.json b/flow/designer.json index b51e1ca..82dfe7f 100644 --- a/flow/designer.json +++ b/flow/designer.json @@ -49,8 +49,8 @@ "component": "wsmqttpublish", "tab": "1612772287426", "name": "WS MQTT publish", - "x": 304.75, - "y": 237, + "x": 281.75, + "y": 174, "connections": { "0": [ { @@ -69,10 +69,6 @@ } ], "2": [ - { - "index": "0", - "id": "1618300863816" - }, { "index": "0", "id": "1634303685503" @@ -107,8 +103,8 @@ "component": "virtualwirein", "tab": "1612772287426", "name": "tb-push", - "x": 86.75, - "y": 375, + "x": 72.75, + "y": 328, "connections": { "0": [ { @@ -144,8 +140,8 @@ "component": "debug", "tab": "1612772287426", "name": "to TB", - "x": 306.75, - "y": 371, + "x": 283.75, + "y": 324, "connections": {}, "disabledio": { "input": [ @@ -170,8 +166,8 @@ "component": "debug", "tab": "1612772287426", "name": "errors from MQTT Broker", - "x": 650, - "y": 76, + "x": 594, + "y": 57, "connections": {}, "disabledio": { "input": [ @@ -270,8 +266,8 @@ "component": "debug", "tab": "1611921777196", "name": "Debug", - "x": 595.8833312988281, - "y": 557.3500061035156, + "x": 596.8833312988281, + "y": 566.3500061035156, "connections": {}, "disabledio": { "input": [], @@ -294,8 +290,8 @@ "component": "debug", "tab": "1611921777196", "name": "tempToTb", - "x": 598.8833312988281, - "y": 654.3500061035156, + "x": 595.8833312988281, + "y": 658.3500061035156, "connections": {}, "disabledio": { "input": [], @@ -318,8 +314,8 @@ "component": "virtualwireout", "tab": "1611921777196", "name": "tb-push", - "x": 594.8833312988281, - "y": 350.25, + "x": 597.8833312988281, + "y": 377.25, "connections": {}, "disabledio": { "input": [], @@ -453,8 +449,8 @@ "color": "gray" }, "options": { - "data": "{line: 3, command: \"turnOff\", force: true}", - "datatype": "object" + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" }, "color": "#F6BB42", "notes": "" @@ -505,8 +501,8 @@ "color": "gray" }, "options": { - "datatype": "string", - "data": "profile_nodes" + "data": "profile_nodes", + "datatype": "string" }, "color": "#F6BB42", "notes": "" @@ -545,8 +541,8 @@ "component": "debug", "tab": "1612772287426", "name": "wsmqtt-exit1", - "x": 650.8833312988281, - "y": 160, + "x": 597.8833312988281, + "y": 149, "connections": {}, "disabledio": { "input": [], @@ -564,32 +560,6 @@ "color": "#967ADC", "notes": "" }, - { - "id": "1618300863816", - "component": "debug", - "tab": "1612772287426", - "name": "wsmqtt-exit2", - "x": 845.8833312988281, - "y": 320, - "connections": {}, - "disabledio": { - "input": [ - 0 - ], - "output": [] - }, - "state": { - "text": "Enabled", - "color": "gray" - }, - "options": { - "type": "data", - "repository": false, - "enabled": true - }, - "color": "#967ADC", - "notes": "" - }, { "id": "1618393583970", "component": "virtualwireout", @@ -701,8 +671,8 @@ "component": "virtualwireout", "tab": "1612772287426", "name": "platform-rpc-call", - "x": 649.8833312988281, - "y": 246, + "x": 597.8833312988281, + "y": 247, "connections": {}, "disabledio": { "input": [], @@ -742,8 +712,8 @@ "color": "gray" }, "options": { - "datatype": "object", - "data": "{line: 1, command: \"turnOn\", force: true}" + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" }, "color": "#F6BB42", "notes": "" @@ -872,8 +842,8 @@ "color": "gray" }, "options": { - "data": "{command: \"turnOnAlarm\"}", - "datatype": "object" + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" }, "color": "#F6BB42", "notes": "" @@ -902,8 +872,8 @@ "color": "gray" }, "options": { - "data": "{command: \"turnOffAlarm\"}", - "datatype": "object" + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" }, "color": "#F6BB42", "notes": "" @@ -913,8 +883,8 @@ "component": "virtualwireout", "tab": "1611921777196", "name": "modbus_to_dido", - "x": 596, - "y": 462, + "x": 599, + "y": 471, "connections": {}, "disabledio": { "input": [], @@ -1039,7 +1009,7 @@ "output": [] }, "state": { - "text": "795.21 MB / 987.80 MB", + "text": "843.78 MB / 985.68 MB", "color": "gray" }, "options": { @@ -1069,7 +1039,7 @@ "output": [] }, "state": { - "text": "5.50 GB / 7.26 GB", + "text": "5.68 GB / 7.26 GB", "color": "gray" }, "options": { @@ -1140,8 +1110,8 @@ "component": "virtualwireout", "tab": "1612772287426", "name": "send-to-services", - "x": 650.8833312988281, - "y": 355.5, + "x": 600.8833312988281, + "y": 341.5, "connections": {}, "disabledio": { "input": [], @@ -1163,8 +1133,8 @@ "tab": "1612772287426", "name": "192.168.252.2:8004/sentmessage", "reference": "", - "x": 480.8833312988281, - "y": 1334.7333374023438, + "x": 506.8833312988281, + "y": 1331.7333374023438, "connections": { "0": [ { @@ -1182,9 +1152,9 @@ "color": "gray" }, "options": { - "stringify": "json", + "url": "http://192.168.252.2:8004/sentmessage", "method": "POST", - "url": "http://192.168.252.2:8004/sentmessage" + "stringify": "json" }, "color": "#5D9CEC", "notes": "" @@ -1194,8 +1164,8 @@ "component": "debug", "tab": "1612772287426", "name": "Debug", - "x": 280.75, - "y": 1446, + "x": 305.75, + "y": 1442, "connections": {}, "disabledio": { "input": [ @@ -1403,7 +1373,7 @@ "component": "debug", "tab": "1612772287426", "name": "Send info", - "x": 480, + "x": 513, "y": 1441, "connections": {}, "disabledio": { @@ -1429,8 +1399,8 @@ "component": "infosender", "tab": "1612772287426", "name": "Info sender", - "x": 285, - "y": 1338, + "x": 301, + "y": 1336, "connections": { "0": [ { @@ -1462,8 +1432,8 @@ "component": "debug", "tab": "1612772287426", "name": "Debug", - "x": 795.8833312988281, - "y": 1329.5, + "x": 837.8833312988281, + "y": 1325.5, "connections": {}, "disabledio": { "input": [ @@ -1525,7 +1495,7 @@ "output": [] }, "state": { - "text": "1.2% / 70.53 MB", + "text": "2% / 86.44 MB", "color": "gray" }, "options": { @@ -1885,8 +1855,8 @@ "component": "debug", "tab": "1611921777196", "name": "MDBToTb", - "x": 759, - "y": 313, + "x": 766, + "y": 324, "connections": {}, "disabledio": { "input": [], @@ -1909,8 +1879,8 @@ "component": "code", "tab": "1611921777196", "name": "device-status", - "x": 755.0833282470703, - "y": 209, + "x": 764.0833282470703, + "y": 222, "connections": { "0": [ { @@ -1932,9 +1902,9 @@ "color": "gray" }, "options": { - "outputs": 1, + "keepmessage": true, "code": "if(value.hasOwnProperty(\"status\"))\n{\n\tif(value.status.includes(\"-em\"))\n\t{\n\t\tsend(0, {\"em_status\": \"NOK\"});\n\t}\n\telse if(value.status.includes(\"twilight\"))\n\t{\n\t\tsend(0, {\"lux_sensor\": \"NOK\"});\n\t}\n\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"NOK\"});\n\t}\n}\n\nif(value.hasOwnProperty(\"values\"))\n{\n\tif(value.values.hasOwnProperty(\"twilight_sensor\"))\n\t{\n\t\tsend(0, {\"lux_sensor\": \"OK\"});\n\t}\n\telse if(value.values.hasOwnProperty(\"Phase_1_power\") ||\n\t\t\tvalue.values.hasOwnProperty(\"Phase_1_voltage\") ||\n\t\t\tvalue.values.hasOwnProperty(\"Total_power\") ||\n\t\t\tvalue.values.hasOwnProperty(\"Phase_1_current\"))\n\t{\n\t\tsend(0, {\"em_status\": \"OK\"});\n\t}\n\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", - "keepmessage": true + "outputs": 1 }, "color": "#656D78", "notes": "" @@ -1945,7 +1915,7 @@ "tab": "1611921777196", "name": "modbus service", "x": 966.0833282470703, - "y": 152, + "y": 165, "connections": {}, "disabledio": { "input": [ @@ -2048,7 +2018,7 @@ "tag_on_include": "[{\"user_id\":\"U072JE5JUQG\", \"includes\":[\"Electrometer\", \"Twilight sensor\"]}]", "message_includes": "[\"is responding again\", \"Flow has been restarted\", \"Node db has changed\"]", "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", - "name": "rvo_senica_20_10.0.0.113" + "name": "" }, "color": "#30E193", "notes": "" @@ -2077,9 +2047,9 @@ "color": "gray" }, "options": { - "stringify": "json", + "url": "http://192.168.252.2:8004/slack", "method": "POST", - "url": "http://192.168.252.2:8004/slack" + "stringify": "json" }, "color": "#5D9CEC", "notes": "" @@ -2134,8 +2104,8 @@ "color": "gray" }, "options": { - "datatype": "object", - "data": "{ \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\": [ { \"ts\": 1716289039281, \"values\": { \"_event\": { \"type\": \"alert\", \"status\": \"new\", \"source\": { \"func\": \"CMD Manager: process cmd\", \"component\": \"1619515097737\", \"component_name\": \"CMD Manager\", \"edge\": \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\" }, \"message\": \"NOW CONNECTED TO SLACK !\", \"message_data\": \"\" } } } ] }" + "data": "{ \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\": [ { \"ts\": 1716289039281, \"values\": { \"_event\": { \"type\": \"alert\", \"status\": \"new\", \"source\": { \"func\": \"CMD Manager: process cmd\", \"component\": \"1619515097737\", \"component_name\": \"CMD Manager\", \"edge\": \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\" }, \"message\": \"NOW CONNECTED TO SLACK !\", \"message_data\": \"\" } } } ] }", + "datatype": "object" }, "color": "#F6BB42", "notes": "" @@ -2145,7 +2115,7 @@ "component": "virtualwireout", "tab": "1612772287426", "name": "platform-rpc-call", - "x": 649.9333343505859, + "x": 599.9333343505859, "y": 541.3500061035156, "connections": {}, "disabledio": { @@ -2167,8 +2137,8 @@ "component": "debug", "tab": "1612772287426", "name": "rpc cloud", - "x": 650.9333343505859, - "y": 451.3500061035156, + "x": 601.9333343505859, + "y": 440.3500061035156, "connections": {}, "disabledio": { "input": [], @@ -2191,8 +2161,8 @@ "component": "virtualwirein", "tab": "1612772287426", "name": "db-init", - "x": 90.75, - "y": 250, + "x": 75.75, + "y": 184, "connections": { "0": [ { @@ -2219,9 +2189,9 @@ "id": "1731068754606", "component": "cloudmqttconnect", "tab": "1612772287426", - "name": "MQTT client - to senica-prod01", - "x": 304.75, - "y": 474, + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, "connections": { "1": [ { @@ -2257,14 +2227,20 @@ "component": "db_init", "tab": "1612772287426", "name": "DB Initialization", - "x": 91.75, - "y": 55.25, + "x": 1003.75, + "y": 240.25, "connections": { "0": [ { "index": "0", "id": "1731069033416" } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } ] }, "disabledio": { @@ -2284,8 +2260,8 @@ "component": "virtualwireout", "tab": "1612772287426", "name": "db-init", - "x": 343.75, - "y": 50.25, + "x": 1244.75, + "y": 233.25, "connections": {}, "disabledio": { "input": [], @@ -2798,7 +2774,7 @@ "tab": "1611921777196", "name": "tempToDido", "x": 594.8833312988281, - "y": 745, + "y": 753, "connections": {}, "disabledio": { "input": [], @@ -2821,8 +2797,8 @@ "component": "virtualwirein", "tab": "1612772287426", "name": "db-init", - "x": 86.75, - "y": 495, + "x": 72.75, + "y": 474, "connections": { "0": [ { @@ -2844,6 +2820,48 @@ }, "color": "#303E4D", "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" } ], "version": 615 diff --git a/flow/dido_controller.js b/flow/dido_controller.js index 2e23549..8d4f47a 100644 --- a/flow/dido_controller.js +++ b/flow/dido_controller.js @@ -58,8 +58,7 @@ const bitwise = require('bitwise'); const DataToTbHandler = require('./helper/DataToTbHandler'); let tbHandler; -const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler'); -const errorHandler = new ErrorToServiceHandler(); +const errorHandler = require('./helper/ErrorToServiceHandler'); let ws = null; let rsPort = null; @@ -741,7 +740,7 @@ exports.install = function(instance) { } - function getPins(controllerType, hasMainSwitch) { + function pinsForRvoStatus(controllerType, hasMainSwitch) { let pins = []; @@ -774,7 +773,7 @@ exports.install = function(instance) { if (status === "OK") { - let pinIndexes = getPins(controller_type, hasMainSwitch); + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); for (const pinIndex of pinIndexes) { if (previousValues[pinIndex] === 0) { @@ -914,21 +913,25 @@ exports.install = function(instance) { else if (type == "door_condition" || type === "state_of_main_switch") { newPinValue === 0 ? value = "open" : value = "closed"; - if (value === "open" && SETTINGS.maintenance_mode) { - sendNotification("switchLogic", rvoTbName, "door_opened", {}, "", SEND_TO.tb, instance, "rvo_door"); + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // zapneme sirenu + // ak sa otvoria dvere len na elektromeri (type === "state_of_main_switch") alarm sa nema spustit. alarm sa spusti len ked sa otvoria hlavne dvere (type === "door_condition") + if (type === "door_condition") turnAlarm("on"); + } } - if (value === "open" && !SETTINGS.maintenance_mode) { - sendNotification("switchLogic", rvoTbName, "door_opened_without_permission", {}, "", SEND_TO.tb, instance, "rvo_door"); - - // zapneme sirenu - // ak sa otvoria dvere len na elektromeri (type === "state_of_main_switch") alarm sa nema spustit. alarm sa spusti len ked sa otvoria hlavne dvere (type === "door_condition") - if (type === "door_condition") turnAlarm("on"); - } if (value === "closed") { if (alarmStatus == "ON") turnAlarm("off"); - sendNotification("switchLogic", rvoTbName, "door_closed", {}, "", SEND_TO.tb, instance, "rvo_door"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); } deviceStatus[type] = value; @@ -1011,34 +1014,6 @@ exports.install = function(instance) { instance.send(SEND_TO.cmd_manager, { sender: "dido_controller", cmd: "reload_relays", line: line, value: value, dataChanged: dataChanged }); reportLineStatus(line); - - //modify table relays - // dbRelays.modify({ contactor: newPinValue }).where("line", line).make(function(builder) { - // builder.callback(function(err, response) { - // if(!err) - // { - // let time = 0; - // if(value) time = 1000 * 10;//10 sekund - - // let dataChanged = false; - // if(relaysData[line].contactor != newPinValue) dataChanged = true; - // relaysData[line].contactor = newPinValue; // 0,1 - - // //ak bola predchadzajuci stav off a novy stav je on, budu sa nastavovat nespracovane node profiles - // //a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor - // setTimeout(function(){ - // instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged}); - // }, time); - - // reportLineStatus(line); - // } - // else - // { - // errLogger.error("modify table relays failed", err); - // } - - // }); - // }); } else if (type === "state_of_breaker") { diff --git a/flow/helper/ErrorToServiceHandler.js b/flow/helper/ErrorToServiceHandler.js index 110ea8b..2b27c32 100644 --- a/flow/helper/ErrorToServiceHandler.js +++ b/flow/helper/ErrorToServiceHandler.js @@ -1,126 +1,91 @@ const { MD5 } = require('./md5.js'); const { networkInterfaces } = require('os'); -class ErrorToServiceHandler -{ - constructor() { +class ErrorToServiceHandler { + constructor() { this.previousValues = {}; - this.projects_id = undefined; + this.project_id = undefined; const nets = networkInterfaces(); - this.ipAddresses = Object.create(null); // Or just '{}', an empty object + this.ipAddresses = {}; for (const name of Object.keys(nets)) { for (const net of nets[name]) { // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses if (net.family === 'IPv4' && !net.internal) { if (!this.ipAddresses[name]) { - this.ipAddresses[name] = []; + this.ipAddresses[name] = []; } this.ipAddresses[name].push(net.address); } } } - - //console.log(this.ipAddresses); - } - setProjectsId(projects_id) - { - this.projects_id = projects_id; + setProjectId(project_id) { + this.project_id = project_id; } - processMessage(message, seconds, message_type) - { - if(message_type == undefined) message_type = "error_message"; - if(Array.isArray(message)) message = message.join(', '); - - let key = MD5(message); - let timestamp = new Date().getTime(); - - //keep in memory - default value is 1h - if (seconds === undefined) seconds = 60*60; - - if(!this.previousValues.hasOwnProperty(key)) - { - this.previousValues[key] = {ts: timestamp, duration: seconds}; - } - - let diff = (timestamp - this.previousValues[key].ts); - if(diff < this.previousValues[key].duration*1000) return false; - - this.previousValues[key].ts = timestamp; - - return true; - } - - sendMessageToService(message, seconds, message_type) - { - - let f = this.processMessage(message, seconds, message_type); - if(!f) return; - - /* - //------------- - if(message_type == undefined) message_type = "error_message"; - if(Array.isArray(message)) message = message.join(', '); + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); let key = MD5(message); - let timestamp = new Date().getTime(); + let ts = Date.now(); - //keep in memory - if (seconds === undefined) seconds = 60*60; + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; - if(!this.previousValues.hasOwnProperty(key)) - { - this.previousValues[key] = {ts: timestamp, duration: seconds}; + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; } - let diff = (timestamp - this.previousValues[key].ts); - if(diff < this.previousValues[key].duration*1000) return; + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; - this.previousValues[key].ts = timestamp; - */ + this.previousValues[key].ts = ts; - //------------------------- + return message; + } - //send to service - - let dataToInfoSender = {id: this.projects_id}; + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; //js_error || error_message - dataToInfoSender[message_type] = message; - dataToInfoSender.ipAddresses = this.ipAddresses; + toService[message_type] = message; - console.log("ErrorToServiceHandler------------------------>send to service", dataToInfoSender); - - //TODO UGLY!!! - // if error occures too early FLOW.GLOBALs.settings.project_id is still undefined - // if(this.projects_id === undefined) this.projects_id = FLOW.GLOBALS.settings.project_id; - if(this.projects_id === undefined) return; - - /* - if(this.projects_id === undefined) - { - console.log("this.projects_id is undefined"); - return; - } - */ + console.log("ErrorToServiceHandler------------------------>send to service", toService); RESTBuilder.make(function(builder) { - builder.method('POST'); - builder.post(dataToInfoSender); - builder.url('http://192.168.252.2:8004/sentmessage'); - - builder.callback(function(err, response, output) { - console.log("process.on error send", err, response, output, dataToInfoSender); - }); + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); }); - } } -module.exports = ErrorToServiceHandler; \ No newline at end of file +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/flow/helper/notification_reporter.js b/flow/helper/notification_reporter.js index 61c0aef..839c12c 100644 --- a/flow/helper/notification_reporter.js +++ b/flow/helper/notification_reporter.js @@ -1,6 +1,9 @@ -//key is device, value = str -let sentValues= {}; +//key is device, value = message {} +let sentValues = {}; let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); let ERRWEIGHT = { EMERGENCY: "emergency", // System unusable @@ -23,82 +26,67 @@ var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); function initNotification() { notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; } + function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { - // return; - let storeToSendValues = true; - if(saveKey == undefined) storeToSendValues = false; + if (saveKey == undefined) storeToSendValues = false; - let lang = FLOW.GLOBALS.settings.language; - if(lang != "en" || lang != "sk") lang = "en"; - - let tpl = key; let weight = ""; + let message = {}; - if(notificationsData[key]) - { - weight = notificationsData[key].weight; - weight = weight.toLowerCase(); + let notification = notificationsData[key]; - tpl = notificationsData[key][lang]; - tpl = template(tpl, params); + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) } - else - { + else { //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); - console.error("sendNotification: Notifications: undefined key", key, func ); + console.error("sendNotification: Notifications: undefined key", key, func); return false; } //detect invalid err weight - if(getKey(ERRWEIGHT, weight) == undefined) - { + if (getKey(ERRWEIGHT, weight) == undefined) { console.error("sendNotification: Notifications: undefined weight", weight, key, func); return false; } - if(sentValues.hasOwnProperty(saveKey)) - { - if(sentValues[saveKey] == tpl) - { + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { return false; } } - if(sentValues[saveKey] == undefined) - { - if(storeToSendValues) - { + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { //do not send - flow is was started - sentValues[saveKey] = tpl; + sentValues[saveKey] = message; return false; } } - if(saveKey == "rvo_door") - { - //console.log("******", saveKey, sentValues[saveKey], tpl); - } - - if(storeToSendValues) sentValues[saveKey] = tpl; - - let str = FLOW.GLOBALS.settings.rvo_name; - if(str != "") str = str + ": "; - str = str + tpl; + if (storeToSendValues) sentValues[saveKey] = message; let content = { "type": weight, "status": "new", "source": { - "func":func, - "component":instance.id, - "component_name":instance.name, - "edge":device + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device }, - "message":str, + "message": message, "message_data": extra }; @@ -107,7 +95,7 @@ function sendNotification(func, device, key, params, extra, tb_output, instance, { "ts": Date.now(), "values": { - "_event":content + "_event": content } } ]; @@ -118,6 +106,7 @@ function sendNotification(func, device, key, params, extra, tb_output, instance, } else { bufferError(msg); }*/ + instance.send(tb_output, msg); // Even if error server is unavailable, send this message to output, for other possible component connections return true; @@ -129,3 +118,4 @@ module.exports = { ERRWEIGHT, initNotification } + diff --git a/flow/helper/serialport_helper.js b/flow/helper/serialport_helper.js index 8efa6af..7f5920d 100644 --- a/flow/helper/serialport_helper.js +++ b/flow/helper/serialport_helper.js @@ -1,6 +1,6 @@ const { exec } = require('child_process'); -function openPort(port){ +function openPort(port) { return new Promise((resolve, reject) => { var callbackError = function(err) { @@ -25,24 +25,24 @@ function openPort(port){ }) } -function runSyncExec(command){ +function runSyncExec(command) { return new Promise((resolve, reject) => { exec(command, (error, stdout, stderr) => { - if(error == null) resolve(stdout); + if (error == null) resolve(stdout); reject(error); }); }) } -async function writeData(port, data, readbytes, timeout){ +async function writeData(port, data, readbytes, timeout) { return new Promise((resolve, reject) => { // If first item in data array is 255, we just write broadcast command to rsPort // We wait 3 seconds and resolve(["broadcast"]) // It is important to resolve with array - if(data[0] == 255) { + if (data[0] == 255) { port.write(Buffer.from(data), function(err) { if (err) { @@ -55,13 +55,12 @@ async function writeData(port, data, readbytes, timeout){ } //cmd-manager mame http route POST / terminal a tomu sa tiez nastavuje timeout!!! - + var callback = function(data) { rsPortReceivedData.push(...data); let l = rsPortReceivedData.length; - if(l >= readbytes) - { + if (l >= readbytes) { port.removeListener('data', callback); clearTimeout(t); diff --git a/flow/infosender.js b/flow/infosender.js index c7afd83..587724f 100644 --- a/flow/infosender.js +++ b/flow/infosender.js @@ -33,69 +33,49 @@ exports.install = function(instance) { let ipAddresses = Object.create(null); // Or just '{}', an empty object for (const name of Object.keys(nets)) { - for (const net of nets[name]) { - // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses - if (net.family === 'IPv4' && !net.internal) { - if (!ipAddresses[name]) { - ipAddresses[name] = []; - } - ipAddresses[name].push(net.address); - } + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); } - } - - function sendValues() - { - if(!configured) return; - - if(Object.keys(allValues).length > 0) - { - if(id) - { - delete allValues.__force__; - let dataToSend = {...allValues}; - dataToSend.id = id; - dataToSend.ipAddresses = ipAddresses; - - instance.send(0, dataToSend); - - allValues = {}; - } - else - { - console.log(exports.title, "unable to send data, no id"); - } - } } - + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + instance.on("close", () => { clearInterval(sendAllValuesInterval); }) instance.on("0", _ => { id = FLOW.GLOBALS.settings.project_id; - configured = true; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); }) instance.on("1", flowdata => { - - allValues = { ...allValues, ...flowdata.data}; + allValues = { ...allValues, ...flowdata.data }; //console.log("DATA RECEIVED", flowdata.data); - - //__force__ - if(flowdata.data.hasOwnProperty("__force__")) - { - if(flowdata.data.__force__) - { - sendValues(); - } - } }) sendAllValuesInterval = setInterval(() => { sendValues(); - }, 60000*3); - + }, 60000 * 3); + } diff --git a/flow/modbus_reader.js b/flow/modbus_reader.js index d383971..65eed75 100644 --- a/flow/modbus_reader.js +++ b/flow/modbus_reader.js @@ -332,8 +332,6 @@ exports.install = function(instance) { noVoltage = FLOW.GLOBALS.settings.no_voltage; mainSocket = new SocketWithClients(); - console.log("novoltage: ", noVoltage, typeof noVoltage); - // this notification is to show, that flow (unipi) has been restarted sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); } diff --git a/flow/slack_filter.js b/flow/slack_filter.js index 753c24a..6b2d2a5 100644 --- a/flow/slack_filter.js +++ b/flow/slack_filter.js @@ -7,7 +7,7 @@ exports.output = 1; exports.author = 'Jakub Klena'; exports.icon = 'plug'; exports.version = '1.0.8'; -exports.options = { 'name':'', 'types': '["emergency", "critical", "error", "alert"]', 'message_includes':'["is responding again"]', 'tag_on_include':'[{"user_id":"U072JE5JUQG", "includes":["Electrometer", "Twilight sensor"]}]', 'slack_channel':'' }; +exports.options = { 'name': '', 'types': '["emergency", "critical", "error", "alert"]', 'message_includes': '["is responding again"]', 'tag_on_include': '[{"user_id":"U072JE5JUQG", "includes":["Electrometer", "Twilight sensor"]}]', 'slack_channel': '' }; exports.html = `
@@ -37,7 +37,7 @@ exports.install = function(instance) { if (!running) return; let value = response.data; if (typeof value !== 'object') return; - + let can = false var k = Object.keys(value); var interested = JSON.parse(instance.options.types); @@ -57,11 +57,11 @@ exports.install = function(instance) { let icon = ':totaljs:'; let type = value[k[0]][0]['values']['_event']['type']; let source = value[k[0]][0]['values']['_event']['source']['func']; - let message = value[k[0]][0]['values']['_event']['message']; + let message = value[k[0]][0]['values']['_event']['message']['en']; let message_data = value[k[0]][0]['values']['_event']['message_data']; let tag = ''; - switch(type){ + switch (type) { case 'debug': icon = ':beetle:'; break; @@ -89,15 +89,15 @@ exports.install = function(instance) { } // Check if this message includes one of the strings we are watching for - for (const msg of msg_incl){ - if (message.includes(msg)){ + for (const msg of msg_incl) { + if (message.includes(msg)) { if (msg == 'is responding again') icon = ':large_green_circle:'; can = true; break; } } // Check if message is one of the types we are watching for - if (interested.includes(type)){ + if (interested.includes(type)) { can = true; } @@ -105,10 +105,10 @@ exports.install = function(instance) { // Check for each person tags based on what the message includes - for (const person of tags){ - for (const msg of person.includes){ - if (message.includes(msg)){ - tag += '<@'+person.user_id+'> '; + for (const person of tags) { + for (const msg of person.includes) { + if (message.includes(msg)) { + tag += '<@' + person.user_id + '> '; break; // Break out from this person checks as they are already tagged now } } @@ -116,46 +116,46 @@ exports.install = function(instance) { // Now that all people are tagged add new line symbol if (tag != '') tag += '\n'; - let send_data = tag+instance.options.name+' '+type.toUpperCase()+'\n*Source*: '+source+'\n*Message*: '+message; + let send_data = tag + instance.options.name + ' ' + type.toUpperCase() + '\n*Source*: ' + source + '\n*Message*: ' + message; if (message_data) { - send_data += '\nData: '+message_data; + send_data += '\nData: ' + message_data; } let ignore_msg = false - if (message.includes('Configuration of dimming profile to node no')){ - for (let i = 0; i < FLOW["savedSlackMessages"].length; i++){ - if (FLOW["savedSlackMessages"][i].message == message){ + if (message.includes('Configuration of dimming profile to node no')) { + for (let i = 0; i < FLOW["savedSlackMessages"].length; i++) { + if (FLOW["savedSlackMessages"][i].message == message) { ignore_msg = true; break; } } - if (!ignore_msg){ - FLOW["savedSlackMessages"].push({message, 'dateandtime': Date.now()}); - if (timer === null){ - timer = setTimeout(checkSavedMessages, 60*60000); + if (!ignore_msg) { + FLOW["savedSlackMessages"].push({ message, 'dateandtime': Date.now() }); + if (timer === null) { + timer = setTimeout(checkSavedMessages, 60 * 60000); } } } - if (!ignore_msg){ - instance.send2({'msg':send_data,'bot_name':instance.options.name+' '+type.toUpperCase(),'bot_icon':icon,'channel':instance.options.slack_channel}); + if (!ignore_msg) { + instance.send2({ 'msg': send_data, 'bot_name': instance.options.name + ' ' + type.toUpperCase(), 'bot_icon': icon, 'channel': instance.options.slack_channel }); } }); - function checkSavedMessages(){ + function checkSavedMessages() { var d = Date.now(); d = d - 86400000; // older then 24hr var a = []; //Remove msgs older then 24hr - for (let i = 0; i < FLOW["savedSlackMessages"].length; i++){ - if (FLOW["savedSlackMessages"][i].dateandtime > d){ + for (let i = 0; i < FLOW["savedSlackMessages"].length; i++) { + if (FLOW["savedSlackMessages"][i].dateandtime > d) { a.push(FLOW["savedSlackMessages"][i]); } } FLOW["savedSlackMessages"] = a; if (FLOW["savedSlackMessages"].length > 0) { - timer = setTimeout(checkSavedMessages, 60*60000); + timer = setTimeout(checkSavedMessages, 60 * 60000); } else { timer = null; } @@ -163,7 +163,7 @@ exports.install = function(instance) { instance.reconfigure = function() { try { - if (!FLOW["savedSlackMessages"]){ + if (!FLOW["savedSlackMessages"]) { FLOW["savedSlackMessages"] = []; } @@ -183,5 +183,4 @@ exports.install = function(instance) { instance.on('options', instance.reconfigure); setTimeout(instance.reconfigure, 10000); - }; diff --git a/flow/wsmqttpublish.js b/flow/wsmqttpublish.js index b2a218d..0eba804 100644 --- a/flow/wsmqttpublish.js +++ b/flow/wsmqttpublish.js @@ -55,7 +55,7 @@ let saveTelemetryOnError = true;//backup_on_failure overrides this value //------------------------ let rollers; -if(createTelemetryBackup) rollers = require('streamroller'); +if (createTelemetryBackup) rollers = require('streamroller'); const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 let insertNoSqlCounter = 0; @@ -70,14 +70,14 @@ let lastRestoreTime = 0; // if there is an error in client connection, flow logs to monitor.txt. Not to log messages every second, we use sendClientError variable let sendClientError = true; -process.on('uncaughtException', function (err) { +process.on('uncaughtException', function(err) { errLogger.error('uncaughtException:', err.message) errLogger.error(err.stack); //TODO //send to service - + //process.exit(1); }) @@ -96,22 +96,19 @@ exports.install = function(instance) { let sendWsStatusVar = null; let wsmqtt_status = 'disconnected'; - function getWsmqttName(host) - { - if(host == "tb-demo.worksys.io" || host == '192.168.252.4') return 'wsmqtt_demo'; - else if(host == "tb-qas01.worksys.io" || host == '192.168.252.5') return 'wsmqtt_qas01'; - else if(host == "tb-prod01.worksys.io" || host == '192.168.252.1') return 'wsmqtt_prod01'; + function getWsmqttName(host) { + if (host == "tb-demo.worksys.io" || host == '192.168.252.4') return 'wsmqtt_demo'; + else if (host == "tb-qas01.worksys.io" || host == '192.168.252.5') return 'wsmqtt_qas01'; + else if (host == "tb-prod01.worksys.io" || host == '192.168.252.1') return 'wsmqtt_prod01'; } - function sendWsStatus() - { - instance.send(SEND_TO.services, {[wsmqttName]: wsmqtt_status}); + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); } - function main() - { - if(!FLOW.dbLoaded) return; + function main() { + if (!FLOW.dbLoaded) return; loadSettings(); clearInterval(sendWsStatus); @@ -119,11 +116,9 @@ exports.install = function(instance) { } //set opts according to db settings - function loadSettings() - { + function loadSettings() { - if(instance.options.host !== "") - { + if (instance.options.host !== "") { //override settings from database var o = instance.options; opts = { @@ -139,13 +134,12 @@ exports.install = function(instance) { console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); } - else - { - + else { + const SETTINGS = FLOW.GLOBALS.settings; backup_on_failure = SETTINGS.backup_on_failure; saveTelemetryOnError = backup_on_failure; - + restore_from_backup = SETTINGS.restore_from_backup; restore_backup_wait = SETTINGS.restore_backup_wait; @@ -170,8 +164,7 @@ exports.install = function(instance) { connectToTbServer(); } - function connectToTbServer() - { + function connectToTbServer() { var url = "mqtt://" + opts.host + ":" + opts.port; console.log("MQTT URL: ", url); @@ -179,7 +172,7 @@ exports.install = function(instance) { client.on('connect', function() { instance.status("Connected", "green"); - monitor.info("MQTT client connected"); + //monitor.info("MQTT client connected"); sendClientError = true; clientReady = true; @@ -198,31 +191,31 @@ exports.install = function(instance) { TRY(function() { message = JSON.parse(message); - if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { - client.publish(topic, `{"device": ${message.device}, "id": ${message.data.id}, "data": {"success": true}}`, {qos:1}); - instance.send(SEND_TO.rpcCall, {"device": message.device, "id": message.data.id, "RPC response": {"success": true}}); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(topic, `{"device": ${message.device}, "id": ${message.data.id}, "data": {"success": true}}`, { qos: 1 }); + instance.send(SEND_TO.rpcCall, { "device": message.device, "id": message.data.id, "RPC response": { "success": true } }); } }, () => instance.debug('MQTT: Error parsing data', message)); } - instance.send(SEND_TO.rpcCall, {"topic":topic, "content":message }); + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); }); client.on('close', function() { clientReady = false; wsmqtt_status = 'disconnected'; - + instance.status("Disconnected", "red"); - instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); }); client.on('error', function(err) { - instance.status("Err: "+ err.code, "red"); - instance.send(SEND_TO.debug, {"message":"Client ERROR signal received !", "error":err, "opt":opts }); - if(sendClientError) { - monitor.info('MQTT client error', err); - sendClientError = false; + instance.status("Err: " + err.code, "red"); + instance.send(SEND_TO.debug, { "message": "Client ERROR signal received !", "error": err, "opt": opts }); + if (sendClientError) { + monitor.info('MQTT client error', err); + sendClientError = false; } clientReady = false; wsmqtt_status = 'disconnected'; @@ -238,45 +231,39 @@ exports.install = function(instance) { instance.on('1', function(data) { - if(clientReady) - { - //do we have some data in backup file? if any, process data from database - if(saveTelemetryOnError) - { + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { //read telemetry data and send back to server - if(!processingData) processDataFromDatabase(); + if (!processingData) processDataFromDatabase(); } - + let stringifiedJson = JSON.stringify(data.data); - client.publish("v1/gateway/telemetry", stringifiedJson, {qos: 1}); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); //backup telemetry - if(createTelemetryBackup) - { + if (createTelemetryBackup) { data.data.id = UID(); nosqlBackup.insert(data.data); insertBackupNoSqlCounter++; - if(insertBackupNoSqlCounter > 150) - { - let options = {compress: true}; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; let path = __dirname + "/../databases/backup/tbdata.nosql"; var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); stream.write(""); stream.end(); insertBackupNoSqlCounter = 0; - } + } } - - } - else - { - //logger.debug("Client unavailable. Data not sent !", JSON.stringify(data.data)); - instance.send(SEND_TO.debug, {"message":"Client unavailable. Data not sent !", "data": data.data }); - if(saveTelemetryOnError) - { + } + else { + //logger.debug("Client unavailable. Data not sent !", JSON.stringify(data.data)); + instance.send(SEND_TO.debug, { "message": "Client unavailable. Data not sent !", "data": data.data }); + + if (saveTelemetryOnError) { //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql makeBackupFromDbFile(); @@ -289,72 +276,63 @@ exports.install = function(instance) { instance.close = function(done) { - if(clientReady){ + if (clientReady) { client.end(); clearInterval(sendWsStatusVar); } }; - - function getDbBackupFileCounter(type) - { + + function getDbBackupFileCounter(type) { var files = fs.readdirSync(__dirname + "/../databases"); let counter = 0; - for(var i = 0; i < files.length; i++) - { + for (var i = 0; i < files.length; i++) { - if(files[i] == "tbdata.nosql") continue; + if (files[i] == "tbdata.nosql") continue; - if(files[i].endsWith(".nosql")) - { + if (files[i].endsWith(".nosql")) { let pos = files[i].indexOf("."); - if(pos > -1) - { + if (pos > -1) { let fileCounter = counter; let firstDigit = files[i].slice(0, pos); fileCounter = parseInt(firstDigit); - if(isNaN(fileCounter)) fileCounter = 0; + if (isNaN(fileCounter)) fileCounter = 0; //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); - - if(type == "max") - { - if(fileCounter > counter) - { + + if (type == "max") { + if (fileCounter > counter) { counter = fileCounter; } } - else if(type == "min") - { - if(counter == 0) counter = fileCounter; + else if (type == "min") { + if (counter == 0) counter = fileCounter; - if(fileCounter < counter) - { + if (fileCounter < counter) { counter = fileCounter; } } } } - + } - - if(type == "max") counter++; + + if (type == "max") counter++; return counter; } const makeBackupFromDbFile = async () => { - if(!saveTelemetryOnError) return; + if (!saveTelemetryOnError) return; //to avoid large file: tbdata.nosql //init value is 0! - if(insertNoSqlCounter > 0) - { + if (insertNoSqlCounter > 0) { --insertNoSqlCounter; return; } @@ -366,8 +344,7 @@ exports.install = function(instance) { var stats = fs.statSync(source); var fileSizeInBytes = stats.size; - if(fileSizeInBytes > noSqlFileSizeLimit) - { + if (fileSizeInBytes > noSqlFileSizeLimit) { let counter = 1; counter = getDbBackupFileCounter("max"); @@ -381,21 +358,20 @@ exports.install = function(instance) { //clear tbdata.nosql fs.writeFileSync(source, ""); fs.truncateSync(source, 0); - + } } const processDataFromDatabase = async () => { - - if(restore_from_backup <= 0) return; + + if (restore_from_backup <= 0) return; //calculate diff const now = new Date(); let currentTime = now.getTime(); let diff = currentTime - lastRestoreTime; - if( (diff / 1000) < restore_backup_wait) - { + if ((diff / 1000) < restore_backup_wait) { //console.log("*********restore_backup_wait", diff, restore_backup_wait); return; } @@ -409,60 +385,55 @@ exports.install = function(instance) { let dataBase = 'tbdata'; var nosql; - if(counter == 0) dataBase = 'tbdata'; + if (counter == 0) dataBase = 'tbdata'; else dataBase = counter + "." + 'tbdata'; nosql = NOSQL(dataBase); //select all data - use limit restore_from_backup let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); - - for(let i = 0; i < records.length; i++) - { - if(clientReady) { + + for (let i = 0; i < records.length; i++) { + if (clientReady) { let item = records[i]; let id = item.id; - if(id !== undefined) - { + if (id !== undefined) { //console.log("------------processDataFromDatabase - remove", id, dataBase, i); try { let message = JSON.parse(JSON.stringify(item)); delete message.id; - - client.publish("v1/gateway/telemetry", JSON.stringify(message), {qos:1}); - + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + //remove from database await promisifyBuilder(nosql.remove().where("id", id)); - } catch(error) { + } catch (error) { //process error console.log("processDataFromDatabase", error); } } - + } - else - { + else { processingData = false; return; } } - if(records.length > 0) - { + if (records.length > 0) { //clean backup file - if(counter > 0) nosql.clean(); + if (counter > 0) nosql.clean(); } //no data in db, remove - if(records.length == 0) - { - if(counter > 0) nosql.drop(); + if (records.length == 0) { + if (counter > 0) nosql.drop(); } const d = new Date();