node-red-contrib-services-mentor
Version:
Mentor Services
225 lines (195 loc) • 8.92 kB
JavaScript
module.exports = function (RED) {
const request = require("superagent");
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.url_alarm = config.url_alarm;
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 !== "" || node.url_alarm !== "") {
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) {
switch (topic) {
case channel:
var msg = JSON.parse(msg.toString());
saveMysql(node, msg);
break;
default:
log.error(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();
var busy = false;
var status = {};
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) {
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, t1.alarm 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;
node.send({ "payload": rows[item].content });
msg.alarm = rows[item].alarm;
msg.data = rows[item].content;
if (node.priority === 0 || node.priority === 2) {
if (node.brokerConn.connected != null && node.brokerConn.connected) {
msg.qos = 0;
msg.retain = false;
msg.payload = JSON.stringify(rows[item]);
msg.topic = "mentor_data";
node.brokerConn.publish(msg);
// log.error("mqtt");
}
} else {
if (msg.alarm === 1)
node.opts.url = node.url_alarm;
else
node.opts.url = node.url;
msg.payload = utils.encode(rows[item].content);
node.opts.body = msg.payload;
sendRestFul(node, msg);
// log.error(node.opts.url);
}
}
});
} else {
node.error("Database not connected", msg);
status = { fill: "red", shape: "ring", text: "not yet connected" };
}
if (!busy) {
busy = true;
node.status(status);
node.tout = setTimeout(function () {
busy = false;
node.status(status);
}, 500);
}
});
node.on('close', function () {
if (node.tout) {
clearTimeout(node.tout);
}
node.mydbConfig.removeAllListeners();
node.status({});
});
} else {
this.error("MySQL database not configured");
}
}
function sendRestFul(node, msg) {
request
.post(node.opts.url)
.set('Content-Type', 'application/json')
.send(msg)
.end(function (err, response) {
if (err) {
console.log("unable to complete request, something went wrong: " + err);
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.opts.url;
msg.statusCode = error.code;
node.send(msg);
node.status({
fill: "red",
shape: "ring",
text: error.code
});
}
} else {
msg.payload = JSON.stringify(response.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);
};