diff --git a/examples/reconnectByStatus.json b/examples/reconnectByStatus.json new file mode 100644 index 0000000..7b44938 --- /dev/null +++ b/examples/reconnectByStatus.json @@ -0,0 +1 @@ +[{"id":"d4ec43d676d71924","type":"tab","label":"example: reconnect by status","disabled":false,"info":"","env":[]},{"id":"0cb6e38f017b0b33","type":"group","z":"d4ec43d676d71924","name":"INIT","style":{"label":true},"nodes":["6334a7a294ee138a","05ca3e81d803501f","5686987baae65ff3","6bec8ffb9cff1e47","990911a805394eff","1e176123b5a58c18","7987ed568df6865a","4742fa2089d90906","8addd7e927a81a19","e9fefaad5535a04c"],"x":54,"y":119,"w":452,"h":362},{"id":"5739ab929deaa284","type":"group","z":"d4ec43d676d71924","name":"ERROR","style":{"label":true},"nodes":["fa3f3cfc6360a790","067dc64f90f811a8","53da5f211817a0c0"],"x":534,"y":119,"w":372,"h":122},{"id":"410ae4259f812de0","type":"group","z":"d4ec43d676d71924","name":"UPDATE","style":{"label":true},"nodes":["2ff7924b.af468e","4fe21db4.c90944","e6d8af0d.b3492","764c719caa4e089e"],"x":534,"y":259,"w":572,"h":122},{"id":"94c2208057c0bc8d","type":"group","z":"d4ec43d676d71924","name":"MAIN","style":{"label":true},"nodes":["7d8d23453abc2f62","b0dcc39950c921d9","c57c8052ebaf3e5e","049d72340fa04735","b2b2e5bab96c311d","3bf37b4d2354aeef","069c2f9ee623c980","fdc56eb61459e6e6","c301409396fad6fe","c7e93c184d3d2e6e","18c42bc8af162820","da9d3f22968f13b8"],"x":54,"y":519,"w":992,"h":322},{"id":"f1339cf8c704e4ed","type":"group","z":"d4ec43d676d71924","name":"RECONNECT","style":{"label":true},"nodes":["cb32c36d796d41fc","12d57fe6012d5b30","4f9d8996e5951c2a","a20d257c94a5b305"],"x":534,"y":379,"w":512,"h":122},{"id":"6334a7a294ee138a","type":"comment","z":"d4ec43d676d71924","g":"0cb6e38f017b0b33","name":"initialize all global driver status flags @ the beginning","info":"","x":270,"y":160,"wires":[]},{"id":"05ca3e81d803501f","type":"inject","z":"d4ec43d676d71924","g":"0cb6e38f017b0b33","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"5","topic":"","payload":"","payloadType":"date","x":170,"y":200,"wires":[["5686987baae65ff3"]]},{"id":"5686987baae65ff3","type":"function","z":"d4ec43d676d71924","g":"0cb6e38f017b0b33","name":"config","func":"global.set('app.status', {\n 'dev1': false, //modbus\n 'dev2': false, //melsec\n //...\n})\n\nglobal.set('app.types', {\n 'dev1': 'modbus',\n 'dev2': 'melsec'\n});\n\nglobal.set('app.config', {\n 'reconnects': { //allowed number of reconnects\n 'dev1': {\n amount: 3, //default: 3 retries; (-1) --> unlimited\n interval: 5, //every 60sec\n },\n 'dev2': {\n amount: -1, //default: 3 retries; (-1) --> unlimited\n interval: 5, //every 60sec\n },\n //...\n }\n});\n\nglobal.set('app.initialized', false);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is started.\nglobal.set('app', undefined)","finalize":"","libs":[],"x":390,"y":200,"wires":[["990911a805394eff","8addd7e927a81a19"]]},{"id":"fa3f3cfc6360a790","type":"catch","z":"d4ec43d676d71924","g":"5739ab929deaa284","name":"","scope":null,"uncaught":false,"x":620,"y":200,"wires":[["067dc64f90f811a8"]]},{"id":"067dc64f90f811a8","type":"debug","z":"d4ec43d676d71924","g":"5739ab929deaa284","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":800,"y":200,"wires":[]},{"id":"53da5f211817a0c0","type":"comment","z":"d4ec43d676d71924","g":"5739ab929deaa284","name":"general error output","info":"","x":650,"y":160,"wires":[]},{"id":"7d8d23453abc2f62","type":"inject","z":"d4ec43d676d71924","g":"94c2208057c0bc8d","name":"1s","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":760,"wires":[["c57c8052ebaf3e5e"]]},{"id":"b0dcc39950c921d9","type":"comment","z":"d4ec43d676d71924","g":"94c2208057c0bc8d","name":"Main application","info":"","x":180,"y":560,"wires":[]},{"id":"c57c8052ebaf3e5e","type":"function","z":"d4ec43d676d71924","g":"94c2208057c0bc8d","name":"initialized?","func":"const app = global.get('app');\n\n//only return msg if initialized\nif (app && app.initialized) //if exisiting and true\n return msg;\nelse \n return null;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":310,"y":760,"wires":[["049d72340fa04735","069c2f9ee623c980","cb32c36d796d41fc"]]},{"id":"049d72340fa04735","type":"debug","z":"d4ec43d676d71924","g":"94c2208057c0bc8d","name":"debug 2","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":480,"y":700,"wires":[]},{"id":"1e176123b5a58c18","type":"modbus-flex-connector","z":"d4ec43d676d71924","g":"0cb6e38f017b0b33","name":"dev1","maxReconnectsPerMinute":4,"emptyQueue":false,"showStatusActivities":true,"showErrors":false,"server":"e47fc77d895bba2e","x":390,"y":320,"wires":[[]]},{"id":"990911a805394eff","type":"function","z":"d4ec43d676d71924","g":"0cb6e38f017b0b33","name":"dev1","func":"//do ist more generically\nmsg.payload = { \n 'connectorType': 'TCP', \n 'tcpHost': '127.0.0.1', \n 'tcpPort': '502',\n 'unitId': 1\n} \n\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":130,"y":320,"wires":[["1e176123b5a58c18","4742fa2089d90906"]]},{"id":"c58aa6ff244ba9cb","type":"comment","z":"d4ec43d676d71924","name":"Dependencies: node-red-contrib-modbus@5.26.0","info":"","x":480,"y":40,"wires":[]},{"id":"6917a078cef0a861","type":"comment","z":"d4ec43d676d71924","name":"Dependencies: node-red-contrib-mcprotocol@1.2.1","info":"","x":490,"y":80,"wires":[]},{"id":"6bec8ffb9cff1e47","type":"comment","z":"d4ec43d676d71924","g":"0cb6e38f017b0b33","name":"initialize connection to modbusTcp dev1","info":"","x":230,"y":240,"wires":[]},{"id":"7987ed568df6865a","type":"comment","z":"d4ec43d676d71924","g":"0cb6e38f017b0b33","name":"modbus dev1","info":"","x":410,"y":280,"wires":[]},{"id":"4742fa2089d90906","type":"function","z":"d4ec43d676d71924","g":"0cb6e38f017b0b33","name":"init --> true","func":"global.set('app.initialized', true);\n","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":410,"y":440,"wires":[]},{"id":"b2b2e5bab96c311d","type":"MC Read","z":"d4ec43d676d71924","g":"94c2208057c0bc8d","name":"dev2","topic":"","connection":"3ad3c430834a457f","address":"address","addressType":"msg","outputFormat":0,"errorHandling":"msg","outputs":1,"x":970,"y":760,"wires":[[]]},{"id":"3bf37b4d2354aeef","type":"modbus-flex-getter","z":"d4ec43d676d71924","g":"94c2208057c0bc8d","name":"dev1","showStatusActivities":true,"showErrors":false,"showWarnings":true,"logIOActivities":false,"server":"e47fc77d895bba2e","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"","x":970,"y":580,"wires":[[],[]]},{"id":"069c2f9ee623c980","type":"function","z":"d4ec43d676d71924","g":"94c2208057c0bc8d","name":"driver select","func":"if (typeof msg.channel !== 'undefined') {\n //here is the space for your driver implementation\n //e.g. msg preparations for specific modbus register \n \n //melsec\n if(msg.channel.includes('melsec'))\n return [msg,null];\n\n //modbus\n if (msg.channel.includes('modbus'))\n return [msg, null];\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":490,"y":760,"wires":[["b2b2e5bab96c311d","3bf37b4d2354aeef"]]},{"id":"fdc56eb61459e6e6","type":"inject","z":"d4ec43d676d71924","g":"94c2208057c0bc8d","name":"melsec;M100","props":[{"p":"channel","v":"melsec","vt":"str"},{"p":"address","v":"M100","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":640,"wires":[["c57c8052ebaf3e5e"]]},{"id":"c301409396fad6fe","type":"comment","z":"d4ec43d676d71924","g":"94c2208057c0bc8d","name":"test trigger","info":"","x":160,"y":600,"wires":[]},{"id":"c7e93c184d3d2e6e","type":"inject","z":"d4ec43d676d71924","g":"94c2208057c0bc8d","name":"modbus","props":[{"p":"command","v":"melsec","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":150,"y":680,"wires":[["c57c8052ebaf3e5e"]]},{"id":"2ff7924b.af468e","type":"comment","z":"d4ec43d676d71924","g":"410ae4259f812de0","name":"updates the online status","info":"","x":670,"y":300,"wires":[]},{"id":"4fe21db4.c90944","type":"status","z":"d4ec43d676d71924","g":"410ae4259f812de0","name":"","scope":["b2b2e5bab96c311d","3bf37b4d2354aeef"],"x":620,"y":340,"wires":[["764c719caa4e089e"]]},{"id":"e6d8af0d.b3492","type":"function","z":"d4ec43d676d71924","g":"410ae4259f812de0","name":"update online status","func":"const app = global.get('app')\n//only msg.status\nif (typeof msg.status !== 'undefined') {\n let fill = msg['status']['fill'] || 'empty';\n let type = msg['status']['source']['type'] || 'empty';\n let status = msg['status']['text'] || 'empty'; \n let key = msg['status']['source']['name'] || 'empty';\n\n app.status[key] = fill === 'green' ? true : false;\n}","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":980,"y":340,"wires":[]},{"id":"764c719caa4e089e","type":"function","z":"d4ec43d676d71924","g":"410ae4259f812de0","name":"initialized?","func":"const app = global.get('app');\n\n//only return msg if initialized\nif (app && app.initialized) //if exisiting and true\n return msg;\nelse \n return null;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":340,"wires":[["e6d8af0d.b3492"]]},{"id":"18c42bc8af162820","type":"comment","z":"d4ec43d676d71924","g":"94c2208057c0bc8d","name":"main trigger","info":"","x":170,"y":720,"wires":[]},{"id":"8addd7e927a81a19","type":"function","z":"d4ec43d676d71924","g":"0cb6e38f017b0b33","name":"dev2","func":"//do ist more generically\nmsg.connect = true;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":130,"y":360,"wires":[["e9fefaad5535a04c"]]},{"id":"e9fefaad5535a04c","type":"link out","z":"d4ec43d676d71924","g":"0cb6e38f017b0b33","name":"init","mode":"link","links":["da9d3f22968f13b8","61df7b4582520ad4"],"x":215,"y":360,"wires":[]},{"id":"da9d3f22968f13b8","type":"link in","z":"d4ec43d676d71924","g":"94c2208057c0bc8d","name":"init","links":["e9fefaad5535a04c"],"x":545,"y":800,"wires":[["b2b2e5bab96c311d"]]},{"id":"cb32c36d796d41fc","type":"function","z":"d4ec43d676d71924","g":"f1339cf8c704e4ed","name":"reinitialize","func":"const app = global.get('app');\n\nfor(let d in app.status) {\n //get every device online status \n const devKey = d;\n const status = app.status[d];\n\n //check if online --> continue\n if (status) {\n continue;\n }\n\n //otherwise initiate a reconnect\n //e.g. melsec\n\n //first execution, so no timer?\n const reconnects = app.config.reconnects;\n if (!reconnects[devKey].hasOwnProperty('timer')) {\n reconnects[devKey].timer = {\n time: new Date().getTime(),\n endTime: new Date().getTime() + reconnects[devKey].interval * 1000\n }\n } else {\n //timer exists already, so it is running\n //is exceeded?\n const timer = reconnects[devKey].timer;\n timer.time = new Date().getTime();\n if (timer.time >= timer.endTime) {\n //only check count if >0\n if (reconnects[devKey].amount>=0) {\n if (!reconnects[devKey].count) {\n reconnects[devKey].count = 1;\n } else {\n //skip for this device\n if (reconnects[devKey].count >= reconnects[devKey].amount) {\n timer.time = 0; //inaktivate timer\n continue;\n }\n //or try to reconnect\n reconnects[devKey].count++;\n }\n\n const types = app.types;\n const m = { dev: devKey };\n //identify the node type\n if (types[devKey] === ' melsec') {\n m.reinitialize = true;\n } // ...\n // ... more device handling here\n \n timer.endTime = new Date().getTime() + reconnects[devKey].interval * 1000\n node.send(m);\n\n } else {\n const types = app.types;\n const m = {dev: devKey};\n //identify the node type\n if (types[devKey] === ' melsec') {\n m.reinitialize = true;\n } // ...\n // ... more device handling here\n\n if (!reconnects[devKey].count) {\n reconnects[devKey].count = 1;\n } else {\n reconnects[devKey].count++;\n }\n\n //reset endTime\n timer.endTime = new Date().getTime() + reconnects[devKey].interval * 1000\n node.send(m);\n }\n } else {}\n }\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":440,"wires":[["4f9d8996e5951c2a"]]},{"id":"12d57fe6012d5b30","type":"debug","z":"d4ec43d676d71924","g":"f1339cf8c704e4ed","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":940,"y":420,"wires":[]},{"id":"4f9d8996e5951c2a","type":"switch","z":"d4ec43d676d71924","g":"f1339cf8c704e4ed","name":"","property":"dev","propertyType":"msg","rules":[{"t":"eq","v":"dev1","vt":"str"},{"t":"eq","v":"dev2","vt":"str"},{"t":"eq","v":"dev3","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":750,"y":440,"wires":[["12d57fe6012d5b30","3bf37b4d2354aeef"],["a20d257c94a5b305","b2b2e5bab96c311d"],[]]},{"id":"a20d257c94a5b305","type":"debug","z":"d4ec43d676d71924","g":"f1339cf8c704e4ed","name":"debug 4","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":940,"y":460,"wires":[]},{"id":"53a831948f8a0081","type":"comment","z":"d4ec43d676d71924","name":"README","info":"two device connects are prefined within the \"config\" node.\none modbusTcp device and one mcprotocol device.\nthis application shows, how a status change displayed by the colored dot indicator below, \ncan be used to retrigger a reconnect a specific connector node, like the mc protocol node.\nTo do so, the connector node needs a possiblitiy to dynamically configure it by msg properties like\nmsg.connect, msg.reinitialize, msg.disconnect.\n\nin this example, the amount of connection retries can be modified within the \"config\" node.\n-1 means unlimited retries. the interval specifies the time period after which a reconnect is executed.","x":120,"y":40,"wires":[],"icon":"node-red/alert.svg"},{"id":"e47fc77d895bba2e","type":"modbus-client","name":"dev1","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"127.0.0.1","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true},{"id":"3ad3c430834a457f","type":"MC Protocol Connection","name":"dev2","host":"127.0.0.1","port":"5001","protocol":"TCP","frame":"3E","plcType":"Q","ascii":false,"PLCStation":"","PCStation":"","PLCModuleNo":"","network":"","octalInputOutput":false,"timeout":"1000"}] \ No newline at end of file