change to new version of code

This commit is contained in:
2025-11-11 13:52:46 +01:00
parent 54e1fd0f43
commit 577c7e3de6
3 changed files with 224 additions and 61 deletions

View File

@@ -59,19 +59,46 @@ class nodeClass {
_updateNodeStatus() {
const vg = this.source;
const mode = vg.mode;
const mode = vg.currentMode;
const scaling = vg.scaling;
const totalFlow =
Math.round(
vg.measurements
.type("flow")
.variant("measured")
.position("downstream")
.variant("predicted")
.position("atEquipment")
.getCurrentValue() * 1
) / 1;
const maxDeltaP =
Math.round(
vg.measurements
.type("maxDeltaP")
.variant("predicted")
.position("delta")
.getCurrentValue() * 1
) / 1;
// Verkrijg alle valves uit de geneste structuur:
const allValves = [];
// Voeg alle valve objects toe aan allValves
for (const [softwareType, typeData] of Object.entries(vg.child)) {
// Filter alleen valves
if (softwareType === 'valve') {
// Loop door categories (valves, etc.)
for (const childrenArray of Object.values(typeData)) {
if (Array.isArray(childrenArray)) {
allValves.push(...childrenArray);
}
}
}
}
// Calculate total capacity based on available valves
const availableValves = Object.values(vg.valves).filter((valve) => {
const availableValves = allValves.filter((valve) => {
if (!valve || !valve.state) {
console.log('Valve missing state:', valve);
return false;
}
const state = valve.state.getCurrentState();
const mode = valve.currentMode;
return !(
@@ -81,8 +108,8 @@ class nodeClass {
);
});
// const totalCapacity = Math.round(vg.dynamicTotals.flow.max * 1) / 1; ADD LATER?
//const totalCapacity = Math.round(vg.dynamicTotals.flow.max * 1) / 1; //ADD LATER?
// Determine overall status based on available valves
const status =
availableValves.length > 0
@@ -91,7 +118,7 @@ class nodeClass {
// Generate status text in a single line
const text = ` ${mode} | 💨=${totalFlow} | ${status}`;
const text = ` ${mode} | 💨=${totalFlow} | maxDeltaP = ${maxDeltaP} | ${status}`;
return {
fill: availableValves.length > 0 ? "green" : "red",
@@ -178,6 +205,7 @@ class nodeClass {
childObj.source,
msg.positionVsParent
);
//console.log('CHECK HERE NOW', childObj);
break;
case 'setMode':

View File

@@ -63,9 +63,7 @@ class ValveGroupControl {
// Initialize measurements
this.measurements = new MeasurementContainer();
this.child = {};
this.valves = {}; // hold child object so we can get information from its child valves
// this.valves = {}; // this.child; // hold child object so we can get information from its child valves
// Initialize variables
this.maxDeltaP = 0; // max deltaP is 0 als er geen child valves zijn
@@ -74,9 +72,66 @@ class ValveGroupControl {
}
registerOnChildEvents() {}
registerChild(child, softwareType) { //checken welke child er zijn
console.log('=== DEBUGGING this.child ===');
console.log('Type of this.child:', typeof this.child);
console.log('this.child:', this.child);
if (Object.keys(this.child).length === 0) {
console.log('✅ this.child is empty');
} else {
console.log('✅ this.child contains:', Object.keys(this.child).length, 'items');
Object.keys(this.child).forEach(key => {
console.log(` - Key: ${key}, Value type: ${typeof this.child[key]}`);
});
}
registerChild(child, positionVsParent) {
this.addEventListenerForChild(child, softwareType); //subscribe to measurement changes from this specific child
}
//MAAK SPECIFIEKE CHILD EVENT LISTENER - KAN EVT IN REGISTERCHILD FUNCTIE WORDEN BIJGEVOEGD
addEventListenerForChild(child, softwareType) {
if (child && child.emitter) {
child.measurements.emitter.on('change', (data) => {
const childName = child.config?.general?.name || `${softwareType}_child`;
console.log('🔔 EVENT RECEIVED!', childName, data);
this.logger.info(`Received change event from child ${childName}:`, data);
this.handleChildChange(child, data);
});
console.log(`✅ Event listener added for ${softwareType} child`);
} else {
console.log(`❌ Child or emitter missing:`, {
child: !!child,
emitter: !!child?.measurements.emitter
});
}
}
handleChildChange(child, data) {
switch(data.type) {
case 'flow':
if (child.source === 'mg') {
this.logger.info("Total flow change from machineGroupControl detected by valveGroupControl");
// als totalflow van mg veranderd, bereken dan de nieuwe valve flows
this.calcValveFlows();
};
break;
case 'pressure':
if (data.position === 'delta') {
this.logger.info("DeltaP change from child valve detected by valveGroupControl");
// als deltaP van een van de childs valves verandert, bereken dan de nieuwe maxDeltaP
this.calcMaxDeltaP();
};
// Insert actions this.calcMaxDeltaP();
this.logger.info("Kijk ik kom bij handle child change aan!")
break;
case 'position':
// Handle position changes
break;
default:
this.logger.debug(`Unhandled change type: ${data.type}`);
}
}
isValidSourceForMode(source, mode) {
@@ -99,7 +154,7 @@ class ValveGroupControl {
await this.executeSequence(parameter);
break;
case "totalFlowChange":
await this.updateFlow(parameter);
await this.updateFlow("predicted", parameter, "atEquipment");
break;
case "emergencyStop":
this.logger.warn(`Emergency stop activated by '${source}'.`);
@@ -175,12 +230,13 @@ updateFlow(variant,value,position) {
default:
this.logger.warn(`Unrecognized variant '${variant}' for flow update.`);
break;
}
}
updateMeasurement(variant, subType, value, position) {
this.logger.debug(`---------------------- updating ${subType} ------------------ `);
this.logger.debug(`---------------------- updating ${subType} ------------------ NOT YET FURTHER DEFINED ------------------`);
switch (subType) {
case "pressure":
// Update pressure measurement
@@ -199,52 +255,129 @@ updateFlow(variant,value,position) {
}
calcValveFlows() {
const totalFlow = this.measurements.type("flow").variant("measured").position("atEquipment").getCurrentValue(); // get the total flow from the measurement container
const totalFlow = this.measurements.type("flow").variant("predicted").position("atEquipment").getCurrentValue(); // get the total flow from the measurement container
let totalKv = 0;
this.logger.debug(`Calculating valve flows... ${totalFlow}`); //Checkpoint
for (const key in this.valves){ //bereken sum kv values om verdeling total flow te maken
this.logger.info('kv: ' + this.valves[key].kv); //CHECKPOINT
if (this.valves[key].state.getCurrentPosition() != null) {
totalKv += this.valves[key].kv;
this.logger.info('Total Kv = ' + totalKv); //CHECKPOINT
}
if(totalKv === 0) {
this.logger.warn('Total Kv is 0, cannot calculate flow distribution.');
return; // Avoid division by zero
// for (const key in this.child){ //bereken sum kv values om verdeling total flow te maken
// if (this.child[key].state.getCurrentPosition() != null) {
// totalKv += this.child[key].kv;
// this.logger.info('Total Kv = ' + totalKv); //CHECKPOINT
// }
// if(totalKv === 0) {
// this.logger.warn('Total Kv is 0, cannot calculate flow distribution.');
// return; // Avoid division by zero
// }
// }
// Loop door de geneste this.child structuur om total kv te berekenen
for (const [softwareType, typeData] of Object.entries(this.child)) {
// Filter alleen op valves
if (softwareType === 'valve') {
// Loop door categories (valves, etc.)
for (const [category, childrenArray] of Object.entries(typeData)) {
if (Array.isArray(childrenArray)) {
// Loop door alle valve objecten in deze array
childrenArray.forEach((valve, index) => {
if (valve && valve.state && valve.state.getCurrentPosition() != null) {
totalKv += valve.kv;
this.logger.info(`Adding valve ${index} Kv: ${valve.kv}, Total Kv now: ${totalKv}`);
}
});
}
}
}
}
for (const key in this.valves){
const valve = this.valves[key];
this.logger.debug(`Calculating ratio for valve total: ${totalKv} valve.kv: ${valve.kv} ratio : ${valve.kv / totalKv}`); //Checkpoint
const ratio = valve.kv / totalKv;
const flow = ratio * totalFlow; // bereken flow per valve
if (totalKv === 0) {
this.logger.warn('Total Kv is 0, cannot calculate flow distribution.');
return; // Avoid division by zero
}
//update flow per valve in de object zelf wat daar vervolgens weer de nieuwe deltaP berekent
valve.updateFlow("predicted", flow, "downstream");
this.logger.info(`--> Sending updated flow to valves --> ${flow} `); //Checkpoint
// for (const key in this.child){
// const valve = this.child[key];
// this.logger.debug(`Calculating ratio for valve total: ${totalKv} valve.kv: ${valve.kv} ratio : ${valve.kv / totalKv}`); //Checkpoint
// const ratio = valve.kv / totalKv;
// const flow = ratio * totalFlow; // bereken flow per valve
// //update flow per valve in de object zelf wat daar vervolgens weer de nieuwe deltaP berekent
// valve.updateFlow("predicted", flow, "downstream");
// this.logger.info(`--> Sending updated flow to valves --> ${flow} `); //Checkpoint
// }
// Flow verdelen over alle valves
for (const [softwareType, typeData] of Object.entries(this.child)) {
if (softwareType === 'valve') {
for (const [category, childrenArray] of Object.entries(typeData)) {
if (Array.isArray(childrenArray)) {
childrenArray.forEach((valve, index) => {
if (valve && valve.state && valve.state.getCurrentPosition() != null) {
const ratio = valve.kv / totalKv;
const flow = ratio * totalFlow;
valve.updateFlow("predicted", flow, "downstream");
this.logger.info(`--> Sending updated flow to valve --> Flow: ${flow}`);
}
});
}
}
}
}
}
calcMaxDeltaP() { // bereken de max deltaP van alle child valves
let maxDeltaP = 0; //max deltaP is 0 als er geen child valves zijn
this.logger.info('Calculating new max deltaP...');
for (const key in this.valves) {
const valve = this.valves[key]; //haal de child valve object op
const deltaP = valve.measurements.type("pressure").variant("predicted").position("delta").getCurrentValue(); //get delta P
this.logger.info(`Delta P for valve ${key}: ${deltaP}`);
if (deltaP > maxDeltaP) { //als de deltaP van de child valve groter is dan de huidige maxDeltaP, dan update deze
maxDeltaP = deltaP;
}
let maxDeltaP = 0;
for (const [softwareType, typeData] of Object.entries(this.child)) {
// Filter alleen op valves
if (softwareType === 'valve') {
// Loop door categories (valves, etc.)
for (const [category, childrenArray] of Object.entries(typeData)) {
if (Array.isArray(childrenArray)) {
// Loop door alle valve objecten in deze array
childrenArray.forEach((valve, index) => {
try{
const deltaP = valve.measurements.type("pressure").variant("predicted").position("delta").getCurrentValue();
if (deltaP > maxDeltaP) {
maxDeltaP = deltaP;
}
} catch (error) {
this.logger.error(`Error retrieving deltaP for valve at index ${index}: ${error}`);
}
});
}
}
}
}
this.logger.info('Max Delta P updated to: ' + maxDeltaP);
this.maxDeltaP = maxDeltaP; //update de max deltaP in de measurement container van de valveGroupControl class
this.measurements.type("maxDeltaP").variant("predicted").position("delta").value(maxDeltaP); //update de max deltaP in de measurement container van de valveGroupControl class
this.maxDeltaP = maxDeltaP; //update de max deltaP
this.logger.info('Max Delta P updated to: ' + maxDeltaP);
}
// let maxDeltaP = 0; //max deltaP is 0 als er geen child valves zijn
// this.logger.info('Calculating new max deltaP...');
// for (const key in this.child) {
// const valve = this.child[key]; //haal de child valve object op
// const deltaP = valve.measurements.type("pressure").variant("predicted").position("delta").getCurrentValue(); //get delta P
// this.logger.info(`Delta P for valve ${key}: ${deltaP}`);
// if (deltaP > maxDeltaP) { //als de deltaP van de child valve groter is dan de huidige maxDeltaP, dan update deze
// maxDeltaP = deltaP;
// }
// }
// this.logger.info('Max Delta P updated to: ' + maxDeltaP);
// this.measurements.type("maxDeltaP").variant("predicted").position("delta").value(maxDeltaP); //update de max deltaP in de measurement container van de valveGroupControl class
// this.maxDeltaP = maxDeltaP; //update de max deltaP
}
getOutput() {
@@ -273,7 +406,6 @@ updateFlow(variant,value,position) {
return output;
}
}
module.exports = ValveGroupControl;
@@ -318,23 +450,23 @@ const stateConfig = {
}
};
const valve1 = new valve(valveConfig, stateConfig);
//const valve1 = new valve(valveConfig, stateConfig);
//const valve2 = new valve(valveConfig, stateConfig);
//const valve3 = new valve(valveConfig, stateConfig);
valve1.kv = 10; // Set Kv value for valve1
//valve1.kv = 10; // Set Kv value for valve1
//valve2.kv = 20; // Set Kv value for valve2
//valve3.kv = 30; // Set Kv value for valve3
valve1.updateMeasurement("measured", "pressure" , 500, "downstream");
//valve1.updateMeasurement("measured", "pressure" , 500, "downstream");
//valve2.updateMeasurement("measured" , "pressure" , 500, "downstream");
//valve3.updateMeasurement("measured" , "pressure" , 500, "downstream");
const vgc = new ValveGroupControl();
//const vgc = new ValveGroupControl();
vgc.childRegistrationUtils.registerChild(valve1, "atEquipment");
//vgc.childRegistrationUtils.registerChild(valve1, "atEquipment");
//vgc.childRegistrationUtils.registerChild(valve2, "atEquipment");
//vgc.childRegistrationUtils.registerChild(valve3, "atEquipment");
vgc.updateFlow("measured", 1000, "atEquipment"); // Update total flow to 100 m3/h
//vgc.updateFlow("measured", 1000, "atEquipment"); // Update total flow to 100 m3/h

View File

@@ -1,12 +1,15 @@
<!--
| S88-niveau | Primair (blokkleur) | Tekstkleur |
| ---------------------- | ------------------- | ---------- |
| **Area** | `#0f52a5` | wit |
| **Process Cell** | `#0c99d9` | wit |
| **Unit** | `#50a8d9` | zwart |
| **Equipment (Module)** | `#86bbdd` | zwart |
| **Control Module** | `#a9daee` | zwart |
brabantse delta kleuren:
#eaf4f1
#86bbdd
#bad33b
#0c99d9
#a9daee
#0f52a5
#50a8d9
#cade63
#4f8582
#c4cce0
-->
<script src="/valveGroupControl/menu.js"></script> <!-- Load the menu script for dynamic dropdowns -->
<script src="/valveGroupControl/configData.js"></script> <!-- Load the config script for node information -->
@@ -14,7 +17,7 @@
<script>
RED.nodes.registerType('valveGroupControl',{
category: "EVOLV",
color: "#50a8d9",
color: "#eaf4f1",
defaults: {
// Define default properties
name: { value: "" },
@@ -35,7 +38,7 @@
outputs:3,
inputLabels: ["Input"],
outputLabels: ["process", "dbase", "parent"],
icon: "font-awesome/fa-tasks",
icon: "font-awesome/fa-tachometer",
label: function () {
return this.positionIcon + " " + "valveGroupControl";