Creation of nodes
This example explains how to create a node that wraps the funcionalities of an IoT service (offered like a Web Service) created by Inter-IoT group. It provides a complete example about how to start the development of nodes that wrap the funcionalities of your own services.
Inter-IoT Translate Service
The IoT service of this example, receive the messages in the platform format and perform it syntactic translation. Offering as output the message sintactically translated.
Package.json
This is a standard file used by Node.js modules to describe their contents. It can be generated using the command npm init.
In this file, Node-RED modules must be included with the path to their Javascript file. In addition, the dependencies that are necessary in order to run the node also must be included, together with the minimum required version. These dependencies have to be installed previosly in the same path that the package.json file using the command npm install.
{
"name": "mwtranslator",
"version": "1.0.0",
"description": "node-red mwtranslator for INTER-IoT project",
"main": "index.js",
"author": "SATRD",
"license": "Apache-2.0",
"node-red": {
"nodes": {
"translator-to": "translator-to/translator-to.js",
"translator-from": "translator-from/translator-from.js",
"translator-server": "translator-server/translator-server.js"
}
},
"dependencies": {
"request": "^2.88.0",
"request-promise": "^4.2.2"
}
}
HTML
Defines the node's appearance and is divided in three different sections
Edit dialog
The edit dialog contains the node's properties that must be configured by the user
<script type="text/x-red" data-template-name="translator-from">
<div class="form-row">
<label for="node-input-server"><i class="icon-tag"></i> Server</label>
<input type="text" id="node-input-server" placeholder="Server">
</div>
<div class="form-row">
<label for="node-input-iotplatform"><i class="icon-bookmark"></i>IoT platform:</label>
<select id="node-input-iotplatform">
<option value="fiware">Fiware</option>
<option value="sofia">Sofia2</option>
<option value="universaal">universAAL</option>
</select>
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label> </label>
<input type="checkbox" id="node-input-setdata" style="display:inline-block; width:auto; vertical-align:top;">
<label for="node-input-setdata" style="width:70%;"><span>Enable manual data input</span></label>
</div>
<div class="form-row" id="node-set-data">
<label for="node-input-data"><i class="icon-tag"></i> Data</label>
<input type="text" id="node-input-data" placeholder="Data">
</div>
</script>
Help text
Describes the information that will be displayed in the Node-RED's dashboard info tab when the node is selected
<script type="text/x-red" data-help-name="translator-from">
<p>Middleware translator from an IoT platform's data model to INTER-IoT's data model</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt>msg.translate
<span class="property-type">string | buffer</span>
</dt>
</dl>
<h3>Outputs</h3>
</script>
Node definition
A node must be registered using the RED.nodes.registerType function, which has two arguments:
-
The type of the node, that must match the value used by the call to RED.nodes.registerType in the corresponding Javascript file
-
The definition of the node
In the following example, the type of the node is 'translator-from' and it is defined as a node of the category 'mwtranslators' with four parameters that correspond with the parameters described in the edit dialog. Furthermore, the node has one input, one output and includes a function in the 'oneditprepare' property that will be executed when Node-RED is deployed.
<script type="text/javascript">
RED.nodes.registerType('translator-from',{
category: 'mwtranslators',
color: '#c2daf1',
defaults: {
name: {value:""},
server: {value:"http://localhost:4568/translate/fiware", type:"translator-server", required: true},
data: {value:""},
iotplatform: {value:"", required: true},
setdata: function(){
return $('#node-input-setdata').is(":checked");
}
},
inputs:1,
outputs:1,
icon: "interiot.png",
label: function() {
return this.name||`mwtranslator from ${this.iotplatform}`;
},
oneditprepare: function(){
var setstate = function () {
if ($('#node-input-setdata').is(":checked")) {
$("#node-set-data").show();
} else {
$("#node-set-data").hide();
}
};
$("#node-input-setdata").change(function () { setstate(); });
setstate();
}
});
</script>
Javascript
Defines the runtime behaviour of the node
Node constructor
Nodes are defined by a constructor function that can be used to create new instances of the node
module.exports = function (RED){
function translatorFrom(config){
// Node behaviour code
}
RED.nodes.registerType("translator-from",translatorFrom);
}
Receiving messages
In a node, input data is received as a msg object, that has different properties like payload (msg.payload).
var node = this;
node.on("input", (msg)=>{
// Code using 'msg'
});
Sending messages
Nodes can send messages to the down-stream nodes in a flow using the send function.
msg.payload=response;
node.send(msg);
Retrieve node's properties
Node's properties previously included in the HTML file can be retrieved as properties of the config JS object. For example:
config.iotplatform
However, if a property has a type that is a config node, its value can be retrieved directly from the node. For example, the property host of the node's server property can be retrieved like:
this.server.host
Complete example
var rp = require('request-promise'); //request Promise
module.exports = function (RED){
function translatorFrom(config){
RED.nodes.createNode(this, config);
// Retrieve the config node
this.server = RED.nodes.getNode(config.server);
var node = this;
node.on("input", (msg)=>{
var _uri = "http://"+this.server.host+":"+this.server.port+"/translate/"+config.iotplatform;
var contentType="";
var _body = "";
if(config.setdata) _body = config.data;
else _body =msg.translate;
if(config.iotplatform=="universaal"){
contentType = "text/plain"
}else{
contentType = "application/json";
_body = JSON.stringify(_body);
}
var options = {
method: 'POST',
uri: _uri,
body: _body ,
headers: {
'Content-Type': contentType,
'Cache-Control': 'no-cache'
}
};
rp(options)
.then(function (response) {
msg.payload=response;
node.send(msg);
})
.catch(function (err) { // API call failed...
node.error(err);
});
});
}
RED.nodes.registerType("translator-from",translatorFrom);
}
Configuration nodes
A configuration node is defined in the same way as other nodes. There are two key differences:
- Its category property is set to config
- The edit template
<input>elements have ids of node-config-input-<propertyname>
A configuration node must be included as a type of a node property in the HTML file. For example, a server property that its type is a config node called translator-server
server: {value:"http://localhost:4568/translate/fiware", type:"translator-server", required: true},
Complete example
-
HTML file
<script type="text/x-red" data-template-name="translator-server"> <div class="form-row"> <label for="node-config-input-port"><i class="icon-bookmark"></i> Host</label> <input type="text" id="node-config-input-host"> </div> <div class="form-row"> <label for="node-config-input-port"><i class="icon-bookmark"></i> Port</label> <input type="text" id="node-config-input-port"> </div> </script> <script type="text/x-red" data-help-name="translator-server"> <p>MWTRANSLATOR SERVER</p> </script> <script type="text/javascript"> RED.nodes.registerType('translator-server',{ category: 'config', defaults: { host: {value:"localhost",required:true}, port: {value:4568,required:true,validate:RED.validators.number()} }, label: function() { return this.host+":"+this.port; } }); </script> -
Javascript file
module.exports = function(RED) { function translatorServer(n) { RED.nodes.createNode(this,n); this.host = n.host; this.port = n.port; } RED.nodes.registerType("translator-server",translatorServer); }
More information
For more information, you can read the official documentation of Node-RED