Change static IP address from dashboard

I'm trying to change the static IP address of my PI from a node red dashboard. I found this link

https://flows.nodered.org/flow/520df02be955b412ddb89bcbf70cce34

[{"id":"2d2bd18e.3e4abe","type":"tab","label":"IP Settings","disabled":false,"info":""},{"id":"6a63b433.e2a73c","type":"exec","z":"2d2bd18e.3e4abe","command":"cat /etc/dhcpcd.conf","addpay":false,"append":"","useSpawn":"","timer":"","name":"","x":476,"y":179,"wires":[["3239ea8.73a1016"],[],[]]},{"id":"3239ea8.73a1016","type":"function","z":"2d2bd18e.3e4abe","name":"parse response","func":"var lines = msg.payload.split(\"\\n\");\nvar data = [];\n\nfor(var i=0; i< lines.length; i++){\n    if(lines[i].indexOf(\"interface eth0\") != -1)\n        break;\n}\n\n//check if interface eth0 is disabled\nif(i < lines.length && lines[i].indexOf(\"#\") >= 0) flow.set('disabled', true);\nelse flow.set('disabled', false);\n\nnode.send({topic:'interface eth0', payload:flow.get('disabled')})\n\ni++;\n\nfor(i; i< lines.length; i++){\n   \n   //new interface, not eth0\n   if(lines[i].indexOf(\"static\") == -1)\n    break;\n    \n    var tmp = lines[i].split(\"=\");\n    if(tmp.length==2){\n        var prop = tmp[0].split(' ')[1].trim();\n        var value = tmp[1].trim();\n        \n        flow.set(prop, value);\n        node.send({topic:prop, payload:value})\n    }\n} ","outputs":1,"noerr":0,"x":716,"y":166,"wires":[["3e969ca3.142384"]]},{"id":"3e969ca3.142384","type":"switch","z":"2d2bd18e.3e4abe","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"ip_address","vt":"str"},{"t":"eq","v":"routers","vt":"str"},{"t":"eq","v":"domain_name_servers","vt":"str"},{"t":"eq","v":"interface eth0","vt":"str"}],"checkall":"false","repair":false,"outputs":4,"x":888,"y":166,"wires":[["2d434d1f.145822"],["502308c7.25bef8"],["6a605c6d.329194","140df8ca.dea297"],["ba4f96ca.0f28b8"]]},{"id":"2d434d1f.145822","type":"ui_text_input","z":"2d2bd18e.3e4abe","name":"ip_address","label":"Indirizzo IP","group":"1cf52e38.3cfee2","order":2,"width":0,"height":0,"passthru":false,"mode":"text","delay":"0","topic":"ip_address","x":1130,"y":120,"wires":[["a825b0e4.2a051"]]},{"id":"502308c7.25bef8","type":"ui_text_input","z":"2d2bd18e.3e4abe","name":"router","label":"Router","group":"1cf52e38.3cfee2","order":3,"width":0,"height":0,"passthru":false,"mode":"text","delay":"0","topic":"routers","x":1109,"y":163,"wires":[["a825b0e4.2a051"]]},{"id":"6a605c6d.329194","type":"ui_text_input","z":"2d2bd18e.3e4abe","name":"dns","label":"DNS","group":"1cf52e38.3cfee2","order":4,"width":0,"height":0,"passthru":false,"mode":"text","delay":"0","topic":"domain_name_servers","x":1109,"y":206,"wires":[["a825b0e4.2a051"]]},{"id":"9ae462fb.d924d","type":"exec","z":"2d2bd18e.3e4abe","command":"sudo sed -i ","addpay":true,"append":"","useSpawn":"","timer":"","oldrc":false,"name":"","x":510,"y":320,"wires":[[],[],[]]},{"id":"1b55bbd2.2f6a74","type":"ui_button","z":"2d2bd18e.3e4abe","name":"reboot","group":"1cf52e38.3cfee2","order":5,"width":"3","height":"1","passthru":false,"label":"Reboot","color":"","bgcolor":"","icon":"","payload":"By pressing OK the device will be rebooted. If settings are wrong this may cause the device to be unreachable","payloadType":"str","topic":"","x":170,"y":480,"wires":[["846fb983.93f448"]]},{"id":"6da389d0.e8d598","type":"exec","z":"2d2bd18e.3e4abe","command":"sudo reboot","addpay":false,"append":"","useSpawn":"","timer":"","name":"","x":650,"y":480,"wires":[[],[],[]]},{"id":"d0341b01.217ee8","type":"ui_button","z":"2d2bd18e.3e4abe","name":"refresh","group":"1cf52e38.3cfee2","order":6,"width":"3","height":"1","passthru":false,"label":"Update","color":"","bgcolor":"","icon":"","payload":"true","payloadType":"bool","topic":"","x":111.44442749023438,"y":247.33291149139404,"wires":[["fb34e190.3926a","c2728ad2.71ac48"]]},{"id":"fb34e190.3926a","type":"delay","z":"2d2bd18e.3e4abe","name":"","pauseType":"delay","timeout":"300","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":278.8888740539551,"y":247.44451141357422,"wires":[["6a63b433.e2a73c"]]},{"id":"c2728ad2.71ac48","type":"function","z":"2d2bd18e.3e4abe","name":"send commands","func":"var properties = flow.get(\"properties\");\n\nvar disabled = flow.get(\"disabled\") ? '#' : '';\n\nif(disabled == '#'){\n    //enable interface (replace only first occurance)\n    var command = `'0,/#interface eth0/s//interface eth0/g;' /etc/dhcpcd.conf`;\n    node.send({payload: command})\n}\n\nfor(var i=0;i<properties.length;i++){\n    var p = properties[i];\n    \n    var old_value = flow.get(p);\n    var new_value = flow.get(p+\"_new\") || old_value;\n    \n    if(old_value && ((old_value != new_value) || disabled == '#'))\n    {\n        //enable interface (replace only first occurance)\n        var command = `'0,\\\\?${disabled}static ${p}=${old_value}?s??static ${p}=${new_value}?g;' /etc/dhcpcd.conf`;\n        node.send({payload: command})\n    }\n}\n\n","outputs":1,"noerr":0,"x":300,"y":320,"wires":[["8d2915b0.eb5188","9ae462fb.d924d"]]},{"id":"846fb983.93f448","type":"ui_toast","z":"2d2bd18e.3e4abe","position":"dialog","displayTime":"3","highlight":"","outputs":1,"ok":"OK","cancel":"Cancel","topic":"ATTENTION","name":"","x":330,"y":480,"wires":[["9f141047.ed494"]]},{"id":"9f141047.ed494","type":"switch","z":"2d2bd18e.3e4abe","name":"OK ?","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"OK","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":490,"y":480,"wires":[["6da389d0.e8d598"]]},{"id":"a825b0e4.2a051","type":"function","z":"2d2bd18e.3e4abe","name":"store new","func":"flow.set(msg.topic+\"_new\", msg.payload);\nreturn msg;","outputs":1,"noerr":0,"x":1419,"y":161,"wires":[["aef2e472.475238"]]},{"id":"b585fb60.e936a8","type":"inject","z":"2d2bd18e.3e4abe","name":"init","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":122,"y":91,"wires":[["a6810bb0.a3e788"]]},{"id":"a6810bb0.a3e788","type":"function","z":"2d2bd18e.3e4abe","name":"set properties","func":"var properties = ['routers', 'ip_address', 'domain_name_servers'];\n\nflow.set(\"properties\", properties);\n\n//init properties\nfor(var i=0;i<properties.length;i++){\n    var p = properties[i];\n    flow.set(p, null);\n    flow.set(p+\"_new\", null);\n}\n\nnode.send({payload: true});\n","outputs":1,"noerr":0,"x":326,"y":91,"wires":[["6a63b433.e2a73c"]]},{"id":"8d2915b0.eb5188","type":"debug","z":"2d2bd18e.3e4abe","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":514,"y":385,"wires":[]},{"id":"fd5e6a37.bc5d38","type":"ui_toast","z":"2d2bd18e.3e4abe","position":"top right","displayTime":"3","highlight":"","outputs":0,"ok":"OK","cancel":"","topic":"","name":"","x":1310,"y":340,"wires":[]},{"id":"140df8ca.dea297","type":"change","z":"2d2bd18e.3e4abe","name":"set","rules":[{"t":"set","p":"payload","pt":"msg","to":"Settings updated. Reboot device to enable new ip","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1097,"y":310,"wires":[["fd5e6a37.bc5d38"]]},{"id":"ba4f96ca.0f28b8","type":"ui_text","z":"2d2bd18e.3e4abe","group":"1cf52e38.3cfee2","order":1,"width":0,"height":0,"name":"","label":"Static ip","format":"{{!msg.payload}}","layout":"row-spread","x":1120,"y":248,"wires":[]},{"id":"fea93690.140ec8","type":"ui_toast","z":"2d2bd18e.3e4abe","position":"top right","displayTime":"3","highlight":"","outputs":0,"ok":"OK","cancel":"","topic":"","name":"","x":1758,"y":161,"wires":[]},{"id":"aef2e472.475238","type":"change","z":"2d2bd18e.3e4abe","name":"set","rules":[{"t":"set","p":"payload","pt":"msg","to":"New setting stored ","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1566,"y":161,"wires":[["fea93690.140ec8"]]},{"id":"4b72781d.d0e178","type":"ui_text","z":"2d2bd18e.3e4abe","group":"1cf52e38.3cfee2","order":1,"width":0,"height":0,"name":"help","label":"","format":"To store the new value, once edited, press ENTER or TAB","layout":"col-center","x":711,"y":91,"wires":[]},{"id":"1cf52e38.3cfee2","type":"ui_group","z":"","name":"IP Settings","tab":"be53a269.02ec3","disp":true,"width":"6","collapse":false},{"id":"be53a269.02ec3","type":"ui_tab","z":"","name":"Settings","icon":"settings"}]

It looks promising. Looks like it does what I want to do, but I can't get it to work. Couple of things:

What is going on in the send commands function block?

var properties = flow.get("properties");

var disabled = flow.get("disabled") ? '#' : '';

if(disabled == '#'){
    //enable interface (replace only first occurance)
    var command = `'0,/#interface eth0/s//interface eth0/g;' /etc/dhcpcd.conf`;
    node.send({payload: command})
}

for(var i=0;i<properties.length;i++){
    var p = properties[i];
    
    var old_value = flow.get(p);
    var new_value = flow.get(p+"_new") || old_value;
    
    if(old_value && ((old_value != new_value) || disabled == '#'))
    {
        //enable interface (replace only first occurance)
        var command1 = `'0,\\?${disabled}static ${p}=${old_value}?s??static ${p}=${new_value}?g;' /etc/dhcpcd.conf`;
        node.send({payload: command1})
    }
}

It passes a payload to the execute block, but I can't see the payload (doesn't show in the debugger node).

Is the sudo sed -i command correct? I've been reading about the sed -i command and it seems I'm missing something. is the function block before it supposed to feed something as part of the execute command?

image

I can change the IP address manually by typing in:

nano /etc/dhcpcd.conf

Please advise. Thanks!

One things which catches my eye is this line in the function node you mentioned:

    var command = `'0,/#interface eth0/s//interface eth0/g;' /etc/dhcpcd.conf`;

The //

Is that supposed to be double?

Oh, and there it is again further down:

        var command = `'0,\\?${disabled}static ${p}=${old_value}?s??static ${p}=${new_value}?g;' /etc/dhcpcd.conf`;

(and something else)
that line is problematic.
You don't need the var at the start.

You have mis-copied the second line.

With the double slashes the first one escapes the second one.

[Edit] I suspect that @traderjoe may have editted the code after you picked it up, in which case you are right, var is not a good idea there as it will be re-declaring the same variable. They should be const (or let if they were not constant) and then they can be the same name without scoping problems, as each one will only exist within its block.

What do you see in the second debug node (give the debug nodes names so it is clear which output is which).

Also, once you get as far as running the exec nodes (I presume you have them disconnected while testing, in order to avoid wrecking your system) connect debug nodes to all three outputs so you will get further information if it doesn't work.

It isn't the problem here, but you should use const or let nowadays, not var, particularly inside blocks.

ok, I gave them names:

So in the refresh node, I get true when I press the refresh button. In the refresh-send cmd debugger, I get the current IP address, not the one I entered into the fields (see below).

image

I did run into scope problems earlier, that's why you see I have var command and var command1.
I changed the var to const.

I thought it was the send commands function you were working on. You have shown us the output from a different debug node.

[Edit] The output from the correct one would have node: refresh - send cmd not node: e822... above it.

There is no way that function can generate that output. It is possible that it doesn't send anything though, if the flow variable "properties" is not an array and disabled is not #.

You are correct. I didn't see I had another debugger active (that's where that IP address is coming from). I disabled, it and that node: refresh-send cmd produces no messages.

I get nothing from the refresh - send cmd when I hit the refresh button:

In that case, as I said, the flow variable 'properties' is not setup correctly. Check what they contain using the Context tab in the right hand pane.

Yes. That is a valid command [Edit: though I don't like the back ticks] to replace the first occurrence of "#interface eth0" with "interface eth0"
Which uncomments the line, probably.
The // means use the same pattern again.

For some reason the other sed calls use a different seperator - ?

sed -i '0,\?static domain_name_servers=192.168.0.1 8.8.8.8 fd51:42f8:caae:d92e::1?s??static domain_name_servers=192.168.3.11 ?g;' /etc/dhcpcd.conf

And I don't know why the first \ is there, maybe he has to escape the first ? but not the others. But why use a seperator that has to be escaped?

Whatever, my /etc/dhcpcd.conf has more than one section for eth0, the (commented out) built-in example and the one I added at the end. So it edits the wrong section.

If I was going to do this, I'd confine the edits to lines between
#start editing here
and
#stop editing here

Something like

'/#start editing here/,/#stop editing here/ s/#interface eth0/interface eth0/'

You looking for this?
image

Looks ok to me. In the properties it shows it is an array with the components I need to write to /etc/dhcpcd.conf...I'm not sure what I'm looking for....

Are flow property "routers", "ip_address" and "domain_name_servers" all supposed to be null? I guess not.