I was wondering if the 'sort order' could be changed to newest at the top. It would save scrolling down to see the latest values. My UIBUILDER skills have not developed far enough yet to be able to do this myself!
Do you mean the topics with most recent data should be moved to the top? The problem is that if you had 100 messages coming in every second (or even 1000) if would be forever jumping about.
Yup ![]()
It doesn't reproduce anywhere near what the real Explorer does - yet.
There are quite a few issues to consider - for example, I'm not sure why the MQTT Explorer app seems to be able to cope with a very large amount of accumulated data whereas the browser seems more sensitive.
At the moment it is not much more than a proof of concept.
I'm open to suggestions of course. ![]()
I think I've already fixed that in my dev version.
Totally agree there. But not yet the highest priority.
Interesting thought, not sure how easy that will be, but should be possible.
Yes, that's true. At present, things are added (to the bottom) but by level. Trying to sort by the bottom up instead might be quite a task. Something to consider though.
Are the sources available in a git repository so that to get your latest version one can just execute a git pull command?
Ah, great question Colin! As of this moment, they are not. However, I will use UIBUILDER's external template feature and create a suitable repo. Then folk will be able to simply re-apply the template to update to the latest version.
Please note however, that an issue has been reported to me that this may require git to be locally installed. That should not be the case but I think something is off with my use of degit. Anyway, you don't need to pull it yourself since UIBUILDER will do the update for you. Of course, you can clone to a local folder if you only want the front-end code. As always with UIBUILDER, the choices are yours. ![]()
Anyway, I'll update in this thread when that is done.
And here we go:
I will update this from time-to-time, I've used the date for the version number so that you can check if there is an update. But please make use of GitHub's "Watch" feature to keep track.
Urm, unexpectedly and thanks to the inclusion of Claude Opus 4.5 in VSCode/GitHut Copilot, I've now also uploaded a complete rewrite!
Version 2025-11-28-a should cater for 10's of thousands of topics, each with 10 historic values! Far better than the previous version. In fact, Copilot tells me that it should be able to deal with over 100,000 topics!
I will leave it running now to see how it copes.
There is also a CHANGELOG file so you can see what is changing as I go along.
Oops, just blew up Node-RED!
Seems that my dev PC really doesn't want to handle 200k MQTT messages PER SECOND! Who would have guessed! ![]()
Maybe I should add in an option to let the browser go direct to MQTT instead?
Quick update. I left my explorer tab going overnight and right up till just now:
Page stats:
So I recon the new approach is stable and capable of handling high workloads. This example includes everything in my MQTT broker excepting two topics that record detailed trace logs from UIBUILDER - that broke Node-RED last time - obvious in hindsight since outputting those triggers an ever-growing cascade of trace messages from the uibuilder node the messages are going through. ![]()
I recon being able to handle over 200,000 topics and nearly 300,000 messages is pretty good. CPU occasionally spikes to maybe 7% on a sudden influx of messages but mostly is running 0-0.1% and the heap size is certainly manageable.
This was set to keep 50 messages per topic to the 46MB should now be pretty stable.
There should be a new full version out tomorrow with a comprehensive flow and the updated front-end which is now closer to the Explorer app and has the ability to publish messages. It should also have the MQTT v5 properties added.
Just tried it...
It is really a great tool. Thank you !!!
As a long time user of MQTT explorer, I really like the possibility to copy only part of the message and not all of it.
The color coding of the mqtt message also fantastic.
In my use case (WIS2 Overview) I am dealing with many MQTT brokers with many topics.
If I can prioritize/suggest an improvement, I'd like to have the number of published messages on each topic. Something MQTT Explorer does...
Thanks for trying it. ![]()
Yes, having it in a web interface is immediately more flexible.
Thanks for saying so. That is a built-in feature in UIBUILDER
You can, of course, use it in any uibuilder controlled UI. Though it isn't actually a complex function so you could always "borrow with pride". ![]()
OK, I will add that to the backlog. At present, I only retain the last 50 messages for each topic. Eventually that will be configurable.
Please try the new version that I've just pushed to GitHub! It has various improvements and most notably is now MUCH better at handling extremely large numbers of topics. Though folk should note that it can take an appreciable amount of time for Node-RED to send all the messages and for the browser to receive and process them - nearly 3 minutes on my dev PC with 83.5k topics and just under 83k messages,
This is, I believe a really good example of the performance overheads of Node-RED vs a more direct node.js (the original MQTT Explorer uses Electron with direct use of the mqtt node.js library). The original MQTT Explorer app is able to load the same or more data in a few seconds.
I'm also noting some inconsistencies when using Node-RED's MQTT nodes - such as $SYS not consistently loading, especially when using dynamic configurations. I want to do a separate set of tests using the MQTT library direct into a function node to see home much difference that makes.
To update your front-end code, simply re-apply the template as described in the first post. It will overwrite everything so if you made any changes, don't forget to take a copy first.
Today's updated version has a whole bunch of improvements and now includes showing MQTT v5 metadata which was one of my original drivers for wanting to do something myself.
Here is the latest version of the flow as well.
[{"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","9b644841684cee87"],["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":"80000","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":"3f52ae570273d29c","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","b569cb8f33603802"],["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":"3f52ae570273d29c","x":1250,"y":120,"wires":[]},{"id":"9b644841684cee87","type":"change","z":"4393d057899d5287","name":"broker","rules":[{"t":"set","p":"broker","pt":"msg","to":"#:(file)::mqtt_broker","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":1165,"y":120,"wires":[["28d293f592db5d7c"]],"l":false},{"id":"b569cb8f33603802","type":"debug","z":"4393d057899d5287","name":"","active":false,"tosidebar":false,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"","statusType":"counter","x":1145,"y":160,"wires":[],"l":false},{"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","baa2a1457dfde295","9d1586f2d1eb7143"],"x":34,"y":247,"w":782,"h":114},{"id":"b9539cb9e22e648f","type":"link in","z":"4393d057899d5287","g":"9a1791d2e0e6a372","name":"link in 3","links":["a7143005e591c86f"],"x":75,"y":320,"wires":[["baa2a1457dfde295"]]},{"id":"baa2a1457dfde295","type":"change","z":"4393d057899d5287","g":"9a1791d2e0e6a372","name":"Reconnect & subscribe to # & $SYS/#","rules":[{"t":"set","p":"action","pt":"msg","to":"subscribe","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"[\"#\",\"$SYS/#\"]","tot":"json"},{"t":"set","p":"force","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":320,"wires":[["9d1586f2d1eb7143"]]},{"id":"9d1586f2d1eb7143","type":"link out","z":"4393d057899d5287","g":"9a1791d2e0e6a372","name":"link out 8","mode":"link","links":["4eaeef39086a6d2e"],"x":775,"y":320,"wires":[]},{"id":"6597251a3ade5ffa","type":"group","z":"4393d057899d5287","name":"Manual Controls","style":{"fill":"#bfbfbf","fill-opacity":"0.26","label":true,"color":"#000000"},"nodes":["4837409ef3162628","60c776388f0db74c","133deb373770dfec","1e8eb8d8bd7bda43","10ed6e3b28a4f7a5"],"x":843,"y":249,"w":423,"h":142},{"id":"4837409ef3162628","type":"change","z":"4393d057899d5287","g":"6597251a3ade5ffa","name":"subscribe # & $SYS","rules":[{"t":"set","p":"action","pt":"msg","to":"subscribe","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"[\"#\",\"$SYS/#\"]","tot":"json"},{"t":"set","p":"force","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1049,"y":290,"wires":[["10ed6e3b28a4f7a5"]]},{"id":"60c776388f0db74c","type":"inject","z":"4393d057899d5287","g":"6597251a3ade5ffa","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":904,"y":350,"wires":[["133deb373770dfec"]],"l":false},{"id":"133deb373770dfec","type":"change","z":"4393d057899d5287","g":"6597251a3ade5ffa","name":"(re)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":"force","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1019,"y":350,"wires":[["10ed6e3b28a4f7a5"]]},{"id":"1e8eb8d8bd7bda43","type":"inject","z":"4393d057899d5287","g":"6597251a3ade5ffa","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":904,"y":290,"wires":[["4837409ef3162628"]],"l":false},{"id":"10ed6e3b28a4f7a5","type":"link out","z":"4393d057899d5287","g":"6597251a3ade5ffa","name":"link out 11","mode":"link","links":["4eaeef39086a6d2e"],"x":1225,"y":320,"wires":[]},{"id":"3f52ae570273d29c","type":"mqtt-broker","name":"dummy","broker":"\"\"","port":"1883","clientid":"","autoConnect":false,"usetls":false,"protocolVersion":"4","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":"d87f95912f77cac5","type":"global-config","env":[],"modules":{"node-red-contrib-uibuilder":"7.6.0"}}]
I have updated to the latest version.
It seems that after having scrolled down to a level of sub topics, the display is more or less frozen to the existing topics at the time of scrolled down.
Not sure it is 100% clear... Said otherwise, no new topics are displayed when the view is "open" see below:
The "historical" MQTT explorer shows much more subtopics...
Darn it, something has gone wrong again. I must have let a regression creep in. I can see that during the initial page load, I'm getting 50% CPU and 90k+ DOM notes which isn't right.
Actually, I think it may be worse than that! The subtopic count increases but you are right, and actually even if closed, the new topic isn't appearing for some reason. Once a topic has been opened, it is not added to.
The display only shows the count for the 1st child level. That is not the same as the app which shows the count for ALL sub-topic levels combined. I don't like that as I don't think it is the best UI.
Fixed in UIBUILDER v7.6.0







