-
Notifications
You must be signed in to change notification settings - Fork 23
Custom nodes
//
//
[Nodes] consist of a pair of files; a JavaScript file that defines what the node does, and an html file that defines the node’s properties, edit dialog and help text.
→ Read Node-RED documentation to learn how to create nodes.
This Wiki does not give you the basics.
Your own nodes must be located in the "node-red-contrib" folder of your bot. Each node should be accompanied by a package.json file in order to be loaded in your Node-RED environment.
The QRCode node is available here.
→ Learn the basics first.
The HTML file consists of 3 main parts: the node's properties, the node's display and the node's informations.
1. The node's properties :
<script type="text/javascript">
RED.nodes.registerType('qrDecode', {
category: 'VISEO_HELPER',
color: '#3FADB5',
defaults: {
name: { value: undefined },
input: { value: undefined },
output: { value: undefined },
pptTypeIn: { value:"msg" },
pptTypeOut: { value:"msg" },
},
inputs: 1,
outputs: 1,
icon: 'qr-code.svg',
align: 'left',
paletteLabel: 'QRDecode',
label: function () { return this.name || 'QRDecode' },
oneditprepare: function() {
$("#node-input-input") .typedInput({ default: this.pptTypeIn || 'msg', types:['msg']});
$("#node-input-output").typedInput({ default: this.pptTypeout || 'msg', types:['msg']});
}
});
</script>
The RED.nodes.registerType function required the node's type and its definition:
- category, color, icon, align and paletteLabel refer to the node's display on the Node-RED palette.
- defaults refers to the node editable properties. They are often needed by the JS file.
- inputs and outputs are set at 1 here; we don't need several outputs.
- oneditprepare function is called when the edit dialog is being built. Here, it is used to set the editable input types.
2. The node's display :
<script type="text/x-red" data-template-name="qrDecode">
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="QRDecode">
</div>
<div class="form-row">
<label for="node-input-input"><i class="icon-tag"></i> Input</label>
<input type="text" id="node-input-input" style="width: 70%" placeholder="prompt.attachments[0].contentUrl"/>
</div>
<div class="form-row">
<label for="node-input-output"><i class="icon-tag"></i> Output</label>
<input type="text" id="node-input-output" style="width: 70%" placeholder="payload"/>
</div>
</script>
Each editable input is linked to a HTML element, except the types here (pptTypeIn and pptTypeOut).
If the input's name is "myowninput" in the defaults section, the id of the input section should be "node-input-myowninput". Otherwise, the input will not be registered.
The <i class="icon-tag">
refers to the icon displayed next to the label.
3. The node's informations :
<script type="text/x-red" data-help-name="qrDecode">
</script>
Here, there isn't any help text to be displayed on Node-RED.
→ Learn the basics first.
→ The complete JS file is available here.
The JS file consists of a main function, module.exports, and the node's behavior functions.
module.exports = function(RED) {
const register = function(config) {
RED.nodes.createNode(this, config);
let node = this;
start(RED, node, config);
this.on('input', (data) => { input(node, data, config) });
this.on('close', (done) => { stop(done) });
}
RED.nodes.registerType("qrDecode", register, {});
}
The first thing to do in the JS file is to create the node with the RED.nodes.createNode function. This is usually done in the register function.
All the editable inputs defined in the HTML file can be found in the config object.
Here, we defined two main methods in our code: input and stop.
const stop = (done) => { done(); }
const start = (RED, node, config) => { }
const input = (node, data, config) => {
let value = helper.getByString(data, config.input || 'prompt.attachments[0].contentUrl');
// 3. End the node
let done = (err, json) => {
if (err) return node.warn('Decode Error: '+err);
helper.setByString(data, config.output || 'payload', json);
node.send(data);
}
// 1. Buffer decode it
if (value instanceof Buffer){
return decodeBuffer(value, done);
}
// 2. URL download Image
if (typeof value === 'string' && value.indexOf('http') === 0){
request({ url: value, method: 'GET', encoding : null }, (err, res) => {
if (err) { return node.warn('HTTP Error: ' + err); }
decodeBuffer(res.body, done);
});
}
}
The input method uses the editable inputs (config.input and config.output) and decribes the node's behavior.
In this node, we only have 1 output. A call to node.send(data) sends the message to the output. A call to node.error(err) sends an error to Node-RED and stops the flow, while a call to node.warn(err) will not stop the flow.
{
"name" : "node-red-contrib-viseo-qrcode",
"version" : "0.0.1",
"description" : "Decodes a given QrCode",
"dependencies" : {
"jsqr": "^0.2.2",
"jimp": "^0.2.27",
"request": "^2.81.0",
"query-string": "^5.0.0",
"node-red-viseo-helper" : "~0.1"
},
"repository" : {
"type":"git",
"url":""
},
"license": "Apache-2.0",
"keywords": [ "viseo", "sarah", "node-red" ],
"node-red" : {
"nodes": {
"qrcode": "node-qrcode.js"
}
}
}
For several nodes in the folder, we should add them to the 'nodes' section.
- All packages should be named
node-red-contrib-viseo-*
to scope and find libraries. - Packages should define a big features (like a MongoDB Node) or set of REST Services (like Microsoft Cognitive Services)
The implementation between Microsoft Computer Vision and Microsoft LUIS is really close whereas Google Computer vision is far from Microsoft implementation. So node-red-contrib-viseo-microsoft
and node-red-contrib-viseo-google
is better than node-red-contrib-viseo-computervision
Nodes properties should be dynamic and set/get the data from the flow. Node Helper library provides setByString()
and getByString()
function to work with deep data.
let property = helper.getByString(data, 'path.to[3].property', 'default')
Node Message
from BotBuilder
package has improved features (see marshall()
) :
- search/replace all
message {with.properties} text
usinghelper.resolve()
- translate all properties in curent bot language
- use Mustache
some {{{mustach code}}} here
🔎 Overview
- Installation - Linux OS
- Installation - Windows OS
- Installation - Docker
- Project creation
- Configuration
- Service start
✏️ UX cookbook
- Channels
- Building bots
- NLP
- Privacy & GDPR