I was just working on this exact problem earlier today!
I'm certain that someone who's more familiar than I am will tell us how to use a Template
node for this. It seems certain that there's a way to populate an editable textbox in a Template
node, and then have a button which causes the current contents of the text box to be passed out of the Template
node as a string.
However, I don't know how to do that. I need to go through about a dozen temperature sensors attached to my Pi, and give each one a name to be associated with its "address". I start out with an array of objects, each of which has an "address", an empty "name", a temperature, and a last read timestamp.
So I did it this way, which I'm not claiming is a good way, but it will work for my purposes for a me-facing dashboard for essentially one-time edits:
I read the file like you do, and then make myself a string out of the contents of the array of objects, using a field and a line delimiter (could be ,
and ;
for example, but I used :
and <br>
).
I used the Text
dashboard node to display the string I'd created that's a list of sensors. Then, below that, I have a Form
node with just one entry on it - a "multiline" entry, which gives a text box. I couldn't find any way to pre-populate the multiline text input box, or I would have.
Anyway, then I can copy the values in the Text
node, paste them into the Form
multiline box, edit them there, and submit the form.
Because I chose to do this with strings, I then have to re-parse the strings and add the names to the relevant sensors based on their address.
Again, I'm not saying this is a good way. But if it's at all useful to you, here's what it's like:
...and below this, there's a "Submit" button. The format I happened to use is just the read number of the sensor : its address which always starts with "28-..." : its name : its current temperature, just to help me figure out which is which before they're all named.
Here's the whole thing if you can make any use of it.
[{"id":"73b5101865bc19a6","type":"inject","z":"159c98d1.b0c3e7","name":"list sensors","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"sensors.temp","payloadType":"global","x":1740,"y":1560,"wires":[["a1cd7f218b34472d"]]},{"id":"156cd5b987468242","type":"function","z":"159c98d1.b0c3e7","name":"make list","func":"var text = \"\";\nvar list = msg.payload.list;\nvar IDlist = msg.payload.IDlist;\nfor (let i=0;i<list.length;i++) {\n text += i+1 + \":\" + list[i].address + \":\" + list[i].name + \":\" + list[i].temp + \"<br>\";\n}\nmsg.payload = text;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1980,"y":1580,"wires":[["e00688179bc41413","b7dd533b8f7def0b"]]},{"id":"e00688179bc41413","type":"debug","z":"159c98d1.b0c3e7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":2170,"y":1540,"wires":[]},{"id":"7808030c9bd7ae02","type":"ui_form","z":"159c98d1.b0c3e7","name":"","label":"Paste any or all lines here and edit:","group":"8748aaffd2cf417e","order":3,"width":0,"height":0,"options":[{"label":"","value":"textReturn","type":"multiline","required":true,"rows":10}],"formValue":{"textReturn":""},"payload":"","submit":"submit","cancel":"","topic":"topic","topicType":"msg","splitLayout":"","className":"","x":1720,"y":1640,"wires":[["15fa84fe7ad8d84e","01c2523abab46ad8"]]},{"id":"b7dd533b8f7def0b","type":"ui_text","z":"159c98d1.b0c3e7","group":"8748aaffd2cf417e","order":2,"width":"10","height":"5","name":"","label":"Copy from here:","format":"{{msg.payload}}","layout":"col-center","className":"","x":2180,"y":1580,"wires":[]},{"id":"2d786ce29643edf1","type":"ui_button","z":"159c98d1.b0c3e7","name":"","group":"8748aaffd2cf417e","order":1,"width":0,"height":0,"passthru":false,"label":"Get current (start here)","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":1700,"y":1520,"wires":[["a1cd7f218b34472d"]]},{"id":"a1cd7f218b34472d","type":"change","z":"159c98d1.b0c3e7","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"sensors.temp","tot":"global","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":1940,"y":1540,"wires":[["156cd5b987468242"]]},{"id":"15fa84fe7ad8d84e","type":"debug","z":"159c98d1.b0c3e7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1970,"y":1680,"wires":[]},{"id":"01c2523abab46ad8","type":"function","z":"159c98d1.b0c3e7","name":"parse input and name sensors","func":"// @ts-nocheck\nvar input = msg.payload.textReturn;\nvar updated = global.get(\"sensors.temp.list\");\nvar inArr = input.split(\"\\n\");\nfor (i=0;i<inArr.length;i++) {\n inArr[i]=inArr[i].split(\":\");\n for (j=0;j<updated.length;j++){\n if (updated[j].address == inArr[i][1]) {\n updated[j].name = inArr[i][2];\n }\n }\n}\nglobal.set(\"sensors.temp.list\",updated); // happens anyway - no deep copy in preceding\nmsg.inArr = inArr;\nmsg.updated = updated;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2030,"y":1640,"wires":[["ef0fbf2b6d356c3f","cf97cdf0bd63f4eb","d0c61e3103f98ea9"]]},{"id":"ef0fbf2b6d356c3f","type":"debug","z":"159c98d1.b0c3e7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"updated","targetType":"msg","statusVal":"","statusType":"auto","x":2310,"y":1660,"wires":[]},{"id":"cf97cdf0bd63f4eb","type":"debug","z":"159c98d1.b0c3e7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"inArr","targetType":"msg","statusVal":"","statusType":"auto","x":2300,"y":1620,"wires":[]},{"id":"d0c61e3103f98ea9","type":"file in","z":"159c98d1.b0c3e7","name":"","filename":"sensors/tempList.json","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":2260,"y":1760,"wires":[["13513f18eb891ffd"]]},{"id":"13513f18eb891ffd","type":"json","z":"159c98d1.b0c3e7","name":"","property":"payload","action":"","pretty":false,"x":2290,"y":1800,"wires":[["656436447bd31306"]]},{"id":"656436447bd31306","type":"function","z":"159c98d1.b0c3e7","name":"update saved sensor names","func":"var history = msg.payload;\nvar updated = msg.updated;\nvar contains = false;\n\nfor (let i=0;i<updated.length;i++) {\n contains = false;\n for (let j=0;j<history.length;j++) {\n if (history.address == updated.address) {\n contains = true;\n }\n }\n if (!contains) {\n history.push(updated[i]);\n }\n}\n\nmsg.payload = history;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2360,"y":1840,"wires":[[]]},{"id":"b0a30bed919bed62","type":"comment","z":"159c98d1.b0c3e7","name":"RogierQ can ignore everything past here.","info":"","x":2240,"y":1720,"wires":[]},{"id":"8748aaffd2cf417e","type":"ui_group","name":"Sensor Assignments","tab":"a0484681450dbb9b","order":2,"disp":true,"width":"10","collapse":false,"className":""},{"id":"a0484681450dbb9b","type":"ui_tab","name":"Pi Settings","icon":"gear","disabled":false,"hidden":false}]