From 5540cee8ecdef1513aa31b318eab14a0365eb33d Mon Sep 17 00:00:00 2001 From: rasta5man Date: Mon, 7 Jul 2025 14:30:03 +0200 Subject: [PATCH] Node status offline without setTimeout; handel turn line logs according to total_energy.js --- databases/total_energy.js | 37 +++++++++ flow/cmd_manager.js | 169 ++++++++++++++------------------------ flow/db_init.js | 31 ++----- flow/modbus_reader.js | 9 +- 4 files changed, 110 insertions(+), 136 deletions(-) create mode 100644 databases/total_energy.js diff --git a/databases/total_energy.js b/databases/total_energy.js new file mode 100644 index 0000000..cc8c018 --- /dev/null +++ b/databases/total_energy.js @@ -0,0 +1,37 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/flow/cmd_manager.js b/flow/cmd_manager.js index 185214f..4ead96b 100644 --- a/flow/cmd_manager.js +++ b/flow/cmd_manager.js @@ -104,25 +104,29 @@ exports.install = function(instance) { let priorities = []; let minutes = 1; - priorities["0"] = minutes; - priorities["1"] = minutes; + priorities["1"] = minutes; // dimming + priorities["76"] = minutes; // power minutes = 5; - priorities["74"] = minutes; - priorities["75"] = minutes; - priorities["76"] = minutes; - priorities["77"] = minutes; - priorities["78"] = minutes; - priorities["79"] = minutes; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas //priorities["84"] = minutes; minutes = 10; - priorities["87"] = minutes; - priorities["6"] = minutes; - priorities["7"] = minutes; - priorities["80"] = minutes; - priorities["8"] = minutes; - priorities["89"] = minutes; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; @@ -164,7 +168,7 @@ exports.install = function(instance) { tbHandler.setSender(exports.title); let now = new Date(); - console.log("CMD Manager installed", now.toLocaleString("sk-SK")); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); sunCalcResult = calculateDuskDawn(); @@ -263,7 +267,7 @@ exports.install = function(instance) { try { nodeProfile = JSON.parse(nodeProfile); } catch (error) { - logger.debug("Cmd_manager - Error parsing node profile", error); + logger.debug("Cmd-mngr: Error parsing node profile", error); } } @@ -679,7 +683,7 @@ exports.install = function(instance) { let status = "NOK"; // if status of node was "OK" before switching it off, we set the node's time_of_last_communication on time, it was switched on again and send OK status to tb. - if (nodesData[k].node_status_before_offline == true || nodesData[k].status === true) { + if (nodesData[k].node_status_before_offline === true || nodesData[k].status === true) { status = "OK"; nodesData[k].time_of_last_communication = time; } @@ -748,7 +752,8 @@ exports.install = function(instance) { function reportOfflineNodeStatus(line) { - logger.debug("Cmd-mngr: ----->reportOfflineNodeStatus for line", line); + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); values = {}; values["dimming"] = 0;//brightness @@ -758,28 +763,24 @@ exports.install = function(instance) { const date = Date.now(); - Object.keys(nodesData).forEach((node, index) => { + Object.keys(nodesData).forEach(node => { - setTimeout(function() { + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { - //potrebujem nody k danej linii - if (line == nodesData[node].line || line == undefined) { + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; - let tbname = nodesData[node].tbname; - let nodeStatus = nodesData[node].status; + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; - //in case we have reported offline node status, we return (continue with next node) - if (nodeStatus === "OFFLINE") return; + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; - nodesData[node].node_status_before_offline = nodeStatus; - nodesData[node].status = "OFFLINE"; - nodesData[node].readout = {}; - - sendTelemetry({ ...values }, tbname, date); - } - - }, (index + 1) * 300); - }) + sendTelemetry({ ...values }, tbname, date); + } + }); } @@ -1034,7 +1035,7 @@ exports.install = function(instance) { } catch (error) { if (profilestr !== "") { //errLogger.error(profilestr, error); - console.log(`Cmd_manager: Unable to process line profile ${line}. Error: `, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); } else { turnLine("off", line, "No line profile. Switching it off on startup"); @@ -1321,7 +1322,7 @@ exports.install = function(instance) { if ((currentTimestamp - reportDuskDawn.dusk_time) < 60 * 1000) { //reportovali sme? if (reportDuskDawn.dusk_time_reported != sunCalcResult.dusk_time) { - //sendNotification("CMD Manager: calculated Time of dusk", SETTINGS.rvoTbName, "dusk_has_occured", { value: sunCalcResult["dusk"] }, "", SEND_TO.tb, instance); + //sendNotification("Cmd-mngr: calculated Time of dusk", SETTINGS.rvoTbName, "dusk_has_occured", { value: sunCalcResult["dusk"] }, "", SEND_TO.tb, instance); reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; } } @@ -1338,7 +1339,7 @@ exports.install = function(instance) { if ((currentTimestamp - reportDuskDawn.dawn_time) < 60 * 1000) { //reportovali sme? if (reportDuskDawn.dawn_time_reported != sunCalcResult.dawn_time) { - //sendNotification("CMD Manager: calculated Time of dawn", SETTINGS.rvoTbName, "dawn_has_occured", { value: sunCalcResult["dawn"] }, "", SEND_TO.tb, instance); + //sendNotification(": calculated Time of dawn", SETTINGS.rvoTbName, "dawn_has_occured", { value: sunCalcResult["dawn"] }, "", SEND_TO.tb, instance); reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; } } @@ -1369,7 +1370,7 @@ exports.install = function(instance) { if (!rsPort.isOpen) { instance.send(SEND_TO.debug, "!rsPort.isOpen"); //await rsPort.open(); - //console.log("Cmd_manager - !rsPort.isOpen"); + //console.log("Cmd-mngr: !rsPort.isOpen"); } let currentTask = tasks[0]; @@ -1390,7 +1391,7 @@ exports.install = function(instance) { let type = params.type; let tbname = params.tbname; let node = params.address; - + let register = params.register; let line = null; let itIsNodeCommand; @@ -1453,39 +1454,6 @@ exports.install = function(instance) { return; } - //zhodeny hlavny istic - let disconnected = false; - //if(rotary_switch_state == "Off") disconnected = true; - - //state_of_breaker[line] - alebo istic linie - if (state_of_breaker.hasOwnProperty(line)) { - //if(state_of_breaker[line] == "Off") disconnected = true; - } - - //toto sa reportuje po prijati dat z dido_controlera - if (disconnected) { - let values = { "status": "OFFLINE" }; - - logger.debug("disconnected", values); - logger.debug("rotary_switch_state", rotary_switch_state); - logger.debug("state_of_breaker", state_of_breaker[line]); - - //report only once! - if (!disconnectedReport.hasOwnProperty(tbname)) disconnectedReport[tbname] = false; - - if (!disconnectedReport[tbname]) { - sendTelemetry(values, tbname) - } - - interval = setInterval(runTasks, SHORT_INTERVAL); - - return; - } - - disconnectedReport[tbname] = false; - - const register = params.register; - if (!SETTINGS.masterNodeIsResponding) { //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master errorHandler.sendMessageToService("Master node is not responding"); @@ -1508,25 +1476,8 @@ exports.install = function(instance) { } // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors - // - // let relayStatus = 1; - // if (relaysData[line] != undefined) { - // relayStatus = relaysData[line].contactor; - // } - - // if (line == 0) relayStatus = 0; - // if (type == "cmd-terminal") relayStatus = 1; - - // //check if rotary_switch_state == "Off" - // if (relayStatus == 0) { - // console.log("------------------------------------relayStatus", relayStatus, line); - // let values = { "status": "OFFLINE" }; - - // if(tbname) sendTelemetry(values, tbname) - - // interval = setInterval(runTasks, SHORT_INTERVAL); - // return; - // } + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? if (!rsPort.isOpen) { interval = setInterval(runTasks, LONG_INTERVAL); @@ -1578,6 +1529,9 @@ exports.install = function(instance) { // await keyword is important, otherwise incorrect data is returned! await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + //sometimes happens, that status of node changes even if line was turned off and should be offline. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + endTime = new Date(); var timeDiff = endTime - startTime; @@ -1610,7 +1564,7 @@ exports.install = function(instance) { dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { builder.callback(function(err, response) { - sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); logger.debug("--> profil úspešne odoslaný na node č. " + node); nodesData[node].processed = true; @@ -1633,7 +1587,7 @@ exports.install = function(instance) { //master node if (node == 0) { - sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "master_node_is_responding_again", {}, "", SEND_TO.tb, instance, "rvo_status"); + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "master_node_is_responding_again", {}, "", SEND_TO.tb, instance, "rvo_status"); SETTINGS.masterNodeIsResponding = true; if (register == 4) values["edge_fw_version"] = SETTINGS.edge_fw_version; } @@ -1698,7 +1652,6 @@ exports.install = function(instance) { function repeatCommand(params) { params.repeatCounter++; - if (params.repeatCounter > 0) console.log("repeated-------", params.address, params.register, params.repeatCounter); if (params.repeatCounter < 4) { params.timestamp = 0; params.addMinutesToTimestamp = 0; @@ -1733,7 +1686,7 @@ exports.install = function(instance) { //master node if (node == 0) { - sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "master_node_is_not_responding", {}, "", SEND_TO.tb, instance, "rvo_status"); + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "master_node_is_not_responding", {}, "", SEND_TO.tb, instance, "rvo_status"); logger.debug("master_node_is_not_responding", params); SETTINGS.masterNodeIsResponding = false; @@ -1745,7 +1698,7 @@ exports.install = function(instance) { logger.debug("profil nebol úspešne odoslaný na node č. ", params); if (!nodeProfileSendFail.has(node)) { - sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); nodeProfileSendFail.add(node); } } @@ -1875,7 +1828,7 @@ exports.install = function(instance) { rsPort.on('open', async function() { - logger.debug("CMD manager - rsPort opened success"); + logger.debug("Cmd-mngr: rsPort opened success"); await runSyncExec(`stty -F /dev/${SETTINGS.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); @@ -1883,17 +1836,17 @@ exports.install = function(instance) { logger.debug(0, "RPC runSyncExec - Promise Resolved:" + status); }).catch(function(reason) { - instance.send(SEND_TO.debug, "CMD manager - RPC runSyncExec - promise rejected:" + reason); + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); }); }); rsPort.on('error', function(err) { errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); - monitor.info("Cmd_manager: Error on rsPort", err.message); + monitor.info("Cmd-mngr: Error on rsPort", err.message); }); rsPort.on("close", () => { - monitor.info("Cmd_manager: rsPort closed, reconnecting..."); + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); setTimeout(handleRsPort, 1000); }); @@ -1969,13 +1922,13 @@ exports.install = function(instance) { if (cmd == "buildTasks") { clearInterval(interval); - logger.debug("-->CMD MANAGER - BUILD TASKS"); + logger.debug("-->Cmd-mngr: BUILD TASKS"); buildTasks(); //logger.debug("tasks:"); //logger.debug(tasks); - logger.debug("-->CMD MANAGER - RUN TASKS"); + logger.debug("-->Cmd-mngr: RUN TASKS"); interval = setInterval(runTasks, 5000); } else if (cmd == "reload_relays") { @@ -2049,8 +2002,8 @@ exports.install = function(instance) { 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 }, "", 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"); + if (value == "Off") sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + else sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); //report status liniu sendTelemetry({ status: status }, tbname) @@ -2248,7 +2201,7 @@ exports.install = function(instance) { if (profile === "") logger.debug("worksys - update node profile done - profile is empty"); //profil úspešne prijatý pre node č. xx - sendNotification("CMD manager", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); nodesData[node].processed = false; nodesData[node].profile = profile; @@ -2302,7 +2255,7 @@ exports.install = function(instance) { 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); + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); }); }); break; @@ -2345,7 +2298,7 @@ exports.install = function(instance) { let params = flowdata.data.body; if (params == undefined) { - //logger.debug("CMD manager flowdata.data.body is undefined"); + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); return; } diff --git a/flow/db_init.js b/flow/db_init.js index 2a5caf9..60a0510 100644 --- a/flow/db_init.js +++ b/flow/db_init.js @@ -6,33 +6,14 @@ exports.version = '1.0.2'; exports.icon = 'sign-out'; exports.output = 2; -exports.html = `
-
-
-
Hostname or IP address (if not empty - setting will override db setting)
-
-
-
Port
-
-
-
-
-
@(Client id)
-
-
-
@(Username)
-
-
-
`; - - exports.readme = ` -# DB initialization + # DB initialization `; const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); const { initNotification } = require('./helper/notification_reporter'); const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); const SEND_TO = { db_init: 0, @@ -41,7 +22,6 @@ const SEND_TO = { exports.install = async function(instance) { - const dbNodes = TABLE("nodes"); const dbRelays = TABLE("relays"); const dbSettings = TABLE("settings"); @@ -70,7 +50,7 @@ exports.install = async function(instance) { Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) dbs.settings = { - edge_fw_version: "2025-04-24", //rok-mesiac-den + edge_fw_version: "2025-07-08", //rok-mesiac-den language: responseSettings[0]["lang"], rvo_name: responseSettings[0]["rvo_name"], project_id: responseSettings[0]["project_id"], @@ -98,6 +78,11 @@ exports.install = async function(instance) { maintenance_mode: false, } + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + FLOW.dbLoaded = true; errorHandler.setProjectId(dbs.settings.project_id); initNotification(); diff --git a/flow/modbus_reader.js b/flow/modbus_reader.js index 064f956..d6d9dad 100644 --- a/flow/modbus_reader.js +++ b/flow/modbus_reader.js @@ -36,6 +36,7 @@ let mainSocket; let phases; //phases where voltage is 0 (set) let noVoltage; +let energyToSwitchLamps; exports.install = function(instance) { @@ -306,15 +307,12 @@ exports.install = function(instance) { const actualTotalPower = values.total_power; - const numberOfNodes = Object.keys(FLOW.GLOBALS.nodesData).length; - if (numberOfNodes == 0) numberOfNodes = 20; // to make sure, we send notification if totalPower is more than 300 - - if (actualTotalPower > numberOfNodes * 15 && this.onNotificationSent == false) { + if (actualTotalPower > energyToSwitchLamps && this.onNotificationSent == false) { sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_on", {}, "", SEND_TO.tb, instance); this.onNotificationSent = true; this.offNotificationSent = false; } - else if (actualTotalPower <= numberOfNodes * 15 && this.offNotificationSent == false) { + else if (actualTotalPower <= energyToSwitchLamps && this.offNotificationSent == false) { sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_off", {}, "", SEND_TO.tb, instance); this.onNotificationSent = false; this.offNotificationSent = true; @@ -332,6 +330,7 @@ exports.install = function(instance) { phases = FLOW.GLOBALS.settings.phases; tbName = FLOW.GLOBALS.settings.rvoTbName; noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off if (deviceConfig.length) mainSocket = new SocketWithClients(); else console.log("Modbus_reader: no modbus device in configuration");