@pickdata/node-red-contrib-emod-simulator
Version:
eManager is an IoT controller designed with eMOD tech for monitoring, control and automation applications. The following nodes are pre-installed in all eMOD devices, although here we present a simulator to practice & test our modular industrial solution.
155 lines (133 loc) • 6.29 kB
JavaScript
/**
Copyright (c) 2020,2021 PickData SL (https://www.pickdata.net/)
All rights reserved.
node-red-contrib-emod-simulator - The BSD 3-Clause License
**/
module.exports = function(RED) {
const di10_simulator = require('@pickdata/emod-js-simulator').DI10;
function EMOD10DI_S(config) {
RED.nodes.createNode(this,config);
var node = this;
node.configNode = RED.nodes.getNode(config.modConfig);
node.modNumEnabled = config.modNumEnabled;
node.modNum = parseInt(config.modNum);
if (!node.modNumEnabled) {
node.modNum = 1;
}
node.config_error = false;
if (node.configNode == null) {
node.status({fill:"red",shape:"ring",text:"Config error"});
node.error("Node has no configuration");
node.config_error = true;
return;
}
var compareModConfig = node.configNode.event_mode == "poll" ? (
function (node, other_node) {
// Ambos nodos deberían tener la misma configuración, ya que corresponden al mismo módulo físico.
if (!other_node.config_error && other_node.configNode.id != node.configNode.id) {
throw new Error("Configuration mismatch between nodes "+node.id+" and "+other_node.id);
}
}
) : (
function (node, other_node) {
// En modo "event" sólo puede haber un único nodo por módulo físico.
throw new Error("Only a single node can be configured in event mode");
}
);
try {
RED.nodes.eachNode(function(n) {
//Si node-red aún no ha instanciado el nodo n o está presente en un flow deshabilitado, esta función devuelve null y puede ser ignorado.
var other_node = RED.nodes.getNode(n.id);
if (other_node != null && other_node.id != node.id) {
if (other_node.type == node.type && other_node.modNum == node.modNum) {
// Esta función se llama con "other_node" para todos los nodos instanciados que sean del mismo tipo y número (mismo módulo físico) que "node"
compareModConfig(node, other_node);
}
}
});
} catch (e) {
node.error(e.message);
node.status({fill:"red",shape:"ring",text:"Config error"});
node.config_error = true;
return;
}
node.simulator = di10_simulator.getInstance(node.modNum);
node.simulator.setPulseFilterTime(node.configNode.pulse_filter_ms);
switch (node.configNode.event_mode) {
case "poll":
node.simulator.setStatusChangeCallback(null);
node.simulator.setPulseCounterCallback(null);
break;
case "status":
node.simulator.setStatusChangeCallback(function(new_status) {
node.send({payload: {all_status: new_status}});
});
node.simulator.setPulseCounterCallback(null);
break;
case "pulse-count":
node.simulator.setStatusChangeCallback(null);
node.simulator.setThreshold(node.configNode.pulse_count_threshold);
node.simulator.setPulseCounterCallback(function(index, counter_value) {
node.send({payload: {counter: {index: index, value: counter_value}}});
});
break;
}
node.on('input', function(msg) {
if ("reset_pulse_count" in msg.payload) {
if (Number.isInteger(msg.payload.reset_pulse_count)) {
if (msg.payload.reset_pulse_count < 0 || msg.payload.reset_pulse_count > 9 ) {
node.warn("Input index out of range");
return;
}
node.simulator.resetPulseCounter(msg.payload.reset_pulse_count);
} else {
node.simulator.resetAllPulseCounter();
}
}
else if ("get_all" in msg.payload) {
if (node.configNode.event_mode != "poll") {
node.warn("Polling request made in non-polling mode");
return;
}
switch (msg.payload.get_all) {
case "status":
var status = node.simulator.getAllStatus();
node.send({payload: {all_status: status}});
break;
case "pulse_count":
var counts = node.simulator.getAllCounters();
node.send({payload: {all_counters: counts}});
break;
}
}
else if ("get_one" in msg.payload && typeof msg.payload.get_one === 'object' && msg.payload.get_one !== null) {
if (node.configNode.event_mode != "poll") {
node.warn("Polling request made in non-polling mode");
return;
}
var input_index = msg.payload.get_one.index;
var input_mode = msg.payload.get_one.mode;
if (!Number.isInteger(input_index) || input_index < 0 || input_index > 9) {
node.warn("Input index out of range");
return;
}
switch (input_mode) {
case "status":
var status = node.simulator.getOneStatus(input_index);
node.send({payload: {status: {index: input_index, value: status}}});
break;
case "pulse_count":
var count = node.simulator.getOneCounter(input_index);
node.send({payload: {counter: {index: input_index, value: count}}});
break;
}
}
else {
node.error("unknown method call.");
}
});
node.simulator.startSimulation();
node.status({});
}
RED.nodes.registerType("10DI-S",EMOD10DI_S);
}