From 4ae6beba3767ae39b8e0fda306c151edec36b768 Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Fri, 31 Oct 2025 18:35:40 +0100 Subject: [PATCH 01/13] updated measurement node to match selected units from user and convert it properly --- src/nodeClass.js | 4 ++-- src/specificClass.js | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/nodeClass.js b/src/nodeClass.js index 6d20326..7fc2acd 100644 --- a/src/nodeClass.js +++ b/src/nodeClass.js @@ -114,8 +114,8 @@ class nodeClass { try { const mode = m.currentMode; const state = m.state.getCurrentState(); - const flow = Math.round(m.measurements.type("flow").variant("predicted").position('downstream').getCurrentValue()); - const power = Math.round(m.measurements.type("power").variant("predicted").position('upstream').getCurrentValue()); + const flow = Math.round(m.measurements.type("flow").variant("predicted").position('downstream').getCurrentValue('m3/h')); + const power = Math.round(m.measurements.type("power").variant("predicted").position('atequipment').getCurrentValue('kW')); let symbolState; switch(state){ case "off": diff --git a/src/specificClass.js b/src/specificClass.js index c5e1a74..999443c 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -48,7 +48,17 @@ class Machine { this.errorMetrics = new nrmse(errorMetricsConfig, this.logger); // Initialize measurements - this.measurements = new MeasurementContainer(); + this.measurements = new MeasurementContainer({ + autoConvert: true, + windowSize: 50, + defaultUnits: { + pressure: 'mbar', + flow: this.config.general.unit, + power: 'kW', + temperature: 'C' + } + }); + this.interpolation = new interpolation(); this.flowDrift = null; @@ -68,11 +78,25 @@ class Machine { this.updatePosition(); }); + //When state changes look if we need to do other updates + this.state.emitter.on("stateChange", (newState) => { + this.logger.debug(`State change detected: ${newState}`); + this._updateState(); + }); + this.child = {}; // object to hold child information so we know on what to subscribe this.childRegistrationUtils = new childRegistrationUtils(this); // Child registration utility } + _updateState(){ + const isOperational = this._isOperationalState(); + if(!isOperational){ + //overrule the last prediction this should be 0 now + this.measurements.type("flow").variant("predicted").position("downstream").value(0); + } + } + /*------------------- Register child events -------------------*/ registerChild(child, softwareType) { this.logger.debug('Setting up child event for softwaretype ' + softwareType); @@ -501,13 +525,14 @@ _callMeasurementHandler(measurementType, value, position, context) { // Update predicted flow if you have prediction capability if (this.predictFlow) { - this.measurements.type("flow").variant("predicted").position("atEquipment").value(this.predictFlow.outputY || 0); + this.measurements.type("flow").variant("predicted").position("downstream").value(this.predictFlow.outputY || 0); } } // Helper method for operational state check _isOperationalState() { const state = this.state.getCurrentState(); + this.logger.debug(`Checking operational state ${this.state.getCurrentState()} ? ${["operational", "accelerating", "decelerating"].includes(state)}`); return ["operational", "accelerating", "decelerating"].includes(state); } @@ -531,6 +556,9 @@ _callMeasurementHandler(measurementType, value, position, context) { this.calcDistanceBEP(efficiency,cog,minEfficiency); } + + + } calcDistanceFromPeak(currentEfficiency,peakEfficiency){ @@ -561,7 +589,6 @@ _callMeasurementHandler(measurementType, value, position, context) { }; } - // Calculate the center of gravity for current pressure calcCog() { From 51f966cfb9375a9f55b7690ee7e3e8f8f67678a2 Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Wed, 5 Nov 2025 15:47:39 +0100 Subject: [PATCH 02/13] Added sanitizing of input for handleInput for rotating machine --- src/specificClass.js | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/src/specificClass.js b/src/specificClass.js index 999443c..2409c4b 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -199,6 +199,11 @@ _callMeasurementHandler(measurementType, value, position, context) { async handleInput(source, action, parameter) { + //sanitize input + if( typeof action !== 'string'){this.logger.error(`Action must be string`); return;} + //convert to lower case to avoid to many mistakes in commands + action = action.toLowerCase(); + if (!this.isValidSourceForMode(source, this.currentMode)) { let warningTxt = `Source '${source}' is not valid for mode '${this.currentMode}'.`; this.logger.warn(warningTxt); @@ -209,23 +214,24 @@ _callMeasurementHandler(measurementType, value, position, context) { try { switch (action) { - case "execSequence": + + case "execsequence": return await this.executeSequence(parameter); - case "execMovement": + case "execmovement": return await this.setpoint(parameter); - case "flowMovement": + case "flowmovement": // Calculate the control value for a desired flow const pos = this.calcCtrl(parameter); // Move to the desired setpoint return await this.setpoint(pos); - case "emergencyStop": + case "emergencystop": this.logger.warn(`Emergency stop activated by '${source}'.`); return await this.executeSequence("emergencyStop"); - case "statusCheck": + case "statuscheck": this.logger.info(`Status Check: Mode = '${this.currentMode}', Source = '${source}'.`); break; @@ -704,23 +710,12 @@ _callMeasurementHandler(measurementType, value, position, context) { // Improved output object generation const output = {}; - //build the output object - this.measurements.getTypes().forEach(type => { - this.measurements.getVariants(type).forEach(variant => { - const downstreamVal = this.measurements.type(type).variant(variant).position("downstream").getCurrentValue(); - const upstreamVal = this.measurements.type(type).variant(variant).position("upstream").getCurrentValue(); - - if (downstreamVal != null) { - output[`downstream_${variant}_${type}`] = downstreamVal; - } - if (upstreamVal != null) { - output[`upstream_${variant}_${type}`] = upstreamVal; - } - if (downstreamVal != null && upstreamVal != null) { - const diffVal = this.measurements.type(type).variant(variant).difference().value; - output[`differential_${variant}_${type}`] = diffVal; - } + Object.entries(this.measurements.measurements).forEach(([type, variants]) => { + Object.entries(variants).forEach(([variant, positions]) => { + Object.entries(positions).forEach(([position, measurement]) => { + output[`${type}.${variant}.${position}`] = measurement.getCurrentValue(); + }); }); }); @@ -733,6 +728,7 @@ _callMeasurementHandler(measurementType, value, position, context) { output["cog"] = this.cog; // flow / power efficiency output["NCog"] = this.NCog; // normalized cog output["NCogPercent"] = Math.round(this.NCog * 100 * 100) / 100 ; + output["maintenanceTime"] = this.state.getMaintenanceTimeHours(); if(this.flowDrift != null){ const flowDrift = this.flowDrift; From 4b5ec33c1d272c215ddbab7a6702338e68b3489b Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Wed, 5 Nov 2025 17:15:47 +0100 Subject: [PATCH 03/13] fixed bugs for rotating machine execSequence --- src/nodeClass.js | 3 +++ src/specificClass.js | 33 ++++++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/nodeClass.js b/src/nodeClass.js index 7fc2acd..2b83066 100644 --- a/src/nodeClass.js +++ b/src/nodeClass.js @@ -145,6 +145,9 @@ class nodeClass { case "decelerating": symbolState = "⏪"; break; + case "maintenance": + symbolState = "🔧"; + break; } const position = m.state.getCurrentPosition(); const roundedPosition = Math.round(position * 100) / 100; diff --git a/src/specificClass.js b/src/specificClass.js index 2409c4b..b2dd199 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -189,26 +189,37 @@ _callMeasurementHandler(measurementType, value, position, context) { // -------- Mode and Input Management -------- // isValidSourceForMode(source, mode) { const allowedSourcesSet = this.config.mode.allowedSources[mode] || []; - return allowedSourcesSet.has(source); + const allowed = allowedSourcesSet.has(source); + allowed? + this.logger.debug(`source is allowed proceeding with ${source} for mode ${mode}`) : + this.logger.warn(`${source} is not allowed in mode ${mode}`); + + return allowed; } isValidActionForMode(action, mode) { const allowedActionsSet = this.config.mode.allowedActions[mode] || []; - return allowedActionsSet.has(action); + const allowed = allowedActionsSet.has(action); + allowed ? + this.logger.debug(`Action is allowed proceeding with ${action} for mode ${mode}`) : + this.logger.warn(`${action} is not allowed in mode ${mode}`); + + return allowed; } async handleInput(source, action, parameter) { + this.logger.debug("hello"); //sanitize input if( typeof action !== 'string'){this.logger.error(`Action must be string`); return;} //convert to lower case to avoid to many mistakes in commands action = action.toLowerCase(); - if (!this.isValidSourceForMode(source, this.currentMode)) { - let warningTxt = `Source '${source}' is not valid for mode '${this.currentMode}'.`; - this.logger.warn(warningTxt); - return {status : false , feedback: warningTxt}; - } + // check for validity of the request + if(!this.isValidActionForMode(action,this.currentMode)){return ;} + if (!this.isValidSourceForMode(source, this.currentMode)) {return ;} + + this.logger.debug("hello2"); this.logger.info(`Handling input from source '${source}' with action '${action}' in mode '${this.currentMode}'.`); @@ -221,6 +232,14 @@ _callMeasurementHandler(measurementType, value, position, context) { case "execmovement": return await this.setpoint(parameter); + case "entermaintenance": + + return await this.executeSequence(parameter); + + + case "exitmaintenance": + return await this.executeSequence(parameter); + case "flowmovement": // Calculate the control value for a desired flow const pos = this.calcCtrl(parameter); From 6ae622b6bf43ff70a8fa42559b44c4f1785c9ca1 Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Thu, 6 Nov 2025 11:19:08 +0100 Subject: [PATCH 04/13] fixed bugs with db output formatting --- src/nodeClass.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nodeClass.js b/src/nodeClass.js index 2b83066..18b723d 100644 --- a/src/nodeClass.js +++ b/src/nodeClass.js @@ -227,8 +227,8 @@ class nodeClass { //this.source.tick(); const raw = this.source.getOutput(); - const processMsg = this._output.formatMsg(raw, this.config, 'process'); - const influxMsg = this._output.formatMsg(raw, this.config, 'influxdb'); + const processMsg = this._output.formatMsg(raw, this.source.config, 'process'); + const influxMsg = this._output.formatMsg(raw, this.source.config, 'influxdb'); // Send only updated outputs on ports 0 & 1 this.node.send([processMsg, influxMsg]); From 994cf641a369a999b9848393738c33911bf70944 Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Fri, 7 Nov 2025 15:10:46 +0100 Subject: [PATCH 05/13] removed some old comments --- src/specificClass.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/specificClass.js b/src/specificClass.js index b2dd199..7653a41 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -209,7 +209,6 @@ _callMeasurementHandler(measurementType, value, position, context) { async handleInput(source, action, parameter) { - this.logger.debug("hello"); //sanitize input if( typeof action !== 'string'){this.logger.error(`Action must be string`); return;} //convert to lower case to avoid to many mistakes in commands @@ -218,8 +217,6 @@ _callMeasurementHandler(measurementType, value, position, context) { // check for validity of the request if(!this.isValidActionForMode(action,this.currentMode)){return ;} if (!this.isValidSourceForMode(source, this.currentMode)) {return ;} - - this.logger.debug("hello2"); this.logger.info(`Handling input from source '${source}' with action '${action}' in mode '${this.currentMode}'.`); From 6528c966d8e365107cd3c6f5d896db3b18702fa3 Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Wed, 12 Nov 2025 17:40:38 +0100 Subject: [PATCH 06/13] added default liquid temp and atm pressure, added nhyd - specific flow and specific energy consumption --- src/specificClass.js | 51 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/src/specificClass.js b/src/specificClass.js index 7653a41..ef679e9 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -1,6 +1,6 @@ const EventEmitter = require('events'); -const {loadCurve,logger,configUtils,configManager,state, nrmse, MeasurementContainer, predict, interpolation , childRegistrationUtils} = require('generalFunctions'); -const { name } = require('../../generalFunctions/src/convert/lodash/lodash._shimkeys'); +const {loadCurve,gravity,logger,configUtils,configManager,state, nrmse, MeasurementContainer, predict, interpolation , childRegistrationUtils,coolprop} = require('generalFunctions'); +const pressure = require('../../generalFunctions/src/convert/definitions/pressure'); class Machine { @@ -84,9 +84,21 @@ class Machine { this._updateState(); }); + + //perform init for certain values + this._init(); + this.child = {}; // object to hold child information so we know on what to subscribe this.childRegistrationUtils = new childRegistrationUtils(this); // Child registration utility + + } + + _init(){ + //assume standard temperature is 20degrees + this.measurements.type('temperature').variant('measured').position('atEquipment').value(15).unit('C'); + //assume standard atm pressure is at sea level + this.measurements.type('atmPressure').variant('measured').position('atEquipment').value(101325).unit('Pa'); } _updateState(){ @@ -670,15 +682,36 @@ _callMeasurementHandler(measurementType, value, position, context) { return { cPower, cFlow }; } - calcEfficiency(power, flow, variant) { + calcEfficiency(power,flow,variant) { + + const pressureDiff = this.measurements.type('pressure').variant('measured').difference('Pa'); + const g = gravity.getStandardGravity(); + const temp = this.measurements.type('temperature').variant('measured').position('atEquipment').getCurrentValue('K'); + const atmPressure = this.measurements.type('atmPressure').variant('measured').position('atEquipment').getCurrentValue('Pa'); + const rho = coolprop.PropsSI('D', 'T', temp, 'P', atmPressure, 'WasteWater'); + + + this.logger.debug(`temp: ${temp} atmPressure : ${atmPressure} rho : ${rho} pressureDiff: ${pressureDiff?.value || 0}`); + const flowM3s = this.measurements.type('flow').variant('predicted').position('atEquipment').getCurrentValue('m3/s'); + const powerWatt = this.measurements.type('power').variant('predicted').position('atEquipment').getCurrentValue('W'); + this.logger.debug(`Flow : ${flowM3s} power: ${powerWatt}`); if (power != 0 && flow != 0) { - // Calculate efficiency after measurements update - this.measurements.type("efficiency").variant(variant).position('atEquipment').value((flow / power)); - } else { - this.measurements.type("efficiency").variant(variant).position('atEquipment').value(null); - } + const specificFlow = flow / power; + const specificEnergyConsumption = power / flow; + this.measurements.type("efficiency").variant(variant).position('atEquipment').value(specificFlow); + this.measurements.type("specificEnergyConsumption").variant(variant).position('atEquipment').value(specificEnergyConsumption); + + if(pressureDiff?.value != null && flowM3s != null && powerWatt != null){ + const meterPerBar = pressureDiff.value / rho * g; + const nHydraulicEfficiency = rho * g * flowM3s * (pressureDiff.value * meterPerBar ) / powerWatt; + this.measurements.type("nHydraulicEfficiency").variant(variant).position('atEquipment').value(nHydraulicEfficiency); + } + + } + + //change this to nhydrefficiency ? return this.measurements.type("efficiency").variant(variant).position('atEquipment').getCurrentValue(); } @@ -768,8 +801,8 @@ _callMeasurementHandler(measurementType, value, position, context) { module.exports = Machine; /*------------------- Testing -------------------*/ -/* +/* curve = require('C:/Users/zn375/.node-red/public/fallbackData.json'); //import a child From fb75fb8a116c7404d8835b2f811f889bfed48dc2 Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Thu, 13 Nov 2025 19:39:05 +0100 Subject: [PATCH 07/13] Removed error when machine doesnt have curve so node-red doesnt crash when you dont select a machine --- rotatingMachine.html | 2 +- src/specificClass.js | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/rotatingMachine.html b/rotatingMachine.html index 6d54b66..77ffcb5 100644 --- a/rotatingMachine.html +++ b/rotatingMachine.html @@ -54,7 +54,7 @@ icon: "font-awesome/fa-cog", label: function () { - return this.positionIcon + " " + this.category.slice(0, -1) || "Machine"; + return this.positionIcon + " " + this.category || "Machine"; }, oneditprepare: function() { diff --git a/src/specificClass.js b/src/specificClass.js index ef679e9..c8bf307 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -35,10 +35,8 @@ class Machine { } else{ this.hasCurve = true; - this.config = this.configUtils.updateConfig(this.config, { - asset: { ...this.config.asset, machineCurve: this.curve } - }); - machineConfig = { ...machineConfig, asset: { ...machineConfig.asset, machineCurve: this.curve } }; // Merge curve into machineConfig + this.config = this.configUtils.updateConfig(this.config, { asset: { ...this.config.asset, machineCurve: this.curve } }); + //machineConfig = { ...machineConfig, asset: { ...machineConfig.asset, machineCurve: this.curve } }; // Merge curve into machineConfig this.predictFlow = new predict({ curve: this.config.asset.machineCurve.nq }); // load nq (x : ctrl , y : flow relationship) this.predictPower = new predict({ curve: this.config.asset.machineCurve.np }); // load np (x : ctrl , y : power relationship) this.predictCtrl = new predict({ curve: this.reverseCurve(this.config.asset.machineCurve.nq) }); // load reversed nq (x: flow, y: ctrl relationship) @@ -106,6 +104,7 @@ class Machine { if(!isOperational){ //overrule the last prediction this should be 0 now this.measurements.type("flow").variant("predicted").position("downstream").value(0); + this.measurements.type("flow").variant("predicted").position("atEquipment").value(0); } } @@ -127,7 +126,7 @@ class Machine { this.logger.debug(`🔄 ${position} ${measurementType} from ${eventData.childName}: ${eventData.value} ${eventData.unit}`); - console.log(` Emitting... ${eventName} with data:`); + this.logger.debug(` Emitting... ${eventName} with data:`); // Store directly in parent's measurement container this.measurements .type(measurementType) @@ -347,13 +346,14 @@ _callMeasurementHandler(measurementType, value, position, context) { if(this.hasCurve) { if (!this._isOperationalState()) { this.measurements.type("flow").variant("predicted").position("downstream").value(0); + this.measurements.type("flow").variant("predicted").position("atEquipment").value(0); this.logger.debug(`Machine is not operational. Setting predicted flow to 0.`); return 0; } - //this.predictFlow.currentX = x; Decrepated const cFlow = this.predictFlow.y(x); this.measurements.type("flow").variant("predicted").position("downstream").value(cFlow); + this.measurements.type("flow").variant("predicted").position("atEquipment").value(cFlow); //this.logger.debug(`Calculated flow: ${cFlow} for pressure: ${this.getMeasuredPressure()} and position: ${x}`); return cFlow; } @@ -361,6 +361,7 @@ _callMeasurementHandler(measurementType, value, position, context) { // If no curve data is available, log a warning and return 0 this.logger.warn(`No curve data available for flow calculation. Returning 0.`); this.measurements.type("flow").variant("predicted").position("downstream").value(0); + this.measurements.type("flow").variant("predicted").position("atEquipment").value(0); return 0; } @@ -425,6 +426,11 @@ _callMeasurementHandler(measurementType, value, position, context) { // returns the best available pressure measurement to use in the prediction calculation // this will be either the differential pressure, downstream or upstream pressure getMeasuredPressure() { + if(this.hasCurve === false){ + this.logger.error(`No valid curve available to calculate prediction using last known pressure`); + return 0; + } + const pressureDiff = this.measurements.type('pressure').variant('measured').difference(); // Both upstream & downstream => differential @@ -560,6 +566,7 @@ _callMeasurementHandler(measurementType, value, position, context) { // Update predicted flow if you have prediction capability if (this.predictFlow) { this.measurements.type("flow").variant("predicted").position("downstream").value(this.predictFlow.outputY || 0); + this.measurements.type("flow").variant("predicted").position("atEquipment").value(this.predictFlow.outputY || 0); } } From 6ca6e536a58be5bf5aab25e4befd7d399e4bc876 Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Thu, 20 Nov 2025 11:09:44 +0100 Subject: [PATCH 08/13] fixed dropdown speed selection --- rotatingMachine.html | 15 +++++++++++++++ src/nodeClass.js | 5 ++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/rotatingMachine.html b/rotatingMachine.html index 77ffcb5..28e210c 100644 --- a/rotatingMachine.html +++ b/rotatingMachine.html @@ -24,6 +24,7 @@ warmup: { value: 0 }, shutdown: { value: 0 }, cooldown: { value: 0 }, + movementMode : { value: "staticspeed" }, // static or dynamic machineCurve : { value: {}}, //define asset properties @@ -74,6 +75,10 @@ document.getElementById("node-input-warmup"); document.getElementById("node-input-shutdown"); document.getElementById("node-input-cooldown"); + const movementMode = document.getElementById("node-input-movementMode"); + if (movementMode) { + movementMode.value = this.movementMode || "staticspeed"; + } }, oneditsave: function() { @@ -99,6 +104,9 @@ node[field] = value; }); + node.movementMode = document.getElementById("node-input-movementMode").value; + console.log(`----------------> Saving movementMode: ${node.movementMode}`); + } }); @@ -127,6 +135,13 @@ +
+ + +
diff --git a/src/nodeClass.js b/src/nodeClass.js index 18b723d..a000f7e 100644 --- a/src/nodeClass.js +++ b/src/nodeClass.js @@ -76,6 +76,8 @@ class nodeClass { _setupSpecificClass(uiConfig) { const machineConfig = this.config; + console.log(`----------------> Loaded movementMode in nodeClass: ${uiConfig.movementMode}`); + // need extra state for this const stateConfig = { general: { @@ -85,7 +87,8 @@ class nodeClass { } }, movement: { - speed: Number(uiConfig.speed) + speed: Number(uiConfig.speed), + mode: uiConfig.movementMode }, time: { starting: Number(uiConfig.startup), From f083e7596ae2f02ed7e2c01f91ba89e914bec476 Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Thu, 20 Nov 2025 22:29:24 +0100 Subject: [PATCH 09/13] update --- src/specificClass.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/specificClass.js b/src/specificClass.js index c8bf307..38117af 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -639,7 +639,7 @@ _callMeasurementHandler(measurementType, value, position, context) { const {efficiencyCurve, peak, peakIndex, minEfficiency } = this.calcEfficiencyCurve(powerCurve, flowCurve); // Calculate the normalized center of gravity - const NCog = (flowCurve.y[peakIndex] - this.predictFlow.currentFxyYMin) / (this.predictFlow.currentFxyYMax - this.predictFlow.currentFxyYMin); + const NCog = (flowCurve.y[peakIndex] - this.predictFlow.currentFxyYMin) / (this.predictFlow.currentFxyYMax - this.predictFlow.currentFxyYMin); // //store in object for later retrieval this.currentEfficiencyCurve = efficiencyCurve; From e8c96c4b1ed81c1bbbb07bf20ce6719632828ac8 Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Tue, 25 Nov 2025 16:19:23 +0100 Subject: [PATCH 10/13] removed useless parameter --- src/specificClass.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/specificClass.js b/src/specificClass.js index 38117af..777d01e 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -1,6 +1,5 @@ const EventEmitter = require('events'); const {loadCurve,gravity,logger,configUtils,configManager,state, nrmse, MeasurementContainer, predict, interpolation , childRegistrationUtils,coolprop} = require('generalFunctions'); -const pressure = require('../../generalFunctions/src/convert/definitions/pressure'); class Machine { From 966ba06faac4639cff071ad63ad88695e68e7f98 Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Thu, 27 Nov 2025 17:46:56 +0100 Subject: [PATCH 11/13] some minor addons to measurement container --- src/specificClass.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/specificClass.js b/src/specificClass.js index 777d01e..ede5709 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -478,6 +478,9 @@ _callMeasurementHandler(measurementType, value, position, context) { const efficiency = this.calcEfficiency(this.predictPower.outputY, this.predictFlow.outputY, "predicted"); //update the distance from peak this.calcDistanceBEP(efficiency,cog,minEfficiency); + //place min and max flow capabilities in containerthis.predictFlow.currentFxyYMax - this.predictFlow.currentFxyYMin + this.measurements.type('flow').variant('predicted').variant('max').value(this.predictFlow.currentFxyYMax).unit(this.config.general.unit); + this.measurements.type('flow').variant('predicted').variant('min').value(this.predictFlow.currentFxyYMin).unit(this.config.general.unit); return 0; } @@ -597,8 +600,6 @@ _callMeasurementHandler(measurementType, value, position, context) { } - - } calcDistanceFromPeak(currentEfficiency,peakEfficiency){ From 446ef81f24bc493a68ddf6ca8f7f5d3d4ebd29b9 Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Fri, 28 Nov 2025 09:59:51 +0100 Subject: [PATCH 12/13] adjusted input for measurement container --- src/specificClass.js | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/specificClass.js b/src/specificClass.js index ede5709..c39e01d 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -96,6 +96,10 @@ class Machine { this.measurements.type('temperature').variant('measured').position('atEquipment').value(15).unit('C'); //assume standard atm pressure is at sea level this.measurements.type('atmPressure').variant('measured').position('atEquipment').value(101325).unit('Pa'); + //populate min and max + const flowunit = this.config.general.unit; + this.measurements.type('flow').variant('predicted').position('max').value(this.predictFlow.currentFxyYMax, Date.now() , flowunit) + this.measurements.type('flow').variant('predicted').position('min').value(this.predictFlow.currentFxyYMin).unit(this.config.general.unit); } _updateState(){ @@ -344,15 +348,15 @@ _callMeasurementHandler(measurementType, value, position, context) { calcFlow(x) { if(this.hasCurve) { if (!this._isOperationalState()) { - this.measurements.type("flow").variant("predicted").position("downstream").value(0); - this.measurements.type("flow").variant("predicted").position("atEquipment").value(0); + this.measurements.type("flow").variant("predicted").position("downstream").value(0,Date.now(),this.config.general.unit); + this.measurements.type("flow").variant("predicted").position("atEquipment").value(0,Date.now(),this.config.general.unit); this.logger.debug(`Machine is not operational. Setting predicted flow to 0.`); return 0; } const cFlow = this.predictFlow.y(x); - this.measurements.type("flow").variant("predicted").position("downstream").value(cFlow); - this.measurements.type("flow").variant("predicted").position("atEquipment").value(cFlow); + this.measurements.type("flow").variant("predicted").position("downstream").value(cFlow,Date.now(),this.config.general.unit); + this.measurements.type("flow").variant("predicted").position("atEquipment").value(cFlow,Date.now(),this.config.general.unit); //this.logger.debug(`Calculated flow: ${cFlow} for pressure: ${this.getMeasuredPressure()} and position: ${x}`); return cFlow; } @@ -479,8 +483,8 @@ _callMeasurementHandler(measurementType, value, position, context) { //update the distance from peak this.calcDistanceBEP(efficiency,cog,minEfficiency); //place min and max flow capabilities in containerthis.predictFlow.currentFxyYMax - this.predictFlow.currentFxyYMin - this.measurements.type('flow').variant('predicted').variant('max').value(this.predictFlow.currentFxyYMax).unit(this.config.general.unit); - this.measurements.type('flow').variant('predicted').variant('min').value(this.predictFlow.currentFxyYMin).unit(this.config.general.unit); + this.measurements.type('flow').variant('predicted').position('max').value(this.predictFlow.currentFxyYMax).unit(this.config.general.unit); + this.measurements.type('flow').variant('predicted').position('min').value(this.predictFlow.currentFxyYMin).unit(this.config.general.unit); return 0; } @@ -694,7 +698,9 @@ _callMeasurementHandler(measurementType, value, position, context) { const pressureDiff = this.measurements.type('pressure').variant('measured').difference('Pa'); const g = gravity.getStandardGravity(); const temp = this.measurements.type('temperature').variant('measured').position('atEquipment').getCurrentValue('K'); - const atmPressure = this.measurements.type('atmPressure').variant('measured').position('atEquipment').getCurrentValue('Pa'); + const atmPressure = this.measurements.type('atmPressure').variant('measured').position('atEquipment').getCurrentValue('Pa'); + + console.log(`--------------------calc efficiency : Pressure diff:${pressureDiff},${temp}, ${g} `); const rho = coolprop.PropsSI('D', 'T', temp, 'P', atmPressure, 'WasteWater'); @@ -765,15 +771,8 @@ _callMeasurementHandler(measurementType, value, position, context) { getOutput() { // Improved output object generation - const output = {}; - Object.entries(this.measurements.measurements).forEach(([type, variants]) => { - Object.entries(variants).forEach(([variant, positions]) => { - Object.entries(positions).forEach(([position, measurement]) => { - output[`${type}.${variant}.${position}`] = measurement.getCurrentValue(); - }); - }); - }); + const output = this.measurements.getFlattenedOutput(); //fill in the rest of the output object output["state"] = this.state.getCurrentState(); From 108d2e23caa3221aee5f76c9443bddc8a9bc3bc4 Mon Sep 17 00:00:00 2001 From: znetsixe <73483679+znetsixe@users.noreply.github.com> Date: Sun, 30 Nov 2025 09:24:37 +0100 Subject: [PATCH 13/13] bug fixes --- src/specificClass.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/specificClass.js b/src/specificClass.js index c39e01d..b350e85 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -16,7 +16,7 @@ class Machine { // Load a specific curve this.model = machineConfig.asset.model; // Get the model from the machineConfig - this.curve = this.model ? loadCurve(this.model) : null; + this.curve = this.model ? loadCurve(this.model) : null; // we need to convert the curve and add units to the curve information //Init config and check if it is valid this.config = this.configUtils.initConfig(machineConfig); @@ -106,8 +106,8 @@ class Machine { const isOperational = this._isOperationalState(); if(!isOperational){ //overrule the last prediction this should be 0 now - this.measurements.type("flow").variant("predicted").position("downstream").value(0); - this.measurements.type("flow").variant("predicted").position("atEquipment").value(0); + this.measurements.type("flow").variant("predicted").position("downstream").value(0,Date.now(),this.config.general.unit); + this.measurements.type("flow").variant("predicted").position("atEquipment").value(0,Date.now(),this.config.general.unit); } } @@ -363,8 +363,8 @@ _callMeasurementHandler(measurementType, value, position, context) { // If no curve data is available, log a warning and return 0 this.logger.warn(`No curve data available for flow calculation. Returning 0.`); - this.measurements.type("flow").variant("predicted").position("downstream").value(0); - this.measurements.type("flow").variant("predicted").position("atEquipment").value(0); + this.measurements.type("flow").variant("predicted").position("downstream").value(0, Date.now(),this.config.general.unit); + this.measurements.type("flow").variant("predicted").position("atEquipment").value(0, Date.now(),this.config.general.unit); return 0; }