I'm trying to move on from the std dashboard: not easy... (It has become too limiting and too slow for me.) One of the things I'm trying to wrap my mind around is whether to introduce subscriptions into the dashboard model.
One of the complexities of adding a dashboard to node-red is how to connect the nodes in node-red with components in the web browser. For that some identifiers are needed. In the std node-red dashboard these identifiers are hidden inside the UI nodes, which is nice for the user, but ultimately limiting. With uibuilder there is no built-in matching, so in principle anything is possible, but looking at uibuilder-vuejs-component-extras the identifiers are made explicit: the user gives each component a "ref ID" and then targets a component by setting that ref ID on messages sent to the uibuilder node. Cinhcet's component-dashboard does something similar by matching messages on the HTML element ID.
Once we have these routing identifiers to match producer and consumer of messages we can start asking how exactly they are matched and when messages are forwarded and what else can be done to messages (such as caching/retaining). For example, in most uses uibuilder needs a caching mechanism to initialize components when a new client connects.
In uibuilder with vuejs-components-extra and in component-dashboard the producer/consumer matching is done on full ID equality. But looking at pub/sub, such as MQTT, generally some form of ID (topic) hierarchy is desirable and supported by some form of prefix matching. So is a topic hierarchy useful in a dashboard implementation as well?
In uibuilder and component-dashboard the producer controls message forwarding. It seems that in general all messages are sent to all clients. Uibuilder adds a SocketID which lets the producer control message forwarding to a single client. In contrast, pub/sub systems let the consumer control message forwarding using subscriptions. Which of the two models is more appropriate for a dashboard implementation?
I believe that the general trend in web design has been to let the consumer control data forwarding: the components on each web page request data from the server and, where a live feed is desired, subscribe to such a feed. In my experience the reason for this trend is that it reduces the coupling between front-end and back-end code: the back-end (server) provides RESTful access to its data in a way somewhat agnostic to the details of the web apps, and the front-end (web components) pull the data they currently need.
How message forwarding is controlled also has performance and complexity aspects. On the performance side a subscription model can ensure that only the data actually needed by the client is transmitted. In node-red dashboard terms,this means that if a single-page-app has 20 tabs (like my current dashboard...) it can choose to only subscribe to the topics relevant to the components displayed on the current tab. On the downside, the subscription model requires subscription messages to be sent and it requires that the server track subscriptions for each client, which adds quite some complexity especially if prefix matching is supported.
I've been using quite a few MQTT terms so far because my node-red implementation does almost all its I/O through MQTT, at least all the devices are attached through MQTT. This leads me to wonder what would happen if the dashboard were attached to node-red via MQTT? Consider the following variation on uibuilder:
- instead of sending messages to the uibuilder node just send to the MQTT broker, control caching by setting the retain flag
- instead of connecting to the node-red process, the dashboard connects directly to the broker via a websocket, speaks MQTT, and subscribes to the topics it needs for display
I believe this would accomplish a number of things:
- supports pub/sub so web pages can subscribe to just the data they need
- supports "caching" through the MQTT retain facility, so a new client gets the last message sent to the topics it subscribes to
- supports direct interaction between IoT devices and the UI: one doesn't have to create a node-red flow just to funnel messages through (this also raises permissions/security issues)
- supports a more general architecture where node-red is just one service on the "MQTT bus" and the dashboard can just as easily interact with additional services via MQTT
Of course attaching the dashboard to MQTT is not attractive for node-red deployments that don't use MQTT and it is also true that a pub/sub mechanism as well as caching could be implemented in node-red/uibuilder/component-dashboard. And there are cons to using MQTT:
- the retain flag only controls retention of the last message, when drawing charts it can be useful to retain the last N messages or the messages for some time-period, which is something a custom caching mechanism around uibuilder could implement
- permissions need to be handled at the MQTT level, which may or may not be a good match for the task
- uibuilder implements quite some machinery to serve-up the UI, including the ability to edit the UI from within node-red
I must say that after thinking through all this I find the pub/sub model for the dashboard very compelling. I also find an MQTT-attached dashboard conceptually very compelling but I'm not sure about the practical aspects (permissions and serving-up the UI). I'd be very interested to hear from others that have much more experience than I do in implementing a dashboard for node-red!