Compare commits
4 Commits
dev-Pieter
...
2fb73e6713
| Author | SHA1 | Date | |
|---|---|---|---|
| 2fb73e6713 | |||
|
|
de0b947c56 | ||
|
|
d99561fa80 | ||
|
|
44033da15d |
@@ -66,15 +66,6 @@
|
|||||||
"units": ["g/m³", "mol/m³"]
|
"units": ["g/m³", "mol/m³"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Quantity (TSS)",
|
|
||||||
"models": [
|
|
||||||
{
|
|
||||||
"name": "VegaSolidsProbe",
|
|
||||||
"units": ["g/m³"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -412,14 +412,6 @@
|
|||||||
],
|
],
|
||||||
"description": "The frequency at which calculations are performed."
|
"description": "The frequency at which calculations are performed."
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"flowNumber": {
|
|
||||||
"default": 1,
|
|
||||||
"rules": {
|
|
||||||
"type": "number",
|
|
||||||
"nullable": false,
|
|
||||||
"description": "Defines which effluent flow of the parent node to handle."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5,18 +5,14 @@ class ChildRegistrationUtils {
|
|||||||
this.registeredChildren = new Map();
|
this.registeredChildren = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
async registerChild(child, positionVsParent) {
|
async registerChild(child, positionVsParent, distance) {
|
||||||
const { softwareType } = child.config.functionality;
|
const { softwareType } = child.config.functionality;
|
||||||
const { name, id } = child.config.general;
|
const { name, id } = child.config.general;
|
||||||
|
|
||||||
this.logger.debug(`Registering child: ${name} (${id}) as ${softwareType} at ${positionVsParent}`);
|
this.logger.debug(`Registering child: ${name} (${id}) as ${softwareType} at ${positionVsParent}`);
|
||||||
|
|
||||||
// Enhanced child setup - multiple parents
|
// Enhanced child setup
|
||||||
if (Array.isArray(child.parent)) {
|
child.parent = this.mainClass;
|
||||||
child.parent.push(this.mainClass);
|
|
||||||
} else {
|
|
||||||
child.parent = [this.mainClass];
|
|
||||||
}
|
|
||||||
child.positionVsParent = positionVsParent;
|
child.positionVsParent = positionVsParent;
|
||||||
|
|
||||||
// Enhanced measurement container with rich context
|
// Enhanced measurement container with rich context
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
const convertModule = require('../convert/index');
|
const convertModule = require('../convert/index');
|
||||||
|
|
||||||
class Measurement {
|
class Measurement {
|
||||||
constructor(type, variant, position, windowSize) {
|
constructor(type, variant, position, windowSize, distance = null) {
|
||||||
this.type = type; // e.g. 'pressure', 'flow', etc.
|
this.type = type; // e.g. 'pressure', 'flow', etc.
|
||||||
this.variant = variant; // e.g. 'predicted' or 'measured', etc..
|
this.variant = variant; // e.g. 'predicted' or 'measured', etc..
|
||||||
this.position = position; // Downstream or upstream of parent object
|
this.position = position; // Downstream or upstream of parent object
|
||||||
this.windowSize = windowSize; // Rolling window size
|
this.windowSize = windowSize; // Rolling window size
|
||||||
|
this.distance = distance; // Distance from parent, if applicable
|
||||||
|
|
||||||
// Place all data inside an array
|
// Place all data inside an array
|
||||||
this.values = []; // Array to store all values
|
this.values = []; // Array to store all values
|
||||||
@@ -36,13 +37,12 @@ class Measurement {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(value, timestamp = Date.now()) {
|
setDistance(distance) {
|
||||||
/*
|
this.distance = distance;
|
||||||
if (value === undefined || value === null) {
|
return this;
|
||||||
value = null ;
|
|
||||||
//throw new Error('Value cannot be null or undefined');
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
setValue(value, timestamp = Date.now()) {
|
||||||
|
|
||||||
//shift the oldest value
|
//shift the oldest value
|
||||||
if(this.values.length >= this.windowSize){
|
if(this.values.length >= this.windowSize){
|
||||||
@@ -168,7 +168,8 @@ class Measurement {
|
|||||||
this.type,
|
this.type,
|
||||||
this.variant,
|
this.variant,
|
||||||
this.position,
|
this.position,
|
||||||
this.windowSize
|
this.windowSize,
|
||||||
|
this.distance
|
||||||
);
|
);
|
||||||
|
|
||||||
// Copy values and timestamps
|
// Copy values and timestamps
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ class MeasurementBuilder {
|
|||||||
this.type = null;
|
this.type = null;
|
||||||
this.variant = null;
|
this.variant = null;
|
||||||
this.position = null;
|
this.position = null;
|
||||||
|
this.distance = null;
|
||||||
this.windowSize = 10; // Default window size
|
this.windowSize = 10; // Default window size
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,6 +33,11 @@ class MeasurementBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setDistance(distance) {
|
||||||
|
this.distance = distance;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
// Validate required fields
|
// Validate required fields
|
||||||
if (!this.type) {
|
if (!this.type) {
|
||||||
@@ -43,12 +49,14 @@ class MeasurementBuilder {
|
|||||||
if (!this.position) {
|
if (!this.position) {
|
||||||
throw new Error('Measurement position is required');
|
throw new Error('Measurement position is required');
|
||||||
}
|
}
|
||||||
|
// distance is not a requirement as it can be derived from position
|
||||||
|
|
||||||
return new Measurement(
|
return new Measurement(
|
||||||
this.type,
|
this.type,
|
||||||
this.variant,
|
this.variant,
|
||||||
this.position,
|
this.position,
|
||||||
this.windowSize
|
this.windowSize,
|
||||||
|
this.distance
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const EventEmitter = require('events');
|
|||||||
const convertModule = require('../convert/index');
|
const convertModule = require('../convert/index');
|
||||||
|
|
||||||
class MeasurementContainer {
|
class MeasurementContainer {
|
||||||
constructor(options = {}) {
|
constructor(options = {},logger) {
|
||||||
this.emitter = new EventEmitter();
|
this.emitter = new EventEmitter();
|
||||||
this.measurements = {};
|
this.measurements = {};
|
||||||
this.windowSize = options.windowSize || 10; // Default window size
|
this.windowSize = options.windowSize || 10; // Default window size
|
||||||
@@ -12,6 +12,7 @@ class MeasurementContainer {
|
|||||||
this._currentType = null;
|
this._currentType = null;
|
||||||
this._currentVariant = null;
|
this._currentVariant = null;
|
||||||
this._currentPosition = null;
|
this._currentPosition = null;
|
||||||
|
this._currentDistance = null;
|
||||||
this._unit = null;
|
this._unit = null;
|
||||||
|
|
||||||
// Default units for each measurement type
|
// Default units for each measurement type
|
||||||
@@ -93,12 +94,18 @@ class MeasurementContainer {
|
|||||||
throw new Error('Variant must be specified before position');
|
throw new Error('Variant must be specified before position');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn string positions into numeric values
|
this._currentPosition = positionValue;
|
||||||
if (typeof positionValue == "string") {
|
|
||||||
positionValue = this._convertPositionStr2Num(positionValue);
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._currentPosition = positionValue;
|
distance(distance) {
|
||||||
|
// If distance is not provided, derive from positionVsParent
|
||||||
|
if(distance === null) {
|
||||||
|
distance = this._convertPositionStr2Num(this._currentPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._currentDistance = distance;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -145,17 +152,18 @@ class MeasurementContainer {
|
|||||||
sourceUnit: sourceUnit,
|
sourceUnit: sourceUnit,
|
||||||
timestamp,
|
timestamp,
|
||||||
position: this._currentPosition,
|
position: this._currentPosition,
|
||||||
|
distance: this._currentDistance,
|
||||||
variant: this._currentVariant,
|
variant: this._currentVariant,
|
||||||
type: this._currentType,
|
type: this._currentType,
|
||||||
// NEW: Enhanced context
|
// NEW: Enhanced context
|
||||||
childId: this.childId,
|
childId: this.childId,
|
||||||
childName: this.childName,
|
childName: this.childName,
|
||||||
parentRef: this.parentRef
|
parentRef: this.parentRef,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Emit the exact event your parent expects
|
// Emit the exact event your parent expects
|
||||||
this.emitter.emit(`${this._currentType}.${this._currentVariant}.${this._currentPosition}`, eventData);
|
this.emitter.emit(`${this._currentType}.${this._currentVariant}.${this._currentPosition}`, eventData);
|
||||||
//console.log(`Emitted event: ${this._currentType}.${this._currentVariant}.${this._currentPosition}`, eventData);
|
console.log(`Emitted event: ${this._currentType}.${this._currentVariant}.${this._currentPosition}`);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -243,22 +251,12 @@ class MeasurementContainer {
|
|||||||
|
|
||||||
// Difference calculations between positions
|
// Difference calculations between positions
|
||||||
difference(requestedUnit = null) {
|
difference(requestedUnit = null) {
|
||||||
|
|
||||||
if (!this._currentType || !this._currentVariant) {
|
if (!this._currentType || !this._currentVariant) {
|
||||||
throw new Error('Type and variant must be specified for difference calculation');
|
throw new Error('Type and variant must be specified for difference calculation');
|
||||||
}
|
}
|
||||||
|
const upstream = this.measurements?.[this._currentType]?.[this._currentVariant]?.['upstream'] || null;
|
||||||
const savedPosition = this._currentPosition;
|
const downstream = this.measurements?.[this._currentType]?.[this._currentVariant]?.['downstream'] || null;
|
||||||
|
|
||||||
// Get upstream and downstream measurements
|
|
||||||
const positions = this.getPositions();
|
|
||||||
|
|
||||||
this._currentPosition = Math.min(...positions);
|
|
||||||
const upstream = this.get();
|
|
||||||
|
|
||||||
this._currentPosition = Math.max(...positions);
|
|
||||||
const downstream = this.get();
|
|
||||||
|
|
||||||
this._currentPosition = savedPosition;
|
|
||||||
|
|
||||||
if (!upstream || !downstream || upstream.values.length === 0 || downstream.values.length === 0) {
|
if (!upstream || !downstream || upstream.values.length === 0 || downstream.values.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
@@ -309,6 +307,7 @@ class MeasurementContainer {
|
|||||||
.setVariant(this._currentVariant)
|
.setVariant(this._currentVariant)
|
||||||
.setPosition(this._currentPosition)
|
.setPosition(this._currentPosition)
|
||||||
.setWindowSize(this.windowSize)
|
.setWindowSize(this.windowSize)
|
||||||
|
.setDistance(this._currentDistance)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +327,7 @@ class MeasurementContainer {
|
|||||||
Object.keys(this.measurements[this._currentType]) : [];
|
Object.keys(this.measurements[this._currentType]) : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
getPositions(asNumber = false) {
|
getPositions() {
|
||||||
if (!this._currentType || !this._currentVariant) {
|
if (!this._currentType || !this._currentVariant) {
|
||||||
throw new Error('Type and variant must be specified before listing positions');
|
throw new Error('Type and variant must be specified before listing positions');
|
||||||
}
|
}
|
||||||
@@ -338,13 +337,9 @@ class MeasurementContainer {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asNumber) {
|
|
||||||
return Object.keys(this.measurements[this._currentType][this._currentVariant]);
|
return Object.keys(this.measurements[this._currentType][this._currentVariant]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.keys(this.measurements[this._currentType][this._currentVariant]).map(this._convertPositionNum2Str);
|
|
||||||
}
|
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this.measurements = {};
|
this.measurements = {};
|
||||||
this._currentType = null;
|
this._currentType = null;
|
||||||
@@ -435,18 +430,15 @@ class MeasurementContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_convertPositionNum2Str(positionValue) {
|
_convertPositionNum2Str(positionValue) {
|
||||||
if (positionValue === 0) {
|
switch (positionValue) {
|
||||||
|
case 0:
|
||||||
return "atEquipment";
|
return "atEquipment";
|
||||||
}
|
case (positionValue < 0):
|
||||||
if (positionValue < 0) {
|
|
||||||
return "upstream";
|
return "upstream";
|
||||||
}
|
case (positionValue > 0):
|
||||||
if (positionValue > 0) {
|
|
||||||
return "downstream";
|
return "downstream";
|
||||||
}
|
default:
|
||||||
|
console.log(`Invalid position provided: ${positionValue}`);
|
||||||
if (this.logger) {
|
|
||||||
this.logger.error(`Invalid position provided: ${positionValue}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,249 +7,325 @@ console.log('retrieving, and converting measurement data with automatic unit han
|
|||||||
// ====================================
|
// ====================================
|
||||||
// BASIC SETUP EXAMPLES
|
// BASIC SETUP EXAMPLES
|
||||||
// ====================================
|
// ====================================
|
||||||
console.log('--- Example 1: Basic Setup & Event Subscription ---');
|
console.log('--- Example 1: Basic Setup & Distance ---');
|
||||||
|
|
||||||
// Create a basic container
|
// Create a basic container
|
||||||
const basicContainer = new MeasurementContainer({ windowSize: 20 });
|
const basicContainer = new MeasurementContainer({ windowSize: 20 });
|
||||||
|
|
||||||
// Subscribe to flow events to monitor changes
|
// Subscribe to events to monitor changes
|
||||||
basicContainer.emitter.on('flow.predicted.upstream', (data) => {
|
basicContainer.emitter.on('flow.predicted.upstream', (data) => {
|
||||||
console.log(`📡 Event: Flow predicted upstream update: ${data.value} at ${new Date(data.timestamp).toLocaleTimeString()}`);
|
console.log(`📡 Event: Flow predicted upstream = ${data.value} ${data.unit || ''} (distance=${data.distance ?? 'n/a'}m)`);
|
||||||
});
|
});
|
||||||
|
|
||||||
//show all flow values from variant measured
|
// Subscribe to all measured flow events using wildcard
|
||||||
basicContainer.emitter.on('flow.measured.*', (data) => {
|
basicContainer.emitter.on('flow.measured.*', (data) => {
|
||||||
console.log(`📡 Event---------- I DID IT: Flow measured ${data.position} update: ${data.value}`)
|
console.log(`📡 Event: Flow measured ${data.position} = ${data.value} ${data.unit || ''} (distance=${data.distance ?? 'n/a'}m)`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Basic value setting with chaining
|
// Basic value setting with distance
|
||||||
console.log('Setting basic pressure values...');
|
console.log('\nSetting pressure values with distances:');
|
||||||
basicContainer.type('pressure').variant('measured').position('upstream').value(100).unit('psi');
|
basicContainer
|
||||||
basicContainer.type('pressure').variant('measured').position('downstream').value(95).unit('psi');
|
.type('pressure')
|
||||||
basicContainer.type('pressure').variant('measured').position('downstream').value(80); // Additional value
|
.variant('measured')
|
||||||
|
.position('upstream')
|
||||||
|
.distance(1.5)
|
||||||
|
.value(100)
|
||||||
|
.unit('psi');
|
||||||
|
|
||||||
|
basicContainer
|
||||||
|
.type('pressure')
|
||||||
|
.variant('measured')
|
||||||
|
.position('downstream')
|
||||||
|
.distance(5.2)
|
||||||
|
.value(95)
|
||||||
|
.unit('psi');
|
||||||
|
|
||||||
|
// Distance persists - no need to set it again for same position
|
||||||
|
basicContainer
|
||||||
|
.type('pressure')
|
||||||
|
.variant('measured')
|
||||||
|
.position('downstream')
|
||||||
|
.value(90); // distance 5.2 is automatically reused
|
||||||
|
|
||||||
console.log('✅ Basic setup complete\n');
|
console.log('✅ Basic setup complete\n');
|
||||||
|
|
||||||
|
// Retrieve and display the distance
|
||||||
|
const upstreamPressure = basicContainer
|
||||||
|
.type('pressure')
|
||||||
|
.variant('measured')
|
||||||
|
.position('upstream')
|
||||||
|
.get();
|
||||||
|
|
||||||
|
console.log(`Retrieved upstream pressure: ${upstreamPressure.getCurrentValue()} ${upstreamPressure.unit}`);
|
||||||
|
console.log(`Distance from parent: ${upstreamPressure.distance ?? 'not set'} m\n`);
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// AUTO-CONVERSION SETUP EXAMPLES
|
// AUTO-CONVERSION SETUP
|
||||||
// ====================================
|
// ====================================
|
||||||
console.log('--- Example 2: Auto-Conversion Setup ---');
|
console.log('--- Example 2: Auto-Conversion Setup ---');
|
||||||
console.log('Setting up a container with automatic unit conversion...\n');
|
|
||||||
|
|
||||||
// Create container with auto-conversion enabled
|
|
||||||
const autoContainer = new MeasurementContainer({
|
const autoContainer = new MeasurementContainer({
|
||||||
autoConvert: true,
|
autoConvert: true,
|
||||||
windowSize: 50,
|
windowSize: 50,
|
||||||
defaultUnits: {
|
defaultUnits: {
|
||||||
pressure: 'bar', // Default pressure unit
|
pressure: 'bar',
|
||||||
flow: 'l/min', // Default flow unit
|
flow: 'l/min',
|
||||||
power: 'kW', // Default power unit
|
power: 'kW',
|
||||||
temperature: 'C' // Default temperature unit
|
temperature: 'C'
|
||||||
},
|
},
|
||||||
preferredUnits: {
|
preferredUnits: {
|
||||||
pressure: 'psi' // Override: store pressure in PSI instead of bar
|
pressure: 'psi'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Values are automatically converted to preferred units
|
// Values automatically convert to preferred units
|
||||||
console.log('Adding pressure data with auto-conversion:');
|
console.log('Adding pressure with auto-conversion:');
|
||||||
autoContainer.type('pressure').variant('measured').position('upstream')
|
autoContainer
|
||||||
|
.type('pressure')
|
||||||
|
.variant('measured')
|
||||||
|
.position('upstream')
|
||||||
|
.distance(0.5)
|
||||||
.value(1.5, Date.now(), 'bar'); // Input: 1.5 bar → Auto-stored as ~21.76 psi
|
.value(1.5, Date.now(), 'bar'); // Input: 1.5 bar → Auto-stored as ~21.76 psi
|
||||||
|
|
||||||
autoContainer.type('pressure').variant('measured').position('downstream')
|
const converted = autoContainer
|
||||||
.value(20, Date.now(), 'psi'); // Input: 20 psi → Stored as 20 psi (already in preferred unit)
|
.type('pressure')
|
||||||
|
.variant('measured')
|
||||||
|
.position('upstream')
|
||||||
|
.get();
|
||||||
|
|
||||||
// Check what was actually stored
|
console.log(`Stored as: ${converted.getCurrentValue()} ${converted.unit} (distance=${converted.distance}m)`);
|
||||||
const storedPressure = autoContainer.type('pressure').variant('measured').position('upstream').get();
|
console.log('✅ Auto-conversion complete\n');
|
||||||
console.log(` Stored upstream pressure: ${storedPressure.getCurrentValue()} ${storedPressure.unit}`);
|
|
||||||
console.log(' Auto-conversion setup complete\n');
|
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// UNIT CONVERSION EXAMPLES
|
// UNIT CONVERSION ON RETRIEVAL
|
||||||
// ====================================
|
// ====================================
|
||||||
console.log('--- Example 3: Unit Conversion on Retrieval ---');
|
console.log('--- Example 3: Unit Conversion on Retrieval ---');
|
||||||
console.log('Getting values in different units without changing stored data...\n');
|
|
||||||
|
|
||||||
// Add flow data in different units
|
autoContainer
|
||||||
autoContainer.type('flow').variant('predicted').position('upstream')
|
.type('flow')
|
||||||
.value(100, Date.now(), 'l/min'); // Stored in l/min (default)
|
.variant('predicted')
|
||||||
|
.position('upstream')
|
||||||
|
.distance(2.4)
|
||||||
|
.value(100, Date.now(), 'l/min');
|
||||||
|
|
||||||
autoContainer.type('flow').variant('predicted').position('downstream')
|
const flowMeasurement = autoContainer
|
||||||
.value(6, Date.now(), 'm3/h'); // Auto-converted from m3/h to l/min
|
.type('flow')
|
||||||
|
.variant('predicted')
|
||||||
|
.position('upstream')
|
||||||
|
.get();
|
||||||
|
|
||||||
// Retrieve the same data in different units
|
console.log(`Flow in l/min: ${flowMeasurement.getCurrentValue('l/min')}`);
|
||||||
const flowLPM = autoContainer.type('flow').variant('predicted').position('upstream').getCurrentValue('l/min');
|
console.log(`Flow in m³/h: ${flowMeasurement.getCurrentValue('m3/h').toFixed(2)}`);
|
||||||
const flowM3H = autoContainer.type('flow').variant('predicted').position('upstream').getCurrentValue('m3/h');
|
console.log(`Flow in gal/min: ${flowMeasurement.getCurrentValue('gal/min').toFixed(2)}`);
|
||||||
const flowGPM = autoContainer.type('flow').variant('predicted').position('upstream').getCurrentValue('gal/min');
|
console.log(`Distance: ${flowMeasurement.distance}m\n`);
|
||||||
|
|
||||||
console.log(`Flow in l/min: ${flowLPM}`);
|
|
||||||
console.log(`Flow in m³/h: ${flowM3H.toFixed(2)}`);
|
|
||||||
console.log(`Flow in gal/min: ${flowGPM.toFixed(2)}`);
|
|
||||||
console.log('Unit conversion examples complete\n');
|
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// SMART UNIT SELECTION
|
// SMART UNIT SELECTION
|
||||||
// ====================================
|
// ====================================
|
||||||
console.log('--- Example 4: Smart Unit Selection ---');
|
console.log('--- Example 4: Smart Unit Selection ---');
|
||||||
console.log('Automatically finding the best unit for readability...\n');
|
|
||||||
|
|
||||||
// Add a very small pressure value
|
autoContainer
|
||||||
autoContainer.type('pressure').variant('test').position('sensor')
|
.type('pressure')
|
||||||
|
.variant('test')
|
||||||
|
.position('sensor')
|
||||||
|
.distance(0.2)
|
||||||
.value(0.001, Date.now(), 'bar');
|
.value(0.001, Date.now(), 'bar');
|
||||||
|
|
||||||
// Get the best unit for this small value
|
const bestUnit = autoContainer
|
||||||
const bestUnit = autoContainer.type('pressure').variant('test').position('sensor').getBestUnit();
|
.type('pressure')
|
||||||
|
.variant('test')
|
||||||
|
.position('sensor')
|
||||||
|
.getBestUnit();
|
||||||
|
|
||||||
if (bestUnit) {
|
if (bestUnit) {
|
||||||
console.log(`Best unit representation: ${bestUnit.val} ${bestUnit.unit}`);
|
console.log(`Best unit: ${bestUnit.val.toFixed(2)} ${bestUnit.unit}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all available units for pressure
|
|
||||||
const availableUnits = autoContainer.getAvailableUnits('pressure');
|
const availableUnits = autoContainer.getAvailableUnits('pressure');
|
||||||
console.log(`Available pressure units: ${availableUnits.slice(0, 8).join(', ')}... (${availableUnits.length} total)`);
|
console.log(`Available units: ${availableUnits.slice(0, 5).join(', ')}...\n`);
|
||||||
console.log('Smart unit selection complete\n');
|
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// BASIC RETRIEVAL AND CALCULATIONS
|
// BASIC RETRIEVAL
|
||||||
// ====================================
|
// ====================================
|
||||||
console.log('--- Example 5: Basic Value Retrieval ---');
|
console.log('--- Example 5: Basic Value Retrieval ---');
|
||||||
console.log('Getting individual values and their units...\n');
|
|
||||||
|
|
||||||
// Using basic container for clear examples
|
const upstreamVal = basicContainer
|
||||||
const upstreamValue = basicContainer.type('pressure').variant('measured').position('upstream').getCurrentValue();
|
.type('pressure')
|
||||||
const upstreamUnit = basicContainer.type('pressure').variant('measured').position('upstream').get().unit;
|
.variant('measured')
|
||||||
console.log(`Upstream pressure: ${upstreamValue} ${upstreamUnit}`);
|
.position('upstream')
|
||||||
|
.getCurrentValue();
|
||||||
|
|
||||||
const downstreamValue = basicContainer.type('pressure').variant('measured').position('downstream').getCurrentValue();
|
const upstreamData = basicContainer
|
||||||
const downstreamUnit = basicContainer.type('pressure').variant('measured').position('downstream').get().unit;
|
.type('pressure')
|
||||||
console.log(`Downstream pressure: ${downstreamValue} ${downstreamUnit}`);
|
.variant('measured')
|
||||||
console.log('Basic retrieval complete\n');
|
.position('upstream')
|
||||||
|
.get();
|
||||||
|
|
||||||
|
console.log(`Upstream: ${upstreamVal} ${upstreamData.unit} at ${upstreamData.distance}m`);
|
||||||
|
|
||||||
|
const downstreamVal = basicContainer
|
||||||
|
.type('pressure')
|
||||||
|
.variant('measured')
|
||||||
|
.position('downstream')
|
||||||
|
.getCurrentValue();
|
||||||
|
|
||||||
|
const downstreamData = basicContainer
|
||||||
|
.type('pressure')
|
||||||
|
.variant('measured')
|
||||||
|
.position('downstream')
|
||||||
|
.get();
|
||||||
|
|
||||||
|
console.log(`Downstream: ${downstreamVal} ${downstreamData.unit} at ${downstreamData.distance}m\n`);
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// CALCULATIONS AND STATISTICS
|
// CALCULATIONS & STATISTICS
|
||||||
// ====================================
|
// ====================================
|
||||||
console.log('--- Example 6: Calculations & Statistics ---');
|
console.log('--- Example 6: Calculations & Statistics ---');
|
||||||
console.log('Using built-in calculation methods...\n');
|
|
||||||
|
|
||||||
// Add flow data for calculations
|
basicContainer
|
||||||
basicContainer.type('flow').variant('predicted').position('upstream').value(200).unit('gpm');
|
.type('flow')
|
||||||
basicContainer.type('flow').variant('predicted').position('downstream').value(195).unit('gpm');
|
.variant('predicted')
|
||||||
|
.position('upstream')
|
||||||
|
.distance(3.0)
|
||||||
|
.value(200)
|
||||||
|
.unit('gpm');
|
||||||
|
|
||||||
const flowAvg = basicContainer.type('flow').variant('predicted').position('upstream').getAverage();
|
basicContainer
|
||||||
console.log(`Average upstream flow: ${flowAvg} gpm`);
|
.type('flow')
|
||||||
|
.variant('predicted')
|
||||||
|
.position('downstream')
|
||||||
|
.distance(8.5)
|
||||||
|
.value(195)
|
||||||
|
.unit('gpm');
|
||||||
|
|
||||||
// Calculate pressure difference between upstream and downstream
|
const flowAvg = basicContainer
|
||||||
const pressureDiff = basicContainer.type('pressure').variant('measured').difference();
|
.type('flow')
|
||||||
console.log(`Pressure difference: ${pressureDiff.value} ${pressureDiff.unit}`);
|
.variant('predicted')
|
||||||
console.log('Calculations complete\n');
|
.position('upstream')
|
||||||
|
.getAverage();
|
||||||
|
|
||||||
|
console.log(`Average upstream flow: ${flowAvg.toFixed(1)} gpm`);
|
||||||
|
|
||||||
|
const pressureDiff = basicContainer
|
||||||
|
.type('pressure')
|
||||||
|
.variant('measured')
|
||||||
|
.difference();
|
||||||
|
|
||||||
|
console.log(`Pressure difference: ${pressureDiff.value} ${pressureDiff.unit}\n`);
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// ADVANCED STATISTICS
|
// ADVANCED STATISTICS & HISTORY
|
||||||
// ====================================
|
// ====================================
|
||||||
console.log('--- Example 7: Advanced Statistics & History ---');
|
console.log('--- Example 7: Advanced Statistics & History ---');
|
||||||
console.log('Adding multiple values and getting comprehensive statistics...\n');
|
|
||||||
|
|
||||||
// Add several flow measurements to build history
|
basicContainer
|
||||||
basicContainer.type('flow').variant('measured').position('upstream')
|
.type('flow')
|
||||||
.value(210).value(215).value(205).value(220).value(200).unit('m3/h');
|
.variant('measured')
|
||||||
basicContainer.type('flow').variant('measured').position('downstream')
|
.position('upstream')
|
||||||
.value(190).value(195).value(185).value(200).value(180).unit('m3/h');
|
.distance(3.0)
|
||||||
|
.value(210)
|
||||||
|
.value(215)
|
||||||
|
.value(205)
|
||||||
|
.value(220)
|
||||||
|
.value(200)
|
||||||
|
.unit('m3/h');
|
||||||
|
|
||||||
|
const stats = basicContainer
|
||||||
|
.type('flow')
|
||||||
|
.variant('measured')
|
||||||
|
.position('upstream');
|
||||||
|
|
||||||
|
const statsData = stats.get();
|
||||||
|
|
||||||
// Get comprehensive statistics
|
|
||||||
const measurement = basicContainer.type('flow').variant('measured').position('upstream');
|
|
||||||
console.log('Flow Statistics:');
|
console.log('Flow Statistics:');
|
||||||
console.log(`- Current value: ${measurement.getCurrentValue()} ${measurement.get().unit}`);
|
console.log(` Current: ${stats.getCurrentValue()} ${statsData.unit}`);
|
||||||
console.log(`- Average: ${measurement.getAverage().toFixed(1)} ${measurement.get().unit}`);
|
console.log(` Average: ${stats.getAverage().toFixed(1)} ${statsData.unit}`);
|
||||||
console.log(`- Minimum: ${measurement.getMin()} ${measurement.get().unit}`);
|
console.log(` Min: ${stats.getMin()} ${statsData.unit}`);
|
||||||
console.log(`- Maximum: ${measurement.getMax()} ${measurement.get().unit}`);
|
console.log(` Max: ${stats.getMax()} ${statsData.unit}`);
|
||||||
|
console.log(` Distance: ${statsData.distance}m`);
|
||||||
|
|
||||||
// Show all values with timestamps
|
const allValues = stats.getAllValues();
|
||||||
const allValues = measurement.getAllValues();
|
console.log(` Samples: ${allValues.values.length}`);
|
||||||
console.log(`- Total samples: ${allValues.values.length}`);
|
console.log(` History: [${allValues.values.join(', ')}]\n`);
|
||||||
console.log(`- Value history: [${allValues.values.join(', ')}]`);
|
|
||||||
console.log('Advanced statistics complete\n');
|
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// DYNAMIC UNIT MANAGEMENT
|
// DYNAMIC UNIT MANAGEMENT
|
||||||
// ====================================
|
// ====================================
|
||||||
console.log('--- Example 8: Dynamic Unit Management ---');
|
console.log('--- Example 8: Dynamic Unit Management ---');
|
||||||
console.log('Changing preferred units at runtime...\n');
|
|
||||||
|
|
||||||
// Change preferred unit for flow measurements
|
|
||||||
autoContainer.setPreferredUnit('flow', 'm3/h');
|
autoContainer.setPreferredUnit('flow', 'm3/h');
|
||||||
console.log('Changed preferred flow unit to m³/h');
|
console.log('Changed preferred flow unit to m³/h');
|
||||||
|
|
||||||
// Add new flow data - will auto-convert to new preferred unit
|
autoContainer
|
||||||
autoContainer.type('flow').variant('realtime').position('inlet')
|
.type('flow')
|
||||||
.value(150, Date.now(), 'l/min'); // Input in l/min, stored as m³/h
|
.variant('realtime')
|
||||||
|
.position('inlet')
|
||||||
|
.distance(1.2)
|
||||||
|
.value(150, Date.now(), 'l/min');
|
||||||
|
|
||||||
const realtimeFlow = autoContainer.type('flow').variant('realtime').position('inlet');
|
const realtimeFlow = autoContainer
|
||||||
console.log(`Stored as: ${realtimeFlow.getCurrentValue()} ${realtimeFlow.get().unit}`);
|
.type('flow')
|
||||||
console.log(`Original unit: ${realtimeFlow.getCurrentValue('l/min')} l/min`);
|
.variant('realtime')
|
||||||
console.log('Dynamic unit management complete\n');
|
.position('inlet')
|
||||||
|
.get();
|
||||||
|
|
||||||
|
console.log(`Stored as: ${realtimeFlow.getCurrentValue()} ${realtimeFlow.unit}`);
|
||||||
|
console.log(`Original: ${realtimeFlow.getCurrentValue('l/min').toFixed(1)} l/min`);
|
||||||
|
console.log(`Distance: ${realtimeFlow.distance}m\n`);
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// DATA EXPLORATION
|
// DATA EXPLORATION
|
||||||
// ====================================
|
// ====================================
|
||||||
console.log('--- Example 9: Data Exploration ---');
|
console.log('--- Example 9: Data Exploration ---');
|
||||||
console.log('Discovering what data is available in the container...\n');
|
|
||||||
|
|
||||||
console.log('Available measurement types:', basicContainer.getTypes());
|
console.log('Available types:', basicContainer.getTypes());
|
||||||
console.log('Pressure variants:', basicContainer.type('pressure').getVariants());
|
console.log('Pressure variants:', basicContainer.type('pressure').getVariants());
|
||||||
console.log('Measured pressure positions:', basicContainer.type('pressure').variant('measured').getPositions());
|
console.log('Measured pressure positions:', basicContainer.type('pressure').variant('measured').getPositions());
|
||||||
|
|
||||||
// Show data structure overview
|
console.log('\nData Structure:');
|
||||||
console.log('\nData Structure Overview:');
|
|
||||||
basicContainer.getTypes().forEach(type => {
|
basicContainer.getTypes().forEach(type => {
|
||||||
console.log(`${type.toUpperCase()}:`);
|
|
||||||
const variants = basicContainer.type(type).getVariants();
|
const variants = basicContainer.type(type).getVariants();
|
||||||
|
if (variants.length > 0) {
|
||||||
|
console.log(`${type.toUpperCase()}:`);
|
||||||
variants.forEach(variant => {
|
variants.forEach(variant => {
|
||||||
const positions = basicContainer.type(type).variant(variant).getPositions();
|
const positions = basicContainer.type(type).variant(variant).getPositions();
|
||||||
positions.forEach(position => {
|
positions.forEach(position => {
|
||||||
const measurement = basicContainer.type(type).variant(variant).position(position).get();
|
const m = basicContainer.type(type).variant(variant).position(position).get();
|
||||||
if (measurement && measurement.values.length > 0) {
|
if (m && m.values.length > 0) {
|
||||||
console.log(` └── ${variant}.${position}: ${measurement.values.length} values (${measurement.unit || 'no unit'})`);
|
console.log(` └─ ${variant}.${position}: ${m.values.length} values, ${m.unit || 'no unit'}, dist=${m.distance ?? 'n/a'}m`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
console.log('Data exploration complete\n');
|
|
||||||
|
console.log('\n✅ All examples complete!\n');
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// BEST PRACTICES SUMMARY
|
// BEST PRACTICES
|
||||||
// ====================================
|
// ====================================
|
||||||
console.log('--- Best Practices Summary ---');
|
console.log('--- Best Practices Summary ---\n');
|
||||||
console.log('BEST PRACTICES FOR NEW USERS:\n');
|
|
||||||
|
|
||||||
console.log('1. SETUP:');
|
console.log('SETUP:');
|
||||||
console.log(' • Enable auto-conversion for consistent units');
|
console.log(' • Enable autoConvert for consistent units');
|
||||||
console.log(' • Define default units for your measurement types');
|
console.log(' • Define defaultUnits for your measurement types');
|
||||||
console.log(' • Set appropriate window size for your data needs\n');
|
console.log(' • Set windowSize based on your data retention needs\n');
|
||||||
|
|
||||||
console.log('2. STORING DATA:');
|
console.log('STORING DATA:');
|
||||||
console.log(' • Always use the full chain: type().variant().position().value()');
|
console.log(' • Chain methods: type().variant().position().distance().value()');
|
||||||
console.log(' • Specify source unit when adding values: .value(100, timestamp, "psi")');
|
console.log(' • Set distance once - it persists for that position');
|
||||||
console.log(' • Set units immediately after first value: .value(100).unit("psi")\n');
|
console.log(' • Specify source unit: .value(100, timestamp, "psi")');
|
||||||
|
console.log(' • Set unit immediately: .value(100).unit("psi")\n');
|
||||||
|
|
||||||
console.log('3. RETRIEVING DATA:');
|
console.log('RETRIEVING DATA:');
|
||||||
console.log(' • Use .getCurrentValue("unit") to get values in specific units');
|
console.log(' • Use .getCurrentValue("unit") for specific units');
|
||||||
console.log(' • Use .getBestUnit() for automatic unit selection');
|
console.log(' • Use .getBestUnit() for automatic selection');
|
||||||
console.log(' • Use .difference() for automatic upstream/downstream calculations\n');
|
console.log(' • Use .difference() for upstream/downstream deltas');
|
||||||
|
console.log(' • Access .get().distance for physical positioning\n');
|
||||||
|
|
||||||
console.log('4. MONITORING:');
|
console.log('MONITORING:');
|
||||||
console.log(' • Subscribe to events for real-time updates');
|
console.log(' • Subscribe: .emitter.on("type.variant.position", callback)');
|
||||||
console.log(' • Use .emitter.on("type.variant.position", callback)');
|
console.log(' • Event data includes: value, unit, timestamp, distance');
|
||||||
console.log(' • Explore available data with .getTypes(), .getVariants(), .getPositions()\n');
|
console.log(' • Explore data: .getTypes(), .getVariants(), .getPositions()\n');
|
||||||
|
|
||||||
console.log('All examples complete! Ready to use MeasurementContainer');
|
module.exports = { basicContainer, autoContainer };
|
||||||
|
|
||||||
// Export for programmatic use
|
|
||||||
module.exports = {
|
|
||||||
runExamples: () => {
|
|
||||||
console.log('Measurement Container Examples - Complete Guide for New Users');
|
|
||||||
console.log('This file demonstrates all features with practical examples.');
|
|
||||||
},
|
|
||||||
|
|
||||||
// Export containers for testing
|
|
||||||
basicContainer,
|
|
||||||
autoContainer
|
|
||||||
};
|
|
||||||
@@ -180,19 +180,47 @@ getSaveInjectionCode(nodeName) {
|
|||||||
return `
|
return `
|
||||||
// PhysicalPosition Save injection for ${nodeName}
|
// PhysicalPosition Save injection for ${nodeName}
|
||||||
window.EVOLV.nodes.${nodeName}.positionMenu.saveEditor = function(node) {
|
window.EVOLV.nodes.${nodeName}.positionMenu.saveEditor = function(node) {
|
||||||
|
console.log("=== PhysicalPosition Save Debug ===");
|
||||||
|
|
||||||
const sel = document.getElementById('node-input-positionVsParent');
|
const sel = document.getElementById('node-input-positionVsParent');
|
||||||
const hasDistanceCheck = document.getElementById('node-input-hasDistance');
|
const hasDistanceCheck = document.getElementById('node-input-hasDistance');
|
||||||
const distanceInput = document.getElementById('node-input-distance');
|
const distanceInput = document.getElementById('node-input-distance');
|
||||||
|
|
||||||
// Save existing position data
|
console.log("→ sel element found:", !!sel);
|
||||||
node.positionVsParent = sel ? sel.value : 'atEquipment';
|
console.log("→ sel:", sel);
|
||||||
node.positionLabel = sel ? sel.options[sel.selectedIndex].textContent : 'At Equipment';
|
console.log("→ sel.value:", sel ? sel.value : "NO ELEMENT");
|
||||||
node.positionIcon = sel ? sel.options[sel.selectedIndex].getAttribute('data-icon') : 'fa fa-cog';
|
console.log("→ sel.selectedIndex:", sel ? sel.selectedIndex : "NO ELEMENT");
|
||||||
|
console.log("→ sel.options:", sel ? Array.from(sel.options).map(o => ({value: o.value, text: o.textContent})) : "NO OPTIONS");
|
||||||
|
|
||||||
|
if (!sel) {
|
||||||
|
console.error("→ positionMenu.saveEditor FAILED: select element not found!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save existing position data
|
||||||
|
const positionValue = sel.value;
|
||||||
|
const selectedOption = sel.options[sel.selectedIndex];
|
||||||
|
|
||||||
|
console.log("→ positionValue:", positionValue);
|
||||||
|
console.log("→ selectedOption:", selectedOption);
|
||||||
|
console.log("→ selectedOption.textContent:", selectedOption ? selectedOption.textContent : "NO OPTION");
|
||||||
|
console.log("→ selectedOption data-icon:", selectedOption ? selectedOption.getAttribute('data-icon') : "NO ICON");
|
||||||
|
|
||||||
|
node.positionVsParent = positionValue || 'atEquipment';
|
||||||
|
node.positionLabel = selectedOption ? selectedOption.textContent : 'At Equipment';
|
||||||
|
node.positionIcon = selectedOption ? selectedOption.getAttribute('data-icon') : 'fa fa-cog';
|
||||||
|
|
||||||
|
console.log("→ node.positionVsParent set to:", node.positionVsParent);
|
||||||
|
console.log("→ node.positionLabel set to:", node.positionLabel);
|
||||||
|
|
||||||
|
// Save distance data
|
||||||
|
console.log("→ hasDistanceCheck found:", !!hasDistanceCheck);
|
||||||
|
console.log("→ hasDistanceCheck.checked:", hasDistanceCheck ? hasDistanceCheck.checked : "NO ELEMENT");
|
||||||
|
|
||||||
// Save distance data (NEW)
|
|
||||||
node.hasDistance = hasDistanceCheck ? hasDistanceCheck.checked : false;
|
node.hasDistance = hasDistanceCheck ? hasDistanceCheck.checked : false;
|
||||||
|
|
||||||
if (node.hasDistance && distanceInput && distanceInput.value) {
|
if (node.hasDistance && distanceInput && distanceInput.value) {
|
||||||
|
console.log("→ distanceInput.value:", distanceInput.value);
|
||||||
node.distance = parseFloat(distanceInput.value) || 0;
|
node.distance = parseFloat(distanceInput.value) || 0;
|
||||||
node.distanceUnit = 'm'; // Fixed to meters for now
|
node.distanceUnit = 'm'; // Fixed to meters for now
|
||||||
|
|
||||||
@@ -200,13 +228,18 @@ getSaveInjectionCode(nodeName) {
|
|||||||
const contexts = window.EVOLV.nodes.${nodeName}.menuData.position.distanceContexts;
|
const contexts = window.EVOLV.nodes.${nodeName}.menuData.position.distanceContexts;
|
||||||
const context = contexts && contexts[node.positionVsParent];
|
const context = contexts && contexts[node.positionVsParent];
|
||||||
node.distanceDescription = context ? context.description : 'Distance from parent';
|
node.distanceDescription = context ? context.description : 'Distance from parent';
|
||||||
|
|
||||||
|
console.log("→ distance set to:", node.distance);
|
||||||
} else {
|
} else {
|
||||||
// Clear distance data if not specified
|
console.log("→ clearing distance data");
|
||||||
delete node.distance;
|
delete node.distance;
|
||||||
delete node.distanceUnit;
|
delete node.distanceUnit;
|
||||||
delete node.distanceDescription;
|
delete node.distanceDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("→ positionMenu.saveEditor result: SUCCESS");
|
||||||
|
console.log("→ final node.positionVsParent:", node.positionVsParent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"general": {
|
"general": {
|
||||||
"name": {
|
"name": {
|
||||||
"default": "Interpolation Configuration",
|
"default": "interpolation configuration",
|
||||||
"rules": {
|
"rules": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "A human-readable name or label for this interpolation configuration."
|
"description": "A human-readable name or label for this interpolation configuration."
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"default": "Interpolator",
|
"default": "interpolator",
|
||||||
"rules": {
|
"rules": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Indicates the role of this configuration (e.g., 'Interpolator', 'DataCurve', etc.)."
|
"description": "Indicates the role of this configuration (e.g., 'Interpolator', 'DataCurve', etc.)."
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ class state{
|
|||||||
return this.stateManager.getRunTimeHours();
|
return this.stateManager.getRunTimeHours();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async moveTo(targetPosition) {
|
async moveTo(targetPosition) {
|
||||||
|
|
||||||
// Check for invalid conditions and throw errors
|
// Check for invalid conditions and throw errors
|
||||||
@@ -86,14 +87,33 @@ class state{
|
|||||||
|
|
||||||
// -------- State Transition Methods -------- //
|
// -------- State Transition Methods -------- //
|
||||||
|
|
||||||
|
abortCurrentMovement(reason = "group override") {
|
||||||
|
if (this.abortController && !this.abortController.signal.aborted) {
|
||||||
|
this.logger.warn(`Aborting movement: ${reason}`);
|
||||||
|
this.abortController.abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async transitionToState(targetState, signal) {
|
async transitionToState(targetState, signal) {
|
||||||
|
|
||||||
const fromState = this.getCurrentState();
|
const fromState = this.getCurrentState();
|
||||||
const position = this.getCurrentPosition();
|
const position = this.getCurrentPosition();
|
||||||
|
|
||||||
|
// Define states that cannot be aborted for safety reasons
|
||||||
|
const protectedStates = ['warmingup', 'coolingdown'];
|
||||||
|
const isProtectedTransition = protectedStates.includes(fromState);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
this.logger.debug(`Starting transition from ${fromState} to ${targetState}.`);
|
this.logger.debug(`Starting transition from ${fromState} to ${targetState}.`);
|
||||||
|
if( isProtectedTransition){
|
||||||
|
//overrule signal to prevent abortion
|
||||||
|
signal = null; // Disable abortion for protected states
|
||||||
|
//spit warning
|
||||||
|
this.logger.warn(`Transition from ${fromState} to ${targetState} is protected and cannot be aborted.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Await the state transition and pass signal for abortion
|
||||||
const feedback = await this.stateManager.transitionTo(targetState,signal);
|
const feedback = await this.stateManager.transitionTo(targetState,signal);
|
||||||
this.logger.info(`Statemanager: ${feedback}`);
|
this.logger.info(`Statemanager: ${feedback}`);
|
||||||
|
|
||||||
@@ -108,7 +128,6 @@ class state{
|
|||||||
//trigger move
|
//trigger move
|
||||||
await this.moveTo(this.delayedMove,signal);
|
await this.moveTo(this.delayedMove,signal);
|
||||||
this.delayedMove = null;
|
this.delayedMove = null;
|
||||||
|
|
||||||
this.logger.info(`moveTo : ${feedback} `);
|
this.logger.info(`moveTo : ${feedback} `);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"general": {
|
"general": {
|
||||||
"name": {
|
"name": {
|
||||||
"default": "State Configuration",
|
"default": "state configuration",
|
||||||
"rules": {
|
"rules": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "A human-readable name for the state configuration."
|
"description": "A human-readable name for the state configuration."
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"default": "StateController",
|
"default": "statecontroller",
|
||||||
"rules": {
|
"rules": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Functional role within the system."
|
"description": "Functional role within the system."
|
||||||
|
|||||||
Reference in New Issue
Block a user