first commit
This commit is contained in:
250
valve.js
Normal file
250
valve.js
Normal file
@@ -0,0 +1,250 @@
|
||||
module.exports = function (RED) {
|
||||
function valve(config) {
|
||||
//create node
|
||||
RED.nodes.createNode(this, config);
|
||||
//call this => node so whenver you want to call a node function type node and the function behind it
|
||||
var node = this;
|
||||
|
||||
try {
|
||||
const Valve = require("./dependencies/valveClass"); // Importeer de valve class
|
||||
const OutputUtils = require("../generalFunctions/helper/outputUtils"); // Importeer de OutputUtils class
|
||||
|
||||
const valveConfig = { // Configuratie van de valve
|
||||
general: {
|
||||
name: config.name || "Default Valve",
|
||||
id: node.id,
|
||||
logging: {
|
||||
enabled: config.eneableLog,
|
||||
logLevel: config.logLevel
|
||||
}
|
||||
},
|
||||
asset: {
|
||||
supplier: config.supplier || "Unknown",
|
||||
/* NOT USED
|
||||
type: config.valveType || "generic",
|
||||
subType: config.subType || "generic",
|
||||
model: config.model || "generic",
|
||||
valveCurve: config.valveCurve */
|
||||
}
|
||||
};
|
||||
|
||||
const stateConfig = { // Configuratie van de state
|
||||
general: {
|
||||
logging: {
|
||||
enabled: config.eneableLog,
|
||||
logLevel: config.logLevel
|
||||
}
|
||||
},
|
||||
|
||||
/* NOT USED
|
||||
movement: {
|
||||
speed: Number(config.speed)
|
||||
},
|
||||
time: {
|
||||
starting: Number(config.startup),
|
||||
warmingup: Number(config.warmup),
|
||||
stopping: Number(config.shutdown),
|
||||
coolingdown: Number(config.cooldown)
|
||||
} */
|
||||
};
|
||||
|
||||
// Create valve instance
|
||||
const v = new Valve(valveConfig, stateConfig);
|
||||
|
||||
// put m on node memory as source
|
||||
node.source = v;
|
||||
|
||||
//load output utils
|
||||
const output = new OutputUtils();
|
||||
|
||||
//Hier worden node-red statussen en metingen geupdate
|
||||
function updateNodeStatus() {
|
||||
try {
|
||||
const mode = v.currentMode; // modus is bijv. auto, manual, etc.
|
||||
const state = v.state.getCurrentState(); //is bijv. operational, idle, off, etc.
|
||||
const flow = Math.round(v.measurements.type("flow").variant("predicted").position("downstream").getCurrentValue());
|
||||
let deltaP = v.measurements.type("pressure").variant("predicted").position("delta").getCurrentValue();
|
||||
if (deltaP !== null) {
|
||||
deltaP = parseFloat(deltaP.toFixed(0));
|
||||
} //afronden op 4 decimalen indien geen "null"
|
||||
if(isNaN(deltaP)) {
|
||||
deltaP = "∞";
|
||||
}
|
||||
const roundedPosition = Math.round(v.state.getCurrentPosition() * 100) / 100;
|
||||
let symbolState;
|
||||
switch(state){
|
||||
case "off":
|
||||
symbolState = "⬛";
|
||||
break;
|
||||
case "idle":
|
||||
symbolState = "⏸️";
|
||||
break;
|
||||
case "operational":
|
||||
symbolState = "⏵️";
|
||||
break;
|
||||
case "starting":
|
||||
symbolState = "⏯️";
|
||||
break;
|
||||
case "warmingup":
|
||||
symbolState = "🔄";
|
||||
break;
|
||||
case "accelerating":
|
||||
symbolState = "⏩";
|
||||
break;
|
||||
case "stopping":
|
||||
symbolState = "⏹️";
|
||||
break;
|
||||
case "coolingdown":
|
||||
symbolState = "❄️";
|
||||
break;
|
||||
case "decelerating":
|
||||
symbolState = "⏪";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
let status;
|
||||
switch (state) {
|
||||
case "off":
|
||||
status = { fill: "red", shape: "dot", text: `${mode}: OFF` };
|
||||
break;
|
||||
case "idle":
|
||||
status = { fill: "blue", shape: "dot", text: `${mode}: ${symbolState}` };
|
||||
break;
|
||||
case "operational":
|
||||
status = { fill: "green", shape: "dot", text: `${mode}: ${symbolState} | ${roundedPosition}% | 💨${flow}m³/h | ΔP${deltaP} mbar`}; //deltaP toegevoegd
|
||||
break;
|
||||
case "starting":
|
||||
status = { fill: "yellow", shape: "dot", text: `${mode}: ${symbolState}` };
|
||||
break;
|
||||
case "warmingup":
|
||||
status = { fill: "green", shape: "dot", text: `${mode}: ${symbolState} | ${roundedPosition}% | 💨${flow}m³/h | ΔP${deltaP} mbar`}; //deltaP toegevoegd
|
||||
break;
|
||||
case "accelerating":
|
||||
status = { fill: "yellow", shape: "dot", text: `${mode}: ${symbolState} | ${roundedPosition}% | 💨${flow}m³/h | ΔP${deltaP} mbar` }; //deltaP toegevoegd
|
||||
break;
|
||||
case "stopping":
|
||||
status = { fill: "yellow", shape: "dot", text: `${mode}: ${symbolState}` };
|
||||
break;
|
||||
case "coolingdown":
|
||||
status = { fill: "yellow", shape: "dot", text: `${mode}: ${symbolState}` };
|
||||
break;
|
||||
case "decelerating":
|
||||
status = { fill: "yellow", shape: "dot", text: `${mode}: ${symbolState} - ${roundedPosition}% | 💨${flow}m³/h | ΔP${deltaP} mbar`}; //deltaP toegevoegd
|
||||
break;
|
||||
default:
|
||||
status = { fill: "grey", shape: "dot", text: `${mode}: ${symbolState}` };
|
||||
}
|
||||
return status;
|
||||
} catch (error) {
|
||||
node.error("Error in updateNodeStatus: " + error.message);
|
||||
return { fill: "red", shape: "ring", text: "Status Error" };
|
||||
}
|
||||
}
|
||||
|
||||
function tick() { // versturen van output messages --> tick van tick op de klop. Is tijd based en niet event based
|
||||
try {
|
||||
const status = updateNodeStatus();
|
||||
node.status(status);
|
||||
|
||||
//v.tick();
|
||||
|
||||
//get output
|
||||
const classOutput = v.getOutput();
|
||||
const dbOutput = output.formatMsg(classOutput, v.config, "influxdb");
|
||||
const pOutput = output.formatMsg(classOutput, v.config, "process");
|
||||
|
||||
//only send output on values that changed
|
||||
let msgs = [];
|
||||
msgs[0] = pOutput;
|
||||
msgs[1] = dbOutput;
|
||||
|
||||
node.send(msgs);
|
||||
|
||||
} catch (error) {
|
||||
node.error("Error in tick function: " + error);
|
||||
node.status({ fill: "red", shape: "ring", text: "Tick Error" });
|
||||
}
|
||||
}
|
||||
|
||||
// register child on first output this timeout is needed because of node - red stuff
|
||||
setTimeout(
|
||||
() => {
|
||||
|
||||
/*---execute code on first start----*/
|
||||
let msgs = [];
|
||||
|
||||
msgs[2] = { topic : "registerChild" , payload: node.id, positionVsParent: "upStream" };
|
||||
msgs[3] = { topic : "registerChild" , payload: node.id, positionVsParent: "downStream" };
|
||||
|
||||
//send msg
|
||||
node.send(msgs);
|
||||
},
|
||||
100
|
||||
);
|
||||
|
||||
//declare refresh interval internal node
|
||||
|
||||
setTimeout(
|
||||
() => {
|
||||
//---execute code on first start----
|
||||
this.interval_id = setInterval(function(){ tick() },1000)
|
||||
},
|
||||
1000
|
||||
);
|
||||
|
||||
node.on("input", function(msg, send, done) { // Functie die wordt aangeroepen wanneer er een input wordt ontvangen
|
||||
console.log("CKECK! Input received: ", msg.topic, msg.payload); // CHECKPOINT
|
||||
try {
|
||||
let result;
|
||||
switch(msg.topic) {
|
||||
case 'registerChild':
|
||||
const childId = msg.payload;
|
||||
const childObj = RED.nodes.getNode(childId);
|
||||
v.childRegistrationUtils.registerChild(childObj.source ,msg.positionVsParent);
|
||||
break;
|
||||
case 'setMode':
|
||||
v.setMode(msg.payload);
|
||||
break;
|
||||
case 'execSequence':
|
||||
const { source: seqSource, action: seqAction, parameter } = msg.payload;
|
||||
v.handleInput(seqSource, seqAction, parameter);
|
||||
break;
|
||||
case 'execMovement':
|
||||
const { source: mvSource, action: mvAction, setpoint } = msg.payload;
|
||||
v.handleInput(mvSource, mvAction, Number(setpoint));
|
||||
break;
|
||||
case 'emergencystop':
|
||||
const { source: esSource, action: esAction } = msg.payload;
|
||||
v.handleInput(esSource, esAction);
|
||||
break;
|
||||
case 'showcurve':
|
||||
v.showCurve();
|
||||
send({ topic : "Showing curve" , payload: v.showCurve() });
|
||||
break;
|
||||
case 'newFlow': //Als nieuwe flow van header node dan moet deltaP weer opnieuw worden berekend en doorgegeven aan header node
|
||||
const { source: nfSource, action: nfAction, parameter: nfParameter } = msg.payload; //parameter is new flow, action should be "calcNewDeltaP"
|
||||
v.handleInput(nfSource, nfAction, nfParameter);
|
||||
}
|
||||
|
||||
if (done) done();
|
||||
} catch (error) {
|
||||
node.error("Error processing input: " + error.message);
|
||||
if (done) done(error);
|
||||
}
|
||||
});
|
||||
|
||||
node.on('close', function(done) { // Functie die wordt aangeroepen wanneer de node wordt gesloten
|
||||
if (node.interval_id) clearTimeout(node.interval_id);
|
||||
if (node.tick_interval) clearInterval(node.tick_interval);
|
||||
if (done) done();
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
node.error("Fatal error in node initialization: " + error.stack);
|
||||
node.status({fill: "red", shape: "ring", text: "Fatal Error"});
|
||||
}
|
||||
|
||||
}
|
||||
RED.nodes.registerType("valve", valve);
|
||||
};
|
||||
Reference in New Issue
Block a user