Does this flow work on your install?

I have attempted to craft a flow that sets a flow variable in file context storage to a string with the value being the IP:PORT of Node-RED and display in status of function.

The only non core node used is node-red-contrib-string (I will see about removing this in the future, but for testing/developing it saves me time).

If you have a minute to test it for me, it would be greatly appreciated. If you choose to, could you respond with whether or not the resulting status was valid for your install (if http://IP:PORT/ or https://IP:PORT/ brings up the editor, report valid). And if any modifications were used to get it to function correctly, or any recommendations.

My goal is to make it function correctly on as many Node-RED installation configurations as possible.

[EDIT] [Skip this flow] Here is flow 1: [REMOVED]
[EDIT] [Skip this flow] Here is flow 2: [REMOVED]
[EDIT] [Skip this flow] Here is flow 3: [REMOVED]
[EDIT] [Skip this flow] Here is flow 4: [REMOVED]

[EDIT] Here is an updated flow we'll call flow 5, a second attempt at multi-platform with OS checks:

[{"id":"fa93a8d0db17300c","type":"group","z":"8427043ceb652fb8","name":"Save Node-RED IP:PORT as a flow variable","style":{"stroke":"#e9967a","label":true},"nodes":["eb01511ae1b2e493","725055ecb7e2d269","75974486fa8d3c0c","5fcb639d39593668","0a473496d59ec53a","b6d1388d2cdf9667","918184ea29eaf45e","ef2dfbc87b4577b7","f2f028d982b0a838","8ef52d8947c12d5b","90bfe4a6c1d53f69","4ebf776c968578ba","d526b6397585be29","fd49cc71b03898e1","cd157e9770a7c6c6","a1876d79f7e61de0","9adbb9c75fc57709","0372f661a5d1f1c2","0d671a161de1e42d","6fd25156afd20d1e","82c5bd495ad105a9","eae61b440aced7e3","278bf7896f4fc418","299a72d1d01ae0e1","1282f5f1f122f731","cb1c2f9dd0026427","06bab8ed203c6c4c"],"x":34,"y":1239,"w":1572,"h":369.5},{"id":"eb01511ae1b2e493","type":"inject","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"kill","props":[{"p":"kill","v":"SIGTERM","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":1560,"wires":[["ef2dfbc87b4577b7","f2f028d982b0a838","a1876d79f7e61de0","82c5bd495ad105a9"]]},{"id":"725055ecb7e2d269","type":"inject","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"run","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":"0.2","topic":"","payload":"","payloadType":"str","x":130,"y":1320,"wires":[["299a72d1d01ae0e1"]]},{"id":"75974486fa8d3c0c","type":"comment","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"save Node-RED IP:PORT","info":"","x":170,"y":1280,"wires":[]},{"id":"5fcb639d39593668","type":"function","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"save IP:PORT","func":"if ((typeof msg.payload === \"string\")&&(msg.payload != \"\")) {\n    flow.set(\"ipPort\", msg.payload, \"file\");\n};\nnode.status({ fill: \"green\", shape: \"dot\", text: flow.get(\"ipPort\", \"file\")||msg.payload });","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1500,"y":1460,"wires":[]},{"id":"0a473496d59ec53a","type":"inject","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"check","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"str","x":1350,"y":1500,"wires":[["5fcb639d39593668"]]},{"id":"b6d1388d2cdf9667","type":"inject","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"set manually","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"127.0.0.1:1880","payloadType":"str","x":1330,"y":1420,"wires":[["5fcb639d39593668"]]},{"id":"918184ea29eaf45e","type":"function","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"format","func":"msg.payload = `${msg.ip}:${msg.port}`;\nreturn { \"payload\": msg.payload };","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1350,"y":1460,"wires":[["5fcb639d39593668"]],"info":"// nrlint function-eslint:off\n"},{"id":"ef2dfbc87b4577b7","type":"exec","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","command":"pwd","addpay":"","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"pwd unix","x":520,"y":1500,"wires":[["8ef52d8947c12d5b"],[],[]]},{"id":"f2f028d982b0a838","type":"exec","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","command":"hostname -I |  cut -d ' ' -f1 | tr -d '\\n'","addpay":"","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"get ip linux","x":530,"y":1440,"wires":[["fd49cc71b03898e1"],[],[]]},{"id":"8ef52d8947c12d5b","type":"string","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"","methods":[{"name":"collapseWhitespace","params":[]},{"name":"ensureRight","params":[{"type":"str","value":"/.node-red"}]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":690,"y":1500,"wires":[["90bfe4a6c1d53f69"]]},{"id":"90bfe4a6c1d53f69","type":"function","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"format","func":"msg.payload = `${msg.payload}/settings.js`;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":810,"y":1500,"wires":[["4ebf776c968578ba"]],"info":"// nrlint function-eslint:off\n"},{"id":"4ebf776c968578ba","type":"file in","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"","filename":"payload","filenameType":"msg","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":940,"y":1500,"wires":[["d526b6397585be29"]]},{"id":"d526b6397585be29","type":"change","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"port","rules":[{"t":"set","p":"port","pt":"msg","to":"$match(payload, /PORT \\|\\|.([0-9]+)/).groups[0]","tot":"jsonata"},{"t":"delete","p":"payload","pt":"msg"},{"t":"delete","p":"filename","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1070,"y":1500,"wires":[["cd157e9770a7c6c6"]]},{"id":"fd49cc71b03898e1","type":"change","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"set ip unix","rules":[{"t":"set","p":"ip","pt":"msg","to":"payload","tot":"msg"},{"t":"delete","p":"payload","pt":"msg"},{"t":"delete","p":"rc","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1060,"y":1440,"wires":[["cd157e9770a7c6c6"]]},{"id":"cd157e9770a7c6c6","type":"join","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"","mode":"custom","build":"merged","property":"","propertyType":"full","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":1230,"y":1460,"wires":[["918184ea29eaf45e"]]},{"id":"a1876d79f7e61de0","type":"exec","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","command":"hostname","addpay":"","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"get ip macOS","x":540,"y":1380,"wires":[["fd49cc71b03898e1"],[],[]]},{"id":"9adbb9c75fc57709","type":"function","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"check os","func":"msg.payload = msg.operatingSystem.name[0].toLowerCase();\nif (msg.payload === \"d\") {\n    node.send([{ \"payload\": \"\" }, null, null ]);\n} else if (msg.payload === \"l\") {\n    node.send([ null, { \"payload\": \"\" }, null ]);\n} else if (msg.payload === \"w\") {\n    node.send([ null, null, { \"payload\": \"\" }]);\n};","outputs":3,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":1440,"wires":[["a1876d79f7e61de0","ef2dfbc87b4577b7"],["f2f028d982b0a838","ef2dfbc87b4577b7"],["82c5bd495ad105a9","eae61b440aced7e3"]],"outputLabels":["mac","linux","windows"]},{"id":"0372f661a5d1f1c2","type":"join","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"","mode":"custom","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"/","joinerType":"str","accumulate":false,"timeout":"","count":"3","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":930,"y":1560,"wires":[["8ef52d8947c12d5b"]]},{"id":"0d671a161de1e42d","type":"switch","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"","property":"payload","propertyType":"msg","rules":[{"t":"index","v":"0","vt":"num","v2":"2","v2t":"num"}],"checkall":"true","repair":false,"outputs":1,"x":810,"y":1560,"wires":[["0372f661a5d1f1c2"]]},{"id":"6fd25156afd20d1e","type":"split","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"","splt":"\\","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":690,"y":1560,"wires":[["0d671a161de1e42d"]]},{"id":"82c5bd495ad105a9","type":"exec","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","command":"echo %cd%","addpay":"","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"pwd windows","x":530,"y":1560,"wires":[["6fd25156afd20d1e"],[],[]]},{"id":"eae61b440aced7e3","type":"function","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"get ip windows","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":540,"y":1320,"wires":[["1282f5f1f122f731"]]},{"id":"278bf7896f4fc418","type":"change","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"set ip windows alt","rules":[{"t":"set","p":"ip","pt":"msg","to":"0.0.0.0","tot":"str"},{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1030,"y":1360,"wires":[["cd157e9770a7c6c6"]]},{"id":"299a72d1d01ae0e1","type":"function","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"os npm module","func":"// info about the current user\nmsg.user = os.userInfo();\n\n// returns the system uptime\nmsg.uptime = {\n    days: (os.uptime() / 86400).toFixed(2),\n    hours: (os.uptime() / 3600).toFixed(2),\n    minutes: (os.uptime() / 60).toFixed(2),\n    seconds: os.uptime().toFixed(2),\n};\n\n// info about the operating system\nmsg.operatingSystem = {\n    name: os.type(),\n    release: os.release(),\n    totalMem: `${parseFloat((os.totalmem() / Math.pow(1024, 3)).toFixed(2))}GB`,\n    freeMem: `${parseFloat((os.freemem() / Math.pow(1024, 3)).toFixed(2))}GB`,\n    architecture: os.arch(),\n    homeDir: os.homedir(),\n    tempDir: os.tmpdir(),\n    networkInt: os.networkInterfaces(),\n};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"os","module":"os"}],"x":280,"y":1320,"wires":[["9adbb9c75fc57709","06bab8ed203c6c4c"]],"info":"// nrlint function-eslint:off\n"},{"id":"1282f5f1f122f731","type":"change","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"set ip windows","rules":[{"t":"set","p":"ip","pt":"msg","to":"127.0.0.1","tot":"str"},{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1040,"y":1400,"wires":[["cd157e9770a7c6c6"]]},{"id":"cb1c2f9dd0026427","type":"debug","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"debug 83","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":660,"y":1280,"wires":[]},{"id":"06bab8ed203c6c4c","type":"function","z":"8427043ceb652fb8","g":"fa93a8d0db17300c","name":"get info","func":"let placeholder = {\n    \"homedirUser\": msg.user.homedir,\n    \"homedirOS\": msg.operatingSystem.homeDir,\n};\nif (msg.operatingSystem.networkInt.eth0) {\n    placeholder.eth0 = msg.operatingSystem.networkInt.eth0[0].address;\n};\nif (msg.operatingSystem.networkInt.wlan0) {\n    placeholder.wlan0 = msg.operatingSystem.networkInt.wlan0[0].address;\n};\nif (msg.operatingSystem.networkInt.lo) {\n    placeholder.lo = msg.operatingSystem.networkInt.lo[0].address;\n};\nmsg = placeholder;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":1280,"wires":[["cb1c2f9dd0026427"]]}]

It does not.

Note that on, for example Debian, there is no netstat available out of the box. Some other commands like lsof require sudo/root to get the details of processes. And the output could differ across operating systems.

What is consistent between OS'es is the settings.js path & file. You use a file read node, path: ./.node-red/settings.js and grep the port from it with a change node using a regular expression/jsonata. eg: $match(payload, /PORT \|\|.([0-9]+)/).groups[0].$number()

Only thing left is the ip address. On linux you can get this via hostname -I

Working flow on my Debian installation without dependencies:

[{"id":"0144825c66a59d94","type":"inject","z":"97a0c8ed238fcbfa","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":132,"y":120,"wires":[["87d31d298a59b64c","8d7d854ea1f34d80"]]},{"id":"87d31d298a59b64c","type":"file in","z":"97a0c8ed238fcbfa","name":"","filename":"./.node-red/settings.js","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":340,"y":96,"wires":[["60aa475801cc345e"]]},{"id":"e4b06da77d9be30a","type":"debug","z":"97a0c8ed238fcbfa","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":910,"y":120,"wires":[]},{"id":"60aa475801cc345e","type":"change","z":"97a0c8ed238fcbfa","name":"port","rules":[{"t":"set","p":"payload","pt":"msg","to":"$match(payload, /PORT \\|\\|.([0-9]+)/).groups[0].$number()","tot":"jsonata"},{"t":"set","p":"topic","pt":"msg","to":"port","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":598,"y":96,"wires":[["d390223bcf992a80"]]},{"id":"8d7d854ea1f34d80","type":"exec","z":"97a0c8ed238fcbfa","command":"hostname -I |  cut -d ' ' -f1 | tr -d '\\n'","addpay":"","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":380,"y":144,"wires":[["f2e133ceae7011ec"],[],[]]},{"id":"d390223bcf992a80","type":"join","z":"97a0c8ed238fcbfa","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":746,"y":120,"wires":[["e4b06da77d9be30a"]]},{"id":"f2e133ceae7011ec","type":"change","z":"97a0c8ed238fcbfa","name":"ip","rules":[{"t":"set","p":"topic","pt":"msg","to":"ip","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":602,"y":144,"wires":[["d390223bcf992a80"]]}]

Tried on my Windows instance

@cymplecy Is localhost:1880 valid for your editor?

@bakman2 I like your approach, but the read file node's path isn't universal either as it doesn't work on my WSL instance of Node-RED.

Yes - it's running on the same windows machine

hmm where is it located then ?

in that case you may want to add an additional flow to check what OS/filesystem it is first.

i though the read file node would handle double slashes, but apperently it does not

On Windows, path separators may need to be escaped,

That is only if you use backslashes. Forward slashes should work fine on Windows.

1 Like

@bakman2 Does flow 2 in the first post (I've edited it) work for you?

Is does not, because pwd gets the path of the working directory, which is above the .node-red dir, will need to add /.node-red

./.node-red/settings.js

though this does not work in windows apparently

@bakman2 Does flow 3 resolve this issue?

Running flow3 on macOS Montery (v12.5) I get undefined:1880
EDIT: Running the get ip exec commands in a cli I get:

Paul@PaulsM1 ~ % hostname -I |  cut -d ' ' -f1 | tr -d '\n'
hostname: illegal option -- I
usage: hostname [-f] [-s | -d] [name-of-host]
Paul@PaulsM1 ~ % hostname                                  
PaulsM1.local
Paul@PaulsM1 ~ % 

Yes cross platform remains a challenge, requires multiple if/else checks.

1 Like

@zenofmud Would PaulsM1.local:1880 be valid for your editor?

It is not a good idea to assume anything about the current directory in node-red. It may also depend on how node-red is installed and run.

1 Like

Yes, that does bring up the editor.

1 Like

If flow 4 does not work for you please confirm your:
OS
Node-RED install location
Description of any errors

same as this:

It does not. In macOS the name is 'Darwin'

Changing the IF to test for a 'd' and it works

1 Like