141 lines
4.5 KiB
JavaScript
141 lines
4.5 KiB
JavaScript
const { Reactor_CSTR, Reactor_PFR } = require('./specificClass.js');
|
|
|
|
|
|
class nodeClass {
|
|
/**
|
|
* Node-RED node class for advanced-reactor.
|
|
* @param {object} uiConfig - Node-RED node configuration
|
|
* @param {object} RED - Node-RED runtime API
|
|
* @param {object} nodeInstance - Node-RED node instance
|
|
* @param {string} nameOfNode - Name of the node
|
|
*/
|
|
constructor(uiConfig, RED, nodeInstance, nameOfNode) {
|
|
// Preserve RED reference for HTTP endpoints if needed
|
|
this.node = nodeInstance;
|
|
this.RED = RED;
|
|
this.name = nameOfNode;
|
|
|
|
this._loadConfig(uiConfig)
|
|
this._registerChild();
|
|
this._setupClass();
|
|
|
|
this._attachInputHandler();
|
|
}
|
|
|
|
/**
|
|
* Handle node-red input messages
|
|
*/
|
|
_attachInputHandler() {
|
|
this.node.on('input', (msg, send, done) => {
|
|
let toggleUpdate = false;
|
|
|
|
switch (msg.topic) {
|
|
case "clock":
|
|
toggleUpdate = true;
|
|
this.reactor.updateState(msg.timestamp);
|
|
send([this.reactor.getEffluent, null, null]);
|
|
send([msg, null, null])
|
|
break;
|
|
case "Fluent":
|
|
this.reactor.setInfluent = msg;
|
|
break;
|
|
case "OTR":
|
|
this.reactor.setOTR = msg;
|
|
break;
|
|
case "Temperature":
|
|
this.reactor.setTemperature = msg;
|
|
break;
|
|
case "Dispersion":
|
|
this.reactor.setDispersion = msg;
|
|
break;
|
|
case 'registerChild':
|
|
// Register this node as a child of the parent node
|
|
const childId = msg.payload;
|
|
const childObj = this.RED.nodes.getNode(childId);
|
|
this.reactor.childRegistrationUtils.registerChild(childObj.source, msg.positionVsParent);
|
|
break;
|
|
default:
|
|
console.log("Unknown topic: " + msg.topic);
|
|
}
|
|
|
|
if (done) {
|
|
done();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Parse node configuration
|
|
* @param {object} uiConfig Config set in UI in node-red
|
|
*/
|
|
_loadConfig(uiConfig) {
|
|
this.config = {
|
|
general: {
|
|
name: uiConfig.name || this.name,
|
|
id: this.node.id,
|
|
unit: null
|
|
},
|
|
functionality: {
|
|
softwareType: null // should be set in config manager
|
|
},
|
|
reactor_type: uiConfig.reactor_type,
|
|
volume: parseFloat(uiConfig.volume),
|
|
length: parseFloat(uiConfig.length),
|
|
resolution_L: parseInt(uiConfig.resolution_L),
|
|
alpha: parseFloat(uiConfig.alpha),
|
|
n_inlets: parseInt(uiConfig.n_inlets),
|
|
kla: parseFloat(uiConfig.kla),
|
|
initialState: [
|
|
parseFloat(uiConfig.S_O_init),
|
|
parseFloat(uiConfig.S_I_init),
|
|
parseFloat(uiConfig.S_S_init),
|
|
parseFloat(uiConfig.S_NH_init),
|
|
parseFloat(uiConfig.S_N2_init),
|
|
parseFloat(uiConfig.S_NO_init),
|
|
parseFloat(uiConfig.S_HCO_init),
|
|
parseFloat(uiConfig.X_I_init),
|
|
parseFloat(uiConfig.X_S_init),
|
|
parseFloat(uiConfig.X_H_init),
|
|
parseFloat(uiConfig.X_STO_init),
|
|
parseFloat(uiConfig.X_A_init),
|
|
parseFloat(uiConfig.X_TS_init)
|
|
]
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register this node as a child upstream and downstream.
|
|
* Delayed to avoid Node-RED startup race conditions.
|
|
*/
|
|
_registerChild() {
|
|
setTimeout(() => {
|
|
this.node.send([
|
|
null,
|
|
null,
|
|
{ topic: 'registerChild', payload: this.node.id, positionVsParent: this.config?.functionality?.positionVsParent || 'atEquipment' },
|
|
]);
|
|
}, 100);
|
|
}
|
|
|
|
/**
|
|
* Setup reactor class based on config
|
|
*/
|
|
_setupClass() {
|
|
let new_reactor;
|
|
|
|
switch (this.config.reactor_type) {
|
|
case "CSTR":
|
|
new_reactor = new Reactor_CSTR(this.config);
|
|
break;
|
|
case "PFR":
|
|
new_reactor = new Reactor_PFR(this.config);
|
|
break;
|
|
default:
|
|
console.warn("Unknown reactor type: " + uiConfig.reactor_type);
|
|
}
|
|
|
|
this.reactor = new_reactor; // protect from reassignment
|
|
}
|
|
}
|
|
|
|
module.exports = nodeClass; |