node-red-contrib-services-mentor
Version:
Mentor Services
228 lines (199 loc) • 6.93 kB
JavaScript
module.exports = function(RED) {
var request = require('request');
var utils = require('./utils.js');
var log = RED.log;
function Node(config) {
RED.nodes.createNode(this, config);
var node = this;
this.mydb = config.mysql;
this.mydbConfig = RED.nodes.getNode(this.mydb);
node.status({});
this.url = config.url;
this.reqTimeout = 120000;
this.mentor = RED.nodes.getNode(config.mentor);
this.broker = config.mqtt;
this.brokerConn = RED.nodes.getNode(this.broker);
this.priority = parseInt(config.priority, 10) || 0;
this.mentor_id = 0;
if (this.mentor) this.mentor_id = this.mentor.mentor_id;
var channel = "mentor_answer_" + this.mentor_id;
if (node.url != "")
{
this.opts = {
method: 'POST',
url: node.url,
timeout: node.reqTimeout,
//followRedirect: nodeFollowRedirects,
//forever: nodePersistentHTTP,
headers: {},
encoding: null,
strictSSL: false
};
//if (this.credentials && (this.credentials.user==null)) {
node.opts.auth = {
user: "",
pass: "", //this.credentials.password,
sendImmediately: false
};
//}
}
if (this.brokerConn) {
this.status({fill:"red",shape:"ring",text:"node-red:common.status.disconnected"});
node.brokerConn.register(this);
node.brokerConn.subscribe(channel,2,function(topic,msg,packet) {
var msg = JSON.parse(msg.toString());
switch (msg.topic)
{
case "mentor_pong":
//log.error(msg);
sendRecords(node, msg);
break;
case "mentor_rec":
saveMysql(node, msg);
break;
default:
log.error(msg.topic);
break;
}
}, this.id);
if (this.brokerConn.connected) {
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
}
this.on('close', function(done) {
node.brokerConn.deregister(node,done);
});
}
if (this.mydbConfig) {
this.mydbConfig.connect();
node.busy = false;
node.mydbConfig.on("state", function(info) {
if (info === "connecting") { node.status({fill:"grey",shape:"ring",text:info}); }
else if (info === "connected") { node.status({fill:"green",shape:"dot",text:info}); }
else {
if (info === "ECONNREFUSED") { info = "connection refused"; }
if (info === "PROTOCOL_CONNECTION_LOST") { info = "connection lost"; }
node.status({fill:"red",shape:"ring",text:info});
}
});
node.on("input", function(msg) {
this.msg_status = {};
sendPing(node,msg);
});
node.on('close', function () {
if (node.tout) { clearTimeout(node.tout); }
node.mydbConfig.removeAllListeners();
node.status({});
});
}
else {
this.error("MySQL database not configured");
}
}
function sendPing(node,msg)
{
if (node.brokerConn) {
msg = {};
//msg.mentor_id = node.mentor_id;
msg.qos = 2;
msg.retain = false;
msg.payload = JSON.stringify({topic:"mentor_ping", mentor_id: node.mentor_id});
msg.topic = "mentor_data";
node.brokerConn.publish(msg);
}
}
function sendRecords(node,msg)
{
if (node.mydbConfig.connected) {
node.status({});
var where = (node.priority === 0 || node.priority === 2) ? " status=0 ": " restful=0 ";
var sql = "SELECT t1.device, t1.time, t1.content FROM mqtt_lecturas t1 JOIN ( SELECT MIN(TIME) AS min_value, device FROM mqtt_lecturas WHERE "+where+" GROUP BY device ) AS t2 ON t1.device = t2.device AND t1.time = t2.min_value WHERE t1."+where;
node.mydbConfig.connection.query(sql, [], function(err, rows) {
if (err) { log.error(err); return;}
else
for (var item in rows) {
rows[item].mentor_id = node.mentor_id;
rows[item].topic = "mentor_rec";
node.send({"payload" : rows[item].content});
msg.data = rows[item].content;
if (node.priority === 0 || node.priority === 2 )
{
if (node.brokerConn.connected) {
msg.qos = 0;
msg.retain = false;
msg.payload = JSON.stringify(rows[item]);
msg.topic = "mentor_data";
node.brokerConn.publish(msg);
}
}
else
{
msg.payload = utils.encode(rows[item].content);
node.opts.body = msg.payload;
sendRestFul(node, msg);
}
}
})
}
else {
node.error("Database not connected",msg);
node.msg_status = {fill:"red",shape:"ring",text:"not yet connected"};
}
if (!node.busy) {
node.busy = true;
node.status(node.msg_status);
node.tout = setTimeout(function() { node.busy = false; node.status(node.msg_status); },500);
}
}
function sendRestFul(node, msg)
{
request(node.opts, function (error, response, body) {
node.status({});
if (error) {
if (error.code === 'ETIMEDOUT') {
node.error(RED._("common.notification.errors.no-response"), msg);
setTimeout(function () {
node.status({
fill: "red",
shape: "ring",
text: "common.notification.errors.no-response"
});
}, 10);
} else {
node.error(error, msg);
msg.payload = error.toString() + " : " + node.url;
msg.statusCode = error.code;
node.send(msg);
node.status({
fill: "red",
shape: "ring",
text: error.code
});
}
} else {
msg.payload = body;
msg.headers = response.headers;
msg.statusCode = response.statusCode;
var obj = JSON.parse(msg.payload);
msg.payload = obj;
node.send(msg);
if (obj.status == 1)
{
obj.device = obj.code;
saveMysql(node, obj);
node.status({fill:"green",shape:"ring",text:"OK"});
}
}
})
}
function saveMysql(node, msg)
{
var update = (node.priority === 0 || node.priority === 2) ? " restful=1, status=" : " status=1, restful=";
node.mydbConfig.connection.query("UPDATE mqtt_lecturas SET " + update + msg.status + " WHERE time*1="+ msg.time + " And device='"+msg.device + "'", [],
function(err, rows) {
if (err) { log.error(err);}
else
node.send({payload: {msg: rows.affectedRows + " record(s) updated", data:msg}});
});
}
RED.nodes.registerType("Sender", Node);
}