diff --git a/src/nodeClass.js b/src/nodeClass.js index 23d156d..47ec062 100644 --- a/src/nodeClass.js +++ b/src/nodeClass.js @@ -101,65 +101,60 @@ class nodeClass { _updateNodeStatus() { const ps = this.source; - try { - // --- Basin & measurements ------------------------------------------------- - const maxVolBeforeOverflow = ps.basin?.maxVolOverflow ?? ps.basin?.maxVol ?? 0; - const volumeMeasurement = ps.measurements.type("volume").variant("measured").position("atEquipment"); - const currentVolume = volumeMeasurement.getCurrentValue("m3") ?? 0; - const netFlowMeasurement = ps.measurements.type("netFlowRate").variant("predicted").position("atEquipment"); - const netFlowM3s = netFlowMeasurement?.getCurrentValue("m3/s") ?? 0; - const netFlowM3h = netFlowM3s * 3600; - const percentFull = ps.measurements.type("volume").variant("procent").position("atEquipment").getCurrentValue() ?? 0; - // --- State information ---------------------------------------------------- - const direction = ps.state?.direction || "unknown"; - const secondsRemaining = ps.state?.seconds ?? null; - - const timeRemaining = secondsRemaining ? `${Math.round(secondsRemaining / 60)}` : 0 + " min"; - - // --- Icon / colour selection --------------------------------------------- - let symbol = "❔"; - let fill = "grey"; - - switch (direction) { - case "filling": - symbol = "⬆️"; - fill = "blue"; - break; - case "draining": - symbol = "⬇️"; - fill = "orange"; - break; - case "stable": - symbol = "⏸️"; - fill = "green"; - break; - default: - symbol = "❔"; - fill = "grey"; - break; + const pickVariant = (type, prefer = ['measured', 'predicted'], position = 'atEquipment', unit) => { + for (const variant of prefer) { + const chain = ps.measurements.type(type).variant(variant).position(position); + const value = unit ? chain.getCurrentValue(unit) : chain.getCurrentValue(); + if (value != null) return { value, variant }; } + return { value: null, variant: null }; + }; - // --- Status text ---------------------------------------------------------- - const textParts = [ - `${symbol} ${percentFull.toFixed(1)}%`, - `V=${currentVolume.toFixed(2)} / ${maxVolBeforeOverflow.toFixed(2)} m³`, - `net=${netFlowM3h.toFixed(1)} m³/h`, - `t≈${timeRemaining}` - ]; + const vol = pickVariant('volume', ['measured', 'predicted'], 'atEquipment', 'm3'); + const volPercent = pickVariant('volumePercent', ['measured','predicted'], 'atEquipment'); // already unitless + const level = pickVariant('level', ['measured', 'predicted'], 'atEquipment', 'm'); + const netFlow = pickVariant('netFlowRate', ['measured', 'predicted'], 'atEquipment', 'm3/s'); - return { - fill, - shape: "dot", - text: textParts.join(" | ") - }; - } catch (error) { - this.node.error("Error in updateNodeStatus: " + error.message); - return { fill: "red", shape: "ring", text: "Status Error" }; + const maxVolBeforeOverflow = ps.basin?.maxVolOverflow ?? ps.basin?.maxVol ?? 0; + const currentVolume = vol.value ?? 0; + const currentvolPercent = volPercent.value ?? 0; + const netFlowM3h = (netFlow.value ?? 0) * 3600; + + const direction = ps.state?.direction ?? 'unknown'; + const secondsRemaining = ps.state?.seconds ?? null; + const timeRemainingMinutes = secondsRemaining != null ? Math.round(secondsRemaining / 60) : null; + + const badgePieces = []; + badgePieces.push(`${currentvolPercent.toFixed(1)}% `); + badgePieces.push( + `V=${currentVolume.toFixed(2)} / ${maxVolBeforeOverflow.toFixed(2)} m³ (${'n/a'})` + ); + badgePieces.push(`net=${netFlowM3h.toFixed(1)} m³/h (${'n/a'})`); + if (timeRemainingMinutes != null) { + badgePieces.push(`t≈${timeRemainingMinutes} min)`); } + + const { symbol, fill } = (() => { + switch (direction) { + case 'filling': return { symbol: '⬆️', fill: 'blue' }; + case 'draining': return { symbol: '⬇️', fill: 'orange' }; + case 'steady': return { symbol: '⏸️', fill: 'green' }; + default: return { symbol: '❔', fill: 'grey' }; + } + })(); + + badgePieces[0] = `${symbol} ${badgePieces[0]}`; + + return { + fill, + shape: 'dot', + text: badgePieces.join(' | ') + }; } + // any time based functions here _startTickLoop() { setTimeout(() => { diff --git a/src/specificClass.js b/src/specificClass.js index d59a3d6..d9ee587 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -1,6 +1,6 @@ const EventEmitter = require('events'); const {logger,configUtils,configManager,childRegistrationUtils,MeasurementContainer,coolprop,interpolation} = require('generalFunctions'); -class PumpingStationV2 { +class PumpingStation { constructor(config = {}) { this.emitter = new EventEmitter(); this.configManager = new configManager(); @@ -18,6 +18,8 @@ class PumpingStationV2 { this.machines = {}; this.stations = {}; + + //variants in determining what gets priority this.flowVariants = ['measured', 'predicted']; this.levelVariants = ['measured', 'predicted']; @@ -61,6 +63,8 @@ class PumpingStationV2 { this._updatePredictedVolume(snapshot); const netFlow = this._selectBestNetFlow(snapshot); + //write netflow in measurment container + //this.measurements() const remaining = this._computeRemainingTime(snapshot, netFlow); this.state = { @@ -160,8 +164,8 @@ class PumpingStationV2 { .value(volume, context.timestamp, 'm3'); this.measurements - .type('volume') - .variant('percent') + .type('volumePercent') + .variant('measured') .position('atequipment') .value(percent, context.timestamp, '%'); } @@ -416,6 +420,22 @@ class PumpingStationV2 { .value(nextLevel, writeTimestamp, 'm') .unit('m'); + //calc how full this is in procen using minVol vs maxVolOverflow + const percent = this.interpolate.interpolate_lin_single_point( + currentVolume, + this.basin.minVol, + this.basin.maxVolOverflow, + 0, + 100 + ); + + //store this percent value + this.measurements + .type('volumePercent') + .variant('predicted') + .position('atequipment') + .value(percent); + this._predictedFlowState.lastTimestamp = writeTimestamp; } @@ -465,7 +485,7 @@ class PumpingStationV2 { .type('volume') .variant('predicted') .position('atEquipment') - .value(maxVol) + .value(maxVolOverflow) .unit('m3'); this.logger.debug( @@ -501,12 +521,12 @@ class PumpingStationV2 { } } -module.exports = PumpingStationV2; +module.exports = PumpingStation; /* ------------------------------------------------------------------------- */ /* Example usage */ /* ------------------------------------------------------------------------- */ - +/* if (require.main === module) { const Measurement = require('../../measurement/src/specificClass'); const RotatingMachine = require('../../rotatingMachine/src/specificClass'); @@ -525,10 +545,10 @@ if (require.main === module) { }, basin: { volume: 43.75, - height: 3.5, - heightInlet: 0.3, + height: 10, + heightInlet: 3, heightOutlet: 0.2, - heightOverflow: 3.0 + heightOverflow: 3.2 }, hydraulics: { refHeight: 'NAP', @@ -630,7 +650,7 @@ if (require.main === module) { } (async function demo() { - const station = new PumpingStationV2(createPumpingStationConfig('PumpingStationDemo')); + const station = new PumpingStation(createPumpingStationConfig('PumpingStationDemo')); const pump1 = new RotatingMachine(createMachineConfig('Pump1','downstream'), createMachineStateConfig()); const pump2 = new RotatingMachine(createMachineConfig('Pump2','upstream'), createMachineStateConfig()); @@ -638,20 +658,19 @@ if (require.main === module) { const inflowSensor = new Measurement(createFlowMeasurementConfig('InfluentFlow', 'in')); const outflowSensor = new Measurement(createFlowMeasurementConfig('PumpDischargeFlow', 'out')); - /* - station.childRegistrationUtils.registerChild(levelSensor, levelSensor.config.functionality.softwareType); - station.childRegistrationUtils.registerChild(inflowSensor, inflowSensor.config.functionality.softwareType); - station.childRegistrationUtils.registerChild(outflowSensor, outflowSensor.config.functionality.softwareType); - */ + //station.childRegistrationUtils.registerChild(levelSensor, levelSensor.config.functionality.softwareType); + //station.childRegistrationUtils.registerChild(inflowSensor, inflowSensor.config.functionality.softwareType); + //station.childRegistrationUtils.registerChild(outflowSensor, outflowSensor.config.functionality.softwareType); + station.childRegistrationUtils.registerChild(pump1, 'machine'); station.childRegistrationUtils.registerChild(pump2, 'machine'); // Seed initial measurements - /* - seedSample(levelSensor, 'level', 1.8, 'm'); - seedSample(inflowSensor, 'flow', 0.35, 'm3/s'); - seedSample(outflowSensor, 'flow', 0.20, 'm3/s'); -*/ + + //seedSample(levelSensor, 'level', 1.8, 'm'); + //seedSample(inflowSensor, 'flow', 0.35, 'm3/s'); + //seedSample(outflowSensor, 'flow', 0.20, 'm3/s'); + setInterval( () => station.tick(), 1000); @@ -672,3 +691,4 @@ if (require.main === module) { console.error('Demo failed:', err); }); } + //*/