Compare commits

...

3 Commits

Author SHA1 Message Date
znetsixe
fa7c59fcab updates 2025-07-24 13:15:33 +02:00
znetsixe
3fc8dbefe8 bug fix 2025-07-02 17:07:19 +02:00
znetsixe
f24a5fb90b bug fixes 2025-07-02 16:00:52 +02:00
3 changed files with 52 additions and 32 deletions

View File

@@ -57,11 +57,11 @@
waitForMenuData();
// your existing projectsettings & asset dropdown logic can remain here
document.getElementById("node-input-speed"),
document.getElementById("node-input-startup"),
document.getElementById("node-input-warmup"),
document.getElementById("node-input-shutdown"),
document.getElementById("node-input-cooldown")
document.getElementById("node-input-speed");
document.getElementById("node-input-startup");
document.getElementById("node-input-warmup");
document.getElementById("node-input-shutdown");
document.getElementById("node-input-cooldown");
},
oneditsave: function() {

View File

@@ -20,12 +20,13 @@ class nodeClass {
this.RED = RED; // This is the Node-RED runtime API, we can use this to create endpoints if needed
this.name = nameOfNode; // This is the name of the node, it should match the file name and the node type in Node-RED
this.source = null; // Will hold the specific class instance
this.config = null; // Will hold the merged configuration
// Load default & UI config
this._loadConfig(uiConfig,this.node);
// Instantiate core Measurement class
this._setupSpecificClass();
// Instantiate core class
this._setupSpecificClass(uiConfig);
// Wire up event and lifecycle handlers
this._bindEvents();
@@ -40,8 +41,6 @@ class nodeClass {
* @param {object} uiConfig - Raw config from Node-RED UI.
*/
_loadConfig(uiConfig,node) {
const cfgMgr = new configManager();
this.defaultConfig = cfgMgr.getConfig(this.name);
// Merge UI config over defaults
this.config = {
@@ -75,7 +74,7 @@ class nodeClass {
/**
* Instantiate the core Measurement logic and store as source.
*/
_setupSpecificClass() {
_setupSpecificClass(uiConfig) {
const machineConfig = this.config;
// need extra state for this
@@ -87,13 +86,13 @@ class nodeClass {
}
},
movement: {
speed: Number(machineConfig.speed)
speed: Number(uiConfig.speed)
},
time: {
starting: Number(machineConfig.startup),
warmingup: Number(machineConfig.warmup),
stopping: Number(machineConfig.shutdown),
coolingdown: Number(machineConfig.cooldown)
starting: Number(uiConfig.startup),
warmingup: Number(uiConfig.warmup),
stopping: Number(uiConfig.shutdown),
coolingdown: Number(uiConfig.cooldown)
}
};
@@ -108,9 +107,7 @@ class nodeClass {
* Bind events to Node-RED status updates. Using internal emitter. --> REMOVE LATER WE NEED ONLY COMPLETE CHILDS AND THEN CHECK FOR UPDATES
*/
_bindEvents() {
this.source.emitter.on('mAbs', (val) => {
this.node.status({ fill: 'green', shape: 'dot', text: `${val} ${this.config.general.unit}` });
});
}
_updateNodeStatus() {
@@ -206,7 +203,7 @@ class nodeClass {
}
/**
* Start the periodic tick loop to drive the Measurement class.
* Start the periodic tick loop.
*/
_startTickLoop() {
setTimeout(() => {
@@ -269,9 +266,9 @@ class nodeClass {
const { source: esSource, action: esAction } = msg.payload;
m.handleInput(esSource, esAction);
break;
case 'showCompleteCurve':
m.showCompleteCurve();
send({ topic : "Showing curve" , payload: m.showCompleteCurve() });
case 'showWorkingCurves':
m.showWorkingCurves();
send({ topic : "Showing curve" , payload: m.showWorkingCurves() });
break;
case 'CoG':
m.showCoG();

View File

@@ -63,6 +63,9 @@ class Machine {
this.model = machineConfig.asset.model; // Get the model from the machineConfig
this.curve = this.model ? loadCurve(this.model) : null;
//Init config and check if it is valid
this.config = this.configUtils.initConfig(machineConfig);
if (!this.model || !this.curve) {
this.logger.warning(`${!this.model ? 'Model not specified' : 'Curve not found for model ' + this.model} in machineConfig. Cannot make predictions.`);
// Set prediction objects to null to prevent method calls
@@ -73,8 +76,10 @@ 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.initConfig(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)
@@ -104,8 +109,6 @@ class Machine {
this.updatePosition();
});
//this.calcCog();
this.childRegistrationUtils = new childRegistrationUtils(this); // Child registration utility
}
@@ -197,7 +200,7 @@ class Machine {
}
setMode(newMode) {
const availableModes = defaultConfig.mode.current.rules.values.map(v => v.value);
const availableModes = this.defaultConfig.mode.current.rules.values.map(v => v.value);
if (!availableModes.includes(newMode)) {
this.logger.warn(`Invalid mode '${newMode}'. Allowed modes are: ${availableModes.join(', ')}`);
return;
@@ -244,6 +247,8 @@ class Machine {
throw new Error("Invalid setpoint: Setpoint must be a non-negative number.");
}
this.logger.info(`Setting setpoint to ${setpoint}. Current position: ${this.state.getCurrentPosition()}`);
// Move to the desired setpoint
await this.state.moveTo(setpoint);
@@ -254,7 +259,7 @@ class Machine {
// Calculate flow based on current pressure and position
calcFlow(x) {
if(!this.hasCurve) {
if(this.hasCurve) {
const state = this.state.getCurrentState();
if (!["operational", "accelerating", "decelerating"].includes(state)) {
@@ -279,7 +284,7 @@ class Machine {
// Calculate power based on current pressure and position
calcPower(x) {
if(!this.hasCurve) {
if(this.hasCurve) {
const state = this.state.getCurrentState();
if (!["operational", "accelerating", "decelerating"].includes(state)) {
this.measurements.type("power").variant("predicted").position('upstream').value(0);
@@ -302,7 +307,7 @@ class Machine {
// calculate the power consumption using only flow and pressure
inputFlowCalcPower(flow) {
if(!this.hasCurve) {
if(this.hasCurve) {
this.predictCtrl.currentX = flow;
const cCtrl = this.predictCtrl.y(flow);
@@ -320,7 +325,7 @@ class Machine {
// Function to predict control value for a desired flow
calcCtrl(x) {
if(!this.hasCurve) {
if(this.hasCurve) {
this.predictCtrl.currentX = x;
const cCtrl = this.predictCtrl.y(x);
this.measurements.type("ctrl").variant("predicted").position('upstream').value(cCtrl);
@@ -407,7 +412,7 @@ class Machine {
}
// get
const upstreamFlow = this.measurements.type('pressure').variant('measured').position('upstream').getCurrentValue();
const upstreamFlow = this.measurements.type('flow').variant('measured').position('upstream').getCurrentValue();
// Only upstream => might still accept it, but warn
if (upstreamFlow != null) {
@@ -416,7 +421,7 @@ class Machine {
}
// get
const downstreamFlow = this.measurements.type('pressure').variant('measured').position('downstream').getCurrentValue();
const downstreamFlow = this.measurements.type('flow').variant('measured').position('downstream').getCurrentValue();
// Only downstream => might still accept it, but warn
if (downstreamFlow != null) {
@@ -450,6 +455,7 @@ class Machine {
if (this.state.getCurrentState() == "operational" || this.state.getCurrentState() == "accelerating" || this.state.getCurrentState() == "decelerating") {
// put value in measurements
this.measurements.type("pressure").variant("measured").position(position).value(value);
this.logger.debug(`Updated measured pressure: ${value} at position: ${position}`);
//when measured pressure gets updated we need some logic to fetch the relevant value which could be downstream or differential pressure
const pressure = this.getMeasuredPressure();
//update the flow power and cog
@@ -539,6 +545,23 @@ class Machine {
return distance;
}
showWorkingCurves() {
// Show the current curves for debugging
const { powerCurve, flowCurve } = this.getCurrentCurves();
return {
powerCurve: powerCurve,
flowCurve: flowCurve,
cog: this.cog,
cogIndex: this.cogIndex,
NCog: this.NCog,
minEfficiency: this.minEfficiency,
currentEfficiencyCurve: this.currentEfficiencyCurve,
absDistFromPeak: this.absDistFromPeak,
relDistFromPeak: this.relDistFromPeak
};
}
// Calculate the center of gravity for current pressure
calcCog() {