node-red-contrib-plcs
Version:
Mentor Monitor Project Plcs Modbus Controllers
217 lines (177 loc) • 8.73 kB
JavaScript
var async = require('async');
module.exports = function (RED) {
var log = RED.log;
const DeviceNode = function (config) {
RED.nodes.createNode(this, config);
var node = this;
this.unitid = parseInt(config.unitid, 10) || 1;
this.columns = config.columns;
this.name = config.name;
this.byteorder = config.byteorder;
this.devicetype = config.devicetype;
this.send_group = config.send_group;
this.group_name = config.group_name;
this.individual = config.individual;
this.defer = parseInt(config.defer, 10) || 0;
this.fc = config.fc;
this.initialdefer = parseInt(config.initialdefer, 10) || 0;
this.retries = parseInt(config.retries, 10) || 1;
this.baseaddress = config.baseaddress;
this.offsetbased = config.offsetbased;
this.valueformat = parseInt(config.valueformat, 10) || -1;
this.on('input', (msg) => { handleMsg(RED, node, msg, config) });
this.mentorConfiguration = RED.nodes.getNode(config.mentorConfiguration);
if (!this.mentorConfiguration) this.mentor_id = 0;
else this.mentor_id = this.mentorConfiguration.mentor_id;
}
function getTypeSize(vartype)
{
var size = 0;
switch(vartype)
{
case 'long32': //DWORD
case 'long': //DWORD
case 'float':
size = 4;
break;
case 'decimal': //WORD
case 'integer': //WORD
size = 2;
break;
default:
size = 2;
break;
}
// log.error("type:" + vartype);
return size;
}
async function handleMsg(RED, node, msg, config) {
var context = node.context().flow;
if (Object.keys(node.columns).length === 0)
{
node.status({fill:"red",shape:"ring",text:"No Variables"});
return;
}
if (node.name == '' || node.name == undefined)
{
node.status({fill:"red",shape:"ring",text:"No Name Device"});
return;
}
var count = {"n": (node.individual ? node.columns.length : 1), "time": msg.payload, "data": new Array(node.individual ? node.columns.length: 1), timeout:1};
context.set(node.name,count);
var time = msg.payload;
node.status({fill:"green",shape:"ring",text:"Sending"});
var address = 0;
var quantity = 2;
var header = {
'mentor_id': node.mentor_id,
'device': node.name,
'group_name': node.group_name,
'time': time,
'devicetype': node.devicetype,
'columns': count.n,
'group': node.send_group,
'format': node.valueformat
};
var detail = [];
for (var i=0; i<node.columns.length; i++) {
var column = node.columns[i];
if (column.name == '' || column.name == undefined )
node.status({fill:"yellow",shape:"ring",text:"No Name Variable"});
else
{
address = (node.offsetbased ? node.baseaddress*1 : 0) + column.address*1;
var field = {
'name': column.name,
'opt': column.opt,
'offset': node.individual ? 0 : (column.address*1 - node.columns[0].address),
'type': column.type,
'size': column.size,
'byteorder': node.byteorder
};
if (node.individual) {
var newMsg = {};
newMsg.topic = {header:header, detail:[]};
newMsg.topic.detail.push(field);
newMsg.payload = {
'fc': parseInt(node.fc,10),
'unitid': node.unitid,
'address': address,
'quantity': quantity
//'topic': newMsg.topic
};
if (node.defer) {
var timerId = setTimeout( function () {
node.send(newMsg);
clearInterval(timerId);
}, node.defer);
} else {
node.send(newMsg);
}
} else {
detail.push(field);
}
}
}
if (!node.individual)
{
address = (node.offsetbased ? node.baseaddress*1+node.columns[0].address*1 : node.columns[0].address*1);
quantity = (node.columns[node.columns.length-1].address*1 - node.columns[0].address*1) * 2 + getTypeSize(node.columns[node.columns.length-1].size);
var newMsg = {};
newMsg.topic = {
'header': header,
'detail': detail,
};
newMsg.payload = {
'fc': parseInt(node.fc,10),
'unitid': node.unitid*1,
'address': address,
'quantity': quantity
//'topic': newMsg.topic
};
sendMsg(node, newMsg);
}
// node.status({fill:"green",shape:"ring",text:"OK"});
}
function sendMsg(node, msg) {
var context = node.context().flow;
async.during(
function (callback) {
return callback(null, context.get(msg.topic.header.device).timeout <= node.retries + 1 && context.get(msg.topic.header.device).timeout > 0);
},
function (callback) {
if (context.get(msg.topic.header.device).timeout > 0)
{
var value = context.get(msg.topic.header.device);
msg.topic.header.try = value.timeout;
if (value.timeout === 1)
{
node.status({fill:"green",shape:"ring",text:"Initial Defer " + node.initialdefer + " msecs. "});
setTimeout(callback, node.initialdefer);
}
else
{
node.status({fill:"yellow",shape:"ring",text:"Defer " + node.defer + " msecs. Try " + (value.timeout - 1) + " of " + node.retries});
node.send([msg, null]);
value.n = value.data.length;
setTimeout(callback, node.defer);
}
value.timeout++;
context.set(msg.topic.header.device, value);
}
},
function (err) {
if (context.get(msg.topic.header.device).timeout > 0)
{
var value = context.get(msg.topic.header.device);
value.timeout = 0;
context.set(msg.topic.header.device, value);
var msgResult = {payload: JSON.stringify({"code":msg.topic.header.device, "time": msg.topic.header.time, "head": ["initialdefer","defer", "retries"], "data":[node.initialdefer, node.defer, node.retries], "text":"Timeout!"})};
node.send([null, msgResult]);
node.status({fill:"red",shape:"ring",text:"Timeout!! " + "Retries " + node.retries + " (" + node.defer + " msecs.)"});
} else node.status({});
}
);
}
RED.nodes.registerType('Generic In', DeviceNode);
}