If that door regulates only air flow thru the empty greenhouse, you can trust any solution. Otherwise make at least two parallel solutions for state checking. Or if you need to sleep well, make make backup for those also.
Colin, actually it does work with one Publish node. I had made a change to the ESP32 code to add an additional hardware check and was testing with the new code. I have not yet added the hardware for the new code. Once I saw my mistake, I set the code back to what it was. The dashboard now works with the single Publish node.
If you are using mosquitto as the broker (which I find works very well) then it is saved to the card at the autosave interval specified in the conf file for mosquitto. It also saves it on a normal shutdown. The save location can also be specified in the conf file, the default location is on the SD card in the case of a Pi.
If the power fails then when the pi restarts it will pick up the last saved value. Presumably if the ESP32 restarts then it picks up the current state and sends it to MQTT. Similarly if the ESP32 sees the MQTT server disappear then later re-appear it should immediately send the current door state.
As above, MQTT will initially give the retained value (open) to any subscribers. If the door has been closed in the meantime then presumably the esp32 will send the new state automatically when the mqtt server appears.
When you connect is irrelevant, the state will be sent to the dashboard node when node-red restarts. When you connect you see the state of the dashboard node that was set when node-red restarted (or the latest state if a new value has been sent).
Colin, thanks for the info. I do not have the autosave interval specified in the conf file for mosquitto. In fact, I have shutdown as much logging and writing to the SD card as possible. IMO the SD card is the weakest link in the Raspberry Pi boards. Maybe the next version will allow the OS to be installed on a hard drive and boot from that. I know you can boot from the SD card and move most everything else to a hard drive. But that is extra work that still gives questionable reliability.
The code on the ESP32 does not send the state of the door when it re-connects to the broker. It simply re-connects and proceeds to the main loop() function. However your comments made the light bulb in my head turn on. I am going to add code to the ESP32 that sends the door state on boot up and anytime it re-connects to the broker. Then if I use the Retain flag I will not need the Status button.
Thanks for you help with all this. I am learning that Node-RED is extremely powerful in what it can do.
There will be a default value, see mosquitto.conf man page | Eclipse Mosquitto
I have everything working the way I want. I still have the status button on the dashboard but only for appearance purposes. The button is not subscribed to any topics so clicking it has no affect on anything.
I modified the ESP32 code to handle the status updates. I timed it and it takes 15 seconds for my garage door to open or close. So when the ESP32 sees the operate button topic come in I start a 20 second timer in the ESP32 code. When the timer expires I send a status update to the dashboard. I also have the retain flag set on the MQTT output node. That means when I connect to the dashboard I see the last status value.
I do have one issue that I wonder if there is an answer to. I would like to change the color of the operate button when it is pressed. When the button is released I would need it to go back to the color it was before it was pressed. I tried the same code that works on the status button but it doesn't work with the operate button. If I can't get the button color change to work is there a dot or a circle that I could put above the button and have it change color when the button is pressed?
My flow is attached.
[{"id":"e09c4485.910ab","type":"tab","label":"ESP32 Flow","disabled":false,"info":""},{"id":"685b0a22.7bd3a4","type":"ui_button","z":"e09c4485.910ab","name":"Status Switch","group":"eb6c6b8d.b6f26","order":2,"width":0,"height":0,"passthru":false,"label":"Status ?","tooltip":"","color":"","bgcolor":"{{background}}","icon":"","payload":"","payloadType":"str","topic":"","x":660,"y":220,"wires":[[]]},{"id":"4b0b7bdf.4e4844","type":"mqtt out","z":"e09c4485.910ab","name":"Publish","topic":"esp32/door/button","qos":"2","retain":"true","broker":"c3002906.2a182","x":660,"y":300,"wires":[]},{"id":"b1e5d737.cb1ff","type":"ui_button","z":"e09c4485.910ab","name":"Door Switch","group":"eb6c6b8d.b6f26","order":3,"width":0,"height":0,"passthru":false,"label":"Operate","tooltip":"","color":"","bgcolor":"GRAY","icon":"","payload":"pressed","payloadType":"str","topic":"esp32/door/button","x":490,"y":300,"wires":[["4b0b7bdf.4e4844"]]},{"id":"75fb3172.402c2","type":"ui_text","z":"e09c4485.910ab","group":"eb6c6b8d.b6f26","order":1,"width":0,"height":0,"name":"Door Status","label":"Door Status","format":"{{msg.payload}}","layout":"row-spread","x":470,"y":140,"wires":[]},{"id":"15b1eb2f.06dac5","type":"mqtt in","z":"e09c4485.910ab","name":"Return Status","topic":"esp32/door/stat-return","qos":"2","datatype":"utf8","broker":"c3002906.2a182","x":290,"y":140,"wires":[["75fb3172.402c2","3d4ed5d6.ee80da","4b0b7bdf.4e4844"]]},{"id":"d4439fd2.ab74b8","type":"rpi-gpio out","z":"e09c4485.910ab","name":"GPIO11","pin":"23","set":true,"level":"0","freq":"","out":"out","x":680,"y":380,"wires":[]},{"id":"575d7cbf.f50d74","type":"mqtt in","z":"e09c4485.910ab","name":"Beam","topic":"esp32/door/beam","qos":"2","datatype":"auto","broker":"c3002906.2a182","x":290,"y":380,"wires":[["4981d4bd.d7d5f4"]]},{"id":"4981d4bd.d7d5f4","type":"change","z":"e09c4485.910ab","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"broken","fromt":"str","to":"1","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"present","fromt":"str","to":"0","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":380,"wires":[["d4439fd2.ab74b8"]]},{"id":"3d4ed5d6.ee80da","type":"function","z":"e09c4485.910ab","name":"Color State","func":"if (msg.payload == \"Door is open\") {\n msg.background = \"RED\";\n} else {\n msg.background = \"GREEN\";\n}\nreturn msg;","outputs":1,"noerr":0,"x":450,"y":220,"wires":[["685b0a22.7bd3a4","949c4b63.425158"]]},{"id":"949c4b63.425158","type":"debug","z":"e09c4485.910ab","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":650,"y":140,"wires":[]},{"id":"c9c08720.82ebf","type":"ui_button","z":"e09c4485.910ab","name":"fake button","group":"eb6c6b8d.b6f26","order":2,"width":0,"height":0,"passthru":false,"label":"fake button","tooltip":"","color":"","bgcolor":"white","icon":"","payload":"","payloadType":"str","topic":"home/door/fake","x":310,"y":280,"wires":[[]]},{"id":"eb6c6b8d.b6f26","type":"ui_group","z":"","name":"Garage Door","tab":"5d370db7.ba1564","disp":true,"width":"6","collapse":false},{"id":"c3002906.2a182","type":"mqtt-broker","z":"","name":"MyPi","broker":"172.16.1.112","port":"1883","clientid":"pi","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"home/Relays","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"5d370db7.ba1564","type":"ui_tab","z":"","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]
Edit: Uploaded correct flow.
This cannot be the complete flow???
Something went wrong with first flow upload. It should be correct now.
Thanks for the alert.
Does this faq help ?
EDIT: @dceejay, funny, just posted a similar thing...
So you have a garage door. You want to operate it via a button. This is a suggested and simple flow that toggles between open/close and it updates the button with the received actual status information
When you click the button, a command for open or closed is sent to the broker. Assumming this will be received by your esp and executed, the new status of the door will be published by the esp and then received by NR, the button text and background colour will be updated, reflecting the new status. Simple.
You have to modify the flow so it fits your settings for the broker, topics, commands sent and received all matching your esp code (or modify the esp code...)
[{"id":"81a8870a.5b9888","type":"ui_button","z":"d01d2553.fd9838","name":"","group":"94cd9b77.f34d68","order":4,"width":0,"height":0,"passthru":false,"label":"{{msg.txt}}","tooltip":"","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"","payloadType":"str","topic":"","x":520,"y":1690,"wires":[["d1f0ab8d.773cf8"]]},{"id":"650ab80f.5a3b58","type":"change","z":"d01d2553.fd9838","name":"","rules":[{"t":"set","p":"background","pt":"msg","to":"green","tot":"str"},{"t":"set","p":"txt","pt":"msg","to":"OPEN","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":1620,"wires":[["81a8870a.5b9888"]]},{"id":"60ac4c4c.fddaa4","type":"change","z":"d01d2553.fd9838","name":"","rules":[{"t":"set","p":"background","pt":"msg","to":"red","tot":"str"},{"t":"set","p":"txt","pt":"msg","to":"CLOSED","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":1760,"wires":[["81a8870a.5b9888"]]},{"id":"d1f0ab8d.773cf8","type":"function","z":"d01d2553.fd9838","name":"","func":"context.set('state',context.get('state')||\"closed\");\n\nfunction updateNodeStatus(color, txt) {\n node.status({\n \tfill : color,\n \tshape : \"dot\",\n \ttext : txt\n });\n}\n\nvar state = context.get('state');\nvar color = '';\n\nswitch (state) {\n case 'OFF':\n state = 'ON';\n color = 'green';\n msg.payload = \"open\";\n break;\n case 'ON':\n state = 'OFF';\n color = 'red';\n msg.payload = \"closed\";\n break;\n default:\n state = 'OFF';\n color = 'red';\n msg.payload = \"closed\";\n break;\n}\n\ncontext.set('state',state);\nupdateNodeStatus(color,msg.payload);\nnode.send(msg);","outputs":"1","noerr":0,"x":680,"y":1690,"wires":[["37f8bfa3.83297"]]},{"id":"37f8bfa3.83297","type":"mqtt out","z":"d01d2553.fd9838","name":"","topic":"Whatever","qos":"","retain":"","broker":"75eba16c.094f9","x":850,"y":1690,"wires":[]},{"id":"2a3d58a1.d29e88","type":"mqtt in","z":"d01d2553.fd9838","name":"","topic":"Whatever","qos":"2","datatype":"auto","broker":"75eba16c.094f9","x":120,"y":1690,"wires":[["58145d51.5973f4"]]},{"id":"58145d51.5973f4","type":"switch","z":"d01d2553.fd9838","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"open","vt":"str"},{"t":"eq","v":"closed","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":280,"y":1690,"wires":[["650ab80f.5a3b58"],["60ac4c4c.fddaa4"]]},{"id":"94cd9b77.f34d68","type":"ui_group","z":"","name":"Sliders","tab":"8f57f520.e87078","disp":true,"width":"6","collapse":false},{"id":"75eba16c.094f9","type":"mqtt-broker","z":"","name":"","broker":"127.0.0.1","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"8f57f520.e87078","type":"ui_tab","z":"","name":"Some stuff","icon":"dashboard","order":3,"disabled":false,"hidden":false}]
krambris,
When you click the button, a command for open or closed is sent to the broker. Assumming this will be received by your esp and executed, the new status of the door will be published by the esp and then received by NR, the button text and background colour will be updated, reflecting the new status.<
I already have the status update button working. I need the operate button to change color. The attached flow may help explain. When the button is pressed it sends a msg.payload of "pressed". That starts code on the ESP32 that 20 seconds later updates the status button which is not shown in this flow.
The ESP32 knows the button is pressed when it receives the /esp32/door/button topic with a payload of "pressed". It has no way of knowing when the button is released. So I need to change the color of this button to red when it is pressed and to green when it is released. This needs to be done without involving the ESP32. The default color of the button should be green.
[{"id":"9fae7d25.0bfba","type":"tab","label":"Flow 3","disabled":false,"info":""},{"id":"a2a8051c.1e9828","type":"ui_button","z":"9fae7d25.0bfba","name":"operate","group":"eb6c6b8d.b6f26","order":0,"width":0,"height":0,"passthru":false,"label":"button","tooltip":"","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"pressed","payloadType":"str","topic":"esp32/door/button","x":470,"y":220,"wires":[["5c2b7270.69b83c"]]},{"id":"5c2b7270.69b83c","type":"mqtt out","z":"9fae7d25.0bfba","name":"Publish","topic":"esp32/door/button","qos":"2","retain":"","broker":"c3002906.2a182","x":650,"y":240,"wires":[]},{"id":"eb6c6b8d.b6f26","type":"ui_group","z":"","name":"Garage Door","tab":"5d370db7.ba1564","disp":true,"width":"6","collapse":false},{"id":"c3002906.2a182","type":"mqtt-broker","z":"","name":"MyPi","broker":"172.16.1.112","port":"1883","clientid":"pi","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"home/Relays","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"5d370db7.ba1564","type":"ui_tab","z":"","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]
So I need to change the color of this button to red when it is pressed and to green when it is released
Dashboard button doesn't have more events available than click (mouse down and mouse up both must happen to fire event). With one public event only you can not have momentary button behavior.
But there is always a way to do it Momentary button on Dashboard
Have you considered adding a confirmation dialogue - Open Garage Door? OK/Cancel
This would prevent accidentally opening or closing the door.
hotNipi, the suggestion by Trying_to_learn in your link appears to be the best solution. Two seconds would be about optimum for button press acknowledge.
The reason that feedback is needed is because visual indication of the button press leaves a lot to be desired. On a PC with a mouse it is acceptable. But on a mobile device you have to look very closely to see the very light flash across the button when you press it.
Paul-Reed, I'm not concerned with accidentally opening and closing the door. I'm concerned with knowing that the button push has actually been acknowledged by my mobile device. I can sit at my workbench and press the operate button 20 times. Sometimes I get 18 responses, 19, or maybe all 20. Node red is not the problem. It is the mobile device itself. I see similar responses when accessing other apps or replying to text messages.
How did you create the confirmation dialogue? That could be the best simple solution.
Well, maybe you did not understand my example, my thought was to get rid of the status button and reflect the actual door status directly on the operate button
But since the actual operation "may take some time", I think such a solution as I propose should have three states: red:closed, yellow:door moving, green:open
And if pressing the button again while moving, yellow, immediate stop
Only one button needed, door status updates integrated
Immediate stop creates one more state for door - floating (not fully opened, not fully closed and not moving). What would be the next action for one button solution?
OK, one more time. My problem was not with the door operation. It was only with the user being able to have visual feedback that they had actually pressed the operate button on the device (typically a cell phone) that is used to start the door moving.
The door open and close operation works perfectly. Even the floating case that hotNipi mentions is handled by the ESP32 code. I have a magnetic switch (S1) on the fully closed end of the door travel. I have a magnetic switch (S2) on the fully open end of the door travel.
After the operate button is pressed (assuming it is actually pressed) the ESP32 waits 20 seconds and then samples the two magnetic switches. If S1 is closed and S2 is open, the "Door Open" payload is sent to the dashboard. If S1 is open and S2 is closed, the "Door Closed payload is sent to the dashboard. Is S1 is open and S2 is open, the "Door Stuck" payload is sent to the dashboard.
At the same time that the payload message is sent, the status button color is changed to reflect the door state. The status button is not really a button since it cannot be pressed. Is is only used as a visual indicator of the door state 20 seconds after the operate button is pressed.
hotNipi, I have implemented the solution that Trying_to_learn shows in the "Momentary button on Dashboard" link that you previously mentioned. I am happy with that solution. When the operate button is pressed and recognized, a check mark icon appears on the operate button. Two seconds later, the check mark disappears and the operate label re-appears. A very elegant solution. If the check mark doesn't appear, the user knows they did not press the button correctly on their device and they simply need to press it again.
The bottom line is that now the problem of no visual feed back from the operate button has been solved. Therefore my project is 100% functional.
Using the notification node (or confusingly also called the ui-toast node - depending where you look!!)
[{"id":"ba8d9e18.0b15c","type":"function","z":"c53060.842a0fa","name":"Filter msg's","func":"//only accept OK msg's\nif (msg.payload == 'OK') {\n msg.payload = true;\n node.send(msg);\n}\nreturn null;","outputs":1,"noerr":0,"x":560,"y":1010,"wires":[["ed8d5b7c.ca4de8"]]},{"id":"64a05f20.ecaf4","type":"ui_button","z":"c53060.842a0fa","name":"","group":"61d2dced.3db8f4","order":5,"width":1,"height":1,"passthru":false,"label":"Open","tooltip":"","color":"#ff0000","bgcolor":"#2a2a2a","icon":"","payload":"Really open garage door?","payloadType":"str","topic":"","x":220,"y":1010,"wires":[["223b4d4.05634b2"]]},{"id":"223b4d4.05634b2","type":"ui_toast","z":"c53060.842a0fa","position":"dialog","displayTime":"3","highlight":"","sendall":true,"outputs":1,"ok":"OK","cancel":"Cancel","topic":"","name":"confirm deploy","x":377,"y":1010,"wires":[["ba8d9e18.0b15c"]]},{"id":"ed8d5b7c.ca4de8","type":"debug","z":"c53060.842a0fa","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":730,"y":1010,"wires":[]},{"id":"61d2dced.3db8f4","type":"ui_group","z":"","name":"flowtest","tab":"3c94630c.13381c","disp":true,"width":"12","collapse":false},{"id":"3c94630c.13381c","type":"ui_tab","z":0,"name":"Test","icon":"dashboard","order":6}]
EDIT - You can also change the button appearance by adding msg.background in the function node, and feeding that back to the button node.
[{"id":"ba8d9e18.0b15c","type":"function","z":"c53060.842a0fa","name":"Filter msg's","func":"//only accept OK msg's\nif (msg.payload == 'OK') {\n var msg1 = { payload:true };\n var msg2 = { background:\"red\" };\n return [[ msg1], msg2];\n}\nreturn null;","outputs":2,"noerr":0,"x":560,"y":1010,"wires":[["ed8d5b7c.ca4de8"],["64a05f20.ecaf4"]]},{"id":"64a05f20.ecaf4","type":"ui_button","z":"c53060.842a0fa","name":"","group":"61d2dced.3db8f4","order":5,"width":1,"height":1,"passthru":false,"label":"Open","tooltip":"","color":"{{msg.background}}","bgcolor":"#2a2a2a","icon":"","payload":"Really open garage door?","payloadType":"str","topic":"","x":220,"y":1060,"wires":[["223b4d4.05634b2"]]},{"id":"223b4d4.05634b2","type":"ui_toast","z":"c53060.842a0fa","position":"dialog","displayTime":"3","highlight":"","sendall":true,"outputs":1,"ok":"OK","cancel":"Cancel","topic":"","name":"confirm deploy","x":377,"y":1010,"wires":[["ba8d9e18.0b15c"]]},{"id":"ed8d5b7c.ca4de8","type":"debug","z":"c53060.842a0fa","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":730,"y":1010,"wires":[]},{"id":"61d2dced.3db8f4","type":"ui_group","z":"","name":"flowtest","tab":"3c94630c.13381c","disp":true,"width":"12","collapse":false},{"id":"3c94630c.13381c","type":"ui_tab","z":0,"name":"Test","icon":"dashboard","order":6}]
Paul-Reed, I tried the first example you show with the Cancel-OK choice. I like that better than the check mark way I was implementing it. I think the Cancel-OK way is the ultimate way to go. There is no doubt the button has been pressed if that confirmation dialog pops up. I just had to modify the payload through the Filter msg's function so the correct payload gets sent to the ESP32.
Here is a flow showing open/close working together;
[{"id":"ba8d9e18.0b15c","type":"function","z":"c53060.842a0fa","name":"Filter msg's","func":"//only accept OK msg's\nif (msg.payload == 'OK') {\n var msg3 = { payload:true };\n var msg1 = { background:\"red\" };\n var msg2 = { background:\"white\" };\n return [[ msg1],[ msg2], msg3];\n}\nreturn null;","outputs":3,"noerr":0,"x":560,"y":1030,"wires":[["9c6b75f1.0a2e48"],["c794d765.bda458"],["9a2743f6.e82f3"]]},{"id":"64a05f20.ecaf4","type":"ui_button","z":"c53060.842a0fa","name":"","group":"61d2dced.3db8f4","order":5,"width":1,"height":1,"passthru":false,"label":"Open","tooltip":"","color":"black","bgcolor":"{{msg.background}}","icon":"","payload":"Really open garage door?","payloadType":"str","topic":"","x":220,"y":1040,"wires":[["223b4d4.05634b2"]]},{"id":"223b4d4.05634b2","type":"ui_toast","z":"c53060.842a0fa","position":"dialog","displayTime":"3","highlight":"","sendall":true,"outputs":1,"ok":"OK","cancel":"Cancel","topic":"","name":"confirm deploy","x":370,"y":1040,"wires":[["ba8d9e18.0b15c"]]},{"id":"c799746.42f8f88","type":"function","z":"c53060.842a0fa","name":"Filter msg's","func":"//only accept OK msg's\nif (msg.payload == 'OK') {\n var msg1 = { payload:false };\n var msg2 = { background:\"red\" };\n var msg3 = { background:\"white\" };\n return [[ msg1],[ msg2], msg3];\n}\nreturn null;","outputs":3,"noerr":0,"x":560,"y":1090,"wires":[["9a2743f6.e82f3"],["903a1cc2.a4139"],["612f3205.aa93fc"]]},{"id":"18da50bd.e1610f","type":"ui_button","z":"c53060.842a0fa","name":"","group":"61d2dced.3db8f4","order":5,"width":1,"height":1,"passthru":false,"label":"Close","tooltip":"","color":"black","bgcolor":"{{msg.background}}","icon":"","payload":"Really close garage door?","payloadType":"str","topic":"","x":220,"y":1080,"wires":[["79bc08da.c5ced8"]]},{"id":"79bc08da.c5ced8","type":"ui_toast","z":"c53060.842a0fa","position":"dialog","displayTime":"3","highlight":"","sendall":true,"outputs":1,"ok":"OK","cancel":"Cancel","topic":"","name":"confirm deploy","x":370,"y":1080,"wires":[["c799746.42f8f88"]]},{"id":"9a2743f6.e82f3","type":"debug","z":"c53060.842a0fa","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":740,"y":1060,"wires":[]},{"id":"612f3205.aa93fc","type":"link out","z":"c53060.842a0fa","name":"","links":["517390c.5b05e7"],"x":685,"y":1140,"wires":[]},{"id":"517390c.5b05e7","type":"link in","z":"c53060.842a0fa","name":"","links":["612f3205.aa93fc","9c6b75f1.0a2e48"],"x":125,"y":1040,"wires":[["64a05f20.ecaf4"]]},{"id":"9c6b75f1.0a2e48","type":"link out","z":"c53060.842a0fa","name":"","links":["517390c.5b05e7"],"x":685,"y":980,"wires":[]},{"id":"903a1cc2.a4139","type":"link out","z":"c53060.842a0fa","name":"","links":["e56c6daf.c723a"],"x":685,"y":1100,"wires":[]},{"id":"e56c6daf.c723a","type":"link in","z":"c53060.842a0fa","name":"","links":["903a1cc2.a4139","c794d765.bda458"],"x":125,"y":1080,"wires":[["18da50bd.e1610f"]]},{"id":"c794d765.bda458","type":"link out","z":"c53060.842a0fa","name":"","links":["e56c6daf.c723a"],"x":685,"y":1020,"wires":[]},{"id":"61d2dced.3db8f4","type":"ui_group","z":"","name":"flowtest","tab":"3c94630c.13381c","disp":true,"width":"12","collapse":false},{"id":"3c94630c.13381c","type":"ui_tab","z":0,"name":"Test","icon":"dashboard","order":6}]