I am new to node-red. I used to get messages from topic using AWS Mqtt node. It was working fine when I have already configured certs and topic. In my case, I want to use dynamic certs configuration and topic.
For this, I created a new node based on node-red-contrib-aws-iot-hub (aws-iot.js).
My new node files pasted here:
index.js:
module.exports = function(RED) {
function LowerCaseNode(config) {
RED.nodes.createNode(this,config);
var node = this;
node.on('input', function(msg) {
var awsIot = require('aws-iot-device-sdk');
function subscribe_topic(top){
device.subscribe(top);
console.log("subscribed"+" "+top);
console.log(msg.node_name_c+" "+"subscribe" );
node.status({
fill : "green",
shape : "ring",
text : "subscribed"
});
}
function unsubscribe_topic(top){
device.unsubscribe(top);
console.log("unsubscribed"+" "+top);
}
function init_device(keyPath_, certPath_, caPath_, clientId_, host_, topic_){
device = awsIot.device({
keyPath: keyPath_,
certPath: certPath_,
caPath: caPath_,
clientId: clientId_,
host: host_,
protocol: 'mqtts'
});
console.log("calling...");
device
.on('connect', function() {
console.log('connect');
node.status({
fill : "yellow",
shape : "ring",
text : "subscribing..."
});
subscribe_topic(topic_);
});
device
.on('message', function(topic_, payload) {
console.log('message', topic_, payload.toString());
msg.payload = {"topic": topic_, "message": payload.toString()};
console.log(msg.node_name_c+" "+"message" );
node.send(msg);
});
device.on('reconnect', function() {
console.log('reconnected');
});
device.on('offline', function() {
console.log('offline');
});
device
.on('error', function(error) {
console.log(error);
node.status({
fill : "error",
shape : "ring",
text : error.message
});
});
var globalContext = node.context().global;
globalContext.set("init_status", 1)
console.log("global variable is set to 1");
}
topics=msg.topics;
topics.forEach(function(topic) {
console.log(msg.node_name_c);
var globalContext = node.context().global;
init_status = globalContext.get("init_status");
console.log(init_status);
var keyPath_ = msg["payload"]["keyPath"];
var certPath_ = msg["payload"]["certPath"];
var caPath_ = msg["payload"]["caPath"];
var clientId_ = msg["payload"]["clientId"];
var host_ = msg["payload"]["host"];
if (init_status==undefined){
device=null;
console.log("first time");
init_device(keyPath_, certPath_, caPath_, clientId_, host_, topic);
}
else{
node.status({
fill : "yellow",
shape : "ring",
text : "subscribing..."
});
subscribe_topic(topic);
}
});
node.on('close', function() {
console.log("closed");
if (device) {
device.end();
}
device = null;
var globalContext = node.context().global;
globalContext.set("init_status", undefined)
node.status({
fill : "blue",
shape : "ring",
text : "Ready"
});
});
//
// Device is an instance returned by mqtt.Client(), see mqtt.js for full
// documentation.
//
});
}
RED.nodes.registerType("custom-mqtt",LowerCaseNode);
}
index.html:
<script type="text/javascript">
RED.nodes.registerType('custom-mqtt',{
category: 'function',
color: '#ff5050',
defaults: {
name: {value:""}
},
inputs:1,
outputs:1,
icon: "bridge.png",
label: function() {
return this.name||"custom-mqtt";
}
});
</script>
<script type="text/html" data-template-name="custom-mqtt">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/html" data-help-name="custom-mqtt">
<p>A simple node that converts the message payloads into all lower-case characters</p>
</script>
package.json:
{
"name": "mqtt-listener",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {"aws-iot-device-sdk": ">=1.0.12"},
"node-red": {
"nodes": {
"custom-mqtt": "index.js"
}
}
}
sample payload:
msg.payload = {"keyPath":"/certs/clientId-private.key",
"certPath":"/certs/clientId-cert.pem",
"caPath":"/certs/root-CA.crt",
"clientId":"clientId",
"host":"host.iot.ap-southeast-1.amazonaws.com"}
msg.topics = ["topic_1", "topic_2"];
msg.node_name_c = "xxxx"
return msg;
The above node takes n topic and subscribe all the listed topics and if any message arrives on any topic it will be sent to next node.
Sample Flow:
This node is unreliable. After some times if any error occurs, the messages are not received. It's almost unreliable. I think I have failed to properly create my first custom node.
My question:
- Can I make some modifications on aws iot node so that it can take certs and topic configurations dynamically?
- How to make my custom node stable. What changes I have to make it more reliable.
Note: I have gone through mqtt-digitaloak. I want similar approach of digitaloak but dynamic certificate configuration.