diff --git a/databases/nodes.table b/databases/nodes.table index 0efaed3..b2f13d9 100644 --- a/databases/nodes.table +++ b/databases/nodes.table @@ -1,2 +1,2 @@ node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number -+|638|rDbQ84xzwgdqEoPm3kbJQWk9anOZY1RXyBv2LVM6|3|{"intervals":[{"cct":3000,"value":20,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":10,"end_time":"05:30","start_time":"20:00"},{"cct":3000,"value":20,"end_time":"13:00","start_time":"05:30"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":-20,"dusk_astro_clock_offset":20,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|0|1725885127396|............................................................................................................................................................................................................................................................|................. ++|638|rDbQ84xzwgdqEoPm3kbJQWk9anOZY1RXyBv2LVM6|3|{"intervals":[{"cct":3000,"value":20,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":10,"end_time":"05:30","start_time":"20:00"},{"cct":3000,"value":20,"end_time":"13:00","start_time":"05:30"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":-20,"dusk_astro_clock_offset":20,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|0|1725885127396|............................................................................................................................................................................................................................................................ diff --git a/flow/cmd_manager.js b/flow/cmd_manager.js index 18807f9..185214f 100644 --- a/flow/cmd_manager.js +++ b/flow/cmd_manager.js @@ -225,7 +225,9 @@ exports.install = function(instance) { params.priority = priority; } - params.addMinutesToTimestamp = 0;//repeat task if value is > 0, + params.addMinutesToTimestamp = 0;//repeat task if value is > 0 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 0; //params.timePointName = "luxOff" // "luxOn", "dusk", "dawn", "profileTimepoint" //params.info = ""; //params.debug = true; // will console.log params in writeData response @@ -642,7 +644,7 @@ exports.install = function(instance) { function reportOnlineNodeStatus(line) { //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness - logger.debug("--->reportOnlineNodeStatus for line", line); + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); const d = new Date(); @@ -746,7 +748,7 @@ exports.install = function(instance) { function reportOfflineNodeStatus(line) { - logger.debug("--->reportOfflineNodeStatus for line", line); + logger.debug("Cmd-mngr: ----->reportOfflineNodeStatus for line", line); values = {}; values["dimming"] = 0;//brightness @@ -766,11 +768,10 @@ exports.install = function(instance) { 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; - nodesData[node].node_status_before_offline = nodeStatus === true ? true : false; + nodesData[node].node_status_before_offline = nodeStatus; nodesData[node].status = "OFFLINE"; nodesData[node].readout = {}; @@ -795,7 +796,6 @@ exports.install = function(instance) { } - function detectIfResponseIsValid(bytes) { //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK let type = "RESPONSE"; @@ -1492,7 +1492,7 @@ exports.install = function(instance) { let stop = true; - if (type == "cmd-terminal" || type == "cmd-master") stop = false; + if (type === "cmd-terminal" || type === "cmd-master") stop = false; if (stop) { interval = setInterval(runTasks, LONG_INTERVAL); return; @@ -1502,7 +1502,7 @@ exports.install = function(instance) { let contactorStatus = 1; if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; - if (line == 0 || contactorStatus == 0) { + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { interval = setInterval(runTasks, LONG_INTERVAL); return; } @@ -1653,7 +1653,6 @@ exports.install = function(instance) { } else { - terminalCommandResponse(params, "ERROR", data); handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); @@ -1697,6 +1696,16 @@ 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; + tasks.push(params); + } + } + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { let node = params.address; @@ -1712,6 +1721,7 @@ exports.install = function(instance) { if (itIsNodeCommand) { values.comm_status = "NOK"; nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); } if (updateStatus) { @@ -1747,10 +1757,12 @@ exports.install = function(instance) { } + function sendNodesData() { Object.keys(nodesData).forEach(node => { if (nodesData[node]["status"] !== "OFFLINE") { sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; } }) } @@ -1763,13 +1775,10 @@ exports.install = function(instance) { */ function terminalCommandResponse(params, responseType, data = null, reason = "") { //success, error, failure - if (params.refFlowdataKey == undefined) { + if (params.refFlowdataKey === undefined) { //console.log("params.refFlowdataKey is undefined", params); return; } - else { - console.log("params.refFlowdataKey: ", params); - } let message = null; let type = null; @@ -1792,7 +1801,6 @@ exports.install = function(instance) { } logger.debug(message); - logger.debug(params); //make http response let responseObj = {} @@ -1851,6 +1859,11 @@ exports.install = function(instance) { function handleRsPort() { + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + //! 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 @@ -1875,16 +1888,13 @@ exports.install = function(instance) { }); rsPort.on('error', function(err) { - - //TODO report to service!!! - //errLogger.error(exports.title, "unable to open port", SETTINGS.serial_port, err.message); errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); - - instance.send(SEND_TO.debug, err.message); + monitor.info("Cmd_manager: Error on rsPort", err.message); }); rsPort.on("close", () => { - setTimeout(() => rsPort.open(), 1000); + monitor.info("Cmd_manager: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); }); rsPort.open(); diff --git a/flow/designer.json b/flow/designer.json index 82dfe7f..7565777 100644 --- a/flow/designer.json +++ b/flow/designer.json @@ -449,8 +449,8 @@ "color": "gray" }, "options": { - "datatype": "object", - "data": "{line: 3, command: \"turnOff\", force: true}" + "data": "{line: 3, command: \"turnOff\", force: true}", + "datatype": "object" }, "color": "#F6BB42", "notes": "" @@ -501,8 +501,8 @@ "color": "gray" }, "options": { - "data": "profile_nodes", - "datatype": "string" + "datatype": "string", + "data": "profile_nodes" }, "color": "#F6BB42", "notes": "" @@ -712,8 +712,8 @@ "color": "gray" }, "options": { - "data": "{line: 1, command: \"turnOn\", force: true}", - "datatype": "object" + "datatype": "object", + "data": "{line: 1, command: \"turnOn\", force: true}" }, "color": "#F6BB42", "notes": "" @@ -842,8 +842,8 @@ "color": "gray" }, "options": { - "datatype": "object", - "data": "{command: \"turnOnAlarm\"}" + "data": "{command: \"turnOnAlarm\"}", + "datatype": "object" }, "color": "#F6BB42", "notes": "" @@ -872,8 +872,8 @@ "color": "gray" }, "options": { - "datatype": "object", - "data": "{command: \"turnOffAlarm\"}" + "data": "{command: \"turnOffAlarm\"}", + "datatype": "object" }, "color": "#F6BB42", "notes": "" @@ -1009,7 +1009,7 @@ "output": [] }, "state": { - "text": "843.78 MB / 985.68 MB", + "text": "840.05 MB / 985.68 MB", "color": "gray" }, "options": { @@ -1039,7 +1039,7 @@ "output": [] }, "state": { - "text": "5.68 GB / 7.26 GB", + "text": "5.78 GB / 7.26 GB", "color": "gray" }, "options": { @@ -1152,9 +1152,9 @@ "color": "gray" }, "options": { - "url": "http://192.168.252.2:8004/sentmessage", + "stringify": "json", "method": "POST", - "stringify": "json" + "url": "http://192.168.252.2:8004/sentmessage" }, "color": "#5D9CEC", "notes": "" @@ -1495,7 +1495,7 @@ "output": [] }, "state": { - "text": "2% / 86.44 MB", + "text": "2.4% / 74.33 MB", "color": "gray" }, "options": { @@ -2018,7 +2018,7 @@ "tag_on_include": "[{\"user_id\":\"U072JE5JUQG\", \"includes\":[\"Electrometer\", \"Twilight sensor\"]}]", "message_includes": "[\"is responding again\", \"Flow has been restarted\", \"Node db has changed\"]", "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", - "name": "" + "name": "rvo_senica_33_10.0.0.127" }, "color": "#30E193", "notes": "" @@ -2047,9 +2047,9 @@ "color": "gray" }, "options": { - "url": "http://192.168.252.2:8004/slack", + "stringify": "json", "method": "POST", - "stringify": "json" + "url": "http://192.168.252.2:8004/slack" }, "color": "#5D9CEC", "notes": "" @@ -2104,8 +2104,8 @@ "color": "gray" }, "options": { - "data": "{ \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\": [ { \"ts\": 1716289039281, \"values\": { \"_event\": { \"type\": \"alert\", \"status\": \"new\", \"source\": { \"func\": \"CMD Manager: process cmd\", \"component\": \"1619515097737\", \"component_name\": \"CMD Manager\", \"edge\": \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\" }, \"message\": \"NOW CONNECTED TO SLACK !\", \"message_data\": \"\" } } } ] }", - "datatype": "object" + "datatype": "object", + "data": "{ \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\": [ { \"ts\": 1716289039281, \"values\": { \"_event\": { \"type\": \"alert\", \"status\": \"new\", \"source\": { \"func\": \"CMD Manager: process cmd\", \"component\": \"1619515097737\", \"component_name\": \"CMD Manager\", \"edge\": \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\" }, \"message\": \"NOW CONNECTED TO SLACK !\", \"message_data\": \"\" } } } ] }" }, "color": "#F6BB42", "notes": "" @@ -2282,8 +2282,8 @@ "component": "showdb", "tab": "1612772287426", "name": "Show db data", - "x": 1121.75, - "y": 814.25, + "x": 1186.75, + "y": 821.25, "connections": { "0": [ { @@ -2309,8 +2309,8 @@ "component": "debug", "tab": "1612772287426", "name": "dbData", - "x": 1315.75, - "y": 853.25, + "x": 1390.75, + "y": 870.25, "connections": {}, "disabledio": { "input": [], @@ -2333,8 +2333,8 @@ "component": "trigger", "tab": "1612772287426", "name": "settings", - "x": 911.75, - "y": 710.75, + "x": 934.75, + "y": 669.75, "connections": { "0": [ { @@ -2360,8 +2360,8 @@ "component": "trigger", "tab": "1612772287426", "name": "relaysData", - "x": 832.75, - "y": 775.75, + "x": 876.75, + "y": 733.75, "connections": { "0": [ { @@ -2387,8 +2387,8 @@ "component": "trigger", "tab": "1612772287426", "name": "nodesData", - "x": 747.75, - "y": 840.75, + "x": 852.75, + "y": 794.75, "connections": { "0": [ { @@ -2414,8 +2414,8 @@ "component": "trigger", "tab": "1612772287426", "name": "pinsData", - "x": 803.75, - "y": 899.75, + "x": 850.75, + "y": 861.75, "connections": { "0": [ { @@ -2441,8 +2441,8 @@ "component": "trigger", "tab": "1612772287426", "name": "sample data", - "x": 858.75, - "y": 959.75, + "x": 857.75, + "y": 928.75, "connections": { "0": [ { @@ -2613,8 +2613,8 @@ "component": "trigger", "tab": "1612772287426", "name": "monitor.txt", - "x": 915.75, - "y": 1017.75, + "x": 882.75, + "y": 991.75, "connections": { "0": [ { @@ -2640,8 +2640,8 @@ "component": "trigger", "tab": "1612772287426", "name": "err.txt", - "x": 966.75, - "y": 1080.75, + "x": 904.75, + "y": 1053.75, "connections": { "0": [ { @@ -2862,6 +2862,33 @@ "options": {}, "color": "#704cff", "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" } ], "version": 615 diff --git a/flow/dido_controller.js b/flow/dido_controller.js index 8d4f47a..d16fb19 100644 --- a/flow/dido_controller.js +++ b/flow/dido_controller.js @@ -124,8 +124,8 @@ exports.install = function(instance) { }; */ - //status for calculating Statecodes - let deviceStatus = { //key is device name: temperature,.... + //status for calculating Statecodes-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) "rotary_switch_state": "Off", //Prevadzkovy "door_condition": "closed", //Dverový kontakt @@ -139,6 +139,7 @@ exports.install = function(instance) { "state_of_contactor": {}, //"Off",//Stykac "twilight_sensor": "OK" //lux sensor }; + let deviceStatus = FLOW.deviceStatus; function main() { @@ -211,18 +212,17 @@ exports.install = function(instance) { function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + //TODO build according to pins!!! //! rsPort to open are the same for lm and unipi and electromer ("/dev/ttymxc0") const setRSPortData = [0xAA, 6, 6, 6, 6, 6, 6, 0, 6, 6, 6, 1, 1, 1, 1, 0, 0, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0]; rsPort = new SerialPort("/dev/ttymxc0", { autoOpen: false }); - rsPort.on('error', function(err) { - logger.debug("rsPort opened error - failed", err.message); - instance.send(SEND_TO.debug, err.message); - - errorHandler.sendMessageToService(exports.title + " rsPort opened error - failed: " + err.message); - }) - rsPort.on('open', async function() { await runSyncExec("stty -F /dev/ttymxc0 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke").then(function(status) { @@ -283,8 +283,18 @@ exports.install = function(instance) { }); + rsPort.on('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + rsPort.on("close", () => { - rsPort.close(); + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); }) rsPort.open(); @@ -293,6 +303,11 @@ exports.install = function(instance) { function handleWebSocket() { + if (ws) { + ws.removeAllListeners(); + ws = null; + } + //to keep websocket opened, we send request every 150 seconds let startRequests = null; @@ -356,23 +371,13 @@ exports.install = function(instance) { }) } - - ws.on('error', (err) => { - monitor.info('websocket error, reconnect') - instance.send(SEND_TO.debug, err.message); - clearInterval(startRequests); - ws = null; - setTimeout(handleWebSocket, 1000); + ws.on('error', err => { + logger.debug('Dido: websocket error', err); }) - ws.onclose = function() { - // connection closed, discard old websocket and create a new one in 5s - // stopRequests(); - monitor.info('websocket onclose, reconnect') + logger.debug('Dido: websocket onclose, reconnecting...') clearInterval(startRequests); - ws = null; - console.log("ws is null now, reconnecting..."); setTimeout(handleWebSocket, 1000); } } @@ -382,7 +387,6 @@ exports.install = function(instance) { if (ws) ws.close(); }) - function getPin(line) { //conversionTable let keys = Object.keys(pinsData); @@ -483,14 +487,14 @@ exports.install = function(instance) { if (!force) { if (relaysData[line].contactor == value) { instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); - logger.debug(`turnLine: line is already ${onOrOff} `, line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); return; } } // if(!rsPort.isOpen && !ws) if (!rsPort && !ws) { - errLogger.error("dido controller - port or websocket is not opened"); + errLogger.error("Dido - port or websocket is not opened"); return; } @@ -502,18 +506,18 @@ exports.install = function(instance) { rsPort.write(Buffer.from(arr), function(err) { if (err === undefined) { - monitor.info(`turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); switchLogic(arr); } else { - monitor.info(`turnLine ${onOrOff} WRITE error`, err); + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); } }); } else if (ws) { //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method - monitor.info(`turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; ws.send(JSON.stringify(cmd)); } diff --git a/flow/modbus_reader.js b/flow/modbus_reader.js index 65eed75..064f956 100644 --- a/flow/modbus_reader.js +++ b/flow/modbus_reader.js @@ -76,6 +76,11 @@ exports.install = function(instance) { let obj = this; + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + this.socket = new SerialPort("/dev/ttymxc0", { baudRate: 9600, }) @@ -86,15 +91,11 @@ exports.install = function(instance) { } this.socket.on('error', function(e) { - console.log('socket connection error', e); - if (e.code == 'ECONNREFUSED' || e.code == 'ECONNRESET') { - console.log(exports.title + ' Waiting 10 seconds before trying to connect again'); - setTimeout(obj.startSocket, 10000); - } + console.log('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? }); this.socket.on('close', function() { - console.log('Socket connection closed ' + exports.title + ' Waiting 10 seconds before trying to connect again'); + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting again'); setTimeout(obj.startSocket, 10000); }); @@ -115,7 +116,8 @@ exports.install = function(instance) { this.deviceAddress = dev.deviceAddress; // 1 or 2 or any number this.device = dev.device; //em340, twilight_sensor - if (this.indexInDeviceConfig == 0) setTimeout(this.readRegisters, this.timeoutInterval); + //if we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) setTimeout(this.readRegisters, this.timeoutInterval); else setTimeout(this.readRegisters, DELAY_BETWEEN_DEVICES); } @@ -330,7 +332,8 @@ exports.install = function(instance) { phases = FLOW.GLOBALS.settings.phases; tbName = FLOW.GLOBALS.settings.rvoTbName; noVoltage = FLOW.GLOBALS.settings.no_voltage; - mainSocket = new SocketWithClients(); + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); // this notification is to show, that flow (unipi) has been restarted sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); diff --git a/flow/show_dbdata.js b/flow/show_dbdata.js index 0e5cbcc..1e23ff7 100644 --- a/flow/show_dbdata.js +++ b/flow/show_dbdata.js @@ -4,7 +4,7 @@ exports.group = 'Worksys'; exports.color = '#888600'; exports.version = '1.0.2'; exports.icon = 'sign-out'; -exports.input = 7; +exports.input = 8; exports.output = 1; const { exec } = require('child_process'); @@ -38,10 +38,12 @@ exports.install = function(instance) { else instance.send(0, stdout); }) }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) }; - const rpcSwitchOffLine = { "topic": "v1/gateway/rpc",