forked from RnD/rotatingMachine
generic updates completed for now
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* measurement.class.js
|
||||
* node class.js
|
||||
*
|
||||
* Encapsulates all node logic in a reusable class. In future updates we can split this into multiple generic classes and use the config to specifiy which ones to use.
|
||||
* This allows us to keep the Node-RED node clean and focused on wiring up the UI and event handlers.
|
||||
@@ -7,9 +7,6 @@
|
||||
const { outputUtils, configManager } = require('generalFunctions');
|
||||
const Specific = require("./specificClass");
|
||||
|
||||
/**
|
||||
* Class representing a Node-RED node.
|
||||
*/
|
||||
class nodeClass {
|
||||
/**
|
||||
* Create a Node.
|
||||
@@ -79,27 +76,32 @@ class nodeClass {
|
||||
* Instantiate the core Measurement logic and store as source.
|
||||
*/
|
||||
_setupSpecificClass() {
|
||||
const machineConfig = this.config;
|
||||
|
||||
// need extra state for this
|
||||
const stateConfig = {
|
||||
general: {
|
||||
logging: {
|
||||
enabled: config.eneableLog,
|
||||
logLevel: config.logLevel
|
||||
enabled: machineConfig.eneableLog,
|
||||
logLevel: machineConfig.logLevel
|
||||
}
|
||||
},
|
||||
movement: {
|
||||
speed: Number(config.speed)
|
||||
speed: Number(machineConfig.speed)
|
||||
},
|
||||
time: {
|
||||
starting: Number(config.startup),
|
||||
warmingup: Number(config.warmup),
|
||||
stopping: Number(config.shutdown),
|
||||
coolingdown: Number(config.cooldown)
|
||||
starting: Number(machineConfig.startup),
|
||||
warmingup: Number(machineConfig.warmup),
|
||||
stopping: Number(machineConfig.shutdown),
|
||||
coolingdown: Number(machineConfig.cooldown)
|
||||
}
|
||||
};
|
||||
|
||||
this.source = new Specific(this.config, stateConfig);
|
||||
this.source = new Specific(machineConfig, stateConfig);
|
||||
|
||||
//store in node
|
||||
this.node.source = this.source; // Store the source in the node instance for easy access
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,7 +225,7 @@ class nodeClass {
|
||||
* Execute a single tick: update measurement, format and send outputs.
|
||||
*/
|
||||
_tick() {
|
||||
this.source.tick();
|
||||
//this.source.tick();
|
||||
|
||||
const raw = this.source.getOutput();
|
||||
const processMsg = this._output.formatMsg(raw, this.config, 'process');
|
||||
@@ -242,6 +244,7 @@ class nodeClass {
|
||||
const m = this.source;
|
||||
switch(msg.topic) {
|
||||
case 'registerChild':
|
||||
// Register this node as a child of the parent node
|
||||
const childId = msg.payload;
|
||||
const childObj = this.RED.nodes.getNode(childId);
|
||||
m.childRegistrationUtils.registerChild(childObj.source ,msg.positionVsParent);
|
||||
|
||||
@@ -44,7 +44,7 @@ maintenanceAlert: this.state.checkMaintenanceStatus()
|
||||
|
||||
//load local dependencies
|
||||
const EventEmitter = require('events');
|
||||
const {logger,configUtils,configManager,state, nrmse, MeasurementContainer, predict, interpolation , childRegistrationUtils} = require('generalFunctions');
|
||||
const {loadCurve,logger,configUtils,configManager,state, nrmse, MeasurementContainer, predict, interpolation , childRegistrationUtils} = require('generalFunctions');
|
||||
|
||||
class Machine {
|
||||
|
||||
@@ -53,13 +53,31 @@ class Machine {
|
||||
|
||||
//basic setup
|
||||
this.emitter = new EventEmitter(); // Own EventEmitter
|
||||
this.logger = new logger(machineConfig.general.logging.enabled,machineConfig.general.logging.logLevel, machineConfig.general.name);
|
||||
this.configManager = new configManager();
|
||||
this.defaultConfig = this.configManager.getConfig('rotatingMachine'); // Load default config for rotating machine
|
||||
this.defaultConfig = this.configManager.getConfig('rotatingMachine'); // Load default config for rotating machine ( use software type name ? )
|
||||
this.configUtils = new configUtils(this.defaultConfig);
|
||||
this.config = this.configUtils.initConfig(machineConfig);
|
||||
|
||||
// Init after config is set
|
||||
this.logger = new logger(this.config.general.logging.enabled,this.config.general.logging.logLevel, this.config.general.name);
|
||||
// Load a specific curve
|
||||
this.model = machineConfig.asset.model; // Get the model from the machineConfig
|
||||
this.curve = this.model ? loadCurve(this.model) : null;
|
||||
|
||||
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
|
||||
this.predictFlow = null;
|
||||
this.predictPower = null;
|
||||
this.predictCtrl = null;
|
||||
this.hasCurve = false;
|
||||
}
|
||||
else{
|
||||
this.hasCurve = true;
|
||||
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)
|
||||
}
|
||||
|
||||
this.state = new state(stateConfig, this.logger); // Init State manager and pass logger
|
||||
this.errorMetrics = new nrmse(errorMetricsConfig, this.logger);
|
||||
@@ -71,10 +89,6 @@ class Machine {
|
||||
|
||||
this.flowDrift = null;
|
||||
|
||||
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)
|
||||
|
||||
this.currentMode = this.config.mode.current;
|
||||
this.currentEfficiencyCurve = {};
|
||||
this.cog = 0;
|
||||
@@ -239,55 +253,84 @@ class Machine {
|
||||
|
||||
// Calculate flow based on current pressure and position
|
||||
calcFlow(x) {
|
||||
const state = this.state.getCurrentState();
|
||||
if(!this.hasCurve) {
|
||||
const state = this.state.getCurrentState();
|
||||
|
||||
if (!["operational", "accelerating", "decelerating"].includes(state)) {
|
||||
this.measurements.type("flow").variant("predicted").position("downstream").value(0);
|
||||
this.logger.debug(`Machine is not operational. Setting predicted flow to 0.`);
|
||||
return 0;
|
||||
}
|
||||
if (!["operational", "accelerating", "decelerating"].includes(state)) {
|
||||
this.measurements.type("flow").variant("predicted").position("downstream").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.logger.debug(`Calculated flow: ${cFlow} for pressure: ${this.getMeasuredPressure()} and position: ${x}`);
|
||||
return cFlow;
|
||||
}
|
||||
|
||||
// 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);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
// Calculate power based on current pressure and position
|
||||
calcPower(x) {
|
||||
const state = this.state.getCurrentState();
|
||||
if (!["operational", "accelerating", "decelerating"].includes(state)) {
|
||||
this.measurements.type("power").variant("predicted").position('upstream').value(0);
|
||||
this.logger.debug(`Machine is not operational. Setting predicted power to 0.`);
|
||||
return 0;
|
||||
}
|
||||
if(!this.hasCurve) {
|
||||
const state = this.state.getCurrentState();
|
||||
if (!["operational", "accelerating", "decelerating"].includes(state)) {
|
||||
this.measurements.type("power").variant("predicted").position('upstream').value(0);
|
||||
this.logger.debug(`Machine is not operational. Setting predicted power to 0.`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//this.predictPower.currentX = x; Decrepated
|
||||
const cPower = this.predictPower.y(x);
|
||||
this.measurements.type("power").variant("predicted").position('upstream').value(cPower);
|
||||
//this.logger.debug(`Calculated power: ${cPower} for pressure: ${this.getMeasuredPressure()} and position: ${x}`);
|
||||
return cPower;
|
||||
}
|
||||
// If no curve data is available, log a warning and return 0
|
||||
this.logger.warn(`No curve data available for power calculation. Returning 0.`);
|
||||
this.measurements.type("power").variant("predicted").position('upstream').value(0);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
// calculate the power consumption using only flow and pressure
|
||||
inputFlowCalcPower(flow) {
|
||||
this.predictCtrl.currentX = flow;
|
||||
const cCtrl = this.predictCtrl.y(flow);
|
||||
this.predictPower.currentX = cCtrl;
|
||||
const cPower = this.predictPower.y(cCtrl);
|
||||
return cPower;
|
||||
if(!this.hasCurve) {
|
||||
|
||||
this.predictCtrl.currentX = flow;
|
||||
const cCtrl = this.predictCtrl.y(flow);
|
||||
this.predictPower.currentX = cCtrl;
|
||||
const cPower = this.predictPower.y(cCtrl);
|
||||
return cPower;
|
||||
}
|
||||
|
||||
// If no curve data is available, log a warning and return 0
|
||||
this.logger.warn(`No curve data available for power calculation. Returning 0.`);
|
||||
this.measurements.type("power").variant("predicted").position('upstream').value(0);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
// Function to predict control value for a desired flow
|
||||
calcCtrl(x) {
|
||||
|
||||
this.predictCtrl.currentX = x;
|
||||
const cCtrl = this.predictCtrl.y(x);
|
||||
this.measurements.type("ctrl").variant("predicted").position('upstream').value(cCtrl);
|
||||
//this.logger.debug(`Calculated ctrl: ${cCtrl} for pressure: ${this.getMeasuredPressure()} and position: ${x}`);
|
||||
return cCtrl;
|
||||
if(!this.hasCurve) {
|
||||
this.predictCtrl.currentX = x;
|
||||
const cCtrl = this.predictCtrl.y(x);
|
||||
this.measurements.type("ctrl").variant("predicted").position('upstream').value(cCtrl);
|
||||
//this.logger.debug(`Calculated ctrl: ${cCtrl} for pressure: ${this.getMeasuredPressure()} and position: ${x}`);
|
||||
return cCtrl;
|
||||
}
|
||||
|
||||
// If no curve data is available, log a warning and return 0
|
||||
this.logger.warn(`No curve data available for control calculation. Returning 0.`);
|
||||
this.measurements.type("ctrl").variant("predicted").position('upstream').value(0);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user