datacake-nodes
Version:
a collection of datacake nodes for node-red
124 lines (109 loc) • 5.94 kB
JavaScript
module.exports = function(RED) {
var mqtt = require("mqtt");
var util = require("util");
var isUtf8 = require('is-utf8');
var url = require('url');
function DatacakeDeviceInputNode(config) {
RED.nodes.createNode(this, config);
var node = this;
var globalContext = this.context().global;
// Retrieve the config node, where the device is configured
node.datacake_configuration = RED.nodes.getNode(config.datacake_configuration);
node.log("Datacake - Device Input: Starting Device Input");
node.device_id = config.device_id;
if(typeof(config.device_id) !== 'undefined' && config.device_id != ""){
node.device_id = config.device_id.split("#")[0];
node.product_slug = config.device_id.split("#")[1];
} else {
node.device_id = "";
node.product_slug = "";
}
node.field_id = config.field_id;
if(!node.datacake_configuration) {
node.warn("Datacake - Device Input: No Configuration");
node.status({fill:"red",shape:"ring",text:"no configuration"});
} else {
node.log("Datacake - Device Input: Starting connection");
node.log("Datacake - Device Input: Device ID: " + node.device_id);
node.log("Datacake - Device Input: Product Slug " + node.product_slug);
node.log("Datacake - Device Input: Field Name " + node.field_id);
// check number of mqtt connections
// X nodes share one mqtt connection per workspace, so we keep the EventEmitter limit in check, adjust this number for performance
// greater number of nodesPerConnection means less strain on the mqtt connection, but greater strain on device running code
var nodesPerConnection = 5;
node.globalCountVariable = 'mqtt_client_' + node.datacake_configuration.workspace_id + '_count';
if(typeof(globalContext.get(node.globalCountVariable)) === 'undefined') {
var globalCount = 1;
} else {
var globalCount = globalContext.get(node.globalCountVariable);
globalCount++;
}
globalContext.set(node.globalCountVariable, globalCount);
node.connectionNumber = Math.ceil(globalCount/nodesPerConnection);
node.globalNodeCountVariable = 'mqtt_client_' + node.datacake_configuration.workspace_id + '_count_' + node.connectionNumber;
if(typeof(globalContext.get(node.globalNodeCountVariable)) === 'undefined') {
var nodeCount = 1;
} else {
var nodeCount = globalContext.get(node.globalNodeCountVariable);
nodeCount++;
}
globalContext.set(node.globalNodeCountVariable, nodeCount);
node.globalVariable = 'mqtt_client_' + node.datacake_configuration.workspace_id + '_' + node.connectionNumber;
if( typeof(globalContext.get(node.globalVariable)) === 'undefined' ){
var client = mqtt.connect('mqtt://mqtt.datacake.co',
{
port: 1883,
username: node.datacake_configuration.api_token,
password: node.datacake_configuration.api_token,
});
globalContext.set(node.globalVariable, client);
} else {
var client = globalContext.get(node.globalVariable);
}
var connectFunc = function () {
var topic = 'dtck/' + node.product_slug + '/' + node.device_id + '/' + node.field_id;
client.subscribe(topic, function (err) {
if(err){
node.log("Datacake - Device Input: Verbindungs Fehler - Konfiguration überprüfen");
node.status({fill:"red",shape:"ring",text:"disconnected"});
} else {
node.log("Datacake - Device Input: Verbindung erfolgreich.");
node.log("Datacake - Device Input: Subscribe to " + topic );
node.log("Datacake - Device Input: " + nodeCount + " nodes running on this connection: " + node.globalVariable);
node.log("Datacake - Device Input: " + globalCount + " nodes connected overall");
node.status({fill:"green",shape:"dot",text:"connected"});
}
})
}
client.on('connect', connectFunc);
var messageFunc = function (topic, message) {
node.send(
{
payload : message.toString(),
deviceId: node.device_id,
fieldName: node.field_id
}
);
}
client.on('message', messageFunc);
node.on('close', function() {
var globalCount = globalContext.get(node.globalCountVariable);
var nodeCount = globalContext.get(node.globalNodeCountVariable);
node.log("Datacake - Device Input: Closing Node");
nodeCount--;
globalCount--;
if(nodeCount < 1){
node.log("Datacake - Device Input: MQTT connection closed, no remaining nodes");
client.removeEventListener(messageFunc);
client.removeEventListener(connectFunc);
client.end();
} else {
node.log("Datacake - Device Input: Node closed, " + nodeCount + " remaining nodes");
}
globalContext.set(node.globalNodeCountVariable, nodeCount);
globalContext.set(node.globalCountVariable, globalCount);
});
}
}
RED.nodes.registerType("datacake-device-input", DatacakeDeviceInputNode);
}