From d289a99d07058bca3082ed3d149f9a078baaa12e Mon Sep 17 00:00:00 2001 From: rasta5man Date: Tue, 14 May 2024 16:29:11 +0200 Subject: [PATCH] new switching line functionality - in progress --- flow/cmd_manager.js | 2660 ++++++++++++++++++++++----------------- flow/dido_controller.js | 9 +- flow/modbus_reader.js | 10 +- 3 files changed, 1485 insertions(+), 1194 deletions(-) diff --git a/flow/cmd_manager.js b/flow/cmd_manager.js index 3c18f1d..b3f9871 100644 --- a/flow/cmd_manager.js +++ b/flow/cmd_manager.js @@ -19,15 +19,15 @@ exports.html = `
RPC - run RPC calls

-
@(User)
-
-
-
@(Password)
-
-
-
@(My edge)
-
-
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
`; @@ -43,38 +43,49 @@ const bitwise = require('bitwise'); var SunCalc = require('./helper/suncalc.js'); const DataToTbHandler = require('./helper/DataToTbHandler.js'); const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler.js'); -const { promisifyBuilder } = require('./helper/db_helper.js'); +const { promisifyBuilder, makeMapFromDbResult} = require('./helper/db_helper.js'); const { sendNotification, initNotifications, ERRWEIGHT } = require('./helper/notification_reporter.js'); +const dbNodes = TABLE("nodes"); +const dbRelays = TABLE("relays"); +const dbSettings = TABLE("settings"); + //https://github.com/log4js-node/log4js-node/blob/master/examples/example.js //file: { type: 'file', filename: path.join(__dirname, 'log/file.log') } - var path = require('path'); var log4js = require("log4js"); const process = require('process'); -log4js.configure({ - appenders: { - errLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'err.txt') }, - monitorLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'monitor.txt') }, - console: { type: 'console' } - }, - categories: { - errLogs: { appenders: ['console', 'errLogs'], level: 'error' }, - monitorLogs: { appenders: ['console', 'monitorLogs'], level: 'trace' }, - //another: { appenders: ['console'], level: 'trace' }, - default: { appenders: ['console'], level: 'trace' } - } -}); +//TODO - to remove? +// runTasks intervals +const SHORT_INTERVAL = 50; +const LONG_INTERVAL = 500; -const errLogger = log4js.getLogger("errLogs"); -const logger = log4js.getLogger(); -const monitor = log4js.getLogger("monitorLogs"); +//send data to following instances: +const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4 +} -//USAGE -//logger.debug("text") -//monitor.info('info'); -//errLogger.error("some error"); +const PRIORITY_TYPES = { + terminal: 0, + fw_detection: 1,//reserved only for FW detection - FLOW.OMS_masterNodeIsResponding + high_priority: 2,//reserverd only for: read dimming / brightness (after set dimming from platform) + relay_profile: 3, + node_broadcast: 4, + node_profile: 5, + node_cmd: 6 +} + +//list of command calls to process. Processing in runTasks function +let tasks = []; + +let interval = null;//timeout for procesing tasks +let refFlowdata = null;//holds reference to httprequest flowdata +let refFlowdataObj = {}; //load from settings let latitude = 48.70826502;//48.682255758; @@ -111,15 +122,9 @@ priorities["8"] = minutes; priorities["3"] = minutes; priorities["89"] = minutes; -//prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app +//prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) let listOfCommands = [0,1,3,6,7,8,74,75,76,77,78,79,80,84,87,89]; -//1 - dimming - -const dbNodes = TABLE("nodes"); -const dbRelays = TABLE("relays"); -const dbSettings = TABLE("settings"); - const errorHandler = new ErrorToServiceHandler(); let rotary_switch_state = "Off"; @@ -133,6 +138,35 @@ let nodesData = {};//key is node, value data from db //helper container for counting resolved group of commands (commands related to set profile) let cmdCounter = {};//key is node, value is counter let cmdNOKNodeCounter = {};//key is node, value is counter + +//END OF VARIABLE SETTINGS +//-------------------------------- + + +log4js.configure({ + appenders: { + errLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'err.txt') }, + monitorLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'monitor.txt') }, + console: { type: 'console' } + }, + categories: { + errLogs: { appenders: ['console', 'errLogs'], level: 'error' }, + monitorLogs: { appenders: ['console', 'monitorLogs'], level: 'trace' }, + //another: { appenders: ['console'], level: 'trace' }, + default: { appenders: ['console'], level: 'trace' } + } +}); + +const errLogger = log4js.getLogger("errLogs"); +const logger = log4js.getLogger(); +const monitor = log4js.getLogger("monitorLogs"); + +//USAGE +//logger.debug("text") +//monitor.info('info'); +//errLogger.error("some error"); + + function cmdCounterResolve(address) { if(cmdCounter.hasOwnProperty(address)) @@ -141,13 +175,12 @@ function cmdCounterResolve(address) let result = cmdCounter[address]; if(result == 0) delete cmdCounter[address]; - return result; } - return -1; } + function getParams(priority) { let params = {}; @@ -163,25 +196,25 @@ function getParams(priority) params.rw = 0;//0: read, 1: write //other values - //params.type = "cmd"; "relay" "cmd-terminal" + //params.type = "cmd"; "relay" "cmd-terminal" "set_node_profile" "process_profiles" "edge_date_time" "number_of_luminaires" //params.tbname = tbname; - params.priority = priorityTypes.node_cmd;//default priority - params.timestamp = 0;//execution time + 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 if(priority != undefined ) { params.timestamp = priority; params.priority = priority; } - params.addMinutesToTimestamp = 0;//repeat if > 0, + params.addMinutesToTimestamp = 0;//repeat task if value is > 0, - //params.isDusk = false; - //params.isDawn = false; + //params.timePointName = "luxOff" // "luxOn", "dusk", "dawn", "profileTimepoint" //params.info = ""; return params; } + async function loadSettings() { let responseSettings = await promisifyBuilder(dbSettings.find()); @@ -200,12 +233,10 @@ async function loadSettings() //logger.debug('settings', responseSettings[0]); - //FLOW.OMS_tem - //rvo_name:string|lang:string|temperature_adress:string|latitude:number|longitude:number - initNotifications(); } + //nastav profil nodu function processNodeProfile(node) { @@ -246,13 +277,13 @@ function processNodeProfile(node) logger.debug("processNodeProfile", node, line, nodeObj, nodeProfile); //return; - //let timestamp = priorityTypes.node_cmd; + //let timestamp = PRIORITY_TYPES.node_cmd; //let now = new Date(); //now.setSeconds(now.getSeconds() + 10); //let timestamp = now.getTime(); - let timestamp = priorityTypes.node_cmd; + let timestamp = PRIORITY_TYPES.node_cmd; //nodeProfile = undefined; removeTask({type: "set_node_profile", address: node}); @@ -270,7 +301,7 @@ function processNodeProfile(node) logger.debug("turn off profile"); - let params = getParams(priorityTypes.node_cmd); + let params = getParams(PRIORITY_TYPES.node_cmd); params.type = "set_node_profile"; params.address = node; params.byte1 = 0; @@ -288,7 +319,7 @@ function processNodeProfile(node) tasks.push(params); - //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.NOTICE, "Master node is working again", "", instanceSendTo.tb, instance ); + //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.NOTICE, "Master node is working again", "", SEND_TO.tb, instance ); } else { @@ -296,10 +327,10 @@ function processNodeProfile(node) //cmdCounter[node] = tasksProfile.length; //tasks.push(tasksProfile); - //let timestamp = priorityTypes.node_cmd; + //let timestamp = PRIORITY_TYPES.node_cmd; - //vypneme profil - Zapísať hodnotu 32 do registra Time Schedule Settings – reset profilu - let params = getParams(priorityTypes.node_cmd); + //vypneme profil - Zapísať hodnotu 32 do registra Time Schedule Settings – reset profilu + let params = getParams(PRIORITY_TYPES.node_cmd); params.type = "set_node_profile"; params.address = node; params.byte1 = 0; @@ -335,7 +366,7 @@ function processNodeProfile(node) Prázdny profil je vtedy keď časový bod obsahuje hodnotu 0xFFFFFFFF (táto hodnota sa zapíše do registrov keď sa aktivuje reset profilu do registru 8). Páry sa prechádzajú časovo zoradené takže teoreticky je jedno v akom poradí sa zapisujú ale je lepšie ich zapisovať v chronologickom poradí od 13:00. Časový bod má formát: - Byte 3: hodiny Byte 2: minúty Byte 1: sekundy Byte 0 – rezervované + Byte 3: hodiny Byte 2: minúty Byte 1: sekundy Byte 0 – rezervované Register úrovne má rovnaký formát ako dimming register (Reg 1). */ @@ -353,7 +384,7 @@ function processNodeProfile(node) logger.debug("processNodeProfile: TS1 Time point ", (i + 1), node); - params = getParams(priorityTypes.node_cmd); + params = getParams(PRIORITY_TYPES.node_cmd); params.type = "set_node_profile"; params.address = node; params.byte1 = parseInt(t[0]);//hh @@ -372,7 +403,7 @@ function processNodeProfile(node) register++; timestamp++; - params = getParams(priorityTypes.node_cmd); + params = getParams(PRIORITY_TYPES.node_cmd); params.type = "set_node_profile"; params.address = node; params.byte1 = 0; @@ -407,7 +438,7 @@ function processNodeProfile(node) logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); - let params = getParams(priorityTypes.node_cmd); + let params = getParams(PRIORITY_TYPES.node_cmd); params.type = "set_node_profile"; params.address = node; params.register = 96; @@ -445,7 +476,7 @@ function processNodeProfile(node) logger.debug("processNodeProfile: DUSK/DAWN max. adjust period", node); - let params = getParams(priorityTypes.node_cmd); + let params = getParams(PRIORITY_TYPES.node_cmd); params.type = "set_node_profile"; params.address = node; params.register = 97; @@ -482,12 +513,12 @@ function processNodeProfile(node) { //Statický offset pre časy úsvitu a súmraku. Byte 1 je pre DUSK, Byte 0 je pre DAWN. Formát: - //Bity 0 – 6: hodnota v minútach - //Bit 7: znamienko (1 – mínus) + //Bity 0 – 6: hodnota v minútach + //Bit 7: znamienko (1 – mínus) logger.debug("processNodeProfile: Static offset", node); - let params = getParams(priorityTypes.node_cmd); + let params = getParams(PRIORITY_TYPES.node_cmd); params.type = "set_node_profile"; params.address = node; params.register = 98; @@ -527,7 +558,7 @@ function processNodeProfile(node) logger.debug("Time schedule settings - turn on", node); - params = getParams(priorityTypes.node_cmd); + params = getParams(PRIORITY_TYPES.node_cmd); params.type = "set_node_profile"; params.address = node; params.register = 8; @@ -556,7 +587,7 @@ function processNodeProfile(node) //Bit 5 – zápis 1 spôsobí reset nastavení profilu (nastavenie prázdneho profilu) bits.push(0); - //Bity 6-7 - zatiaľ nepoužité + //Bity 6-7 - zatiaľ nepoužité bits.push(0); bits.push(0); @@ -607,53 +638,29 @@ function processNodeProfile(node) } -const instanceSendTo = { - debug: 0, - tb: 1, - http_response: 2, - dido_controller: 3, - infoSender: 4 -} - -const priorityTypes = { - terminal: 0, - fw_detection: 1,//reserved only for FW detection - FLOW.OMS_masterNodeIsResponding - high_priority: 2,//reserverd only for: read dimming / brightness (after set dimming from platform) - relay_profile: 3, - node_broadcast: 4, - node_profile: 5, - node_cmd: 6 -} - - -let interval = null;//timeout for procesing tasks -let refFlowdata = null;//holds reference to httprequest flowdata -let refFlowdataObj = {}; function cleanUpRefFlowdataObj() { - let now = new Date(); - let timestamp = now.getTime(); + let now = new Date(); + let timestamp = now.getTime(); - //clear old refFlowdata references - let keys = Object.keys(refFlowdataObj); - for(let i = 0; i < keys.length; i++) - { - let timestampKey = keys[i]; + //clear old refFlowdata references + let keys = Object.keys(refFlowdataObj); + for(let i = 0; i < keys.length; i++) + { + let timestampKey = keys[i]; - if((timestamp - timestampKey) > 60*1000 ) - { - console.log("cleanUpRefFlowdataObj delete", timestampKey); - delete refFlowdataObj[ timestampKey ]; - } - } + if((timestamp - timestampKey) > 60*1000 ) + { + console.log("cleanUpRefFlowdataObj delete", timestampKey); + delete refFlowdataObj[ timestampKey ]; + } + } } -let tasks = [];//list of command calls to process function removeTask(obj) { - let keys = Object.keys(obj); tasks = tasks.filter((task) => { @@ -665,25 +672,41 @@ function removeTask(obj) { if(task[key] == obj[key]) counter++; } - } if(counter == keys.length) return false; return true; - }); - } -//TODO - to remove? -const shortIterval = 10; -const longInterval = 100; - loadSettings(); + exports.install = function(instance) { + let now = new Date(); + console.log("CMD Manager installed", now.toLocaleString("sk-SK")); + + const tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + //FLOW.OMS_projects_id, name: FLOW.OMS_rvo_name + //const errorHandler = new ErrorToServiceHandler(instance, SEND_TO.infoSender); + errorHandler.setProjectsId(FLOW.OMS_projects_id); + //const errorHandler = new ErrorToServiceHandler(instance); + //errorHandler.sendMessageToService("ahoj", 0); + + let sunCalcResult = calculateDuskDawn(); + + let reportDuskDawn = { + dusk_time: sunCalcResult.dusk_time, + dawn_time: sunCalcResult.dawn_time, + dusk_time_reported: undefined, + dawn_time_reported: undefined + }; + + process.on('uncaughtException', function (err) { //TODO send to service @@ -697,253 +720,170 @@ exports.install = function(instance) { //te();//force error - const tbHandler = new DataToTbHandler(instanceSendTo.tb); - tbHandler.setSender(exports.title); - //FLOW.OMS_projects_id, name: FLOW.OMS_rvo_name - //const errorHandler = new ErrorToServiceHandler(instance, instanceSendTo.infoSender); - errorHandler.setProjectsId(FLOW.OMS_projects_id); - //const errorHandler = new ErrorToServiceHandler(instance); - //errorHandler.sendMessageToService("ahoj", 0); - - - async function loadRelaysData(line) + function processAllNodeProfilesOnLine(line) { - logger.debug("loadRelaysData", line); - - //ak zapiname liniu, mali by sme skontrolovat kde processed je false - //nodes.table: node:number|tbname:string|line:number|profile:string|processed:boolean - //vyselektujem vsetky nodes a spracujem profil - - return new Promise((resolve, reject) => { - - dbRelays.find().make(function(builder) { - builder.callback(function(err, response) { - - if(err != null) reject(err); - - let relaysDataTmp = {}; - for(let i = 0; i < response.length; i++) - { - let record = response[i]; - let line = record["line"]; - relaysDataTmp[ record["line"] ] = record; - - //porovname predchadzajuce hodnoty - //ak record.contactor == 1, a aktualna hodnota record.contactor == 0 - //to znamena, ze sa zmenil stav - linia bola vypnuta - - let prevData = relaysData[ record["line"] ]; - - //ugly but do not remove!!! - relaysData[ record["line"] ] = record; - - let state = "";//on, off or empty (no change) - if(prevData != undefined) - { - /* - if(prevData.contactor == 1 && record.contactor == 0) - { - state = "off"; - reportOfflineNodeStatus(line); - } - - if(prevData.contactor == 0 && record.contactor == 1) - { - state = "on"; - reportOnlineNodeStatus(line); - } - */ - - } - else - { - //start flowu - state = "start"; - } - - if(line != undefined) - { - //ak sa jedna o update profilu linie - pozor di_co_controller posiela command pre loadRelaysData - if(line != record["line"] ) continue; - } - - //je zapnuta linia? contactor = 1 a processed = false, spracujeme profil - if(record.contactor == 1) - { - - //nespracovany profil, zapisem do nodu - //rotary_switch_state = Automatic - profilu pre nody sa vykonavaju - //ak je spracovany, a automatic - tak ho zapnem - - if(rotary_switch_state == "Automatic") - { - //prejs nodes - nacitame vsetky nody z pre danu liniu - for (let k in nodesData) { - //node:number|tbname:string|line:number|profile:string|processed:boolean - - //potrebujem nody k danej linii - if(record.line == nodesData[k].line) - { - let node = nodesData[k].node; - let processed = nodesData[k].processed; - - if(!processed) - { - processNodeProfile(node); - } - else{ - //logger.debug( `node ${node} profile for line ${nodesData[k].line} was already processed`); - } - } - } - - } - else - { - logger.debug("unable to process profile - rotary_switch_state is", rotary_switch_state); - } - - } - } - - relaysData = {...relaysDataTmp}; - - resolve("OK"); - - }); - }); - //resolve(stdout); - //reject(error); - - }) + + for (let k in nodesData) { + //node:number|tbname:string|line:number|profile:string|processed:boolean + + if(line == nodesData[k].line) + { + let node = nodesData[k].node; + let processed = nodesData[k].processed; + + if(!processed) + { + processNodeProfile(node); + } + else + { + logger.debug( `Node ${node} profile for line ${nodesData[k].line} was already processed`); + } + } + } } + + async function loadRelaysData(line) { + + relaysData = await promisifyBuilder(dbRelays.find()); + relaysData = makeMapFromDbResult(relaysData, "line"); + + for (const [key, value] of Object.entries(relaysData)) + { + if(key == "0") continue; + if(line != undefined) + { + //ak sa jedna o update profilu linie - pozor di_co_controller posiela command pre loadRelaysData + if(line != value.line ) continue; + } + + if(value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + +// console.log('.........', relaysData); + } + + function reportOnlineNodeStatus(line) { - //broadcast cas, o 1-2 sek neskor - status, brightness - + //broadcast cas, o 3 sek neskor - status, brightness //Po zapnutí línie broadcastovo aktualizovať predtým čas. logger.debug("--->reportOnlineNodeStatus for line", line); //return; + + //run broadcast //Actual time + addMinutesToTimestamp = 0; + let params = {}; + + let recipient = 2;//2 broadcast, address = 0 + let address = 0;//0 + if(recipient === 2) { - //run broadcast //Actual time - addMinutesToTimestamp = 0; - - 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 - params.byte1 = hours;//h - params.byte2 = minutes;//m - params.byte3 = seconds;//s - params.byte4 = 0; - params.recipient = recipient; - params.register = 87;//Actual time - params.rw = 1;//write - - let timestampStart = priorityTypes.node_broadcast; - - //other values - params.type = "cmd"; - //params.tbname = tbname; - params.timestamp = timestampStart; - params.addMinutesToTimestamp = addMinutesToTimestamp; - params.info = "run broadcast: Actual time"; - - tasks.push(params); - - let sec = 3; - setTimeout(function(){ - //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel - - for (let k in nodesData) { - - //potrebujem nody k danej linii - if(line == nodesData[k].line || line == undefined) - { - let tbname = nodesData[k].tbname; - let node = nodesData[k].node; - - //prud, vykon - current, input power pre liniu pre vsetky nody - - //a pridame aj vyreportovanie dimmingu - { - let params = getParams(priorityTypes.high_priority); - - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 1;//dimming - params.recipient = 1;//slave - params.rw = 0;//read - params.timestamp = priorityTypes.high_priority; - params.info = 'read dimming / brightness (after set dimming from platform)'; - //params.debug = true; - - tasks.push(params); - } - - //Prúd - { - let params = getParams(priorityTypes.high_priority); - - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 75;//prud - params.recipient = 1;//slave - params.rw = 0;//read - params.timestamp = priorityTypes.high_priority; - params.info = 'read current (after set dimming from platform)'; - //params.debug = true; - - tasks.push(params); - } - - //výkon - { - let params = getParams(priorityTypes.high_priority); - - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 76;//výkon - params.recipient = 1;//slave - params.rw = 0;//read - params.timestamp = priorityTypes.high_priority; - params.info = 'read power (after set dimming from platform)'; - //params.debug = true; - - tasks.push(params); - } - - } - } - - },sec*1000); - + address = 0xffffffff;//Broadcast } + var d = new Date(); + let hours = d.getHours(); + let minutes = d.getMinutes(); + let seconds = d.getSeconds(); + + params.address = address;//broadcast + params.byte1 = hours;//h + params.byte2 = minutes;//m + params.byte3 = seconds;//s + params.byte4 = 0; + params.recipient = recipient; + params.register = 87;//Actual time + params.rw = 1;//write + + let timestampStart = PRIORITY_TYPES.node_broadcast; + + //other values + params.type = "cmd"; + //params.tbname = tbname; + params.timestamp = timestampStart; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + + let sec = 3; + setTimeout(function(){ + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + for (let k in nodesData) { + + //potrebujem nody k danej linii + if(line == nodesData[k].line || line == undefined) + { + let tbname = nodesData[k].tbname; + let node = nodesData[k].node; + + //prud, vykon - current, input power pre liniu pre vsetky nody + + //a pridame aj vyreportovanie dimmingu + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + //Prúd + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read current'; + //params.debug = true; + + tasks.push(params); + } + + //výkon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + } + } + },sec*1000); } + function reportOfflineNodeStatus(line) { - logger.debug("--->reportOfflineNodeStatus for line", line); values = {}; @@ -970,7 +910,7 @@ exports.install = function(instance) { ] } - //instance.send(instanceSendTo.tb, dataToTb); + //instance.send(SEND_TO.tb, dataToTb); tbHandler.sendToTb(dataToTb, instance); } } @@ -982,40 +922,35 @@ exports.install = function(instance) { //values["status"] = "OFFLINE";//prúd } - let now = new Date(); - console.log("CMD Manager installed", now.toLocaleString("sk-SK")); function turnOnLine(line, info) { let obj = { - line: line, - command: "turnOn", - info: info + line: line, + command: "turnOn", + info: info }; logger.debug("linia", line, obj); - - instance.send(instanceSendTo.dido_controller, obj); + instance.send(SEND_TO.dido_controller, obj); } function turnOffLine(line, info) { let obj = { - line: line, - command: "turnOff", - info: info - }; + line: line, + command: "turnOff", + info: info + }; - logger.debug("linia", line, obj); - - instance.send(instanceSendTo.dido_controller, obj); + logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); } + function detectIfResponseIsValid(bytes) { - //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK - let type = "RESPONSE"; if(bytes[4] == 0) type = "RESPONSE"; else if(bytes[4] == 1) type = "ERROR"; @@ -1033,7 +968,7 @@ exports.install = function(instance) { //CRC_ERROR message = "NOK"; error = "CRC_ERROR c1"; - instance.send(instanceSendTo.debug, "CRC_ERROR c1"); + instance.send(SEND_TO.debug, "CRC_ERROR c1"); } if(c2 != bytes[10]) @@ -1041,16 +976,16 @@ exports.install = function(instance) { //CRC_ERROR message = "NOK"; error = "CRC_ERROR c2"; - instance.send(instanceSendTo.debug, "CRC_ERROR c2"); + instance.send(SEND_TO.debug, "CRC_ERROR c2"); } //crc error if(type != "RESPONSE") { - instance.send(instanceSendTo.debug, bytes); - instance.send(instanceSendTo.debug, "RESPONSE " + type + " - " + bytes[4]); + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); - //logger.debug(instanceSendTo.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); error = "type is: " + type; @@ -1060,16 +995,16 @@ exports.install = function(instance) { return {message: message, type: type, error: error}; } + + //BUILD TASKS// function buildTasks(params) { - //report FLOW.OMS_edge_fw_version as fw_version //report date as startdate monitor.info("buildTasks - params", params); let processLine; //defined line - let init = false; let processLineProfiles = true; let processBroadcast = true; @@ -1079,7 +1014,6 @@ exports.install = function(instance) { { init = true; tasks = []; - logger.debug("-->buildTasks clear tasks"); } else @@ -1103,12 +1037,12 @@ exports.install = function(instance) { let keys = Object.keys(relaysData); for(let i = 0; i < keys.length; i++) { - let line = keys[i];//line is turned off by default + let line = parseInt(keys[i]); //line is turned off by default let profilestr = relaysData[line].profile; //Reset linii let resetLine = false; - if(FLOW.OMS_rvo_name == "Kovalov RVO 2" && line != '0' && init == true) resetLine = true; + if(FLOW.OMS_rvo_name == "Kovalov RVO 2" && line != 0 && init == true) resetLine = true; if(resetLine) { @@ -1116,18 +1050,18 @@ exports.install = function(instance) { Takže v Koválove sú nastavené offesty pre dusk a dawn nasledovne: - DUSK: offset +20 minút – teda napr. namiesto 17:00 bude 17:20 a reštart by sa robil v čase 17:19, teda o minútu skôr. Tak aby keď budeš robiť zapnutie o 17:20 tak na RVO1 sa svietidlá zapnú v rovnakom čase. Teda: vypnutie v čase DUSK_TIME + 19 minút, zapnutie v čase DUSK_TIME + 20 minút + DUSK: offset +20 minút – teda napr. namiesto 17:00 bude 17:20 a reštart by sa robil v čase 17:19, teda o minútu skôr. Tak aby keď budeš robiť zapnutie o 17:20 tak na RVO1 sa svietidlá zapnú v rovnakom čase. + Teda: vypnutie v čase DUSK_TIME + 19 minút, zapnutie v čase DUSK_TIME + 20 minút DAWN: offset -30 minút – teda napr. namiesto 7:00 bude 6:30 a reštart by sa robil v čase 6:30, tak aby sa svietidlá zhasli rovnako s RVO1. Zapnutie by bolo 6:31. - - Teda: vypnutie v čase DAWN_TIME -30 minút, zapnutie v čase DAWN_TIME -29 minút + Teda: vypnutie v čase DAWN_TIME -30 minút, zapnutie v čase DAWN_TIME -29 minút Vždy po reštarte asi 30 sekúnd po zapnutí treba poslať aktuálny čas na nody. */ - //function calculateDuskDown(date, line, duskOffset = 0, dawnOffset = 0) + //function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) let duskOffset = 20; let dawnOffset = -30; - let sunCalcResult = calculateDuskDown(new Date(), undefined, duskOffset, dawnOffset); + let sunCalcResult = calculateDuskDawn(new Date(), undefined, duskOffset, dawnOffset); console.log(sunCalcResult); monitor.info("--> dusk - dawn", sunCalcResult); @@ -1141,13 +1075,11 @@ exports.install = function(instance) { //vypneme liniu a o minitu zapneme { let value = 0;//vypneme liniu - let isDusk = true; - let isDawn = false; let dusk_time = sunCalcResult.dusk_time; if(dusk_time < now.getTime()) dusk_time = dusk_time + 24*60*60*1000;//1den - let params = getParams(priorityTypes.relay_profile); + let params = getParams(PRIORITY_TYPES.relay_profile); params.type = "relay"; params.line = line; params.value = value; @@ -1160,8 +1092,7 @@ exports.install = function(instance) { params.addMinutesToTimestamp = 24*60; //this will be recalculated - params.isDusk = isDusk; - params.isDawn = isDawn; + params.timePointName = "dusk" if(params.value == 0) params.info = "reset - KOVALOV - force turn off line: " + line; else if(params.value == 1) params.info = "reset - KOVALOV - force turn on line: " + line; @@ -1177,13 +1108,11 @@ exports.install = function(instance) { //a o minutu zapneme { let value = 1;//zapneme liniu - let isDusk = true; - let isDawn = false; let dusk_time = sunCalcResult.dusk_time + 60*1000;//o minutu neskor po vypnuti zapneme if(dusk_time < now.getTime()) dusk_time = dusk_time + 24*60*60*1000;//1den - let params = getParams(priorityTypes.relay_profile); + let params = getParams(PRIORITY_TYPES.relay_profile); params.type = "relay"; params.line = line; params.value = value; @@ -1196,8 +1125,7 @@ exports.install = function(instance) { params.addMinutesToTimestamp = 24*60; //this will be recalculated - params.isDusk = isDusk; - params.isDawn = isDawn; + params.timePointName = "dusk" if(params.value == 0) params.info = "reset - KOVALOV - force turn off line: " + line; else if(params.value == 1) params.info = "reset - KOVALOV - force turn on line: " + line; @@ -1218,13 +1146,11 @@ exports.install = function(instance) { //vypneme liniu a o minitu zapneme { let value = 0;//vypneme liniu - let isDusk = false; - let isDawn = true; let dawn_time = sunCalcResult.dawn_time; if(dawn_time < now.getTime()) dawn_time = dawn_time + 24*60*60*1000;//1den - let params = getParams(priorityTypes.relay_profile); + let params = getParams(PRIORITY_TYPES.relay_profile); params.type = "relay"; params.line = line; params.value = value; @@ -1238,8 +1164,7 @@ exports.install = function(instance) { params.addMinutesToTimestamp = 24*60; //this will be recalculated - params.isDusk = isDusk; - params.isDawn = isDawn; + params.timePointName = "dawn"; if(params.value == 0) params.info = "reset - KOVALOV - force turn off line: " + line; else if(params.value == 1) params.info = "reset - KOVALOV - force turn on line: " + line; @@ -1255,13 +1180,11 @@ exports.install = function(instance) { //a o minitu zapneme { let value = 1;//vypneme liniu - let isDusk = false; - let isDawn = true; let dawn_time = sunCalcResult.dawn_time + 1000*60;//o minutu neskor po vypnuti zapneme if(dawn_time < now.getTime()) dawn_time = dawn_time + 24*60*60*1000;//1den - let params = getParams(priorityTypes.relay_profile); + let params = getParams(PRIORITY_TYPES.relay_profile); params.type = "relay"; params.line = line; params.value = value; @@ -1275,8 +1198,7 @@ exports.install = function(instance) { params.addMinutesToTimestamp = 24*60; //this will be recalculated - params.isDusk = isDusk; - params.isDawn = isDawn; + params.timePointName = "dawn"; if(params.value == 0) params.info = "reset - KOVALOV - force turn off line: " + line; else if(params.value == 1) params.info = "reset - KOVALOV - force turn on line: " + line; @@ -1300,11 +1222,11 @@ exports.install = function(instance) { if(processLine != line) continue; } - try{ + try { - if(profilestr === "") throw ("profile is not defined"); + if(profilestr === "") throw ("Profile is not defined"); let profile = JSON.parse(profilestr); - if(Object.keys(profile).length === 0) throw ("profile is not defined"); + if(Object.keys(profile).length === 0) throw ("Profile is empty"); monitor.info("buildTasks: profile for line", line); monitor.info("profile:", profile); @@ -1312,52 +1234,61 @@ exports.install = function(instance) { let time_points = profile.time_points; if(time_points == undefined) time_points = profile.intervals; + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + //monitor.info("buildTasks: time_points", time_points); let currentValue = 0; - if(time_points.length > 0) currentValue = time_points[ time_points.length - 1].value; + if(time_points.length > 0) currentValue = time_points[time_points.length - 1].value; - //create task for tun on + turn off, calculate dusk/down + /** + * if astro_clock is true, we create timepoints, that switch on/off relays accordingly. + * we need to manage, astro clock timepoints has the greatest priority - normal timepoints will not switch off/on lines before dusk or dawn + * if dawn/dusk_lux_sensor is true, it has higher priority than astro_clock switching + */ if(profile.astro_clock == true) { - //let now = new Date().toLocaleString("en-US", {timeZone: "Europe/Bratislava"}); - let sunCalcResult = calculateDuskDown(new Date(), line); - // monitor.info("dusk and dawn sunCalcResult", line, sunCalcResult); + // if astro clock true, we remove all regular profile points + time_points = []; - //add to timpoints - if(profile.dawn_lux_sensor == false) time_points.push( {"start_time": sunCalcResult["dawn"], "value": 1, "isDawn": true} ); - if(profile.dusk_lux_sensor == false) time_points.push( {"start_time": sunCalcResult["dusk"], "value": 0, "isDusk": true} ); + let sunCalcResult = calculateDuskDawn(new Date(), line); - //aby nam to neostalo svietit + // adding dusk dawn to timpoints + if(profile.dawn_lux_sensor == false) time_points.push({"start_time": sunCalcResult["dawn"], "value": 0, "name":"dawn"}); + if(profile.dusk_lux_sensor == false) time_points.push({"start_time": sunCalcResult["dusk"], "value": 1, "name":"dusk"}); + + //if dusk/dawn is true, lines will switch on/off according to lux_sensor value. In case it fails, we create lux_timepoints, to make sure lines will switch on/off (aby nam to nezostalo svietit) + //force to turn off after timestamp: dawn + dawn_lux_sensor_time_window if(profile.dawn_lux_sensor == true) { - //force to turn off after timestamp: dawn + dawn_lux_sensor_time_window let [ahours, aminutes, aseconds] = sunCalcResult["dawn"].split(':'); - let ad = new Date(); - ad.setHours( parseInt(ahours) ); - ad.setMinutes( parseInt(aminutes) + profile.dawn_lux_sensor_time_window ); + ad.setHours(parseInt(ahours)); + ad.setMinutes(parseInt(aminutes) + profile.dawn_lux_sensor_time_window); ad.setSeconds(0); let strDate = ad.getHours() + ":" + ad.getMinutes(); - time_points.push( {"value": 0, "start_time": strDate} ); + time_points.push({"value": 0, "start_time": strDate, "name": "luxOff"}); } if(profile.dusk_lux_sensor == true) { - //force to turn off after timestamp: dawn + dawn_lux_sensor_time_window let [ahours, aminutes, aseconds] = sunCalcResult["dusk"].split(':'); - let ad = new Date(); - ad.setHours( parseInt(ahours) ); - ad.setMinutes( parseInt(aminutes) + profile.dawn_lux_sensor_time_window ); + ad.setHours(parseInt(ahours)); + ad.setMinutes(parseInt(aminutes) + profile.dusk_lux_sensor_time_window); ad.setSeconds(0); let strDate = ad.getHours() + ":" + ad.getMinutes(); - time_points.push( {"value": 1, "start_time": strDate} ); + time_points.push({"value": 1, "start_time": strDate, "name": "luxOn"}); + //time_points.push({"value": 1, "start_time": "15:19", "name": "luxOn"}); //testing } } @@ -1380,76 +1311,57 @@ exports.install = function(instance) { return ad.getTime() - bd.getTime(); }); + console.log("line timepoints ........", time_points); + monitor.info("-->comming events turn on/off lines:"); for(let t = 0; t < time_points.length; t++) { let start_time = new Date(); + let [hours, minutes, seconds] = time_points[t].start_time.split(':'); - let isDusk = false; - let isDawn = false; - if(time_points[t].hasOwnProperty("isDusk")) isDusk = time_points[t].isDusk; - if(time_points[t].hasOwnProperty("isDawn")) isDawn = time_points[t].isDawn; - - if(isDusk) time_points[t].value = 1;//sumrak - zapneme svetlo - if(isDawn) time_points[t].value = 0;//vychod - vypneme svetlo - - if(time_points[t].hasOwnProperty("start_time")) - { - let [hours, minutes, seconds] = time_points[t].start_time.split(':'); - - start_time.setHours( parseInt(hours) ); - start_time.setMinutes( parseInt(minutes) ); - start_time.setSeconds(0); - } + start_time.setHours( parseInt(hours) ); + start_time.setMinutes( parseInt(minutes) ); + start_time.setSeconds(0); //task is the past if(now.getTime() > start_time.getTime()) { currentValue = time_points[t].value; - //je v minulosti, pridame 24h + //timepoint is in past, we add 24 hours start_time.setDate(start_time.getDate() + 1); } - let params = getParams(priorityTypes.relay_profile); + let params = getParams(PRIORITY_TYPES.relay_profile); params.type = "relay"; - params.line = line; + params.line = parseInt(line); params.value = time_points[t].value; params.tbname = relaysData[line].tbname; params.timestamp = start_time.getTime(); params.addMinutesToTimestamp = 0; - //once a day - if(!isDusk && !isDawn) params.addMinutesToTimestamp = 24*60; + // it timepoints are not calculated (dawn, dusk, lux_timepoint), but static points in line profile, we just repeat the task every day + if(time_points[t].name == "profileTimepoint") params.addMinutesToTimestamp = 24*60; - //inak sa cas vypocita dynamicky + //astro timepoints will be recalculated dynamically: + params.timePointName = time_points[t].name; - //this will be recalculated - params.isDusk = isDusk; - params.isDawn = isDawn; - - //if(profile.astro_clock == true && profile.dusk_lux_sensor == false && profile.dawn_lux_sensor == false) - - if(params.value == 0) + // if astro timepoint, we save time window: + if(['luxOn', 'luxOff', 'dusk','dawn'].includes(params.timePointName)) { - params.info = "turn off line: " + line; - if(isDusk) params.info = "dusk: turn off line: " + line; - if(isDawn) params.info = "dawn: turn off line: " + line; - } - else if(params.value == 1) - { - params.info = "turn on line: " + line; - if(isDusk) params.info = "dusk: turn on line: " + line; - if(isDawn) params.info = "dawn: turn on line: " + line; + params.dawn_lux_sensor_time_window = profile.dawn_lux_sensor_time_window; + params.dusk_lux_sensor_time_window = profile.dusk_lux_sensor_time_window; } + if(params.value == 0) params.info = `${params.timePointName}: turn off line: ` + line; + else if(params.value == 1) params.info = `${params.timePointName}: turn on line: ` + line; + params.debug = true; //turn on/off line tasks.push(params); - monitor.info(params.info, start_time); } @@ -1457,15 +1369,13 @@ exports.install = function(instance) { monitor.info("-->time_points final", line, time_points); //ensure to turn on/off according to calculated value - let params = getParams(priorityTypes.terminal); + let params = getParams(PRIORITY_TYPES.terminal); params.type = "relay"; params.line = parseInt(line); params.tbname = relaysData[line].tbname; params.value = currentValue; - params.isDusk = false; - params.isDawn = false; - params.timestamp = priorityTypes.terminal; + params.timestamp = PRIORITY_TYPES.terminal; params.addMinutesToTimestamp = 0; params.debug = true; @@ -1478,7 +1388,6 @@ exports.install = function(instance) { tasks.push(params); - } catch (error) { if(profilestr !=="" ) { @@ -1509,7 +1418,7 @@ exports.install = function(instance) { // addMinutesToTimestamp = 60*5; addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk - let params = getParams(priorityTypes.node_broadcast); + let params = getParams(PRIORITY_TYPES.node_broadcast); let recipient = 2;//2 broadcast, address = 0 let address = 0;//0 @@ -1518,7 +1427,7 @@ exports.install = function(instance) { address = 0xffffffff;//Broadcast } - let sunCalcResult = calculateDuskDown(); + let sunCalcResult = calculateDuskDawn(); let dusk_hours = sunCalcResult["dusk_hours"]; let dusk_minutes = sunCalcResult["dusk_minutes"]; @@ -1531,7 +1440,7 @@ exports.install = function(instance) { params.register = 6;//Time of dusk - Reg 6 params.rw = 1;//write - let timestampStart = priorityTypes.node_broadcast; + let timestampStart = PRIORITY_TYPES.node_broadcast; //other values params.type = "cmd"; @@ -1550,7 +1459,7 @@ exports.install = function(instance) { // addMinutesToTimestamp = 60*5; addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn - let params = getParams(priorityTypes.node_broadcast); + let params = getParams(PRIORITY_TYPES.node_broadcast); let recipient = 2;//2 broadcast, address = 0 let address = 0;//0 @@ -1559,7 +1468,7 @@ exports.install = function(instance) { address = 0xffffffff;//Broadcast } - let sunCalcResult = calculateDuskDown(); + let sunCalcResult = calculateDuskDawn(); let dawn_hours = sunCalcResult["dawn_hours"]; let dawn_minutes = sunCalcResult["dawn_minutes"]; @@ -1572,7 +1481,7 @@ exports.install = function(instance) { params.register = 7;//Time of dawn - Reg 6 params.rw = 1;//write - let timestampStart = priorityTypes.node_broadcast; + let timestampStart = PRIORITY_TYPES.node_broadcast; //other values params.type = "cmd"; @@ -1589,7 +1498,7 @@ exports.install = function(instance) { //run broadcast //Actual time addMinutesToTimestamp = 5; - let params = getParams(priorityTypes.node_broadcast); + let params = getParams(PRIORITY_TYPES.node_broadcast); let recipient = 2;//2 broadcast, address = 0 let address = 0;//0 @@ -1612,7 +1521,7 @@ exports.install = function(instance) { params.register = 87;//Actual time params.rw = 1;//write - let timestampStart = priorityTypes.node_broadcast; + let timestampStart = PRIORITY_TYPES.node_broadcast; //other values params.type = "cmd"; @@ -1631,7 +1540,7 @@ exports.install = function(instance) { //Do tohto registra posiela riadiaca jednotka hodnotu intenzity osvetlenia ktorú meria jej senzor pre potreby riadenia časov súmraku resp. úsvitu podľa intenzity osvetlenia. //Byty 0 (LSB) a 1 obsahujú 16 bitový integer s luxami. - let params = getParams(priorityTypes.node_broadcast); + let params = getParams(PRIORITY_TYPES.node_broadcast); addMinutesToTimestamp = 15; @@ -1646,7 +1555,7 @@ exports.install = function(instance) { //16 bitový integer s luxami params.byte3 = lux_sensor; params.byte4 = lux_sensor; - params.timestamp = priorityTypes.node_broadcast; + params.timestamp = PRIORITY_TYPES.node_broadcast; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "run broadcast: Actual Lux level from cabinet"; params.register = 95;//Actual Lux level from cabinet @@ -1671,7 +1580,7 @@ exports.install = function(instance) { { register = listOfCommands[i]; - let params = getParams(priorityTypes.node_cmd); + let params = getParams(PRIORITY_TYPES.node_cmd); //core rpc values params.address = address; @@ -1685,7 +1594,7 @@ exports.install = function(instance) { let addMinutesToTimestamp = priorities[register]; - let timestampStart = priorityTypes.node_cmd; //run imediatelly in function runTasks + let timestampStart = PRIORITY_TYPES.node_cmd; //run imediatelly in function runTasks if(addMinutesToTimestamp > 1) { timestampStart = timestampStart + addMinutesToTimestamp * 60000; @@ -1724,12 +1633,12 @@ exports.install = function(instance) { //Adresa mastera je 0. V prípade že kedykoľvek nastane situácia že Master Node neodpovedá (napríklad pri vyčítaní telemetrie z nodu nevráti žiadne dáta), //tak treba vyreportovať string "NOK". { - let params = getParams(priorityTypes.fw_detection); + let params = getParams(PRIORITY_TYPES.fw_detection); params.type = "cmd"; params.register = 4; params.address = 0; - let timestampStart = priorityTypes.fw_detection; + let timestampStart = PRIORITY_TYPES.fw_detection; params.timestamp = timestampStart; params.addMinutesToTimestamp = 5; params.tbname = FLOW.OMS_edgeName; @@ -1743,10 +1652,10 @@ exports.install = function(instance) { //kazdu hodinu skontrolovat nastavenie profilov { - let params = getParams(priorityTypes.fw_detection); + let params = getParams(PRIORITY_TYPES.fw_detection); params.type = "process_profiles"; - let timestampStart = priorityTypes.relay_profile; + let timestampStart = PRIORITY_TYPES.relay_profile; params.timestamp = timestampStart; params.addMinutesToTimestamp = 60;//60 = every hour params.info = "detekcia nespracovaných profilov linie a nodov"; @@ -1758,10 +1667,10 @@ exports.install = function(instance) { { //edge_date_time - let params = getParams(priorityTypes.node_cmd); + let params = getParams(PRIORITY_TYPES.node_cmd); params.type = "edge_date_time"; - let timestampStart = priorityTypes.node_cmd; + let timestampStart = PRIORITY_TYPES.node_cmd; params.timestamp = timestampStart; params.addMinutesToTimestamp = 1; params.tbname = FLOW.OMS_edgeName; @@ -1773,10 +1682,10 @@ exports.install = function(instance) { { //edge_date_time - let params = getParams(priorityTypes.node_cmd); + let params = getParams(PRIORITY_TYPES.node_cmd); params.type = "number_of_luminaires"; - let timestampStart = priorityTypes.node_cmd + 1; + let timestampStart = PRIORITY_TYPES.node_cmd + 1; params.timestamp = timestampStart; params.addMinutesToTimestamp = 1; params.tbname = FLOW.OMS_edgeName; @@ -1788,6 +1697,7 @@ exports.install = function(instance) { monitor.info("tasks created:", tasks.length); } + function turnOnOffLinesAccordingToLuxSensor(lux_sensor_value) { //let dusk_hours = sunCalcResult["dusk_hours"]; @@ -1832,7 +1742,7 @@ exports.install = function(instance) { if(profile.astro_clock == true) { - let sunCalcResult = calculateDuskDown(now, line); + let sunCalcResult = calculateDuskDawn(now, line); //dawn: usvit/vychod - lux je nad hranicou - vypnem //dusk: zapad pod hranicou - zapnem @@ -1905,14 +1815,6 @@ exports.install = function(instance) { } } - let sunCalcResult = calculateDuskDown(); - - let reportDuskDawn = { - dusk_time: sunCalcResult.dusk_time, - dawn_time: sunCalcResult.dawn_time, - dusk_time_reported: undefined, - dawn_time_reported: undefined - }; async function upateNodeStatus(node, status) { @@ -1937,10 +1839,10 @@ exports.install = function(instance) { }); } } - + async function runTasks() { - + clearInterval(interval); let currentTimestamp = Date.now(); @@ -1954,7 +1856,7 @@ exports.install = function(instance) { //reportovali sme? if(reportDuskDawn.dusk_time_reported != sunCalcResult.dusk_time) { - sendNotification("CMD Manager: calculated Time of dusk", FLOW.OMS_edgeName, "dusk_has_occured", {value: sunCalcResult["dusk"]}, "", instanceSendTo.tb, instance); + sendNotification("CMD Manager: calculated Time of dusk", FLOW.OMS_edgeName, "dusk_has_occured", {value: sunCalcResult["dusk"]}, "", SEND_TO.tb, instance); reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; } } @@ -1962,7 +1864,7 @@ exports.install = function(instance) { var nextDay = new Date(); nextDay.setDate(nextDay.getDate() + 1); - sunCalcResult = calculateDuskDown(nextDay); + sunCalcResult = calculateDuskDawn(nextDay); reportDuskDawn.dusk_time = sunCalcResult.dusk_time; } @@ -1974,7 +1876,7 @@ exports.install = function(instance) { //reportovali sme? if(reportDuskDawn.dawn_time_reported != sunCalcResult.dawn_time) { - sendNotification("CMD Manager: calculated Time of dawn", FLOW.OMS_edgeName, "dawn_has_occured", {value: sunCalcResult["dawn"]}, "", instanceSendTo.tb, instance); + sendNotification("CMD Manager: calculated Time of dawn", FLOW.OMS_edgeName, "dawn_has_occured", {value: sunCalcResult["dawn"]}, "", SEND_TO.tb, instance); reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; } } @@ -1982,39 +1884,32 @@ exports.install = function(instance) { var nextDay = new Date(); nextDay.setDate(nextDay.getDate() + 1); - sunCalcResult = calculateDuskDown(nextDay); + sunCalcResult = calculateDuskDawn(nextDay); reportDuskDawn.dawn_time = sunCalcResult.dawn_time; } //-------------------------------------------------------- - //sort tasks - //tasks.sort((a,b) => a.timestamp - b.timestamp ); - + //sort tasks based on timestamp tasks.sort(function (a, b) { - if(a.timestamp <= currentTimestamp && b.timestamp <= currentTimestamp) { return a.priority - b.priority; } - return a.timestamp - b.timestamp; }); if(tasks.length == 0 ) { - instance.send(instanceSendTo.debug, "no tasks created"); - interval = setInterval(runTasks, longInterval); - + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); return; } if(!rsPort.isOpen) { - instance.send(instanceSendTo.debug, "!rsPort.isOpen"); + instance.send(SEND_TO.debug, "!rsPort.isOpen"); //await rsPort.open(); - - //continue } let currentTask = tasks[0]; @@ -2028,47 +1923,36 @@ exports.install = function(instance) { { let params = {...tasks[0]}; - if(FLOW.OMS_maintenance_mode) + //allow terminal commands + if(FLOW.OMS_maintenance_mode && params.type !== "cmd-terminal") { - - //allow terminal commands - if(params.type == "cmd-terminal"); - else - { - interval = setInterval(runTasks, longInterval); - return; - } + interval = setInterval(runTasks, LONG_INTERVAL); + return; } let type = params.type; let tbname = params.tbname; let nodeKey = params.address; - let useProfile = params.useProfile; - if(useProfile === undefined) useProfile = true; - let duskOffset = params.duskOffset; - let dawnOffset = params.dawnOffset; - let line = null; + //rpc related if(nodesData[nodeKey] !== undefined) line = nodesData[nodeKey].line; if(params.line !== undefined) line = params.line; let repeatTask = false; - if(params.addMinutesToTimestamp > 0) repeatTask = true; - if(params.isDawn || params.isDusk) repeatTask = true; + if(params.addMinutesToTimestamp > 0 || params.timePointName) repeatTask = true; if(repeatTask) { - if(type == "cmd") + if(type === "cmd") { //set next start time automatically tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; - } + } } else { - //terminal data... tasks.shift(); } @@ -2114,17 +1998,16 @@ exports.install = function(instance) { ] } - //instance.send(instanceSendTo.tb, dataToTb); + //instance.send(SEND_TO.tb, dataToTb); tbHandler.sendToTb(dataToTb, instance); - interval = setInterval(runTasks, shortIterval); + interval = setInterval(runTasks, SHORT_INTERVAL); return; } } - //kontrola nespracovanych profilov nodov if(type == "process_profiles") { @@ -2160,7 +2043,7 @@ exports.install = function(instance) { //vsetky linie kt. su zapnute, a spracuju sa nespracovane profily nodov loadRelaysData(); - interval = setInterval(runTasks, shortIterval); + interval = setInterval(runTasks, SHORT_INTERVAL); return; } @@ -2186,10 +2069,10 @@ exports.install = function(instance) { tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; - //instance.send(instanceSendTo.tb, dataToTb); + //instance.send(SEND_TO.tb, dataToTb); tbHandler.sendToTb(dataToTb, instance); - interval = setInterval(runTasks, shortIterval); + interval = setInterval(runTasks, SHORT_INTERVAL); return; } @@ -2198,56 +2081,69 @@ exports.install = function(instance) { if(type == "relay") { - //ak je dusk, alebo dawn, vypocitame si dynamicky nove values - if(params.isDawn || params.isDusk) + const timePointName = params.timePointName; + const value = params.value; + + // used just in Kovalov RVO 2 + const useProfile = params.useProfile; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if(!useProfile) { - let date = new Date(); - date.setDate(date.getDate() + 1);//next day - - let sunCalcResult; - if(useProfile) sunCalcResult = calculateDuskDown(date, params.line); - else - { - //do not use profile, line is there for undefined - sunCalcResult = calculateDuskDown(date, undefined, duskOffset, dawnOffset); - } - - if(params.isDawn) - { - tasks[0].timestamp = sunCalcResult.dawn_time; - } - - if(params.isDusk) - { - tasks[0].timestamp = sunCalcResult.dusk_time; - } + sunCalcResult = calculateDuskDawn(date, params.line); } else { - if(tasks[0].addMinutesToTimestamp == 0);// tasks.shift(); - else tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + //do not use profile, line is there for undefined + sunCalcResult = calculateDuskDawn(date, undefined, params.duskOffset, params.dawnOffset); } + if(timePointName == "dawn") + { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if(timePointName == "dusk") + { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if(timePointName == "luxOn") + { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if(timePointName == "luxOff") + { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if(timePointName == "profileTimepoint") + { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + //monitor.info("new relay timepoint sunCalcResult ,,,,,,,,,,", sunCalcResult); + let info; - if(useProfile) info = "aplikovaný bod profilu"; - else info = params.info; + if(!useProfile) info = "aplikovaný bod profilu"; + else info = params.info; //kovalov rvo params.info let message = ""; - if(params.value == 1) + if(value == 1) { turnOnLine(params.line, info); message = "on"; } - else if(params.value == 0) + else if(value == 0) { turnOffLine(params.line, info); message = "off"; } - //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.INFO, "aplikovaný bod profilu línie " + params.line + " - stav: " + message, "", instanceSendTo.tb, instance, null ); - if(useProfile) sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "switching_profile_point_applied_to_line", {line: params.line, value: message}, "", instanceSendTo.tb, instance ); + //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.INFO, "aplikovaný bod profilu línie " + params.line + " - stav: " + message, "", SEND_TO.tb, instance, null ); + if(!useProfile) sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "switching_profile_point_applied_to_line", {line: params.line, value: message}, "", SEND_TO.tb, instance ); - interval = setInterval(runTasks, shortIterval); + interval = setInterval(runTasks, SHORT_INTERVAL); return; } @@ -2285,11 +2181,11 @@ exports.install = function(instance) { if(!disconnectedReport[tbname]) { - //instance.send(instanceSendTo.tb, dataToTb); + //instance.send(SEND_TO.tb, dataToTb); tbHandler.sendToTb(dataToTb, instance); } - interval = setInterval(runTasks, shortIterval); + interval = setInterval(runTasks, SHORT_INTERVAL); return; } @@ -2310,10 +2206,9 @@ exports.install = function(instance) { if(stop) { - interval = setInterval(runTasks, longInterval); + interval = setInterval(runTasks, LONG_INTERVAL); return; } - } let relayStatus = 1; @@ -2341,17 +2236,16 @@ exports.install = function(instance) { ] } - //instance.send(instanceSendTo.tb, dataToTb); + //instance.send(SEND_TO.tb, dataToTb); tbHandler.sendToTb(dataToTb, instance); - interval = setInterval(runTasks, shortIterval); - + interval = setInterval(runTasks, SHORT_INTERVAL); return; } if(!rsPort.isOpen) { - interval = setInterval(runTasks, longInterval); + interval = setInterval(runTasks, LONG_INTERVAL); return; } @@ -2370,15 +2264,14 @@ exports.install = function(instance) { params.byte4 = 0; } - //set dusk/down for broadcast - + //SET DUSK/DAWN FOR BROADCAST //Time of dusk if(params.register == 6 && params.recipient === 2) { if(params.type != "cmd-terminal") { - let sunCalcResult = calculateDuskDown(); + let sunCalcResult = calculateDuskDawn(); let dusk_hours = sunCalcResult["dusk_hours"]; let dusk_minutes = sunCalcResult["dusk_minutes"]; @@ -2389,7 +2282,7 @@ exports.install = function(instance) { //TODO astrohodiny let dusk = "Time of dusk: " + sunCalcResult["dusk"]; - //sendNotification("CMD Manager: calculated Time of dusk", relaysData[0].tbname, ERRWEIGHT.INFO, dusk, "", instanceSendTo.tb, instance, null ); + //sendNotification("CMD Manager: calculated Time of dusk", relaysData[0].tbname, ERRWEIGHT.INFO, dusk, "", SEND_TO.tb, instance, null ); } } @@ -2398,7 +2291,7 @@ exports.install = function(instance) { { if(params.type != "cmd-terminal") { - let sunCalcResult = calculateDuskDown(); + let sunCalcResult = calculateDuskDawn(); let dawn_hours = sunCalcResult["dawn_hours"]; let dawn_minutes = sunCalcResult["dawn_minutes"]; @@ -2409,7 +2302,7 @@ exports.install = function(instance) { //TODO astrohodiny let dawn = "Time of dawn: " + sunCalcResult["dawn"]; - //sendNotification("CMD Manager: calculated Time of dusk", relaysData[0].tbname, ERRWEIGHT.INFO, dawn, "", instanceSendTo.tb, instance, null ); + //sendNotification("CMD Manager: calculated Time of dusk", relaysData[0].tbname, ERRWEIGHT.INFO, dawn, "", SEND_TO.tb, instance, null ); } } @@ -2417,26 +2310,14 @@ exports.install = function(instance) { let register = params.register; - instance.send(instanceSendTo.debug, "address: " + params.address + " register:" + params.register + "type: " + params.type); + instance.send(SEND_TO.debug, "address: " + params.address + " register:" + params.register + "type: " + params.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 readBytes = 11; - //if broadcast WRITE - do not read - //if(params.recipient == 2) readBytes = 0; - - //WRITE + BROADCAST = readBytes = 0; - // if(params.rw == 1 && params.recipient == 2) readBytes = 0; - - if(params.hasOwnProperty("debug")) - { - //console.log("--->readBytes", readBytes, params); - } - await writeData(rsPort, resp, readBytes).then(function (data) { endTime = new Date(); @@ -2496,7 +2377,7 @@ exports.install = function(instance) { builder.callback(function(err, response) { - sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "dimming_profile_was_successfully_received_by_node", {node: params.address}, "", instanceSendTo.tb, instance ); + sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "dimming_profile_was_successfully_received_by_node", {node: params.address}, "", SEND_TO.tb, instance ); logger.debug( "--> profil úspešne odoslaný na node č. " + params.address); nodesData[params.address].processed = true; @@ -2524,17 +2405,17 @@ exports.install = function(instance) { if(params.address == 0) { - //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.NOTICE, "Master node is working again", "", instanceSendTo.tb, instance, "rvo_status" ); - //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, "master_node_is_responding_again", {}, "", instanceSendTo.tb, instance, "rvo_status" ); - sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "master_node_is_responding_again", {}, "", instanceSendTo.tb, instance, "rvo_status" ); + //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" ); + sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "master_node_is_responding_again", {}, "", SEND_TO.tb, instance, "rvo_status" ); FLOW.OMS_masterNodeIsResponding = true; } //odoslanie príkazu z terminálu - dáta if(params.type == "cmd-terminal") { - //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.DEBUG, "odoslanie príkazu z terminálu", params, instanceSendTo.tb, instance, null ); - sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "command_was_sent_from_terminal_interface", {}, params, instanceSendTo.tb, instance ); + //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 ); } if(params.debug) @@ -2553,7 +2434,7 @@ exports.install = function(instance) { ] } - //instance.send(instanceSendTo.tb, dataToTb); + //instance.send(SEND_TO.tb, dataToTb); tbHandler.sendToTb(dataToTb, instance); } @@ -2574,11 +2455,11 @@ exports.install = function(instance) { responseObj["bytes"] = data; //params.refFlowdata.data = responseObj; - //instance.send(instanceSendTo.http_response, params.refFlowdata); + //instance.send(SEND_TO.http_response, params.refFlowdata); let refFlowdata = refFlowdataObj[ params.refFlowdataKey ]; refFlowdata.data = responseObj; - instance.send(instanceSendTo.http_response, refFlowdata); + instance.send(SEND_TO.http_response, refFlowdata); } else @@ -2607,13 +2488,13 @@ exports.install = function(instance) { responseObj["bytes"] = data; //params.refFlowdata.data = responseObj; - //instance.send(instanceSendTo.http_response, params.refFlowdata); + //instance.send(SEND_TO.http_response, params.refFlowdata); let refFlowdata = refFlowdataObj[ params.refFlowdataKey ]; if(refFlowdata !== undefined) { refFlowdata.data = responseObj; - instance.send(instanceSendTo.http_response, refFlowdata); + instance.send(SEND_TO.http_response, refFlowdata); } @@ -2634,7 +2515,7 @@ exports.install = function(instance) { responseObj["bytes"] = data; params.refFlowdata.data = responseObj; - instance.send(instanceSendTo.http_response, params.refFlowdata); + instance.send(SEND_TO.http_response, params.refFlowdata); } } @@ -2642,8 +2523,8 @@ exports.install = function(instance) { if(params.address == 0) { - //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.ALERT, "Master node not responding", "", instanceSendTo.tb, instance, "rvo_status"); - sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "master_node_is_not_responding", {}, "", instanceSendTo.tb, instance, "rvo_status"); + //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; } @@ -2655,8 +2536,8 @@ exports.install = function(instance) { 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, "", instanceSendTo.tb, instance, null ); - sendNotification("CMD Manager: process cmd", tbname, "configuration_of_dimming_profile_to_node_failed", {node: params.address}, "", instanceSendTo.tb, instance ); + //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? @@ -2682,11 +2563,11 @@ exports.install = function(instance) { ] } - //instance.send(instanceSendTo.tb, dataToTb); + //instance.send(SEND_TO.tb, dataToTb); tbHandler.sendToTb(dataToTb, instance); } - //instance.send(instanceSendTo.debug, result); + //instance.send(SEND_TO.debug, result); if(params.hasOwnProperty("debug")) { @@ -2716,13 +2597,13 @@ exports.install = function(instance) { responseObj["message"] = "ERROR WRITE FAILED: " + reason;// //params.refFlowdata.data = responseObj; - //instance.send(instanceSendTo.http_response, params.refFlowdata); + //instance.send(SEND_TO.http_response, params.refFlowdata); let refFlowdata = refFlowdataObj[ params.refFlowdataKey ]; if(refFlowdata !== undefined) { refFlowdata.data = responseObj; - instance.send(instanceSendTo.http_response, refFlowdata); + instance.send(SEND_TO.http_response, refFlowdata); } @@ -2742,7 +2623,7 @@ exports.install = function(instance) { //responseObj["bytes"] = data; params.refFlowdata.data = responseObj; - instance.send(instanceSendTo.http_response, params.refFlowdata); + instance.send(SEND_TO.http_response, params.refFlowdata); //refFlowdata = undefined; } @@ -2766,8 +2647,8 @@ exports.install = function(instance) { if(params.address == 0) { - //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.ALERT, "Master node not responding", "", instanceSendTo.tb, instance, "rvo_status"); - sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "master_node_is_not_responding", {}, "", instanceSendTo.tb, instance, "rvo_status"); + //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; @@ -2780,8 +2661,8 @@ exports.install = function(instance) { 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", "", instanceSendTo.tb, instance, null ); - sendNotification("CMD Manager: process cmd", tbname, "configuration_of_dimming_profile_to_node_failed", {node: params.address}, "", instanceSendTo.tb, instance ); + //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? @@ -2807,7 +2688,7 @@ exports.install = function(instance) { ] } - //instance.send(instanceSendTo.tb, dataToTb); + //instance.send(SEND_TO.tb, dataToTb); tbHandler.sendToTb(dataToTb, instance); FLOW.OMS_masterNodeIsResponding = false; @@ -2829,11 +2710,11 @@ exports.install = function(instance) { ] } - instance.send(instanceSendTo.tb, dataToTb); + instance.send(SEND_TO.tb, dataToTb); } */ - instance.send(instanceSendTo.debug, reason); + instance.send(SEND_TO.debug, reason); }); } @@ -2845,615 +2726,584 @@ exports.install = function(instance) { logger.debug("currentTask is not processed - task is in the future", currentTask); } - interval = setInterval(runTasks, longInterval); + interval = setInterval(runTasks, LONG_INTERVAL); return; } //console.log("----->runTasks - setInterval", new Date()); - interval = setInterval(runTasks, shortIterval); + interval = setInterval(runTasks, SHORT_INTERVAL); } + //! rsPort LM = "/dev/ttymxc4", rsPort UNIPI = "/dev/ttyUSB0" - // const rsPort = new SerialPort("/dev/ttymxc4", { autoOpen: false }); //LM - // const rsPort = new SerialPort("/dev/ttyUSB0", { autoOpen: false }); // UNIPI + // const rsPort = new SerialPort("/dev/ttymxc4", { autoOpen: false }); //LM + // const rsPort = new SerialPort("/dev/ttyUSB0", { autoOpen: false }); // UNIPI - if(FLOW.OMS_serial_port == "") FLOW.OMS_serial_port = "ttymxc4"; - if(FLOW.OMS_serial_port == undefined) FLOW.OMS_serial_port = "ttymxc4"; - if(FLOW.OMS_serial_port.length === 1) FLOW.OMS_serial_port = "ttymxc4"; - - const rsPort = new SerialPort(`/dev/${FLOW.OMS_serial_port}`, { autoOpen: false }); + if(FLOW.OMS_serial_port == "" || FLOW.OMS_serial_port == undefined || FLOW.OMS_serial_port.length === 1) FLOW.OMS_serial_port = "ttymxc4"; + const rsPort = new SerialPort(`/dev/${FLOW.OMS_serial_port}`, { autoOpen: false }); //(node:16372) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 13 data listeners added to [SerialPort]. Use emitter.setMaxListeners() to increase limit //rsPort.setMaxListeners(0); - rsPort.on('open', async function() { + rsPort.on('open', async function() { logger.debug("CMD manager - rsPort opened sucess"); - await loadRelaysData(); + loadRelaysData(); - await runSyncExec(`stty -F /dev/${FLOW.OMS_serial_port} 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke`).then(function (status) { - instance.send(instanceSendTo.debug, "RPC runSyncExec - Promise Resolved:" + status); + await runSyncExec(`stty -F /dev/${FLOW.OMS_serial_port} 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke`).then(function (status) { + instance.send(SEND_TO.debug, "RPC runSyncExec - Promise Resolved:" + status); - logger.debug(0, "RPC runSyncExec - Promise Resolved:" + status); + logger.debug(0, "RPC runSyncExec - Promise Resolved:" + status); - //APP START - let dataToInfoSender = {id: FLOW.OMS_projects_id, name: FLOW.OMS_rvo_name}; - dataToInfoSender.fw_version = FLOW.OMS_edge_fw_version; - dataToInfoSender.startdate = new Date().toISOString().slice(0, 19).replace('T', ' '); - dataToInfoSender.__force__ = true; - - instance.send(instanceSendTo.infoSender, dataToInfoSender); + //APP START + let dataToInfoSender = {id: FLOW.OMS_projects_id, name: FLOW.OMS_rvo_name}; + dataToInfoSender.fw_version = FLOW.OMS_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); + logger.debug(0, "---------------------------->START message send to service", dataToInfoSender); - //---- + }).catch(function (reason) { + instance.send(SEND_TO.debug, "CMD manager - RPC runSyncExec - promise rejected:" + reason); + }); + }); - nodesData = {}; - - dbNodes.find().make(function(builder) { - builder.callback(function(err, response) { - - for(let i = 0; i < response.length; i++) - { - let node = response[i]; - let key = node["node"]; - - nodesData[ key ] = node; - } - - //buildTasks(); - //interval = setInterval(runTasks, longInterval); - // console.log('******** nodesData',nodesData); - - }); - }); - - }).catch(function (reason) { - instance.send(instanceSendTo.debug, "CMD manager - RPC runSyncExec - promise rejected:" + reason); - }); - - }); - - rsPort.on('error', function(err) { + rsPort.on('error', function(err) { //TODO report to service!!! //errLogger.error(exports.title, "unable to open port", FLOW.OMS_serial_port, err.message); errorHandler.sendMessageToService([exports.title, "unable to open port", FLOW.OMS_serial_port, err.message], 0); - instance.send(instanceSendTo.debug, err.message); + instance.send(SEND_TO.debug, err.message); }); - rsPort.on("close", () => { - rsPort.close(); - }); + rsPort.on("close", () => { + rsPort.close(); + }); //loadRelaysData(); rsPort.open(); - instance.on("close", () => { + instance.on("close", () => { clearInterval(interval); - rsPort.close(); - }); + rsPort.close(); + }); + - //onData instance.on("data", async function(flowdata) { - //instance.on("data", (data) => { - //instance.send(instanceSendTo.debug, "on Data"); - //instance.send(instanceSendTo.debug, flowdata); - - //logger.debug(flowdata.data); + //instance.send(SEND_TO.debug, "on Data"); + //instance.send(SEND_TO.debug, flowdata); + + //logger.debug(flowdata.data); - //just testing functions - if(flowdata.data == "open") - { - if(!rsPort.isOpen) rsPort.open(); - return; - } - else if(flowdata.data == "close") - { - rsPort.close(); - return; - } - else if(flowdata.data == "clean") - { - tasks = []; - return; - } - else if(flowdata.data == "buildtasks") - { - //build & run - return; - } - else if(flowdata.data == "run") - { - //durations = []; + //just testing functions + if(flowdata.data == "open") + { + if(!rsPort.isOpen) rsPort.open(); + return; + } + else if(flowdata.data == "close") + { + rsPort.close(); + return; + } + else if(flowdata.data == "clean") + { + tasks = []; + return; + } + else if(flowdata.data == "buildtasks") + { + //build & run + return; + } + else if(flowdata.data == "run") + { + //durations = []; - if(tasks.length == 0) + if(tasks.length == 0) + { + + buildTasks(); + + if(rsPort.isOpen) { - - buildTasks(); - - if(rsPort.isOpen) - { - interval = setInterval(runTasks, 100); - } - else - { - instance.send(instanceSendTo.debug, "port is not opened!!!"); - } + interval = setInterval(runTasks, 100); + } + else + { + instance.send(SEND_TO.debug, "port is not opened!!!"); } } - else + } + else + { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if(typeof flowdata.data === 'object') { - //terminal data - object - //logger.debug("flowdata", flowdata.data); - - if(typeof flowdata.data === 'object') + //logger.debug("dido", flowdata.data); + if(flowdata.data.hasOwnProperty("sender")) { - //logger.debug("dido", flowdata.data); - if(flowdata.data.hasOwnProperty("sender")) + //data from dido_controller + if(flowdata.data.sender == "dido_controller") { - //data from dido_controller - if(flowdata.data.sender == "dido_controller") + + if(flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; - if(flowdata.data.hasOwnProperty("cmd")) + + if(cmd == "buildTasks") { - let cmd = flowdata.data.cmd; + clearInterval(interval); + logger.debug("-->CMD MANAGER - BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->CMD MANAGER - RUN TASKS"); + interval = setInterval(runTasks, LONG_INTERVAL); + } + else if(cmd == "reload_relays") + { + loadRelaysData(flowdata.data.line); + + if(flowdata.data.dataChanged) + { + if(!flowdata.data.value) + { + reportOfflineNodeStatus(flowdata.data.line); + } + else + { + reportOnlineNodeStatus(flowdata.data.line); + } + } - if(cmd == "buildTasks") + } + else if(cmd == "rotary_switch_state") + { + //state was changed + if(rotary_switch_state != flowdata.data.value) { - clearInterval(interval); - - logger.debug("-->CMD MANAGER - BUILD TASKS"); - buildTasks(); - - //logger.debug("tasks:"); - //logger.debug(tasks); - - logger.debug("-->CMD MANAGER - RUN TASKS"); - interval = setInterval(runTasks, longInterval); - } - else if(cmd == "reload_relays") - { - await loadRelaysData(flowdata.data.line); - - if(flowdata.data.dataChanged) + if(rotary_switch_state == "Off") { - if(!flowdata.data.value) - { - reportOfflineNodeStatus(flowdata.data.line); - } - else - { - reportOnlineNodeStatus(flowdata.data.line); - } + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); } - + else reportOnlineNodeStatus(); + } - else if(cmd == "rotary_switch_state") + + rotary_switch_state = flowdata.data.value; + } + else if(cmd == "lux_sensor") + { + lux_sensor = parseInt(flowdata.data.value); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + else if(cmd == "state_of_breaker") + { + //istic linie + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if(state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + let weight = ERRWEIGHT.NOTICE; + let message = `zapnutý istič línie č. ${line}`; + if(value == "Off") { - //state was changed - if(rotary_switch_state != flowdata.data.value) + weight = ERRWEIGHT.ERROR; + message = `vypnutý istič línie č. ${line}`; + status = "NOK"; + } + + if(dataChanged) { + + if(relaysData.hasOwnProperty(line)) { - if(rotary_switch_state == "Off") - { - //vyreportovat vsetky svietdla - reportOfflineNodeStatus(); - } - else reportOnlineNodeStatus(); + let tbname = relaysData[line].tbname; - } + if(value == "Off") sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_off_line", {line: line}, "", SEND_TO.tb, instance, "circuit_breaker"); + else sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_on_line", {line: line}, "", SEND_TO.tb, instance, "circuit_breaker"); - rotary_switch_state = flowdata.data.value; - } - else if(cmd == "lux_sensor") - { - lux_sensor = parseInt(flowdata.data.value); - - //process profiles - turnOnOffLinesAccordingToLuxSensor(lux_sensor); - } - else if(cmd == "state_of_breaker") - { - //istic linie - let value = flowdata.data.value; - let line = parseInt(flowdata.data.line); - - let dataChanged = false; - if(state_of_breaker[line] != value) dataChanged = true; - - state_of_breaker[line] = value; - - let status = "OK"; - let weight = ERRWEIGHT.NOTICE; - let message = `zapnutý istič línie č. ${line}`; - if(value == "Off") - { - weight = ERRWEIGHT.ERROR; - message = `vypnutý istič línie č. ${line}`; - status = "NOK"; - } - - if(dataChanged) { - - if(relaysData.hasOwnProperty(line)) - { - let tbname = relaysData[line].tbname; - - if(value == "Off") sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_off_line", {line: line}, "", instanceSendTo.tb, instance, "circuit_breaker"); - else sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_on_line", {line: line}, "", instanceSendTo.tb, instance, "circuit_breaker"); - - //report status liniu - let values = { - "status": status - }; - - let dataToTb = { - [tbname]: [ - { - "ts": Date.now(), - "values": values - } - ] - } - - //instance.send(instanceSendTo.tb, dataToTb); - tbHandler.sendToTb(dataToTb, instance); - - //current value - if(value == "Off") - { - //vyreportovat vsetky svietdla na linii - reportOfflineNodeStatus(line); + //report status liniu + let values = { + "status": status + }; + + let dataToTb = { + [tbname]: [ + { + "ts": Date.now(), + "values": values + } + ] } - else reportOnlineNodeStatus(line); - } + + //instance.send(SEND_TO.tb, dataToTb); + tbHandler.sendToTb(dataToTb, instance); + //current value + if(value == "Off") + { + //vyreportovat vsetky svietdla na linii + reportOfflineNodeStatus(line); + } + else reportOnlineNodeStatus(line); } + } - else{ - logger.debug("undefined cmd", cmd); - } + } + else{ + logger.debug("undefined cmd", cmd); } } - - return; } - //data from worksys - if(flowdata.data.hasOwnProperty("topic")) + return; + } + + //data from worksys + if(flowdata.data.hasOwnProperty("topic")) + { + + let data = flowdata.data.content.data; + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if(profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + logger.debug("--->worksys", flowdata.data, data.params, entity, entity_type, command, method); + logger.debug("----------------------------"); + + if(entity_type == "street_luminaire"|| entity_type === "street_luminaire_v4_1" || entity_type === "street_luminaire_v4_1cez" || entity_type === "street_luminaire_v4") { - - let data = flowdata.data.content.data; - - let command = data.params.command; - let method = data.method; - let profile = data.params.payload; - if(profile == undefined) profile = ""; - let entity = data.params.entities[0]; - let entity_type = entity.entity_type; - let tbname = entity.tb_name; - - instance.send(instanceSendTo.debug, flowdata.data); - logger.debug("--->worksys", flowdata.data, data.params, entity, entity_type, command, method); - logger.debug("----------------------------"); - - if(entity_type == "street_luminaire"|| entity_type === "street_luminaire_v4_1" || entity_type === "street_luminaire_v4_1cez" || entity_type === "street_luminaire_v4") + if(method == "set_command") { - if(method == "set_command") + + //let command = data.params.command; + let value = data.params.payload.value; + + if(command == "dimming") { - //let command = data.params.command; - let value = data.params.payload.value; - - if(command == "dimming") - { - - let nodeWasFound = false; - let keys = Object.keys(nodesData); - - //logger.debug("-----", keys); - - for(let i = 0; i < keys.length; i++) - { - let node = keys[i]; - //logger.debug( node, nodesData[node], tbname); - - if(tbname == nodesData[node].tbname.trim()) - { - let params = getParams(priorityTypes.high_priority); - - value = parseInt(value); - if(value > 0) value = value + 128; - - //set dimming - LUM1_13 - 647 je node linie 1 kt. dobre vidime - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 1;//dimming - params.recipient = 1;//slave - params.byte4 = value; - params.rw = 1;//write - params.timestamp = priorityTypes.high_priority; - params.info = 'set dimming from platform'; - //params.debug = true; - - //ak linia je - - //debug(params); - logger.debug("dimming", params); - - tasks.push(params); - - setTimeout(function(){ - - //spustime o 4 sekundy neskor, s prioritou priorityTypes.high_priority - //a pridame aj vyreportovanie dimmingu - { - let params = getParams(priorityTypes.high_priority); - - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 1;//dimming - params.recipient = 1;//slave - params.rw = 0;//read - params.timestamp = priorityTypes.high_priority; - params.info = 'read dimming (after set dimming from platform)'; - params.debug = true; - - tasks.push(params); - } - - //pridame aj vyreportovanie - vykon - { - let params = getParams(priorityTypes.high_priority); - - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 76; - params.recipient = 1;//slave - params.rw = 0;//read - params.timestamp = priorityTypes.high_priority; - params.info = 'read Input Power (after set dimming from platform)'; - params.debug = true; - - tasks.push(params); - } - - //pridame aj vyreportovanie - prud svietidla - { - let params = getParams(priorityTypes.high_priority); - - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 75; - params.recipient = 1;//slave - params.rw = 0;//read - params.timestamp = priorityTypes.high_priority; - params.info = 'read Input Current (after set dimming from platform)'; - params.debug = true; - - tasks.push(params); - } - - //pridame aj vyreportovanie - power faktor - ucinnik - { - let params = getParams(priorityTypes.high_priority); - - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 77; - params.recipient = 1;//slave - params.rw = 0;//read - params.timestamp = priorityTypes.high_priority; - params.info = 'read power factor - Cos phi (after set dimming from platform)'; - params.debug = true; - - tasks.push(params); - } - - },4000); - - - nodeWasFound = true; - - break; - } - } - - if(!nodeWasFound) - { - logger.debug("set dimming from platform", "unable to find tbname", tbname); - } - } - else - { - instance.send(instanceSendTo.debug, "undefined command " + command); - logger.debug("undefined command", command); - } - - return; - - } - else if(method == "set_profile") - { - //nastav profil nodu - logger.debug("-->set_profile for node", data.params); - logger.debug("------profile data", profile); - //instance.send(instanceSendTo.debug, "set_profile" + command); - + let nodeWasFound = false; let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + for(let i = 0; i < keys.length; i++) { let node = keys[i]; + //logger.debug( node, nodesData[node], tbname); + if(tbname == nodesData[node].tbname.trim()) { + let params = getParams(PRIORITY_TYPES.high_priority); - if(profile != "") profile = JSON.stringify(profile); - dbNodes.modify({ processed: false, profile: profile }).where("node", node).make(function(builder) { + value = parseInt(value); + if(value > 0) value = value + 128; - builder.callback(function(err, response) { + //set dimming - LUM1_13 - 647 je node linie 1 kt. dobre vidime + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.byte4 = value; + params.rw = 1;//write + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; - logger.debug("worksys - update node profile done", profile); - if(profile === "") logger.debug("worksys - update node profile done - profile is empty"); + //ak linia je - //profil úspešne prijatý pre node č. xx - //sendNotification("CMD manager", tbname, ERRWEIGHT.INFO, `profil úspešne poslaný z platformy na RVO pre node č. ${node}`, profile, instanceSendTo.tb, instance, null ); - sendNotification("CMD manager", tbname, "dimming_profile_was_processed_for_node", {node: node}, profile, instanceSendTo.tb, instance ); + //debug(params); + logger.debug("dimming", params); - nodesData[node].processed = false; - nodesData[node].profile = profile; + tasks.push(params); - let line = nodesData[node].line; - processNodeProfile(node); + setTimeout(function(){ - }); - }); + //spustime o 4 sekundy neskor, s prioritou PRIORITY_TYPES.high_priority + //a pridame aj vyreportovanie dimmingu + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor - Cos phi (after set dimming from platform)'; + params.debug = true; + + tasks.push(params); + } + + },4000); + + + nodeWasFound = true; + + break; } } + + if(!nodeWasFound) + { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } } else { - - instance.send(instanceSendTo.debug, "unknown method " + method); - logger.debug("unknown method", method); - - return; - } - - } - - //nastav profil linie z platformy - else if(entity_type == "edb_line" || entity_type == "edb" || entity_type == "edb_line_ver4" || entity_type == "edb_ver4_se") - { - //profil linie - //relays.table line:number|tbname:string|contactor:number|profile:string - //najdeme line relaysData - - if(method == "set_profile") - { - - logger.debug("-->set_profile for line", data.params); - logger.debug("profile data:", profile); - - let keys = Object.keys(relaysData); - for(let i = 0; i < keys.length; i++) - { - let line = keys[i]; - if(tbname == relaysData[line].tbname) - { - //zmazeme tasky - removeTask({type: "relay", line: line}); - - if(profile != "") profile = JSON.stringify(profile); - dbRelays.modify({ profile: profile }).where("line", line).make(function(builder) { - - builder.callback(function(err, response) { - - //update profile - logger.debug("worksys - update relay profile done:", profile); - instance.send(instanceSendTo.debug, "worksys - update relay profile done"); - - loadRelaysData(line).then(function (data) { - logger.debug("loadRelaysData DONE for line", line); - buildTasks({processLineProfiles: true, line: line}); - }); - - sendNotification("CMD manager - set profile from worksys", tbname, "switching_profile_was_processed_for_line", {line: line}, profile, instanceSendTo.tb, instance ); - - }); - }); - - break; - } - } - } - else if(method == "set_command") - { - let value = data.params.payload.value; - - if(command === "switch") - { - - // if we receive rpc from platform, to switch maintenance mode, we set OMS_maintenance_mode flow variable to value; - if(entity_type === "edb" || entity_type === "edb_ver4_se") FLOW.variables.OMS_maintenance_mode = value; - - let responseRelays = await promisifyBuilder(dbRelays.find().where("tbname", tbname)); - - let line = 0; - if(responseRelays.length == 1) line = responseRelays[0].line; - - if(value == false) turnOffLine(line, "command received form platform"); - else turnOnLine(line, "command received form platform"); - } - - } - else - { - instance.send(instanceSendTo.debug, "undefined method " + method); - logger.debug("undefined method", method); + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); } return; - - } - else{ - instance.send(instanceSendTo.debug, "UNKNOW entity_type " + entity_type); - logger.debug("UNKNOW entity_type", entity_type); } + else if(method == "set_profile") + { + //nastav profil nodu + logger.debug("-->set_profile for node", data.params); + logger.debug("------profile data", profile); + //instance.send(SEND_TO.debug, "set_profile" + command); - return; + let keys = Object.keys(nodesData); + for(let i = 0; i < keys.length; i++) + { + let node = keys[i]; + if(tbname == nodesData[node].tbname.trim()) + { + + if(profile != "") profile = JSON.stringify(profile); + dbNodes.modify({ processed: false, profile: profile }).where("node", node).make(function(builder) { + + builder.callback(function(err, response) { + + logger.debug("worksys - update node profile done", profile); + if(profile === "") logger.debug("worksys - update node profile done - profile is empty"); + + //profil úspešne prijatý pre node č. xx + //sendNotification("CMD manager", tbname, ERRWEIGHT.INFO, `profil úspešne poslaný z platformy na RVO pre node č. ${node}`, profile, SEND_TO.tb, instance, null ); + sendNotification("CMD manager", tbname, "dimming_profile_was_processed_for_node", {node: node}, profile, SEND_TO.tb, instance ); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + let line = nodesData[node].line; + processNodeProfile(node); + + }); + }); + } + } + } + else + { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } } - //terminal - if(!rsPort.isOpen) await rsPort.open(); - - let params = flowdata.data.body; - if(params == undefined) + //nastav profil linie z platformy + else if(entity_type == "edb_line" || entity_type == "edb" || entity_type == "edb_line_ver4" || entity_type == "edb_ver4_se") { - //logger.debug("CMD manager flowdata.data.body is undefined"); + //profil linie + //relays.table line:number|tbname:string|contactor:number|profile:string + //najdeme line relaysData + + if(method == "set_profile") + { + + logger.debug("-->set_profile for line", data.params); + logger.debug("profile data:", profile); + + let keys = Object.keys(relaysData); + for(let i = 0; i < keys.length; i++) + { + let line = keys[i]; + if(tbname == relaysData[line].tbname) + { + //zmazeme tasky + removeTask({type: "relay", line: line}); + + if(profile != "") profile = JSON.stringify(profile); + dbRelays.modify({ profile: profile }).where("line", line).make(function(builder) { + + builder.callback(function(err, response) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + loadRelaysData(line).then(function (data) { + logger.debug("loadRelaysData DONE for line", line); + buildTasks({processLineProfiles: true, line: line}); + }); + + sendNotification("CMD manager - set profile from worksys", tbname, "switching_profile_was_processed_for_line", {line: line}, profile, SEND_TO.tb, instance ); + + }); + }); + break; + } + } + } + else if(method == "set_command") + { + let value = data.params.payload.value; + + if(command === "switch") + { + + // if we receive rpc from platform, to switch maintenance mode, we set OMS_maintenance_mode flow variable to value; + if(entity_type === "edb" || entity_type === "edb_ver4_se") FLOW.variables.OMS_maintenance_mode = value; + + let responseRelays = await promisifyBuilder(dbRelays.find().where("tbname", tbname)); + + let line = 0; + if(responseRelays.length == 1) line = responseRelays[0].line; + + if(value == false) turnOffLine(line, "command received form platform"); + else turnOnLine(line, "command received form platform"); + } + } + else + { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + return; } - - params.priority = priorityTypes.terminal; - params.type = "cmd-terminal"; - params.tbname = ""; - params.timestamp = priorityTypes.terminal; - params.addMinutesToTimestamp = 0;// do not repeat task!!! - params.debug = true; - - let timestamp = Date.now(); - params.refFlowdataKey = timestamp; - //params.refFlowdata = flowdata; - //refFlowdata = flowdata; - - //console.log("flowdata", flowdata); - - cleanUpRefFlowdataObj(); - - refFlowdataObj[ timestamp ] = flowdata; - - //fix - //params.address = params.adress; - logger.debug("received from terminal", params); - logger.debug("date/time:", new Date()); - logger.debug("tasks length:", tasks.length); - - //tasks = []; - - //add to tasks - tasks.push(params); - + else + { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; } + + //terminal + if(!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if(params == undefined) + { + //logger.debug("CMD manager flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[ timestamp ] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + } - }) + } + }) } // end of instance.export @@ -3586,7 +3436,7 @@ setCorrectPlcTimeOnceADay(); ///helper functions -function calculateDuskDown(date, line, duskOffset = 0, dawnOffset = 0) +function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { if(date === undefined) date = new Date(); @@ -3611,7 +3461,7 @@ function calculateDuskDown(date, line, duskOffset = 0, dawnOffset = 0) let dusk_astro_clock_offset = duskOffset;//minutes let dawn_astro_clock_offset = dawnOffset;//minutes - try{ + try { let profile = JSON.parse(profilestr); if(Object.keys(profile).length === 0) throw ("profile is not defined"); @@ -3671,6 +3521,7 @@ function calculateDuskDown(date, line, duskOffset = 0, dawnOffset = 0) return result; } + function processResponse(register, bytes) { @@ -3796,56 +3647,56 @@ function processResponse(register, bytes) //naklon if(register == 84) { - let temp; - if(byte3 >= 128) - { - temp = (byte3 - 128) * (-1); - } - else - { - temp = byte3; - } + let temp; + if(byte3 >= 128) + { + temp = (byte3 - 128) * (-1); + } + else + { + temp = byte3; + } - let inclination_x; - if(byte2 >= 128) - { - inclination_x = (byte2 - 128) * (-1); - } - else - { - inclination_x = byte2; - } + let inclination_x; + if(byte2 >= 128) + { + inclination_x = (byte2 - 128) * (-1); + } + else + { + inclination_x = byte2; + } - let inclination_y; - if(byte1 >= 128) - { - inclination_y = (byte1 - 128) * (-1); - } - else - { - inclination_y = byte1; - } + let inclination_y; + if(byte1 >= 128) + { + inclination_y = (byte1 - 128) * (-1); + } + else + { + inclination_y = byte1; + } - let inclination_z; - if(byte0 >= 128) - { - inclination_z = (byte0 - 128) * (-1); - } - else - { - inclination_z = byte0; - } + let inclination_z; + if(byte0 >= 128) + { + inclination_z = (byte0 - 128) * (-1); + } + else + { + inclination_z = byte0; + } - values["temperature"] = temp; + values["temperature"] = temp; - //náklon x - values["inclination_x"] = inclination_x; + //náklon x + values["inclination_x"] = inclination_x; - //náklon y - values["inclination_y"] = inclination_y; + //náklon y + values["inclination_y"] = inclination_y; - //náklon z - values["inclination_z"] = inclination_z; + //náklon z + values["inclination_z"] = inclination_z; } let h = byte3; @@ -3868,7 +3719,6 @@ function processResponse(register, bytes) timestamp = d.getTime(); } - //aktuálny čas if(register == 87) { @@ -3900,13 +3750,13 @@ function processResponse(register, bytes) if(register == 89) { //formát: "Byte3: Byte2.Byte1 (Byte0)" - values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; } return values; } + //byte1 MSB = data3, byte2 = data2, byte3 = data1, byte4 = data0 LSB function com_generic(adresa, rec, rw, register, name, byte1, byte2, byte3, byte4) { let resp = []; @@ -3921,7 +3771,7 @@ function com_generic(adresa, rec, rw, register, name, byte1, byte2, byte3, byte4 if (rw === 0) { - cmd = cmd + 0x8000; + cmd = cmd + 0x8000; } //master @@ -3935,24 +3785,24 @@ function com_generic(adresa, rec, rw, register, name, byte1, byte2, byte3, byte4 //recipient if (rec === 3) { - resp.push(0xFF); - resp.push(0xFF); - resp.push(0xFF); - resp.push(0xFF); - resp.push( adresa & 0xFF );//band + resp.push(0xFF); + resp.push(0xFF); + resp.push(0xFF); + resp.push(0xFF); + resp.push( adresa & 0xFF );//band } else { - resp.push( (adresa >> 24) & 0xFF);//rshift - resp.push( (adresa >> 16) & 0xFF); - resp.push( (adresa >> 8) & 0xFF); - resp.push( adresa & 0xFF ); + resp.push( (adresa >> 24) & 0xFF);//rshift + resp.push( (adresa >> 16) & 0xFF); + resp.push( (adresa >> 8) & 0xFF); + resp.push( adresa & 0xFF ); - if (rec === 2) - { - resp.push(0xFF); - } - else resp.push(0); + if (rec === 2) + { + resp.push(0xFF); + } + else resp.push(0); } resp.push( (cmd >> 8) & 0xFF);//rshift @@ -3980,3 +3830,441 @@ function com_generic(adresa, rec, rw, register, name, byte1, byte2, byte3, byte4 + + + +const lineTimepointsExample1 = +[ + { start_time: '05:17', value: 0, name: 'dawn' }, + { value: 0, end_time: '13:00', start_time: '05:30' }, + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 1, end_time: '05:30', start_time: '20:00' }, + { start_time: '20:19', value: 1, name: 'dusk' } +] + + + +const lineTimepointsExample2 = +[ + { value: 0, end_time: '13:00', start_time: '05:30' }, + { value: 0, start_time: '5:47', name: 'luxOff' }, + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 1, end_time: '05:30', start_time: '20:00' }, + { value: 1, start_time: '20:49', name: 'luxOn' } +] + + + + +// SAMPLE DATA + + +const relaysDataExample = +{ + '0': { + line: 0, + tbname: 'jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV', + contactor: 1, + profile: '' + }, + '1': { + line: 1, + tbname: 'MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O', + contactor: 1, + profile: '{"intervals":[{"value":1,"end_time":"13:00","start_time":"13:00"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' + }, + '2': { + line: 2, + tbname: 'jBL12pg63eX4N9P7zy0lJLyEJKmlbkGwZMx0avQV', + contactor: 1, + profile: '{"intervals":[{"value":1,"end_time":"13:00","start_time":"13:00"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' + }, + '3': { + line: 3, + tbname: 'aAOzENGrvpbe0VoK7D6E1a819PZmdg3nl24JLQMk', + contactor: 1, + profile: '{"intervals":[{"value":1,"end_time":"13:00","start_time":"13:00"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' + } +} + + +// [2024-05-08T11:43:33.055] [DEBUG] default - --->reportOfflineNodeStatus for line 2 +// [2024-05-08T11:43:33.055] [DEBUG] default - --->reportOfflineNodeStatus for line 3 +// [2024-05-08T11:43:35.737] [DEBUG] default - -->CMD MANAGER - BUILD TASKS +// [2024-05-08T11:43:35.742] [INFO] monitorLogs - buildTasks - params undefined +// [2024-05-08T11:43:35.743] [DEBUG] default - -->buildTasks clear tasks +// [2024-05-08T11:43:35.744] [INFO] monitorLogs - buildTasks: profile for line 1 +// [2024-05-08T11:43:35.745] [INFO] monitorLogs - profile: { +// intervals: [ { value: 1, end_time: '13:00', start_time: '13:00' } ], +// astro_clock: false, +// dawn_lux_sensor: false, +// dusk_lux_sensor: false, +// dawn_lux_sensor_value: 5, +// dusk_lux_sensor_value: 5, +// dawn_astro_clock_offset: 0, +// dusk_astro_clock_offset: 0, +// dawn_lux_sensor_time_window: 30, +// dusk_lux_sensor_time_window: 30, +// dawn_astro_clock_time_window: 60, +// dusk_astro_clock_time_window: 60 +// } +// [2024-05-08T11:43:35.747] [INFO] monitorLogs - -->comming events turn on/off lines: +// [2024-05-08T11:43:35.748] [INFO] monitorLogs - turn on line: 1 2024-05-08T11:00:00.747Z +// [2024-05-08T11:43:35.749] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, end_time: '13:00', start_time: '13:00' } ] +// [2024-05-08T11:43:35.751] [INFO] monitorLogs - -->currentValue for relay 1 1 +// +// +// typ paramu ...... / cmd + + + +const rpcSwitchOffLine = +{ + "topic": "v1/gateway/rpc", + "content": { + "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV", + "data": { + "id": 8, + "method": "set_command", + "params": { + "entities": [ + { + "entity_type": "edb_line", + "tb_name": "MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O" + } + ], + "command": "switch", + "payload": { + "value": false + } + } + } + } +} + +const rpcSetNodeDimming = +{ + "topic": "v1/gateway/rpc", + "content": { + "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV", + "data": { + "id": 10, + "method": "set_command", + "params": { + "entities": [ + { + "entity_type": "street_luminaire", + "tb_name": "jbN4q7JPZmexgdnz2yKbWdDYAWwO0Q3BMX6ERLoV" + } + ], + "command": "dimming", + "payload": { + "value": 5 + } + } + } + } +} + +const rpcLineProfile = +{ + "topic": "v1/gateway/rpc", + "content": { + "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV", + "data": { + "id": 9, + "method": "set_profile", + "params": { + "entities": [ + { + "entity_type": "edb_line", + "tb_name": "MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O" + } + ], + "payload": { + "intervals": [ + { + "value": 0, + "end_time": "20:00", + "start_time": "13:00" + }, + { + "value": 1, + "end_time": "05:30", + "start_time": "20:00" + }, + { + "value": 0, + "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": 0, + "dusk_astro_clock_offset": 0, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + } + } + } + } +} + + +const rpcNodeProfile = +{ + "topic": "v1/gateway/rpc", + "content": { + "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV", + "data": { + "id": 11, + "method": "set_profile", + "params": { + "entities": [ + { + "entity_type": "street_luminaire", + "tb_name": "jbN4q7JPZmexgdnz2yKbWdDYAWwO0Q3BMX6ERLoV" + } + ], + "payload": { + "intervals": [ + { + "cct": 3000, + "value": 0, + "end_time": "17:50", + "start_time": "13:00" + }, + { + "cct": 3000, + "value": 100, + "end_time": "21:30", + "start_time": "17:50" + }, + { + "cct": 3000, + "value": 0, + "end_time": "13:00", + "start_time": "07:10" + }, + { + "cct": 3000, + "value": 50, + "end_time": "00:00", + "start_time": "21:30" + }, + { + "cct": 3000, + "value": 10, + "end_time": "04:30", + "start_time": "00:00" + }, + { + "cct": 3000, + "value": 100, + "end_time": "07:10", + "start_time": "04: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": 30, + "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 + } + } + } + } +} + + + + const sunCalcExample = { + dusk_no_offset: '20:18', + dawn_no_offset: '05:19', + dusk: '20:18', + dusk_hours: 20, + dusk_minutes: 18, + dawn: '05:19', + dawn_hours: 5, + dawn_minutes: 19, + dusk_time: 1715278688962, + dawn_time: 1715224744357, + dusk_astro_clock_offset: 0, + dawn_astro_clock_offset: 0 +} + + +// TODO - in runTasks function, when processing tasks, wrong task gets updated +/* +[2024-05-09T20:48:00.200] [DEBUG] default - currentTask is not processed - task is in the future { + address: 0, + byte1: 0, + byte2: 0, + byte3: 0, + byte4: 0, + recipient: 0, + register: -1, + rw: 0, + priority: 3, + timestamp: 1715280480204, + addMinutesToTimestamp: 0, + type: 'relay', + line: 1, + value: 1, + tbname: 'MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O', + timePointName: 'luxOn', + dawn_lux_sensor_time_window: 30, + dusk_lux_sensor_time_window: 30, + info: 'luxOn: turn on line: 1', + debug: true +} +[2024-05-09T20:48:00.302] [INFO] monitorLogs - pparrams ************* { + address: 0, + byte1: 0, + byte2: 0, + byte3: 0, + byte4: 0, + recipient: 0, + register: -1, + rw: 0, + priority: 3, + timestamp: 1715280480204, + addMinutesToTimestamp: 0, + type: 'relay', + line: 1, + value: 1, + tbname: 'MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O', + timePointName: 'luxOn', + dawn_lux_sensor_time_window: 30, + dusk_lux_sensor_time_window: 30, + info: 'luxOn: turn on line: 1', + debug: true +} +new relay task ............ { + address: 4292, + byte1: 0, + byte2: 0, + byte3: 0, + byte4: 0, + recipient: 1, + register: 1, + rw: 0, + priority: 6, + timestamp: 1715280540301, + addMinutesToTimestamp: 1, + type: 'cmd', + tbname: 'jbN4q7JPZmexgdnz2yKbWdDYAWwO0Q3BMX6ERLoV', + info: 'generated cmd - buildTasks (node)' +} +[2024-05-09T20:48:00.304] [INFO] monitorLogs - new relay task ............. { + address: 4292, + byte1: 0, + byte2: 0, + byte3: 0, + byte4: 0, + recipient: 1, + register: 1, + rw: 0, + priority: 6, + timestamp: 1715280540301, + addMinutesToTimestamp: 1, + type: 'cmd', + tbname: 'jbN4q7JPZmexgdnz2yKbWdDYAWwO0Q3BMX6ERLoV', + info: 'generated cmd - buildTasks (node)' +} +*/ + + + + +/* +~~~~~~~~~~~~~~~~~~~~~pp { + address: 0, + byte1: 0, + byte2: 0, + byte3: 0, + byte4: 0, + recipient: 0, + register: -1, + rw: 0, + priority: 0, + timestamp: 0, + addMinutesToTimestamp: 0, + type: 'relay', + line: 1, + tbname: 'MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O', + value: 0, + debug: true, + info: 'turn off line on startup: 1' +} +deleting task from tasks +++++++++++++++++++++ { + address: 0, + byte1: 0, + byte2: 0, + byte3: 0, + byte4: 0, + recipient: 0, + register: -1, + rw: 0, + priority: 0, + timestamp: 0, + addMinutesToTimestamp: 0, + type: 'relay', + line: 1, + tbname: 'MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O', + value: 0, + debug: true, + info: 'turn off line on startup: 1' +} +[2024-05-10T09:31:36.629] [INFO] monitorLogs - pparrams ************* { + address: 0, + byte1: 0, + byte2: 0, + byte3: 0, + byte4: 0, + recipient: 0, + register: -1, + rw: 0, + priority: 0, + timestamp: 0, + addMinutesToTimestamp: 0, + type: 'relay', + line: 1, + tbname: 'MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O', + value: 0, + debug: true, + info: 'turn off line on startup: 1' +} +else task in relay ????? should be ??? +[2024-05-10T09:31:36.631] [INFO] monitorLogs - new relay task ............. { + address: 0, + byte1: 0, + byte2: 0, + byte3: 0, + byte4: 0, + recipient: 0, + register: -1, + rw: 0, + priority: 0, + timestamp: 0, + addMinutesToTimestamp: 0, + type: 'relay', + line: 2, + tbname: 'jBL12pg63eX4N9P7zy0lJLyEJKmlbkGwZMx0avQV', + value: 1, + debug: true, + info: 'turn on line on startup: 2' +} +*/ diff --git a/flow/dido_controller.js b/flow/dido_controller.js index 60e3976..50bec74 100644 --- a/flow/dido_controller.js +++ b/flow/dido_controller.js @@ -60,7 +60,7 @@ state_of_contactor - podľa indexu stykača sa reportuje jeho stav, teda //globals //FIRMWARE version -FLOW.OMS_edge_fw_version = "2023-10-18";//rok-mesiac-den +FLOW.OMS_edge_fw_version = "2024-05-10";//rok-mesiac-den FLOW.OMS_edgeName = ""; FLOW.OMS_maintenance_mode = false; @@ -507,15 +507,18 @@ exports.install = function(instance) { ws.on('error', (err) => { + monitor.info('websocket error, reconnect') instance.send(instanceSendTo.debug, err.message); clearInterval(startRequests); - startRequests = null; + ws = null; + setTimeout(handleWebSocket, 1000); }) ws.onclose = function(){ // connection closed, discard old websocket and create a new one in 5s // stopRequests(); + monitor.info('websocket onclose, reconnect') clearInterval(startRequests); ws = null; console.log("ws is null now, reconnecting..."); @@ -705,7 +708,7 @@ exports.install = function(instance) { // if(!rsPort.isOpen && !ws) if(!rsPort && !ws) { - errLogger.error("di do controller - port or websocket is not opened"); + errLogger.error("dido controller - port or websocket is not opened"); return; } diff --git a/flow/modbus_reader.js b/flow/modbus_reader.js index fd1ac62..52a3af6 100644 --- a/flow/modbus_reader.js +++ b/flow/modbus_reader.js @@ -139,16 +139,16 @@ exports.install = function(instance) { obj.transformResponse(resp, register, obj.deviceAddress); - obj.error = 0; + obj.errors = 0; obj.index++; obj.readAnotherRegister(); }).catch (function () { - console.log("error pri citani modbus registra", register, obj.indexInDeviceConfig, tbName, tbAttribute); + console.log("errors pri citani modbus registra", register, obj.indexInDeviceConfig, tbName, tbAttribute); - obj.error++; - if(obj.error == obj.lengthOfActualDeviceStream) + obj.errors++; + if(obj.errors == obj.lengthOfActualDeviceStream) { instance.send(instanceSendTo.dido_controller, {status: "NOK-" + obj.device}); // NOK-em340, NOK-em111, NOK-twilight_sensor, NOK-thermometer @@ -168,7 +168,7 @@ exports.install = function(instance) { numberOfNotResponding[obj.device] = 1; } - obj.error = 0; + obj.errors = 0; numberOfNotResponding[obj.device] += 1; }