diff --git a/config b/config index f3a7be7..287769b 100644 --- a/config +++ b/config @@ -8,5 +8,6 @@ package#flow (Object) : { url: '/' } table.relays : line:number|tbname:string|contactor:number|profile:string table.nodes : node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number table.settings : rvo_name:string|lang:string|temperature_adress:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|projects_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number|node_status_nok_time:number -table.pins : pin:number|type:string|line:number +table.pins : pin:string|type:string|line:number table.notifications : key:string|weight:string|sk:string|en:string +table.status : thermometer:string|em:string|twilight_sensor:string diff --git a/databases/status.table b/databases/status.table new file mode 100644 index 0000000..6d4f686 --- /dev/null +++ b/databases/status.table @@ -0,0 +1,2 @@ +thermometer:string|em:string|twilight_sensor:string ++|OK|OK|OK|............. diff --git a/flow/cmd_manager.js b/flow/cmd_manager.js index 734bc3d..0fdfea1 100644 --- a/flow/cmd_manager.js +++ b/flow/cmd_manager.js @@ -80,6 +80,8 @@ const PRIORITY_TYPES = { node_cmd: 6 } +const TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION = 600000; // 10 minutes + //list of command calls to process. Processing in runTasks function let tasks = []; @@ -141,7 +143,6 @@ let cmdCounter = {};//key is node, value is counter let cmdNOKNodeCounter = {};//key is node, value is counter let testTbName = "deleteAfterTesting" //for status testing purposes; - //END OF VARIABLE SETTINGS //-------------------------------- @@ -786,12 +787,9 @@ exports.install = function(instance) { 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.timestamp = Date.now() + 60000; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "run broadcast: Actual time"; @@ -1261,18 +1259,13 @@ exports.install = function(instance) { params.register = 6;//Time of dusk - Reg 6 params.rw = 1;//write - let timestampStart = PRIORITY_TYPES.node_broadcast; - //other values params.type = "cmd"; - //params.tbname = tbname; - params.timestamp = timestampStart; params.timestamp = Date.now() + 60000; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "Broadcast-duskTime"; tasks.push(params); - } { @@ -1296,12 +1289,8 @@ exports.install = function(instance) { params.register = 7;//Time of dawn - Reg 6 params.rw = 1;//write - let timestampStart = PRIORITY_TYPES.node_broadcast; - //other values params.type = "cmd"; - //params.tbname = tbname; - params.timestamp = timestampStart; params.timestamp = Date.now() + 60000; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "Broadcast-dawnTime"; @@ -1329,12 +1318,8 @@ exports.install = function(instance) { 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.timestamp = Date.now() + 60000; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "run broadcast: Actual time"; @@ -1416,10 +1401,6 @@ exports.install = function(instance) { params.type = "cmd-master"; params.register = 4; params.address = 0; - - let timestampStart = PRIORITY_TYPES.fw_detection; - params.timestamp = timestampStart; - params.timestamp = Date.now() + 60000; params.addMinutesToTimestamp = 5; params.tbname = FLOW.OMS_edgeName; @@ -1435,9 +1416,7 @@ exports.install = function(instance) { { let params = getParams(PRIORITY_TYPES.fw_detection); params.type = "process_profiles"; - - let timestampStart = PRIORITY_TYPES.relay_profile; - params.timestamp = timestampStart; + params.timestamp = Date.now() + 60000; params.addMinutesToTimestamp = 60;//60 = every hour params.info = "detekcia nespracovaných profilov linie a nodov"; //params.debug = true; @@ -1556,17 +1535,17 @@ exports.install = function(instance) { return true; } - if(newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication > now - 600000){ + if(newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication > now - TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION){ if(node == 638 || node == 637) console.log("true true, return", node, now); return; } - if(newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication < now - 600000) + if(newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication < now - TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION) { dbNodes.modify({ time_of_last_communication: now}).where("node", node).make(function(builder) { builder.callback(function(err, response) { - if(err == null) { + if(!err) { nodeObj.time_of_last_communication = now; if(node == 638 || node == 637) console.log('zapisane do db => status true & true', node, now) @@ -1585,7 +1564,7 @@ exports.install = function(instance) { else { dbNodes.modify({ status: newStatus}).where("node", node).make(function(builder) { builder.callback(function(err, response) { - if(err == null) { + if(!err) { nodeObj.status = newStatus; if(node == 638 || node == 637) console.log('zapisane do db => status false & true', node, now) @@ -1600,7 +1579,7 @@ exports.install = function(instance) { { dbNodes.modify({ status: newStatus, time_of_last_communication: now}).where("node", node).make(function(builder) { builder.callback(function(err, response) { - if(err == null) { + if(!err) { nodeObj.status = newStatus; nodeObj.time_of_last_communication = now; @@ -1989,7 +1968,7 @@ exports.install = function(instance) { startTime = new Date(); let saveToTb = true; - if(tbname == null || tbname == undefined || tbname == "") saveToTb = false; + if(!tbname) saveToTb = false; let itIsNodeCommand = listOfCommands.includes(register); //reading data from node (voltage, current, dimming, status) let resp = com_generic(nodeAddress, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); @@ -2053,18 +2032,15 @@ exports.install = function(instance) { let result = cmdCounterResolve(nodeAddress); if(result == 0) { - dbNodes.modify({ processed: true }).where("node", nodeAddress).make(function(builder) { - builder.callback(function(err, response) { - sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "dimming_profile_was_successfully_received_by_node", {node: nodeAddress}, "", SEND_TO.tb, instance ); - - logger.debug( "--> profil úspešne odoslaný na node č. " + nodeAddress); - nodesData[nodeAddress].processed = true; - - }); + sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "dimming_profile_was_successfully_received_by_node", {node: nodeAddress}, "", SEND_TO.tb, instance ); + + logger.debug( "--> profil úspešne odoslaný na node č. " + nodeAddress); + nodesData[nodeAddress].processed = true; }); + }); } } @@ -2296,7 +2272,7 @@ exports.install = function(instance) { else responseObj["bytes"] = data; let refFlowdata = refFlowdataObj[params.refFlowdataKey]; - if(refFlowdata !== undefined) + if(refFlowdata) { refFlowdata.data = responseObj; instance.send(SEND_TO.http_response, refFlowdata); @@ -2311,17 +2287,21 @@ exports.install = function(instance) { if(!FLOW.OMS_edgeName) return; + //Number of ok and nok nodes on platform does not equals to total number of nodes. + //possible error is, that nodesData object is changing all the time. To make a proper calculation of ok,nok luminaires, we make a copy of it: + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + const ts = Date.now(); - const keys = Object.keys(nodesData); + const keys = Object.keys(nodesData_clone); const number_of_luminaires = keys.length; let number_of_ok_luminaires = 0; let number_of_nok_luminaires = 0; - + for(let i = 0; i < keys.length; i++) { let key = keys[i]; - let nodeObj = nodesData[key]; + let nodeObj = nodesData_clone[key]; if(nodeObj.tbname == undefined) continue; if(nodeObj.status) number_of_ok_luminaires++; diff --git a/flow/dido_controller.js b/flow/dido_controller.js index b429b14..05cf3b4 100644 --- a/flow/dido_controller.js +++ b/flow/dido_controller.js @@ -6,7 +6,6 @@ exports.color = '#2134B0'; exports.input = 3; exports.output = ["red", "white", "yellow"]; exports.click = false; -exports.author = 'Daniel Segeš'; exports.icon = 'bolt'; exports.options = { edge: "undefined" }; @@ -136,9 +135,11 @@ exports.install = function(instance) { //process.exit(1); }) - let previousValues = {temperature: 0}; + // temperature value is initialized to -1000. It can be literally anything, we just needs to be able to enter if block in ws.onmessage function, when first temperatere data comes + let previousValues = {temperature: {value: -1000, lastTimeTemperatureReceived: Date.now() / 1000}}; let rsPortReceivedData = []; + //to be able to get proper twilight values, when let twilight_sensor_interval = 5;//minutes let twilight_sensor = []; const twilight_sensor_array = []; @@ -146,7 +147,7 @@ exports.install = function(instance) { let edgeName = ""; - monitor.info("DI_DO_Relay_Controller installed"); + monitor.info("DIDO_Relay_Controller installed"); //key is PIN number , line: 0 = RVO /* @@ -173,28 +174,25 @@ exports.install = function(instance) { const dbRelays = TABLE("relays"); let relaysData = {};//key is line + const dbStatus = TABLE("status"); + let statusData = null; + //status for calculating Statecodes - let deviceStatuses = {};//key is device name: temperature,.... - deviceStatuses["state_of_main_switch"] = "Off";//Hlavný istič - deviceStatuses["rotary_switch_state"] = "Off";//Prevádzkový mód - deviceStatuses["door_condition"] = "closed";//Dverový kontakt - deviceStatuses["em"] = "OK";//elektromer rvo - deviceStatuses["temperature"] = "OK";//templomer - deviceStatuses["battery"] = "OK";//Batéria - deviceStatuses["power_supply"] = "OK";//Zdroj - deviceStatuses["master_node"] = "OK";//MN - FLOW.OMS_masterNodeIsResponding - deviceStatuses["no_voltage"] = "OK";//FLOW.OMS_no_voltage - výpadok napätia na fáze + let deviceStatus = {};//key is device name: temperature,.... + deviceStatus["state_of_main_switch"] = "Off";//Hlavný istič + deviceStatus["rotary_switch_state"] = "Off";//Prevádzkový mód + deviceStatus["door_condition"] = "closed";//Dverový kontakt + deviceStatus["em"] = "OK";//elektromer rvo + deviceStatus["temperature"] = "OK";//templomer + deviceStatus["battery"] = "OK";//Batéria + deviceStatus["power_supply"] = "OK";//Zdroj + deviceStatus["master_node"] = "OK";//MN - FLOW.OMS_masterNodeIsResponding + deviceStatus["no_voltage"] = "OK";//FLOW.OMS_no_voltage - výpadok napätia na fáze - deviceStatuses["state_of_breaker"] = {};//"Off";//Istič - deviceStatuses["state_of_contactor"] = {};//"Off";//Stykač - deviceStatuses["twilight_sensor"] = "OK"; //lux sensor + deviceStatus["state_of_breaker"] = {};//"Off";//Istič + deviceStatus["state_of_contactor"] = {};//"Off";//Stykač + deviceStatus["twilight_sensor"] = "OK"; //lux sensor - /* - dbRelays.on('change', function(doc, old) { - console.log("'DI_DO_Controller - dbRelays.on('change'"); - instance.send(SEND_TO.cmd_manager, "reload_relays"); - }); - */ const SerialPort = require('serialport'); const WebSocket = require('ws'); @@ -202,12 +200,15 @@ exports.install = function(instance) { let ws = null; let rsPort = null; - //const { exec } = require('child_process'); - const { openPort, runSyncExec, writeData } = require('./helper/serialport_helper.js'); + const { runSyncExec } = require('./helper/serialport_helper.js'); const { bytesToInt, resizeArray } = require('./helper/utils'); const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); - const { sendNotification, ERRWEIGHT } = require('./helper/notification_reporter.js'); + const { sendNotification } = require('./helper/notification_reporter.js'); const bitwise = require('bitwise'); + + const DataToTbHandler = require('./helper/DataToTbHandler.js'); + const tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler.js'); const errorHandler = new ErrorToServiceHandler(); @@ -219,6 +220,7 @@ exports.install = function(instance) { console.log(exports.title, "controller type: ", controller_type); + async function loadAllDb() { let responsePins = await promisifyBuilder(dbPins.find()); @@ -227,6 +229,10 @@ exports.install = function(instance) { let responseRelays = await promisifyBuilder(dbRelays.find()); relaysData = makeMapFromDbResult(responseRelays, "line"); + let responseStatus = await promisifyBuilder(dbStatus.find()); + statusData = responseStatus[0]; // {thermometer: '{"status":"OK","temperature":0}', em: 'OK', twilight_sensor: 'OK'} + deviceStatus["temperature"] = statusData.thermometer; + FLOW.OMS_rvo_tbname = relaysData[0].tbname; if(controller_type === "lm") @@ -300,7 +306,7 @@ exports.install = function(instance) { instance.send(SEND_TO.tb, dataToTb); - let time = 3*1000; + let time = 5*1000; setTimeout(function(){ instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "buildTasks"}); @@ -425,6 +431,7 @@ exports.install = function(instance) { }, 150000) }; + // SAMPLE DATA FROM WEBSOCKET // { // glob_dev_id: 1, @@ -453,25 +460,21 @@ exports.install = function(instance) { data = JSON.parse(data.data); // data comes in array except of "temperature" ==> it comes as an object - if(!Array.isArray(data)) + if(isObject(data)) { let value = data['value']; + previousValues["temperature"]["lastTimeTemperatureReceived"] = data['time']; - // temperature value comes very often. To handle it, we check if it change for more than 0.2 degrees, if yes, we send to TB - if(Math.abs(previousValues["temperature"] - value) > 0.21 ) + if(deviceStatus["temperature"] === "NOK") { - const dataToTb = { - [FLOW.OMS_rvo_tbname]: [ - { - "ts": Date.now(), - "values": {temperature: value} - } - ] - }; - - deviceStatuses["temperature"] = "OK"; - previousValues["temperature"] = value; - instance.send(SEND_TO.tb, dataToTb); + writeThermometerStatusToDb("OK"); + } + + // temperature value comes very often. To handle it, we check if it change for more than 0.3 degrees, if yes, we send to TB + if(Math.abs(previousValues["temperature"]["value"] - value) > 0.21 ) + { + previousValues["temperature"]["value"] = value; + sendTelemetry({temperature: value}, FLOW.OMS_rvo_tbname); } return; } @@ -517,7 +520,6 @@ exports.install = function(instance) { // }, 150000) // } - instance.on("close", () => { if(rsPort) rsPort.close(); if(ws) ws.close(); @@ -526,6 +528,7 @@ exports.install = function(instance) { loadAllDb(); + function getPin(line) { //conversionTable @@ -605,13 +608,13 @@ exports.install = function(instance) { let bits = []; - if(deviceStatuses["state_of_breaker"][line] == "On") + if(deviceStatus["state_of_breaker"][line] == "On") { bits.push(0); } else bits.push(1); - if(deviceStatuses["state_of_contactor"][line] == "On") + if(deviceStatus["state_of_contactor"][line] == "On") { bits.push(0); } @@ -720,7 +723,7 @@ exports.install = function(instance) { //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method let cmd = {"cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": 1}; ws.send(JSON.stringify(cmd)); - //switchLogic(pin, 1) + switchLogic(pin, 1) } } @@ -766,7 +769,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; } @@ -797,7 +800,7 @@ exports.install = function(instance) { //monitor.info("turnOffLine pin (relay)", pin); let cmd = {"cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": 0}; ws.send(JSON.stringify(cmd)); - //switchLogic(pin, 0) + switchLogic(pin, 0) } } @@ -817,15 +820,17 @@ exports.install = function(instance) { const status = flowdata.data.status; if(status == "NOK-twilight_sensor") { - deviceStatuses["twilight_sensor"] = "NOK"; + deviceStatus["twilight_sensor"] = "NOK"; } else if(status == "NOK-em340" || status == "NOK-em111") { - deviceStatuses["em"] = "NOK"; + deviceStatus["em"] = "NOK"; } + //"NOK-thermometer" comes just from LM. Unipi handles thermometer from ws evok. else if(status == "NOK-thermometer") { - deviceStatuses["temperature"] = "NOK"; + previousValues["temperature"]["lastTimeTemperatureReceived"] = null; + deviceStatus["temperature"] = "NOK"; } } else if(flowdata.data?.values) @@ -834,16 +839,18 @@ exports.install = function(instance) { if(values.hasOwnProperty("twilight_sensor")) { instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "lux_sensor", value: values["twilight_sensor"]}); - deviceStatuses["twilight_sensor"] = "OK" + deviceStatus["twilight_sensor"] = "OK" } + //"temperature" comes just from LM. Unipi handles thermometer from ws evok. else if(values.hasOwnProperty("temperature")) { - deviceStatuses["temperature"] = "OK"; + previousValues["temperature"]["lastTimeTemperatureReceived"] = Date.now() / 1000; //time in seconds + deviceStatus["temperature"] = "OK"; } // EM else if(values.hasOwnProperty("total_power") || values.hasOwnProperty("total_energy") || values.hasOwnProperty("power_factor") || values.hasOwnProperty("Phase_1_voltage") || values.hasOwnProperty("Phase_1_current")) { - deviceStatuses["em"] = "OK"; + deviceStatus["em"] = "OK"; } else { @@ -876,7 +883,6 @@ exports.install = function(instance) { else if(obj.command == "turnOnAlarm") turnOnAlarm(); else if(obj.command == "turnOffAlarm") turnOffAlarm(); - //! ake data prichadzaju z cmd_manager.js ??? //TODO transform to websocket if (Array.isArray(obj)){ @@ -897,11 +903,11 @@ exports.install = function(instance) { let bits = []; //Hlavný istič - state_of_main_switch - if(deviceStatuses["state_of_main_switch"] == "On") + if(deviceStatus["state_of_main_switch"] == "On") { bits.push(0); } - else if(deviceStatuses["state_of_main_switch"] == "Off") + else if(deviceStatus["state_of_main_switch"] == "Off") { bits.push(1); } @@ -909,19 +915,19 @@ exports.install = function(instance) { //Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY if(!FLOW.OMS_maintenance_mode) { - if(deviceStatuses["rotary_switch_state"] == "Manual") + if(deviceStatus["rotary_switch_state"] == "Manual") { bits.push(0); bits.push(1); } - if(deviceStatuses["rotary_switch_state"] == "Automatic") + if(deviceStatus["rotary_switch_state"] == "Automatic") { bits.push(0); bits.push(0); } - if(deviceStatuses["rotary_switch_state"] == "Off") + if(deviceStatus["rotary_switch_state"] == "Off") { bits.push(1); bits.push(0); @@ -933,7 +939,7 @@ exports.install = function(instance) { } //Dverový kontakt - if(deviceStatuses["door_condition"] == "closed") + if(deviceStatus["door_condition"] == "closed") { bits.push(0); } @@ -943,7 +949,7 @@ exports.install = function(instance) { } //EM - if(deviceStatuses["em"] == "NOK") + if(deviceStatus["em"] == "NOK") { bits.push(1); } @@ -953,7 +959,7 @@ exports.install = function(instance) { } //Teplomer - if(deviceStatuses["temperature"] == "NOK") + if(deviceStatus["temperature"] == "NOK") { bits.push(1); } @@ -963,7 +969,7 @@ exports.install = function(instance) { } //Batéria - if(deviceStatuses["battery"] == "NOK") + if(deviceStatus["battery"] == "NOK") { bits.push(1); } @@ -973,7 +979,7 @@ exports.install = function(instance) { } //Zdroj - if(deviceStatuses["power_supply"] == "NOK") + if(deviceStatus["power_supply"] == "NOK") { bits.push(1); } @@ -983,7 +989,7 @@ exports.install = function(instance) { } //MN - if(deviceStatuses["master_node"] == "NOK") + if(deviceStatus["master_node"] == "NOK") { bits.push(1); } @@ -993,7 +999,7 @@ exports.install = function(instance) { } //výpadok napätia na fáze - if(deviceStatuses["no_voltage"] == "NOK") + if(deviceStatus["no_voltage"] == "NOK") { bits.push(1); } @@ -1002,7 +1008,7 @@ exports.install = function(instance) { bits.push(0); } - if(deviceStatuses["twilight_sensor"] == "NOK") + if(deviceStatus["twilight_sensor"] == "NOK") { bits.push(1); } @@ -1017,7 +1023,7 @@ exports.install = function(instance) { bits.push(0); } - // console.log("calculateStateCode - deviceStatuses", deviceStatuses); + // console.log("calculateStateCode - deviceStatus", deviceStatus); // console.log("calculateStateCode", bits); let byte0 = bitwise.byte.write(bits.slice(0,8).reverse()); @@ -1031,16 +1037,54 @@ exports.install = function(instance) { } + function sendDeviceStatus() { + + const table = { + "OK": 1, + "NOK": 0 + }; + + const dataToTb = { + "electrometer_status": table[deviceStatus["em"]], + "twilight_sensor_status": table[deviceStatus["twilight_sensor"]], + "thermometer_status": table[deviceStatus["temperature"]], + "phase_1_status": 1, + "phase_2_status": 1, + "phase_3_status": 1, + "master_node_status": table[deviceStatus["master_node"]] + }; + + for (const phase of FLOW.OMS_no_voltage) { + if(phase == 1) dataToTb["phase_1_status"] = 0; + if(phase == 2) dataToTb["phase_2_status"] = 0; + if(phase == 3) dataToTb["phase_3_status"] = 0; + } + + //thermometer did not send data for more than a hour. Time in seconds + if(deviceStatus["temperature"] === "OK") + { + if(previousValues["temperature"]["lastTimeTemperatureReceived"] + 3600 < Date.now() / 1000) + { + writeThermometerStatusToDb("NOK"); + dataToTb["thermometer_status"] = 0; + } + } + + sendTelemetry(dataToTb, FLOW.OMS_rvo_tbname); + } + + setInterval(sendDeviceStatus, 150000); + + function checkFinalRVOStatus() { // we check if any of these pins values are 0 --> it means status RVO is "NOK" - // pinIndex 6 is door_condition - if open in maintenance mode - status = OK + // pinIndex 6 is door_condition - if it is opened in maintenance mode - status = OK //set RVO state - let status = "OK"; - if(deviceStatuses["em"] == "NOK") + if(deviceStatus["em"] == "NOK") { let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: EM status is NOK"); if(writeToFile) errLogger.error("checkFinalRVOStatus: EM status is NOK"); @@ -1048,7 +1092,7 @@ exports.install = function(instance) { status = "NOK"; } - if(deviceStatuses["twilight_sensor"] == "NOK") + if(deviceStatus["twilight_sensor"] == "NOK") { let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: twilight_sensor is NOK"); if(writeToFile) errLogger.error("checkFinalRVOStatus: twilight sensor is NOK"); @@ -1057,7 +1101,7 @@ exports.install = function(instance) { } //ak teplomer NOK, rvo nok - if(deviceStatuses["temperature"] == "NOK") + if(deviceStatus["temperature"] == "NOK") { let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: temperature status is NOK"); @@ -1105,9 +1149,9 @@ exports.install = function(instance) { errorHandler.sendMessageToService("Master node is not responding"); status = "NOK"; - deviceStatuses["master_node"] = "NOK"; + deviceStatus["master_node"] = "NOK"; } - else deviceStatuses["master_node"] = "OK"; + else deviceStatus["master_node"] = "OK"; //console.log("checkFinalRVOStatus", status); if(FLOW.OMS_no_voltage.size > 0) @@ -1117,14 +1161,13 @@ exports.install = function(instance) { status = "NOK"; - deviceStatuses["no_voltage"] = "NOK"; + deviceStatus["no_voltage"] = "NOK"; } - else deviceStatuses["no_voltage"] = "OK"; + else deviceStatus["no_voltage"] = "OK"; if(status == "NOK") { sendTelemetry({status: "NOK"}, FLOW.OMS_rvo_tbname); - return false; } @@ -1155,13 +1198,13 @@ exports.install = function(instance) { } let obj = pinsData[pinIndex]; - if(obj == undefined) { previousValues[pinIndex] = newPinValue; return; } + //tbname is added to pinsData in initialSettings function let type = obj.type; let line = obj.line; let tbname = obj.tbname; @@ -1180,13 +1223,13 @@ exports.install = function(instance) { sendNotification("switchLogic", edgeName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance , "state_of_main_switch"); values["status"] = "NOK"; - deviceStatuses["state_of_main_switch"] = "Off"; + deviceStatus["state_of_main_switch"] = "Off"; } else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { sendNotification("switchLogic", edgeName, "main_switch_has_been_turned_on", {}, "", SEND_TO.tb, instance , "state_of_main_switch"); - deviceStatuses["state_of_main_switch"] = "On"; + deviceStatus["state_of_main_switch"] = "On"; } } @@ -1223,7 +1266,7 @@ exports.install = function(instance) { if (pin2 == 0 && pin3 == 0) value = "Off"; if (pin2 == 0 && pin3 == 1) value = "Automatic"; - deviceStatuses["rotary_switch_state"] = value; + deviceStatus["rotary_switch_state"] = value; //automatic - profilu pre nody sa vykonavaju //ak je spracovany, a automatic - tak ho zapnem @@ -1242,14 +1285,14 @@ exports.install = function(instance) { sendNotification("switchLogic", edgeName, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); values["status"] = "NOK"; - deviceStatuses["power_supply"] = "NOK"; + deviceStatus["power_supply"] = "NOK"; } else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { //sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Power supply is is OK", "", SEND_TO.tb, instance); sendNotification("switchLogic", edgeName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); - deviceStatuses["power_supply"] = "OK"; + deviceStatus["power_supply"] = "OK"; } } //Batéria - pin 5 @@ -1261,14 +1304,14 @@ exports.install = function(instance) { sendNotification("switchLogic", edgeName, "battery_level_is_low", {}, "", SEND_TO.tb, instance, "battery_level"); values["status"] = "NOK"; - deviceStatuses["battery"] = "NOK"; + deviceStatus["battery"] = "NOK"; } else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { //sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Battery is OK", "", SEND_TO.tb, instance); sendNotification("switchLogic", edgeName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); - deviceStatuses["battery"] = "OK"; + deviceStatus["battery"] = "OK"; } } //Dverový kontakt - pin 6 @@ -1310,13 +1353,13 @@ exports.install = function(instance) { sendNotification("switchLogic", edgeName, "door_has_been_closed", {}, "", SEND_TO.tb, instance, "rvo_door"); } - deviceStatuses["door_condition"] = value; + deviceStatus["door_condition"] = value; } //lux sensor else if(type == "twilight_sensor") { - //! TODO - to show nok status, if lux value is not changing more then 10 times. From unipi for example comes value from 0-1000. + //! TODO - to show nok status, if lux value is not changing more then 10 times. //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. values["status"] = "OK"; @@ -1382,65 +1425,45 @@ exports.install = function(instance) { { //sendNotification("switchLogic", edgeName, ERRWEIGHT.INFO, `State of contactor ${line} is now ${value}`, "", SEND_TO.tb, instance ); - if(!(deviceStatuses["state_of_contactor"][line] == value)) + if(!(deviceStatus["state_of_contactor"][line] == value)) { sendNotification("switchLogic", edgeName, "state_of_contactor_for_line", {line: line, value: value}, "", SEND_TO.tb, instance ); } - else - { - deviceStatuses["state_of_contactor"][line] = value; - } + + deviceStatus["state_of_contactor"][line] = value; //true, false if(value === "On") value = true; - else if(value === "Off") value = false; + else if(value === "Off") value = false; //modify table relays dbRelays.modify({ contactor: newPinValue }).where("line", line).make(function(builder) { - builder.callback(function(err, response) { - - /* - if(useTurnOffCounter) + if(!err) { - turnOffCounter--; + let time = 0; + if(value) time = 1000 * 10;//10 sekund - if(turnOffCounter <= 0) - { - useTurnOffCounter = false; - } - } - */ + let dataChanged = false; + if(relaysData[line].contactor != value) dataChanged = true; + relaysData[line].contactor = value; + + //ak bola predchadzajuci stav off a novy stav je on, budu sa nastavovat nespracovane node profiles + //a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor - if(err == undefined) - { + setTimeout(function(){ + instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged}); + }, time); - let time = 0; - if(value) time = 1000 * 10;//10 sekund + reportLineStatus(line); + } + else + { + errLogger.error("modify table relays failed", err); + } - let dataChanged = false; - if(relaysData[line].contactor != value) dataChanged = true; - relaysData[line].contactor = value; - - //ak bola predchadzajuci stav off a novy stav je on, budu sa nastavovat nespracovane node profiles - //a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor - - setTimeout(function(){ - instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged}); - }, time); - - reportLineStatus(line); - - - } - else - { - errLogger.error("modify table relays failed", err); - } - - - }); }); + }); } if(type === "state_of_breaker") @@ -1467,7 +1490,7 @@ exports.install = function(instance) { instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: lineOnSameBraker[i]}); - deviceStatuses["state_of_breaker"][lineOnSameBraker[i]] = value; + deviceStatus["state_of_breaker"][lineOnSameBraker[i]] = value; reportLineStatus(lineOnSameBraker[i]); values[type] = value; @@ -1486,7 +1509,7 @@ exports.install = function(instance) { { instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: line + 3}); - deviceStatuses["state_of_breaker"][line + 3] = value; + deviceStatus["state_of_breaker"][line + 3] = value; reportLineStatus(line + 3); values[type] = value; @@ -1495,14 +1518,13 @@ exports.install = function(instance) { delete values[type]; } - } } if(value == "Off") values["status"] = "NOK"; - deviceStatuses["state_of_breaker"][line] = value; + deviceStatus["state_of_breaker"][line] = value; reportLineStatus(line); } @@ -1569,8 +1591,7 @@ exports.install = function(instance) { } - function sendTelemetry(values, tbname) - { + function sendTelemetry(values, tbname) { let dataToTb = { [tbname]: [ { @@ -1578,12 +1599,33 @@ exports.install = function(instance) { "values": values } ] - } + }; - instance.send(SEND_TO.tb, dataToTb); + // instance.send(SEND_TO.tb, dataToTb); + tbHandler.sendToTb(dataToTb, instance); } -} + + function writeThermometerStatusToDb(status) { + dbStatus.modify({ thermometer: status }).make(function(builder) { + builder.callback(function(err, response) { + if(!err) + { + deviceStatus["temperature"] = status; + console.log(`Wrote to db status: thermometer ${status}`); + } + }); + }); + } + + + function isObject (item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + +} //end of instance diff --git a/flow/helper/DataToTbHandler.js b/flow/helper/DataToTbHandler.js index 8010581..cf29b82 100644 --- a/flow/helper/DataToTbHandler.js +++ b/flow/helper/DataToTbHandler.js @@ -3,6 +3,9 @@ class DataToTbHandler constructor(index) { this.index = index; + // time, after new value for the given key will be resend to tb (e.g. {status: "OK"}) + this.timeToHoldTbValue = 30*60; //30 minutes + this.previousValues = {}; this.debug = false; this.messageCounter = 0; @@ -99,14 +102,9 @@ class DataToTbHandler getDiffTimestamp(key) { - let seconds = 30*60;//30 minutes - //TODO set different value for given key!!! - //if(key == "status") seconds = 2*60*60;//2h - - let timestampDiffToRemoveKey = seconds*1000; - - return timestampDiffToRemoveKey; + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; } prepareValuesForTb(tbname, timestamp, values) diff --git a/flow/modbus_reader.js b/flow/modbus_reader.js index f34ec9a..3bee223 100644 --- a/flow/modbus_reader.js +++ b/flow/modbus_reader.js @@ -287,7 +287,6 @@ exports.install = function(instance) { let l = singleValue.split("_"); let phase = parseInt(l[1]); - if(FLOW.OMS_no_voltage == undefined) FLOW.OMS_no_voltage = new Set(); // console.log(values[singleValue], tbName); if(values[singleValue] == 0) diff --git a/flow/thermometer.js b/flow/thermometer.js index 1a5714f..9b51fac 100644 --- a/flow/thermometer.js +++ b/flow/thermometer.js @@ -216,5 +216,9 @@ exports.install = function(instance) { }, 15000); startRead = setInterval(start, timeoutMin * 1000 * 60); + + //testing + //setInterval(() => {instance.send(instanceSendTo.dido_controller, {status: "NOK-thermometer"})}, 180000); + +}; -}; \ No newline at end of file diff --git a/flow/wsmqttpublish.js b/flow/wsmqttpublish.js index 794fedc..3064de1 100644 --- a/flow/wsmqttpublish.js +++ b/flow/wsmqttpublish.js @@ -73,6 +73,11 @@ let errLogger; let logger; let monitor; +//TODO brokerready and sendBrokerError seems to be the same. Moreover, we use FLOW_OMS_brokerready variable!! +// +// if there is an error in broker connection, flow logs to monitor.txt. Not to log messages every second, we use sendBrokerError variable +let sendBrokerError = true; + if(useLog4js) { var path = require('path'); @@ -217,6 +222,8 @@ exports.install = function(instance) { instance.status("Connected", "green"); monitor.info("MQTT broker connected"); + sendBrokerError = true; + brokerready = true; FLOW.OMS_brokerready = brokerready; wsmqtt_status = 'connected'; @@ -266,8 +273,10 @@ exports.install = function(instance) { broker.on('error', function(err) { instance.status("Err: "+ err.code, "red"); instance.send(instanceSendTo.debug, {"message":"Broker ERROR signal received !", "error":err, "opt":opts }); - monitor.info('MQTT broker error', err); - + if(sendBrokerError) { + monitor.info('MQTT broker error', err); + sendBrokerError = false; + } brokerready = false; FLOW.OMS_brokerready = brokerready; wsmqtt_status = 'disconnected';