diff --git a/config b/config index b10cd71..f3a7be7 100644 --- a/config +++ b/config @@ -6,7 +6,7 @@ package#flow (Object) : { url: '/' } table.relays : line:number|tbname:string|contactor:number|profile:string -table.nodes : node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean -table.settings : rvo_name:string|lang:string|temperature_adress:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|projects_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number -table.pins : pin:string|type:string|line:number +table.nodes : node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number +table.settings : rvo_name:string|lang:string|temperature_adress:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|projects_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number|node_status_nok_time:number +table.pins : pin:number|type:string|line:number table.notifications : key:string|weight:string|sk:string|en:string diff --git a/databases/nodes.table b/databases/nodes.table index 57331db..0efaed3 100644 --- a/databases/nodes.table +++ b/databases/nodes.table @@ -1,31 +1,2 @@ -node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean -+|3522|RO8rjaBDy21qPQJzW7oD96ApK3xmNleVZg9Ed4Gw|1||1|1|........... -+|4018|3JjOWdylwgNLzxVab7NEznkZ2vG64rq8PEB5QmDo|1||1|1|........... -+|4019|Z5KyJe9nEg1QNbWlX0wWRB0oDjBLdqzR83VGv624|1||1|1|........... -+|4154|1JMYvnx2RzKEo4aWQ7DmN5AL8yZV3m9NBePXbrdj|1||1|0|........... -+|3907|PjLblDgRBO6WQqnxmkJ59r0Jv3ewZN4p5a89yKdY|1||1|1|........... -+|4148|dz4ojlpP85JMgDLZWkQOoGAaKYqQexEr62GXRV1y|1||1|1|........... -+|4153|d5xjWYMwEJon6rLlK7yBYmAqgV4DaOeNB9ZX3Gzb|1||1|1|........... -+|3938|gRoJEyXVx4qD9er287LP1v7wBzGldaPjLWQKm3Mv|1||1|1|........... -+|3802|K94XLav1glVRnyQ6r01BNzkme3YJwBxM5oOzdP2j|1||1|1|........... -+|4015|d9x2V5LGYBzXp4mMRAOBDj7PloaqJwnQj6DgrNe3|1||1|0|........... -+|3929|B5EoxeMVp4zwr8nqW0GjDpARjvD1PNamOGbLg63Z|1||1|1|........... -+|3946|aw4eELG2DlPMdn1JW0B1DnAqQXOZRN3xB5yp8VKr|1||1|1|........... -+|4014|ZmRwd93QL4gaezxEbAxW5971prn2XjlPvGyqJ6BO|1||1|1|........... -+|4155|eod9aRWLVl34Gx1Dn7VoaaA2rz6qjgmpEXwQJN5Z|1||1|1|........... -+|4149|3a5oqJN1bgnx4Ol9dk86NBAByE6jQ8mKDWMpGrLV|1||1|1|........... -+|3642|EjgWGnXaLy9opPOz20n694086BlYM3w1deVQvbKr|1||1|1|........... -+|3636|wvKJdZML6mXP4DzWBAXWNW7jxNloa5g23Ve9Y1ry|1||1|1|........... -+|3991|Nzp2OoJlqn6r1ZgvdA3GWdAabBwP5G4eE3RQmyxD|1||1|1|........... -+|3994|PLBJzmK1r3Gynd6OW0gGdM0e5wV4vx9bDEqNgYR8|1||1|1|........... -+|3990|52dD6ZlV1QaOpRBmbAqKZgkKnGzWMLj4eJq38Pgo|1||1|1|........... -+|3967|rDbQ84xzwgdqEoPm3kbJw3k9anOZY1RXyBv2LVM6|1||1|1|........... -+|3977|E6Kg9oDnLWyzPRMva7vrwa7Jxp4VG58qO2w1lZYe|1||1|1|........... -+|3757|roKgWqY95V3mXMRzyAjm8D7bLjexpJPvaGDBw826|1||1|1|........... -+|3633|nJL5lPMwBx23YpqRe0rlKV7damXvWVbOrD4gNzy8|1||1|1|........... -+|3744|ZmRwd93QL4gaezxEbAxW5O71prn2XjlPvGyqJ6BO|1||1|1|........... -+|4023|eod9aRWLVl34Gx1Dn7VoaMA2rz6qjgmpEXwQJN5Z|1||1|1|........... -+|3720|3a5oqJN1bgnx4Ol9dk86NZAByE6jQ8mKDWMpGrLV|1||1|1|........... -+|3734|EjgWGnXaLy9opPOz20n69V086BlYM3w1deVQvbKr|1||1|1|........... -+|3741|wvKJdZML6mXP4DzWBAXWN17jxNloa5g23Ve9Y1ry|1||1|1|........... -+|3721|Nzp2OoJlqn6r1ZgvdA3GWKAabBwP5G4eE3RQmyxD|1||0|0|........... +node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|638|rDbQ84xzwgdqEoPm3kbJQWk9anOZY1RXyBv2LVM6|3|{"intervals":[{"cct":3000,"value":20,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":10,"end_time":"05:30","start_time":"20:00"},{"cct":3000,"value":20,"end_time":"13:00","start_time":"05:30"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":-20,"dusk_astro_clock_offset":20,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|0|1725885127396|............................................................................................................................................................................................................................................................|................. diff --git a/flow/cmd_manager.js b/flow/cmd_manager.js index 48b4987..734bc3d 100644 --- a/flow/cmd_manager.js +++ b/flow/cmd_manager.js @@ -7,7 +7,7 @@ exports.output = ['red', 'blue', 'yellow', 'blue', 'white']; //blue - send message to relays -exports.input = true; +exports.input = 2; exports.author = 'Daniel Segeš'; exports.icon = 'cloud-upload'; //exports.npm = ['serialport' , 'child_process']; @@ -84,6 +84,7 @@ const PRIORITY_TYPES = { let tasks = []; let interval = null;//timeout for procesing tasks +let customTasksInterval = null; let refFlowdata = null;//holds reference to httprequest flowdata let refFlowdataObj = {}; @@ -139,6 +140,8 @@ let nodesData = {};//key is node, value data from db let cmdCounter = {};//key is node, value is counter let cmdNOKNodeCounter = {};//key is node, value is counter +let testTbName = "deleteAfterTesting" //for status testing purposes; + //END OF VARIABLE SETTINGS //-------------------------------- @@ -196,7 +199,7 @@ function getParams(priority) params.rw = 0;//0: read, 1: write //other values - //params.type = "cmd"; "relay" "cmd-terminal" "set_node_profile" "process_profiles" "edge_date_time" "number_of_luminaires" + //params.type = "cmd"; "relay" "cmd-terminal" "set_node_profile" "process_profiles" //params.tbname = tbname; params.priority = PRIORITY_TYPES.node_cmd; //default priority - if more tasks with the same timestamp, we sort them based on priority params.timestamp = 0; //execution time - if timestamp < Date.now(), the task is processed @@ -230,7 +233,7 @@ async function loadSettings() FLOW.OMS_temperature_adress = responseSettings[0]["temperature_adress"]; FLOW.OMS_controller_type = responseSettings[0]["controller_type"]; FLOW.OMS_serial_port = responseSettings[0]["serial_port"]; - + FLOW.OMS_node_status_nok_time = responseSettings[0]["node_status_nok_time"] * 60 * 60 * 1000; // hour * minutes * seconds //logger.debug('settings', responseSettings[0]); initNotifications(); @@ -277,8 +280,8 @@ function processNodeProfile(node) logger.debug("processNodeProfile: start - set profile for ", node, profile); let nodeProfile; - try{ - nodeProfile = JSON.parse( profile ); + try { + nodeProfile = JSON.parse(profile); if(Object.keys(nodeProfile).length === 0) throw ("profile is not defined"); } catch (error) { logger.debug("Error parsing node profile", error); @@ -289,10 +292,6 @@ function processNodeProfile(node) let timestamp = PRIORITY_TYPES.node_cmd; removeTask({type: "set_node_profile", address: node}); - cmdNOKNodeCounter[node] = 0; - - //co ked sa prave spracovava? - //if(cmdNOKNodeCounter[params.address] < 5) saveToTb = false; if(nodeProfile === undefined) { @@ -325,10 +324,6 @@ function processNodeProfile(node) else { let tasksProfile = []; - //cmdCounter[node] = tasksProfile.length; - //tasks.push(tasksProfile); - - //let timestamp = PRIORITY_TYPES.node_cmd; //vypneme profil - Zapísať hodnotu 32 do registra Time Schedule Settings – reset profilu let params = getParams(PRIORITY_TYPES.node_cmd); @@ -565,8 +560,6 @@ function processNodeProfile(node) params.register = 8; params.recipient = 1; params.rw = 1;//write - - //Time schedule settings let bits = []; @@ -681,8 +674,6 @@ function removeTask(obj) } - - exports.install = function(instance) { let now = new Date(); @@ -708,7 +699,6 @@ exports.install = function(instance) { process.on('uncaughtException', function (err) { - //TODO send to service errLogger.error('uncaughtException:', err.message) @@ -780,24 +770,19 @@ exports.install = function(instance) { let params = {}; - let recipient = 2;//2 broadcast, address = 0 - let address = 0;//0 - if(recipient === 2) - { - address = 0xffffffff;//Broadcast - } - var d = new Date(); let hours = d.getHours(); let minutes = d.getMinutes(); let seconds = d.getSeconds(); - params.address = address;//broadcast + let time = d.getTime(); // time in ms + + params.address = 0xffffffff;//Broadcast params.byte1 = hours;//h params.byte2 = minutes;//m params.byte3 = seconds;//s params.byte4 = 0; - params.recipient = recipient; + params.recipient = 2;//2 broadcast, address = 0 params.register = 87;//Actual time params.rw = 1;//write @@ -823,6 +808,26 @@ exports.install = function(instance) { { let tbname = nodesData[k].tbname; let node = nodesData[k].node; + let status = "NOK"; + + // if status of node was "OK" before switching it off, we set the node's time_of_last_communication on time, it was switched on again and send OK status to tb. + if(nodesData[k].status) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + let dataToTb = { + [tbname]: [ + { + ts: time, + values: { + status: status + } + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); //prud, vykon - current, input power pre liniu pre vsetky nody @@ -890,7 +895,7 @@ exports.install = function(instance) { values["dimming"] = 0;//brightness values["power"] = 0;//výkon values["current"] = 0;//prúd - values["status"] = "OFFLINE";//prúd + values["status"] = "OFFLINE"; for (let k in nodesData) { @@ -903,23 +908,18 @@ exports.install = function(instance) { let dataToTb = { [tbname]: [ - { - "ts": Date.now(), - "values": values - } - ] - } - - //instance.send(SEND_TO.tb, dataToTb); - tbHandler.sendToTb(dataToTb, instance); + { + "ts": Date.now(), + "values": values + } + ] + } + + //instance.send(SEND_TO.tb, dataToTb); + tbHandler.sendToTb(dataToTb, instance); } } - //report OFFLINE for line - //relaysData[line].tbname; - - //values = {}; - //values["status"] = "OFFLINE";//prúd } @@ -992,7 +992,7 @@ exports.install = function(instance) { message = "NOK"; } - return {message: message, type: type, error: error}; + return {message, type, error}; } @@ -1267,6 +1267,7 @@ exports.install = function(instance) { params.type = "cmd"; //params.tbname = tbname; params.timestamp = timestampStart; + params.timestamp = Date.now() + 60000; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "Broadcast-duskTime"; @@ -1301,6 +1302,7 @@ exports.install = function(instance) { params.type = "cmd"; //params.tbname = tbname; params.timestamp = timestampStart; + params.timestamp = Date.now() + 60000; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "Broadcast-dawnTime"; @@ -1333,6 +1335,7 @@ exports.install = function(instance) { params.type = "cmd"; //params.tbname = tbname; params.timestamp = timestampStart; + params.timestamp = Date.now() + 60000; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "run broadcast: Actual time"; @@ -1392,7 +1395,7 @@ exports.install = function(instance) { if(k == 698) params.debug = true; } */ - + tasks.push(params); } @@ -1400,7 +1403,6 @@ exports.install = function(instance) { } - //niektore ulohy sa vygeneruju iba 1x pri starte!!! if(!init) return; @@ -1411,12 +1413,14 @@ exports.install = function(instance) { //tak treba vyreportovať string "NOK". { let params = getParams(PRIORITY_TYPES.fw_detection); - params.type = "cmd"; + params.type = "cmd-master"; params.register = 4; params.address = 0; let timestampStart = PRIORITY_TYPES.fw_detection; params.timestamp = timestampStart; + + params.timestamp = Date.now() + 60000; params.addMinutesToTimestamp = 5; params.tbname = FLOW.OMS_edgeName; params.info = "Master node FW verzia"; @@ -1441,36 +1445,6 @@ exports.install = function(instance) { tasks.push(params); } - { - //edge_date_time - - let params = getParams(PRIORITY_TYPES.node_cmd); - params.type = "edge_date_time"; - - let timestampStart = PRIORITY_TYPES.node_cmd; - params.timestamp = timestampStart; - params.addMinutesToTimestamp = 1; - params.tbname = FLOW.OMS_edgeName; - params.info = "reportovanie aktuálneho času na LM - EDGE-Date Time"; - //logger.debug("BUILD Master node FW verzia"); - tasks.push(params); - } - - { - //edge_date_time - - let params = getParams(PRIORITY_TYPES.node_cmd); - params.type = "number_of_luminaires"; - - let timestampStart = PRIORITY_TYPES.node_cmd + 1; - params.timestamp = timestampStart; - params.addMinutesToTimestamp = 1; - params.tbname = FLOW.OMS_edgeName; - params.info = "reportovanie number_of_luminaires"; - - tasks.push(params); - } - monitor.info("tasks created:", tasks.length); } @@ -1559,8 +1533,14 @@ exports.install = function(instance) { } - - async function upateNodeStatus(node, status) + /** + * function updates status and time_of_last_communication of node in the dbNodes + * it only updates if conditions are met + * it only updates time_of_last_communication of node, if the last written time was more than 10 minutes ago (600000 miliseconds) + * if newStatus of node is always receiving false, and it is already for more than FLOW.OMS_node_status_nok_time value, we update status to "NOK" in tb + * function returns true, if status of node needs to be updated in TB (newStatus attribute is false in this case). + */ + function updateNodeStatus(node, newStatus) { //MASTER if(node == 0) return; @@ -1568,24 +1548,72 @@ exports.install = function(instance) { let nodeObj = nodesData[node]; if(nodeObj == undefined) return; - if(status) - { - cmdNOKNodeCounter[node] = 0; - } - else cmdNOKNodeCounter[node]++; + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); - if(nodeObj.status !== status) + if(newStatus == false && nodeCurrentStatus == false) { + if(node == 638 || node == 637) console.log("false, false, return", node, now) + return true; + } + + if(newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication > now - 600000){ + + if(node == 638 || node == 637) console.log("true true, return", node, now); + return; + } + + if(newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication < now - 600000) { - await dbNodes.modify({ status: status }).where("node", node).make(function(builder) { + dbNodes.modify({ time_of_last_communication: now}).where("node", node).make(function(builder) { builder.callback(function(err, response) { - if(err == null) nodesData[node].status = status; + if(err == null) { + nodeObj.time_of_last_communication = now; + + if(node == 638 || node == 637) console.log('zapisane do db => status true & true', node, now) + } }); }); + return; + } + + if(newStatus == false && nodeCurrentStatus == true) + { + if(nodeObj.time_of_last_communication + FLOW.OMS_node_status_nok_time > now) { + if(node == 638 || node == 637) console.log('false true, return', node, now); + return; + } + else { + dbNodes.modify({ status: newStatus}).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + if(err == null) { + nodeObj.status = newStatus; + + if(node == 638 || node == 637) console.log('zapisane do db => status false & true', node, now) + } + }); + }); + return true; + } + } + + if(newStatus == true && nodeCurrentStatus == false) + { + dbNodes.modify({ status: newStatus, time_of_last_communication: now}).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + if(err == null) { + nodeObj.status = newStatus; + nodeObj.time_of_last_communication = now; + + if(node == 638 || node == 637) console.log('zapisane do db => status false & true', node, now) + } + }); + }); + return; } } - async function runTasks() { + async function runTasks(){ clearInterval(interval); @@ -1676,12 +1704,12 @@ exports.install = function(instance) { let type = params.type; let tbname = params.tbname; - let nodeKey = params.address; + let nodeAddress = params.address; let line = null; //rpc related - if(nodesData[nodeKey] !== undefined) line = nodesData[nodeKey].line; + if(nodesData[nodeAddress] !== undefined) line = nodesData[nodeAddress].line; if(params.line !== undefined) line = params.line; let repeatTask = false; @@ -1689,7 +1717,7 @@ exports.install = function(instance) { if(repeatTask) { - if(type === "cmd") + if(type === "cmd" || type === "cmd-master") { //set next start time automatically tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; @@ -1700,58 +1728,6 @@ exports.install = function(instance) { tasks.shift(); } - //custom tasks - if(type == "number_of_luminaires") - { - tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; - - //treba reportovat node status - { - //number_of_luminaires - //number_of_ok_luminaires - //number_of_nok_luminaires - - let keys = Object.keys(nodesData); - - let number_of_luminaires = keys.length; - let number_of_ok_luminaires = 0; - let number_of_nok_luminaires = 0; - - for(let i = 0; i < keys.length; i++) - { - let key = keys[i]; - let nodeObj = nodesData[key]; - if(nodeObj.tbname == undefined) continue; - - if(nodeObj.status) number_of_ok_luminaires++; - else number_of_nok_luminaires++; - } - - let values = { - number_of_luminaires: number_of_luminaires, - number_of_ok_luminaires: number_of_ok_luminaires, - number_of_nok_luminaires: number_of_nok_luminaires - }; - - let dataToTb = { - [FLOW.OMS_edgeName]: [ - { - "ts": Date.now(), - "values": values - } - ] - } - - //instance.send(SEND_TO.tb, dataToTb); - tbHandler.sendToTb(dataToTb, instance); - - interval = setInterval(runTasks, SHORT_INTERVAL); - - return; - } - } - - //kontrola nespracovanych profilov nodov if(type == "process_profiles") { @@ -1791,27 +1767,6 @@ exports.install = function(instance) { return; } - if(type == "edge_date_time") - { - const ts = Date.now(); - - let values = {"edge_date_time": ts}; - - let dataToTb = { - [tbname]: [ - { - "ts": ts, - "values": values - } - ] - } - - tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; - - instance.send(SEND_TO.tb, dataToTb); - interval = setInterval(runTasks, SHORT_INTERVAL); - return; - } //relay if(type == "relay") @@ -1912,6 +1867,8 @@ exports.install = function(instance) { disconnectedReport[tbname] = false; + const register = params.register; + //high_priority if(!FLOW.OMS_masterNodeIsResponding) { @@ -1919,11 +1876,9 @@ exports.install = function(instance) { errorHandler.sendMessageToService("Master node is not responding"); let stop = true; - if(params.type == "cmd-terminal") stop = false; //fw version - register == 4 - if(params.type == "cmd" && params.register == 4 && params.address == 0) stop = false; - + if(type == "cmd-terminal" || register == 4) stop = false; if(stop) { interval = setInterval(runTasks, LONG_INTERVAL); @@ -1938,7 +1893,7 @@ exports.install = function(instance) { } if(line == 0) relayStatus = 0; - if(params.type == "cmd-terminal") relayStatus = 1; + if(type == "cmd-terminal") relayStatus = 1; //check if rotary_switch_state == "Off" @@ -1971,7 +1926,7 @@ exports.install = function(instance) { //RE-CALCULATE VALUES //set actual time for broadcast - if(params.register == 87 && params.recipient === 2) + if(register == 87 && params.recipient === 2) { var d = new Date(); let hours = d.getHours(); @@ -1986,10 +1941,10 @@ exports.install = function(instance) { //SET DUSK/DAWN FOR BROADCAST //Time of dusk - if(params.register == 6 && params.recipient === 2) + if(register == 6 && params.recipient === 2) { - if(params.type != "cmd-terminal") + if(type != "cmd-terminal") { let sunCalcResult = calculateDuskDawn(); let dusk_hours = sunCalcResult["dusk_hours"]; @@ -2007,9 +1962,9 @@ exports.install = function(instance) { } //Time of dawn - if(params.register == 7 && params.recipient === 2) + if(register == 7 && params.recipient === 2) { - if(params.type != "cmd-terminal") + if(type != "cmd-terminal") { let sunCalcResult = calculateDuskDawn(); let dawn_hours = sunCalcResult["dawn_hours"]; @@ -2028,17 +1983,20 @@ exports.install = function(instance) { } //----------------------- - - let register = params.register; - instance.send(SEND_TO.debug, "address: " + params.address + " register:" + params.register + "type: " + params.type); + instance.send(SEND_TO.debug, "address: " + nodeAddress + " register:" + register + "type: " + type); var startTime, endTime; startTime = new Date(); - let resp = com_generic(params.address, params.recipient, params.rw, params.register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let saveToTb = true; + if(tbname == null || tbname == undefined || tbname == "") saveToTb = false; + let itIsNodeCommand = listOfCommands.includes(register); //reading data from node (voltage, current, dimming, status) + + let resp = com_generic(nodeAddress, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); let readBytes = 11; let timeout = 5000; + // await keyword is important, otherwise incorrect data is returned! await writeData(rsPort, resp, readBytes, timeout).then(function (data) { endTime = new Date(); @@ -2051,57 +2009,59 @@ exports.install = function(instance) { let result = detectIfResponseIsValid(bytes); - let message = result.message; - let type = result.type; + //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; - //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK - + //testing purpose node 638, tbname rDbQ84xzwgdqEoPm3kbJQWk9anOZY1RXyBv2LVM6 + if(tbname == testTbName) { + message = "NOK"; + message_type = "ERROR"; + error = "type is: ERROR"; + } + if(params.debug != "generated cmd") { - //debug("writeData: done " + type + " duration: " + timeDiff + " type: " + params.debug, params); + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug, params); } - if(params.hasOwnProperty("debug")) - { - if(params.debug) - { - console.log("detected response:", result); + // if(params.hasOwnProperty("debug")) + // { + // if(params.debug) + // { + // console.log("detected response:", result); - logger.debug("writeData: done " + type + " duration: " + timeDiff + " type: " + params.debug, params, result); - } - } + // logger.debug("writeData: done " + message_typetype + " duration: " + timeDiff + " type: " + params.debug, params, result); + // } + // } - //debug("writeData: done " + type + " duration: " + timeDiff + " type: " + params.debug); - //debug("writeData done", type, "duration", timeDiff, "type", params.debug, result); + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug); + //debug("writeData done", message_type, "duration", timeDiff, "message_type", params.debug, result); - let tbname = params.tbname; - - let saveToTb = true; - if(tbname == null || tbname == undefined || tbname == "") saveToTb = false; - //-- + let values = {}; //CMD FINISHED if(message == "OK") { - upateNodeStatus(params.address, true); + updateNodeStatus(nodeAddress, true); //write - if(params.type == "set_node_profile") + if(type == "set_node_profile") { - let result = cmdCounterResolve(params.address); + let result = cmdCounterResolve(nodeAddress); if(result == 0) { - dbNodes.modify({ processed: true }).where("node", params.address).make(function(builder) { + dbNodes.modify({ processed: true }).where("node", nodeAddress).make(function(builder) { builder.callback(function(err, response) { - sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "dimming_profile_was_successfully_received_by_node", {node: params.address}, "", SEND_TO.tb, instance ); + sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "dimming_profile_was_successfully_received_by_node", {node: nodeAddress}, "", SEND_TO.tb, instance ); - logger.debug( "--> profil úspešne odoslaný na node č. " + params.address); - nodesData[params.address].processed = true; + logger.debug( "--> profil úspešne odoslaný na node č. " + nodeAddress); + nodesData[nodeAddress].processed = true; }); }); @@ -2109,22 +2069,25 @@ exports.install = function(instance) { } //parse read response - let values = {}; - if(params.rw == 0) { - values = processResponse(register, dataBytes);//read - } - if(params.rw == 1) - { //write command - //set command dimming - if(params.register == 1) values = {"comm_status": message}; + if(params.rw == 0) + { + values = processResponse(register, dataBytes); //read } - if(params.register == 0) values["status"] = message; + if(itIsNodeCommand) + { + values.comm_status = "OK"; + values.status = "OK"; + } - //fw version - register == 4 - if(params.register == 4) values["edge_fw_version"] = FLOW.OMS_edge_fw_version; + //master node + if(nodeAddress == 0 && register == 4) + { + values.status = "OK"; + values["edge_fw_version"] = FLOW.OMS_edge_fw_version; + } - if(params.address == 0) + if(nodeAddress == 0) { //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.NOTICE, "Master node is working again", "", SEND_TO.tb, instance, "rvo_status" ); //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, "master_node_is_responding_again", {}, "", SEND_TO.tb, instance, "rvo_status" ); @@ -2133,7 +2096,7 @@ exports.install = function(instance) { } //odoslanie príkazu z terminálu - dáta - if(params.type == "cmd-terminal") + if(type == "cmd-terminal") { //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.DEBUG, "odoslanie príkazu z terminálu", params, SEND_TO.tb, instance, null ); sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "command_was_sent_from_terminal_interface", {}, params, SEND_TO.tb, instance ); @@ -2141,7 +2104,7 @@ exports.install = function(instance) { if(params.debug) { - logger.debug("saveToTb", saveToTb, tbname, values); + //logger.debug("saveToTb", saveToTb, tbname, values); } if(saveToTb) @@ -2157,199 +2120,40 @@ exports.install = function(instance) { //instance.send(SEND_TO.tb, dataToTb); tbHandler.sendToTb(dataToTb, instance); - } else { - - if(params.type == "cmd-terminal") + if(type == "cmd-terminal") { - if(params.refFlowdataKey != undefined) - { - - logger.debug("cmd-terminal SUCCESS"); - logger.debug(currentTask); - - //make http response - let responseObj = {}; - responseObj["type"] = "SUCESS"; - responseObj["bytes"] = data; - - //params.refFlowdata.data = responseObj; - //instance.send(SEND_TO.http_response, params.refFlowdata); - - let refFlowdata = refFlowdataObj[ params.refFlowdataKey ]; - refFlowdata.data = responseObj; - instance.send(SEND_TO.http_response, refFlowdata); - - } - else - { - console.log("params.refFlowdataKey is undefined", params); - } + terminalCommandResponse(params, "SUCCESS", data); } - } } else { - upateNodeStatus(params.address, false); - - if(params.refFlowdataKey != undefined) - { - - logger.debug("cmd-terminal FAILED"); - logger.debug(currentTask); - - //make http response - let responseObj = {}; - responseObj["type"] = "ERROR"; - responseObj["bytes"] = data; - - //params.refFlowdata.data = responseObj; - //instance.send(SEND_TO.http_response, params.refFlowdata); - - let refFlowdata = refFlowdataObj[ params.refFlowdataKey ]; - if(refFlowdata !== undefined) - { - refFlowdata.data = responseObj; - instance.send(SEND_TO.http_response, refFlowdata); - } - - - } - - /* - if(params.type == "cmd-terminal") - { - if(params.refFlowdata != undefined) - { - - logger.debug("cmd-terminal FAILED"); - logger.debug(currentTask); - - //make http response - let responseObj = {}; - responseObj["type"] = "ERROR"; - responseObj["bytes"] = data; - - params.refFlowdata.data = responseObj; - instance.send(SEND_TO.http_response, params.refFlowdata); + terminalCommandResponse(params, "ERROR", data) + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); - } - } - */ - - if(params.address == 0) - { - //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.ALERT, "Master node not responding", "", SEND_TO.tb, instance, "rvo_status"); - sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "master_node_is_not_responding", {}, "", SEND_TO.tb, instance, "rvo_status"); - logger.debug("master_node_is_not_responding", params); - FLOW.OMS_masterNodeIsResponding = false; - } - - if(params.type == "set_node_profile") - { - delete cmdCounter[params.address]; - let tbname = nodesData[ params.address ].tbname; - - logger.debug( "profil nebol úspešne odoslaný na node č. ", params, result, resp); - - //sendNotification("CMD Manager: process cmd", tbname, ERRWEIGHT.ALERT, "profil nebol úspešne odoslaný na node č. " + params.address, "", SEND_TO.tb, instance, null ); - sendNotification("CMD Manager: process cmd", tbname, "configuration_of_dimming_profile_to_node_failed", {node: params.address}, "", SEND_TO.tb, instance ); - } - - //is it node? - if(nodesData.hasOwnProperty(params.address)) - { - if(cmdNOKNodeCounter[params.address] < 5) saveToTb = false; - } - - //Master node version - //if(params.register == 4 && saveToTb) - if(saveToTb) - { - let values = { - "status": "NOK" - }; - - let dataToTb = { - [tbname]: [ - { - "ts": Date.now(), - "values": values - } - ] - } - - //instance.send(SEND_TO.tb, dataToTb); - tbHandler.sendToTb(dataToTb, instance); - } - - //instance.send(SEND_TO.debug, result); - if(params.hasOwnProperty("debug")) { if(params.debug) { - logger.debug("writeData err: ", error, result, params); + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, nodeAddress, register, values); } } //logger.debug(error, result, params); } - - }).catch(function (reason) { + }).catch(function(reason) { console.log("writeData catch exception", reason); - logger.debug(currentTask); + instance.send(SEND_TO.debug, reason); - if(params.refFlowdataKey != undefined) - { - - logger.debug("catch: cmd-terminal FAILED"); - logger.debug(currentTask); - - //make http response - let responseObj = {}; - responseObj["type"] = "ERROR";// - responseObj["message"] = "ERROR WRITE FAILED: " + reason;// - - //params.refFlowdata.data = responseObj; - //instance.send(SEND_TO.http_response, params.refFlowdata); - - let refFlowdata = refFlowdataObj[ params.refFlowdataKey ]; - if(refFlowdata !== undefined) - { - refFlowdata.data = responseObj; - instance.send(SEND_TO.http_response, refFlowdata); - } - - - } - /* - if(params.type == "cmd-terminal") - { - if(params.refFlowdata != undefined) - { - - logger.debug("cmd-terminal FAILED"); - logger.debug(currentTask); - - //make http response - let responseObj = {}; - responseObj["type"] = "ERROR WRITE FAILED: " + reason; - //responseObj["bytes"] = data; - - params.refFlowdata.data = responseObj; - instance.send(SEND_TO.http_response, params.refFlowdata); - - //refFlowdata = undefined; - } - } - */ + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); if(params.hasOwnProperty("debug")) { @@ -2359,93 +2163,16 @@ exports.install = function(instance) { } } - upateNodeStatus(params.address, false); - - let tbname = params.tbname; - - let saveToTb = true; - if(tbname == null || tbname == undefined || tbname == "") saveToTb = false; - - if(params.address == 0) - { - //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.ALERT, "Master node not responding", "", SEND_TO.tb, instance, "rvo_status"); - sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "master_node_is_not_responding", {}, "", SEND_TO.tb, instance, "rvo_status"); - logger.debug("master_node_is_not_responding", params); - - FLOW.OMS_masterNodeIsResponding = false; - } - - if(params.type == "set_node_profile") - { - delete cmdCounter[params.address]; - let tbname = nodesData[ params.address ].tbname; - - logger.debug( "profil nebol úspešne odoslaný na node č. ", params, resp); - - //sendNotification("CMD Manager: process cmd", tbname, ERRWEIGHT.ALERT, "odosielanie profilu na node č. " + params.address + " zlyhalo", "", SEND_TO.tb, instance, null ); - sendNotification("CMD Manager: process cmd", tbname, "configuration_of_dimming_profile_to_node_failed", {node: params.address}, "", SEND_TO.tb, instance ); - } - - //is it node? - if(nodesData.hasOwnProperty(params.address)) - { - if(cmdNOKNodeCounter[params.address] < 5) saveToTb = false; - } - - //Master node version - if(params.register == 4 && saveToTb) - { - let values = { - "status": "NOK", - "master_node_version": "NOK" - }; - - let dataToTb = { - [tbname]: [ - { - "ts": Date.now(), - "values": values - } - ] - } - - //instance.send(SEND_TO.tb, dataToTb); - tbHandler.sendToTb(dataToTb, instance); - - FLOW.OMS_masterNodeIsResponding = false; - } - //treba? - /* - else if(saveToTb) - { - let values = { - "comm_status": "no_comm" - }; - - let dataToTb = { - [tbname]: [ - { - "ts": Date.now(), - "values": values - } - ] - } - - instance.send(SEND_TO.tb, dataToTb); - } - */ - - instance.send(SEND_TO.debug, reason); }); } else { - if(currentTask.debug) - { - //currentTask.timestamp <= currentTimestamp - logger.debug("currentTask is not processed - task is in the future", currentTask); - } + // if(currentTask.debug) + // { + // //currentTask.timestamp <= currentTimestamp + // logger.debug("currentTask is not processed - task is in the future", currentTask); + // } interval = setInterval(runTasks, LONG_INTERVAL); return; @@ -2454,7 +2181,178 @@ exports.install = function(instance) { //console.log("----->runTasks - setInterval", new Date()); interval = setInterval(runTasks, SHORT_INTERVAL); } + + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb){ + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + tbName && (tbName = nodesData[node].tbname); + + let values = {}; + + console.log(message); + let updateStatus = updateNodeStatus(node, false); + + if(node == 0) + { + //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.ALERT, "Master node not responding", "", SEND_TO.tb, instance, "rvo_status"); + sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "master_node_is_not_responding", {}, "", SEND_TO.tb, instance, "rvo_status"); + logger.debug("master_node_is_not_responding", params); + FLOW.OMS_masterNodeIsResponding = false; + } + + if(type == "set_node_profile") + { + delete cmdCounter[node]; + logger.debug( "profil nebol úspešne odoslaný na node č. ", params, resp); + + //sendNotification("CMD Manager: process cmd", tbname, ERRWEIGHT.ALERT, "odosielanie profilu na node č. " + node + " zlyhalo", "", SEND_TO.tb, instance, null ); + sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", {node: node}, "", SEND_TO.tb, instance ); + } + + if(itIsNodeCommand) + { + values.comm_status = "NOK"; + } + + if(updateStatus) + { + values.status = "NOK"; + } + + //master node + if(node == 0 && register == 4) + { + values.status = "NOK"; + values["master_node_version"] = "NOK"; + } + + console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if(saveToTb && Object.keys(values).length > 0 && tbName) + { + + let dataToTb = { + [tbName]: [ + { + "ts": Date.now(), + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + } + /** + * function handles requests from terminal + * responseType can be "SUCCESS", "ERROR" or "FAILURE", depending on rsPort data. + * FAILURE means, that we got into catch block of writeData function. + */ + function terminalCommandResponse(params, responseType, data=null, reason="") { //success, error, failure + + if(params.refFlowdataKey == undefined) + { + //console.log("params.refFlowdataKey is undefined", params); + return; + } + else + { + console.log("params.refFlowdataKey: ", params); + } + + let message = null; + let type = null; + + switch (responseType) { + case "SUCCESS": + message = "cmd-terminal SUCCESS"; + type = "SUCCESS"; + break; + case "ERROR": + message = "cmd-terminal FAILED"; + type = "ERROR"; + break; + case "FAILURE": + message = "ERROR WRITE FAILED: " + reason; + type = "ERROR"; + break; + default: + type = undefined; + } + + logger.debug(message); + logger.debug(params); + + //make http response + let responseObj = {} + responseObj["type"] = type; + + if(responseType == "FAILURE") responseObj["message"] = "ERROR WRITE FAILED: " + reason; + else responseObj["bytes"] = data; + + let refFlowdata = refFlowdataObj[params.refFlowdataKey]; + if(refFlowdata !== undefined) + { + refFlowdata.data = responseObj; + instance.send(SEND_TO.http_response, refFlowdata); + } + } + + + /** + * function handles tasks, that are not needed to run through masterNode. To make them run smooth without waiting for other tasks to be completed, we moved them in separate function + */ + function reportEdgeDateTimeAndNumberOfLuminaires(){ + + if(!FLOW.OMS_edgeName) return; + + const ts = Date.now(); + const keys = Object.keys(nodesData); + + const number_of_luminaires = keys.length; + let number_of_ok_luminaires = 0; + let number_of_nok_luminaires = 0; + + for(let i = 0; i < keys.length; i++) + { + let key = keys[i]; + let nodeObj = nodesData[key]; + if(nodeObj.tbname == undefined) continue; + + if(nodeObj.status) number_of_ok_luminaires++; + else number_of_nok_luminaires++; + } + + const values = { + "number_of_luminaires": number_of_luminaires, + "number_of_ok_luminaires": number_of_ok_luminaires, + "number_of_nok_luminaires": number_of_nok_luminaires, + "edge_date_time": ts + }; + + let dataToTb = { + [FLOW.OMS_edgeName]: [ + { + "ts": ts, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + //instance.send(SEND_TO.tb, dataToTb); + } + + //to ensure, edgeDateTime will be send to tb at full minute + customTasksInterval = setInterval(function() { + if(new Date().getSeconds() === 0) reportEdgeDateTimeAndNumberOfLuminaires(); + }, 1000); + //! rsPort LM = "/dev/ttymxc4", rsPort UNIPI = "/dev/ttyUSB0" // const rsPort = new SerialPort("/dev/ttymxc4", { autoOpen: false }); //LM @@ -2509,9 +2407,16 @@ exports.install = function(instance) { instance.on("close", () => { clearInterval(interval); + clearInterval(customTasksInterval); rsPort.close(); }); + instance.on("1", function(flowdata){ + if(flowdata.data.hasOwnProperty("testTbName")) + { + testTbName = flowdata.data.testTbName; + } + }) instance.on("data", async function(flowdata) { diff --git a/flow/helper/DataToTbHandler.js b/flow/helper/DataToTbHandler.js index 8fff312..8010581 100644 --- a/flow/helper/DataToTbHandler.js +++ b/flow/helper/DataToTbHandler.js @@ -92,15 +92,14 @@ class DataToTbHandler } //console.log(this.sender + " DATA SEND TO TB ", tbname, this.messageCounter, new Date(ts), dataToTbModified[tbname][0].values, this.instance); - if(this.debug) console.log(this.sender + " DATA SEND TO TB ", this.index, tbname, arrayOfValuesToSend); + //if(this.debug) console.log(this.sender + " DATA SEND TO TB ", this.index, tbname, arrayOfValuesToSend); instance.send(this.index, dataToTbModified); } getDiffTimestamp(key) { - let seconds = 60*60;//1h - //seconds = 1;//for testing + let seconds = 30*60;//30 minutes //TODO set different value for given key!!! //if(key == "status") seconds = 2*60*60;//2h @@ -160,4 +159,4 @@ class DataToTbHandler } } -module.exports = DataToTbHandler; \ No newline at end of file +module.exports = DataToTbHandler;