What is Node-RED?
Node-RED is a powerful tool for building IoT applications and services. Its genesis was triggered exactly by this need to rapidly prototype IoT applications. An open source project led by the IBM Emerging Technologies group, in particular the two researchers, Nick O’Leary and Dave Conway-Jones, Node-RED was initially a tool for themselves as they were working on IoT projects and were “looking for a way to simplify the process of hooking together systems and sensors when building proof-of-concept technologies for customers.”
In this article, we'll use both Ubidots MQTT nodes and Node-RED's native HTTP and MQTT libraries ("nodes") to read/send data to/from Ubidots.
1. Installing Ubidots' MQTT nodes
Once Node-RED is running on your computer, head to the top-right menu and then click on the 'Manage pallets' option. A window, as depicted below, will appear. Go to the 'Install' tab, run a search for 'ubidots' and install the nodes called 'ubidots-nodered'.
Finally, close and re-open Node-RED. You should now see Ubidots' MQTT nodes in the input and output section, respectively, found in the left-hand Node panel.
NOTE: By default Ubidots MQTT nodes use QoS 1.
2. Using Ubidots' MQTT nodes
Ubidots' MQTT publish node
As its name suggests, this node publishes data to Ubidots. The following is a typical setup for the node:
Where:
Account type defines the broker to which the data will be sent: Ubidots.
Name refers to the node’s name [optional].
Token of your Ubidots account. It can be either an Account Token or Organizational Token [required].
Device Label: The label of the Device to which the data will be published. It can be sent dynamically in the input message JSON object with the key: "ubidotsDeviceLabel". If no Device label is sent, it will take the default value from the Device Label field. Keep in mind that the Device Label is required.
TLS: By default, all sent data is encrypted via TLS. Uncheck if data should be sent unencrypted.
The node accepts the following parameters as input:
msg.payload: Contains the body of the message. In this case, the values to be published on the given Device in JSON format. Each key is the label of the variable.
msg.payload.ubidotsDeviceLabel: The label of the Device to which the packet will be published. If no Device Label is sent, it takes the Device Label from the Device Label field in the node settings.
Publish example: The following simple node arrangement publishes Temperature, Humidity and Pressure values to an Ubidots Device called as “Machine_1”:
The example uses inject nodes to send fixed values and a function node to build the JSON payload accepted by the platform. At the right just below the Ubidots’ out node there’s a debug node that helps inspecting the output payload as shown below:
Here’s the clipboard version of the publish example so you can easily import it into your Node-RED project.
[{"id":"c365b578.54a618","type":"inject","z":"99b17f5d.db16","name":"Temperature","topic":"temperature","payload":"58","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":270,"y":140,"wires":[["2403cd9b.1b5802"]]},{"id":"daf81333.2a9aa","type":"inject","z":"99b17f5d.db16","name":"Humidity","topic":"Humidity","payload":"47","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":260,"y":180,"wires":[["2403cd9b.1b5802"]]},{"id":"452f88ba.1f1488","type":"inject","z":"99b17f5d.db16","name":"Pressure","topic":"pressure","payload":"60","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":260,"y":220,"wires":[["2403cd9b.1b5802"]]},{"id":"2403cd9b.1b5802","type":"function","z":"99b17f5d.db16","name":"function","func":"var label = msg.topic;\nvar value = msg.payload;\n\nmsg.payload = {\n [label]: value\n};\n\nmsg.payload.ubidotsDeviceLabel = \"Machine_1\";\n\nreturn msg;","outputs":1,"noerr":0,"x":520,"y":180,"wires":[["391d78a3.4a1418","a52cd0b9.af8af"]]},{"id":"391d78a3.4a1418","type":"debug","z":"99b17f5d.db16","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":690,"y":240,"wires":[]},{"id":"a52cd0b9.af8af","type":"ubidots_out","z":"99b17f5d.db16","name":"","token":"YOUR-UBIDOTS-TOKEN","label_device":"","device_label":"Machine_x","tier":"business","tls_checkbox":true,"x":690,"y":180,"wires":[]}]
Ubidots' MQTT Subscribe node
As its name suggests, this node subscribes to variables or topics (10 as maximum). The following is a typical setup for the node:
Where:
Account type defines the broker to which the data will be sent: Ubidots.
Name refers to the node’s name [optional].
Token of your account. It can be either an Account Token or Organizational Token.
Device Label: The label of the Device to which the packet will be published. Please keep in mind that this field is ignored in case custom topics are used.
TLS: By default all data is sent encrypted via TLS. Uncheck if data should be sent unencrypted.
Use Custom Topics: Enable subscription to custom topics, hence, disabling subscription to variables.
Variable Labels/Custom topics: If “Use Custom Topics” option is disabled, you must enter the label of the Variable the node will subscribe to. Otherwise, you must enter the topic in the following format:
Device_Label/Variable_Label
. Optionally/lv
can be added to subscribe to the Last Value only. Topics support wildcard characters: "+" for single-level and "#" for multi-level.Last Value of the variable. Only available when “Use Custom Topic” option is disabled.
Add Variable/Add Topic: Add an additional variable/topic (up to 10).
The output is a JSON object with the variable label as key and the Last Value/Dot object as value, e.g.:
{"variable_label": {"value": 100, "timestamp": 1583523586668, "context": { "key1": "value1", "key2": "value2"}, "created_at": 1583523586732}
Variable subscription example: The following node arrangement subscribes to Temperature's last value , Humidity variable and Pressure variable, all of them from an Ubidots device called as “Machine_1”:
The example uses a function node to split 3 variables into single outputs. In that way, you can handle them separately. The following image shows the JSON object response when variables get an update.
Here’s the clipboard version so you can import it easily into your node project.
[{"id":"a7bea0eb.9b358","type":"function","z":"99b17f5d.db16","name":"function","func":"const varLabels = [\n \"temperature\",\n \"humidity\",\n \"pressure\"\n ];\n \nvar payload = msg.payload;\nvar label = Object.keys(payload)[0];\nvar output = [];\nvarLabels.forEach(function (varLabel){\n if (label == varLabel) {\n msg.payload = payload[label].value;\n output.push(msg);\n } else {\n output.push(null);\n }\n});\n\nreturn output;","outputs":3,"noerr":0,"x":460,"y":480,"wires":[["1a30a1cc.46933e"],["563aac2d.eb64b4"],["2a5f0a3a.a77b46"]]},{"id":"1a30a1cc.46933e","type":"debug","z":"99b17f5d.db16","name":"Temperature","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":650,"y":440,"wires":[]},{"id":"563aac2d.eb64b4","type":"debug","z":"99b17f5d.db16","name":"Humidity","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":640,"y":480,"wires":[]},{"id":"2a5f0a3a.a77b46","type":"debug","z":"99b17f5d.db16","name":"Pressure","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":640,"y":520,"wires":[]},{"id":"3173299f.902716","type":"ubidots_in","z":"99b17f5d.db16","tier":"business","name":"Ubidots in","token":"YOUR-UBIDOTS-TOKEN","device_label":"machine_1","tls_checkbox_in":true,"custom_topic_checkbox":false,"label_variable_1":"temperature","label_variable_2":"humidity","label_variable_3":"pressure","label_variable_4":"","label_variable_5":"","label_variable_6":"","label_variable_7":"","label_variable_8":"","label_variable_9":"","label_variable_10":"","checkbox_variable_1_last_value":true,"checkbox_variable_2_last_value":false,"checkbox_variable_3_last_value":false,"checkbox_variable_4_last_value":true,"checkbox_variable_5_last_value":true,"checkbox_variable_6_last_value":true,"checkbox_variable_7_last_value":true,"checkbox_variable_8_last_value":true,"checkbox_variable_9_last_value":true,"checkbox_variable_10_last_value":true,"x":260,"y":480,"wires":[["a7bea0eb.9b358"]]}]
Topic subscription example: The following node arrangement subscribes to the topic “+/status/lv
” and “machine_2/#
”. Therefore, it will return every update in variables with the label “status” regardless of the Device and every variable update of the Machine 2 Device:
The example uses a function node to split both topics outputs into single outputs so that you can handle them by separate. The following image shows the JSON object response:
Here’s the clipboard version so you can import it easily into your node project.
[{"id":"77f94f4b.91c54","type":"ubidots_in","z":"99b17f5d.db16","tier":"business","name":"Ubidots in","token":"YOUR-UBIDOTS-TOKEN","device_label":"machine_1","tls_checkbox_in":true,"custom_topic_checkbox":true,"label_variable_1":"+/status/lv","label_variable_2":"machine_2/#","label_variable_3":"","label_variable_4":"","label_variable_5":"","label_variable_6":"","label_variable_7":"","label_variable_8":"","label_variable_9":"","label_variable_10":"","checkbox_variable_1_last_value":true,"checkbox_variable_2_last_value":false,"checkbox_variable_3_last_value":true,"checkbox_variable_4_last_value":true,"checkbox_variable_5_last_value":true,"checkbox_variable_6_last_value":true,"checkbox_variable_7_last_value":true,"checkbox_variable_8_last_value":true,"checkbox_variable_9_last_value":true,"checkbox_variable_10_last_value":true,"x":260,"y":700,"wires":[["cc9719d3.ba4a78"]]},{"id":"cc9719d3.ba4a78","type":"function","z":"99b17f5d.db16","name":"function","func":"var payload = msg.payload;\nvar key = Object.keys(payload)[0]\nvar output;\n\nswitch(key.includes(\"status\")){\n case true:\n output = [msg, null];\n break;\n \n case false:\n output = [null, msg];\n break;\n}\nreturn output;","outputs":2,"noerr":0,"x":460,"y":700,"wires":[["fe1b808a.ecfba"],["92898340.777d4"]]},{"id":"fe1b808a.ecfba","type":"debug","z":"99b17f5d.db16","name":"status","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":630,"y":681,"wires":[]},{"id":"92898340.777d4","type":"debug","z":"99b17f5d.db16","name":"Machine 2 Variables","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":680,"y":721,"wires":[]}]
3. Using Node-RED's native HTTP and MQTT nodes
Why use native libraries instead of Ubidots' library?
Through our experience and interaction with thousands of developers, Node-RED and Ubidots complement each other's services well when:
Grasp the concepts behind IoT protocols: Working with native HTTP and MQTT libraries will help you understand the concepts behind these protocols, enriching your IoT expertise. Using a library that wraps these protocols might save you lines of code but will hide important concepts that might be useful for troubleshooting and scaling your project.
Connecting from any Node-RED device/server: Some Node-RED environments make it hard to install 3rd party libraries. For example, if you're running Node-RED from a server and you're not the admin and cannot install libraries. Using already built-in libraries can save you time, headache, and development costs.
In the examples below, we'll use an "Inject node" to simulate data but, of course in real-world applications, you need only replace this node with its actual source of data.
Node-RED + Ubidots using HTTP
Here's a simple node arrangement that sends a random "current" value, between 0 and 5, and a fixed "voltage" value to an Ubidots device called "node-red":
All the magic happens in the "function" node called "Setup Request", which prepares the request according to Ubidots API expected HTTP details:
Here's the clipboard version, so you can import it into your project - just copy and paste, if needed.
[{"id":"c53b887d.a27888","type":"inject","z":"98e9cf79.a372f8","name":"","topic":"","payload":"","payloadType":"none","repeat":"5","crontab":"","once":true,"x":110,"y":100,"wires":[["90633f9e.bc1a58"]]},{"id":"90633f9e.bc1a58","type":"function","z":"98e9cf79.a372f8","name":"Setup Request","func":"var msg;\ndevice_label = \"Node-RED\";\nubidots_token = \"BBFF-xxxxxxxxxxxxxx\";\nmsg.method = \"POST\";\nmsg.url = \"http://industrial.api.ubidots.com/api/v1.6/devices/\" + device_label + \"/?token=\" + ubidots_token;\nmsg.payload = {\"current\":5*Math.round(Math.random() * 100) / 100,\"voltage\":\"110\"};\nreturn msg;","outputs":1,"noerr":0,"x":275,"y":100,"wires":[["4b95b329.d784c4"]]},{"id":"8cf48dc0.84df7","type":"debug","z":"98e9cf79.a372f8","name":"","active":true,"console":"false","complete":"payload","x":629,"y":100,"wires":[]},{"id":"4b95b329.d784c4","type":"http request","z":"98e9cf79.a372f8","name":"","method":"use","ret":"txt","url":"","x":453,"y":100,"wires":[["8cf48dc0.84df7"]]}]
Node-RED + Ubidots using MQTT
Here's an example that publishes temperature data to Ubidots' MQTT broker and subscribes to the updated variable:
This example uses an inject node to publish the payload {"temperature":123} to an MQTT publish node configured as specified in Ubidots' MQTT documentation, that is:
Ubidots Broker:
industrial.api.ubidots.com
Port: 1883
Username: Your Ubidots token
Password: Leave blank
Publish topic:
/v1.6/devices/{LABEL_DEVICE}
Subscribe topic:
/v1.6/devices/{LABEL_DEVICE}/{VARIABLE_LABEL}/lv
Note that "lv" stands for last value. This means, this topic only returns the last value of the variable, without the JSON formatting, making it easier to parse if needed.
Entering all of this in Node-RED would look like this:
In the MQTT publish node:
When clicking in the edit button of the broker:
In the MQTT subscribe node:
Finally, here's the clipboard version so you can easily import this sample into your project:
[{"id":"8765d540.6b6bc8","type":"inject","z":"eb630143.270018","name":"","topic":"","payload":"{\"temperature\":123}","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":190,"y":200,"wires":[["f3c857d3.8d10c"]]},{"id":"f3c857d3.8d10c","type":"mqtt out","z":"eb630143.270018","name":"","topic":"/v1.6/devices/node-red","qos":"","retain":"","broker":"694beaca.29a254","x":577,"y":201,"wires":[]},{"id":"cc230b36.52f4e8","type":"mqtt in","z":"eb630143.270018","name":"","topic":"/v1.6/devices/node-red/temperature/lv","qos":"2","datatype":"auto","broker":"694beaca.29a254","x":220,"y":331,"wires":[["3e83a146.589e16"]]},{"id":"3e83a146.589e16","type":"debug","z":"eb630143.270018","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":594,"y":330,"wires":[]},{"id":"694beaca.29a254","type":"mqtt-broker","z":"","name":"","broker":"industrial.api.ubidots.com","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]
NOTE: you will need to configure the MQTT broker even after pasting the clipboard version above.
Other users also found the following helpful...