MQTT nodes need a dummy broker entry to allow fully dynamic settings?

In trying to implement a Node-RED/UIBUILDER replacement for MQTT Explorer, I'm hitting some issues that I'm not sure can be worked around.

While both the mqtt-in and -out nodes allow dynamic settings, they also require an actual broker to be pre-configured otherwise they don't work. Or at least, I can't find a way to make them work.

I need to be able to dynamically disconnect/reconnect to any broker in order to trigger the output of retained messages. That is on the MQTT-in node.

I also need to be able to publish to that dynamically connected broker using an mqtt-out node to allow publishing of arbitrary messages from the UI.

What I don't want to have to do is create a working broker configuration for my own system because that gets exported when sharing the flow and that is not appropriate. This alone seems not possible?

But in addition, all the messing with having to send multiple commands makes the whole thing quite messy even if that last issue wasn't present.

I am open to ideas here but at present I can't see any way forwards other than creating a custom function node that uses the mqtt npm package directly.

This is where I'm up to so far:

Note that this may not work as given because the DUMMY broker may not exist.

[{"id":"9f1e743afa926865","type":"uibuilder","z":"4393d057899d5287","name":"","topic":"","url":"mqtt-explorer","okToGo":true,"fwdInMessages":false,"allowScripts":false,"allowStyles":false,"copyIndex":true,"templateFolder":"blank","extTemplate":"","showfolder":false,"reload":false,"sourceFolder":"src","deployedVersion":"5.0.0-dev.2","showMsgUib":false,"title":"A Node-RED replacement for MQTT Explorer","descr":"","editurl":"vscode://file/D:\\src\\uibRoot/mqtt-explorer/?windowId=_blank","x":860,"y":160,"wires":[["7d8dc679995a88bd","28d293f592db5d7c"],["7f8edb94b02a119a"]]},{"id":"ae90065eb89d6ad5","type":"switch","z":"4393d057899d5287","name":"Filter high \\n volume topics","property":"topic","propertyType":"msg","rules":[{"t":"cont","v":"nrlog","vt":"str"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":480,"y":160,"wires":[[],["046efcf288d44964"]]},{"id":"7d8dc679995a88bd","type":"debug","z":"4393d057899d5287","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"","statusType":"counter","x":1065,"y":100,"wires":[],"l":false},{"id":"affb2d9a74d04af4","type":"debug","z":"4393d057899d5287","name":"","active":false,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"","statusType":"counter","x":1105,"y":200,"wires":[],"l":false},{"id":"046efcf288d44964","type":"delay","z":"4393d057899d5287","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"40000","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":670,"y":160,"wires":[["9f1e743afa926865"]]},{"id":"9bc3728ee0f43c66","type":"change","z":"4393d057899d5287","name":"Add \\n Timestamp","rules":[{"t":"set","p":"lastUpdate","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":160,"wires":[["ae90065eb89d6ad5"]]},{"id":"222b4689c997d575","type":"mqtt in","z":"4393d057899d5287","name":"","topic":"","qos":"2","datatype":"auto-detect","broker":"5913b4dac3da598b","nl":false,"rap":true,"rh":0,"inputs":1,"x":170,"y":160,"wires":[["9bc3728ee0f43c66"]]},{"id":"7f8edb94b02a119a","type":"switch","z":"4393d057899d5287","name":"","property":"uibuilderCtrl","propertyType":"msg","rules":[{"t":"eq","v":"client connect","vt":"str"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":995,"y":180,"wires":[["a7143005e591c86f"],["affb2d9a74d04af4"]],"l":false},{"id":"a7143005e591c86f","type":"link out","z":"4393d057899d5287","name":"link out 7","mode":"link","links":["b9539cb9e22e648f"],"x":1065,"y":160,"wires":[]},{"id":"4eaeef39086a6d2e","type":"link in","z":"4393d057899d5287","name":"link in 6","links":["9d1586f2d1eb7143","10ed6e3b28a4f7a5"],"x":85,"y":160,"wires":[["222b4689c997d575"]]},{"id":"28d293f592db5d7c","type":"mqtt out","z":"4393d057899d5287","name":"","topic":"","qos":"","retain":"","respTopic":"INFO/Explorer","contentType":"text/plain","userProps":"{\"source\":\"UIBUILDER MQTT Explorer\"}","correl":"Fourty Two","expiry":"9999","broker":"5913b4dac3da598b","x":1330,"y":120,"wires":[]},{"id":"ed0b87c57af8f5fe","type":"link in","z":"4393d057899d5287","name":"link in 7","links":["6b05bf8d70e7d956"],"x":1255,"y":180,"wires":[["28d293f592db5d7c"]]},{"id":"9a1791d2e0e6a372","type":"group","z":"4393d057899d5287","name":"Client Connection. Disconnects then connects to trigger output of all retained messages. Then Subscribes to # and $SYS/# \\n Uses a flow variable for the broker URL. \\n ","style":{"fill":"#ffff00","fill-opacity":"0.22","label":true,"color":"#000000"},"nodes":["b9539cb9e22e648f","4a6e282ea6cdf446","57ba48574e197269","4b11bb56f5299381","baa2a1457dfde295","f6151e28e2d5e0da","9d1586f2d1eb7143","6b05bf8d70e7d956"],"x":34,"y":227,"w":782,"h":194},{"id":"b9539cb9e22e648f","type":"link in","z":"4393d057899d5287","g":"9a1791d2e0e6a372","name":"link in 3","links":["a7143005e591c86f"],"x":75,"y":300,"wires":[["4a6e282ea6cdf446"]]},{"id":"4a6e282ea6cdf446","type":"change","z":"4393d057899d5287","g":"9a1791d2e0e6a372","name":"disconnect","rules":[{"t":"set","p":"broker","pt":"msg","to":"#:(file)::mqtt_broker","tot":"flow"},{"t":"set","p":"action","pt":"msg","to":"disconnect","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"#","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":135,"y":300,"wires":[["57ba48574e197269","9d1586f2d1eb7143","6b05bf8d70e7d956"]],"l":false},{"id":"57ba48574e197269","type":"delay","z":"4393d057899d5287","g":"9a1791d2e0e6a372","name":"","pauseType":"delay","timeout":"100","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":215,"y":340,"wires":[["4b11bb56f5299381"]],"l":false},{"id":"4b11bb56f5299381","type":"change","z":"4393d057899d5287","g":"9a1791d2e0e6a372","name":"connect","rules":[{"t":"set","p":"broker","pt":"msg","to":"#:(file)::mqtt_broker","tot":"flow"},{"t":"set","p":"action","pt":"msg","to":"connect","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"#","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":275,"y":340,"wires":[["f6151e28e2d5e0da","9d1586f2d1eb7143","6b05bf8d70e7d956"]],"l":false},{"id":"baa2a1457dfde295","type":"change","z":"4393d057899d5287","g":"9a1791d2e0e6a372","name":"subscribe #","rules":[{"t":"set","p":"action","pt":"msg","to":"subscribe","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"[\"#\",\"$SYS/#\"]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":575,"y":380,"wires":[["9d1586f2d1eb7143"]],"l":false},{"id":"f6151e28e2d5e0da","type":"delay","z":"4393d057899d5287","g":"9a1791d2e0e6a372","name":"","pauseType":"delay","timeout":"100","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":525,"y":380,"wires":[["baa2a1457dfde295"]],"l":false},{"id":"9d1586f2d1eb7143","type":"link out","z":"4393d057899d5287","g":"9a1791d2e0e6a372","name":"link out 8","mode":"link","links":["4eaeef39086a6d2e"],"x":775,"y":300,"wires":[]},{"id":"6b05bf8d70e7d956","type":"link out","z":"4393d057899d5287","g":"9a1791d2e0e6a372","name":"link out 54","mode":"link","links":["ed0b87c57af8f5fe"],"x":335,"y":380,"wires":[]},{"id":"6597251a3ade5ffa","type":"group","z":"4393d057899d5287","name":"Manual Controls","style":{"fill":"#bfbfbf","fill-opacity":"0.26","label":true,"color":"#000000"},"nodes":["4837409ef3162628","60c776388f0db74c","9a66c3fd2155c9cc","a96dea07b9dd4a3a","133deb373770dfec","1e8eb8d8bd7bda43","10ed6e3b28a4f7a5"],"x":854,"y":259,"w":342,"h":162},{"id":"4837409ef3162628","type":"change","z":"4393d057899d5287","g":"6597251a3ade5ffa","name":"subscribe #","rules":[{"t":"set","p":"action","pt":"msg","to":"subscribe","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"[\"#\",\"$SYS/#\"]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":1030,"y":300,"wires":[["10ed6e3b28a4f7a5"]]},{"id":"60c776388f0db74c","type":"inject","z":"4393d057899d5287","g":"6597251a3ade5ffa","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":915,"y":340,"wires":[["133deb373770dfec"]],"l":false},{"id":"9a66c3fd2155c9cc","type":"inject","z":"4393d057899d5287","g":"6597251a3ade5ffa","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":915,"y":380,"wires":[["a96dea07b9dd4a3a"]],"l":false},{"id":"a96dea07b9dd4a3a","type":"change","z":"4393d057899d5287","g":"6597251a3ade5ffa","name":"disconnect","rules":[{"t":"set","p":"broker","pt":"msg","to":"#:(file)::mqtt_broker","tot":"flow"},{"t":"set","p":"action","pt":"msg","to":"disconnect","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"#","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1030,"y":380,"wires":[["10ed6e3b28a4f7a5"]]},{"id":"133deb373770dfec","type":"change","z":"4393d057899d5287","g":"6597251a3ade5ffa","name":"connect","rules":[{"t":"set","p":"broker","pt":"msg","to":"#:(file)::mqtt_broker","tot":"flow"},{"t":"set","p":"action","pt":"msg","to":"connect","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"#","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1020,"y":340,"wires":[["10ed6e3b28a4f7a5"]]},{"id":"1e8eb8d8bd7bda43","type":"inject","z":"4393d057899d5287","g":"6597251a3ade5ffa","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":915,"y":300,"wires":[["4837409ef3162628"]],"l":false},{"id":"10ed6e3b28a4f7a5","type":"link out","z":"4393d057899d5287","g":"6597251a3ade5ffa","name":"link out 11","mode":"link","links":["4eaeef39086a6d2e"],"x":1155,"y":340,"wires":[]},{"id":"5913b4dac3da598b","type":"mqtt-broker","name":"DUMMY","broker":"localhost","port":1883,"clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"5","keepalive":60,"cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"b22fc429536545bd","type":"global-config","env":[],"modules":{"node-red-contrib-uibuilder":"7.6.0"}}]

I use

const action = "subscribe"
const force = true
const topic = "<topic>"
const broker = {}

broker.broker = "<ip>"
broker.port = 1883
broker.username = ""
broker.password = ""

msg.broker = broker
msg.force = force
msg.topic = topic
msg.action = action

return msg

It will force a dis/reconnect on the broker, or if it is the same broker, you can also unsubscribe or disconnect/reconnect

Thanks for that. That is part of the issue then. The help for the mqtt-in node is vague when it comes to the force setting as it reads as though it should go on the broker property.

Looks like I can get round having to also connect to the mqtt-out node by simply supplying msg.broker again. Again, this is far from clear in the help.

So, there still seems no way to have a "dummy" broker configuration? And so no way to have a true dynamic connection. If so, that is my feature request.


So, from the above, I can simplify the flow:

Still not ideal though since there is no direct way to share this flow without temporarily creating a dummy broker config (which whinges constantly in the logs) or manually editing the flow JSON to remove the private details of a broker the flow probably does not want to connect to anyway.