How to communicate between Node-RED editor and Node-RED runtime

The official guide to making the Node-RED editor and Node-RED runtime communication a two-way street with open-source node.

Table of Contents

When developing custom Node-RED nodes, sometimes it is necessary to communicate between the node's front-end as defined in the node's HTML file (which runs in the web browser, in Node-RED's editor, hitherto referred to as "node's editor") and the node's back-end as defined in the node's JavaScript file (which runs in Node-RED's runtime, hitherto referred to as "node's runtime").

The two communication directions to consider are thus: a) node editor to node runtime, and b) node runtime to node editor.

To extend Node-RED's capabilities for enterprise-level applications and scalability, check out Prescient's solution for Node-RED users - Enterprise IoT for Node-RED Users

 APIs and methods to use to communicate between a Node-RED node editor and its runtime

How can this communication be accomplished? The answer lies in a few undocumented APIs... caveat emptor, because these APIs are undocumented, it is possible that they might change without notice in the future but, as far as the author can surmise, these APIs have been stable for quite a few versions, and the functionality that they unlock is worth the (estimated small) risk of having to change the code of a custom node to support newer Node-RED versions.

Node editor to node runtime communication

This communication can be achieved by creating an HTTP endpoint in the node runtime and making an HTTP call to that endpoint from the node editor. The HTTP endpoint may be created using routing APIs of Node-RED's runtime Express app, exposed to the node's JavaScript file by RED.httpAdmin. All Express' routing methods are available, and authorization middleware may be implemented using the RED.auth.needsPermission API if a given endpoint needs to have specific restrictions.

A fairly complete example of how to create a POST HTTP endpoint is in the inject node:

This API call creates an /inject endpoint, which takes an Express route parameter id, meant to be the node ID, and is only accessible with appropriate write permissions specific to this node type. The RED.auth.needsPermission call may be omitted if no specific restrictions are needed, thus the API call would have only two callback functions, as in:

The inject node code snippet also shows how to access the route parameters using the req.params object, in this case to get a specific node's runtime object via the RED.nodes.getNode Node-RED runtime API. Getting a node's object allows for sending input messages to it via Node-RED's node receive API.

Another Node-RED runtime API of note in the inject node code snippet is the RED._ i18n (internationalization) API. The first argument of the call is the internationalization string to use, and the second argument is an object providing values to be replaced in the internationalization string. This can be thought of as a simple templating engine, where in the internationalization string any word of the form __arg__is replaced by the value corresponding to the property arg in the object passed as the second argument in the RED._ API call. In the snippet, the internationalizing string inject-comm.failed is "Inject failed: __error__", thus the second argument of the RED._ API call provides the value for the error argument.

On the node editor, the HTTP endpoint may be accessed using jQuery's ajax API. The relevant code parts in the inject node's editor are:

The HTTP POST call is done in the doInject function ($ is the traditional identifier of the jQuery() function), where the node object contains the node ID, which is used in the URL.

Node runtime to node editor communication

This direction relies on the WebSocket that Node-RED's runtime maintains with its editor. The Node-RED runtime RED.events API is used to access this functionality. The downloadfile node runtime shows an example of this:

A runtime-event is emitted whose payload is an object with three relevant fields, id, retain, and payload. id is the identifier of the event payload. retain is a Boolean flag that indicates whether the event payload should be retained to be sent when a new WebSocket client connects or not. Note that if retain is true, the event payload is saved in an object keyed by the event payload id, thus if this id is not unique, the previously retained event payload is overwritten. payload is the data that needs to be communicated to the editor, and can be of any serializable type (if null an empty object is sent). The event payload is sent through the WebSocket to the editor with the topic notification/[EVENT-PAYLOAD-ID], where [EVENT-PAYLOAD-ID] represents the value of the event payload id property.

On the node editor side, an event listener can be instantiated using the RED.comms.subscribe API. This API has two parameters, the topic to subscribe to, and a callback to be used when a message with the subscribed topic is received. To subscribe to runtime-event events, the downloadfile node uses the notification/# topic, which captures all runtime-event events. The appropriate topic coming from the node runtime is then filtered and acted upon, in this case a browser's file save dialog opens, giving the user the ability to save messages from the editor to a local file system.

Resources

To download the download-file node:

https://tinyurl.com/downloadfilenode

To watch our video tutorial:

Previous
Previous

MING Stack Demystified: MQTT, InfluxDB, Node-RED and Grafana

Next
Next

Node-RED vs. Prescient Designer: What's the difference?