297 lines
10 KiB
JavaScript
297 lines
10 KiB
JavaScript
const Machine = require('./machine');
|
|
const specs = require('../../../generalFunctions/datasets/assetData/pumps/hydrostal/centrifugal pumps/models.json');
|
|
|
|
class MachineTester {
|
|
constructor() {
|
|
this.totalTests = 0;
|
|
this.passedTests = 0;
|
|
this.failedTests = 0;
|
|
this.machineCurve = specs[0].machineCurve;
|
|
}
|
|
|
|
assert(condition, message) {
|
|
this.totalTests++;
|
|
if (condition) {
|
|
console.log(`✓ PASS: ${message}`);
|
|
this.passedTests++;
|
|
} else {
|
|
console.log(`✗ FAIL: ${message}`);
|
|
this.failedTests++;
|
|
}
|
|
}
|
|
|
|
createBaseMachineConfig(name) {
|
|
return {
|
|
general: {
|
|
logging: { enabled: true, logLevel: "debug" },
|
|
name: name,
|
|
unit: "m3/h"
|
|
},
|
|
functionality: {
|
|
softwareType: "machine",
|
|
role: "RotationalDeviceController"
|
|
},
|
|
asset: {
|
|
type: "pump",
|
|
subType: "Centrifugal",
|
|
model: "TestModel",
|
|
supplier: "Hydrostal",
|
|
machineCurve: this.machineCurve
|
|
},
|
|
mode: {
|
|
current: "auto",
|
|
allowedActions: {
|
|
auto: ["execSequence", "execMovement", "statusCheck"],
|
|
virtualControl: ["execMovement", "statusCheck"],
|
|
fysicalControl: ["statusCheck"]
|
|
},
|
|
allowedSources: {
|
|
auto: ["parent", "GUI"],
|
|
virtualControl: ["GUI"],
|
|
fysicalControl: ["fysical"]
|
|
}
|
|
},
|
|
sequences: {
|
|
startup: ["starting", "warmingup", "operational"],
|
|
shutdown: ["stopping", "coolingdown", "idle"],
|
|
emergencystop: ["emergencystop", "off"],
|
|
boot: ["idle", "starting", "warmingup", "operational"]
|
|
},
|
|
calculationMode: "medium"
|
|
};
|
|
}
|
|
|
|
async testBasicOperations() {
|
|
console.log('\nTesting Basic Machine Operations...');
|
|
|
|
const machine = new Machine(this.createBaseMachineConfig("TestMachine"));
|
|
|
|
try {
|
|
// Test 1: Initialization
|
|
this.assert(
|
|
machine.currentMode === "auto",
|
|
'Machine should initialize in auto mode'
|
|
);
|
|
|
|
// Test 2: Set pressure measurement
|
|
machine.measurements.type("pressure").variant("measured").position("downstream").value(800);
|
|
const pressure = machine.handleMeasuredPressure();
|
|
this.assert(
|
|
pressure === 800,
|
|
'Should correctly handle pressure measurement'
|
|
);
|
|
|
|
// Test 3: State transition
|
|
await machine.state.transitionToState("idle");
|
|
this.assert(
|
|
machine.state.getCurrentState() === "idle",
|
|
'Should transition to idle state'
|
|
);
|
|
|
|
// Test 4: Mode change
|
|
machine.setMode("virtualControl");
|
|
this.assert(
|
|
machine.currentMode === "virtualControl",
|
|
'Should change mode to virtual control'
|
|
);
|
|
} catch (error) {
|
|
console.error('Test failed with error:', error);
|
|
this.failedTests++;
|
|
}
|
|
}
|
|
|
|
async testPredictions() {
|
|
console.log('\nTesting Machine Predictions...');
|
|
|
|
const machine = new Machine(this.createBaseMachineConfig("TestMachine"));
|
|
machine.measurements.type("pressure").variant("measured").position("downstream").value(800);
|
|
|
|
try {
|
|
// Test 1: Flow prediction
|
|
const flow = machine.calcFlow(50);
|
|
this.assert(
|
|
flow > 0 && !isNaN(flow),
|
|
'Should calculate valid flow for control value'
|
|
);
|
|
|
|
// Test 2: Power prediction
|
|
const power = machine.calcPower(50);
|
|
this.assert(
|
|
power > 0 && !isNaN(power),
|
|
'Should calculate valid power for control value'
|
|
);
|
|
|
|
// Test 3: Control prediction
|
|
const ctrl = machine.calcCtrl(100);
|
|
this.assert(
|
|
ctrl >= 0 && ctrl <= 100,
|
|
'Should calculate valid control value for desired flow'
|
|
);
|
|
} catch (error) {
|
|
console.error('Test failed with error:', error);
|
|
this.failedTests++;
|
|
}
|
|
}
|
|
|
|
async testSequenceExecution() {
|
|
console.log('\nTesting Machine Sequences...');
|
|
|
|
const machine = new Machine(this.createBaseMachineConfig("TestMachine"));
|
|
|
|
try {
|
|
// Test 1: Startup sequence
|
|
await machine.handleInput("parent", "execSequence", "startup");
|
|
this.assert(
|
|
machine.state.getCurrentState() === "operational",
|
|
'Should complete startup sequence'
|
|
);
|
|
|
|
// Test 2: Movement after startup
|
|
await machine.handleInput("parent", "execMovement", 50);
|
|
this.assert(
|
|
machine.state.getCurrentPosition() === 50,
|
|
'Should move to specified position'
|
|
);
|
|
|
|
// Test 3: Shutdown sequence
|
|
await machine.handleInput("parent", "execSequence", "shutdown");
|
|
this.assert(
|
|
machine.state.getCurrentState() === "idle",
|
|
'Should complete shutdown sequence'
|
|
);
|
|
|
|
// Test 4: Emergency stop
|
|
await machine.handleInput("parent", "execSequence", "emergencystop");
|
|
this.assert(
|
|
machine.state.getCurrentState() === "off",
|
|
'Should execute emergency stop'
|
|
);
|
|
} catch (error) {
|
|
console.error('Test failed with error:', error);
|
|
this.failedTests++;
|
|
}
|
|
}
|
|
|
|
async testMeasurementHandling() {
|
|
console.log('\nTesting Measurement Handling...');
|
|
|
|
const machine = new Machine(this.createBaseMachineConfig("TestMachine"));
|
|
|
|
try {
|
|
// Test 1: Pressure measurement
|
|
machine.measurements.type("pressure").variant("measured").position("downstream").value(800);
|
|
machine.measurements.type("pressure").variant("measured").setUpstream(1000);
|
|
const pressure = machine.handleMeasuredPressure();
|
|
this.assert(
|
|
pressure === 200,
|
|
'Should calculate correct differential pressure'
|
|
);
|
|
|
|
// Test 2: Flow measurement
|
|
machine.measurements.type("flow").variant("measured").position("downstream").value(100);
|
|
const flow = machine.handleMeasuredFlow();
|
|
this.assert(
|
|
flow === 100,
|
|
'Should handle flow measurement correctly'
|
|
);
|
|
|
|
// Test 3: Power measurement
|
|
machine.measurements.type("power").variant("measured").setUpstream(75);
|
|
const power = machine.handleMeasuredPower();
|
|
this.assert(
|
|
power === 75,
|
|
'Should handle power measurement correctly'
|
|
);
|
|
|
|
// Test 4: Efficiency calculation
|
|
machine.calcEfficiency();
|
|
const efficiency = machine.measurements.type("efficiency").variant("measured").getDownstream();
|
|
this.assert(
|
|
efficiency > 0 && !isNaN(efficiency),
|
|
'Should calculate valid efficiency'
|
|
);
|
|
} catch (error) {
|
|
console.error('Test failed with error:', error);
|
|
this.failedTests++;
|
|
}
|
|
}
|
|
|
|
async testCurveHandling() {
|
|
console.log('\nTesting Machine Curve Handling...');
|
|
|
|
const machine = new Machine(this.createBaseMachineConfig("TestMachine"));
|
|
|
|
try {
|
|
// Test 1: Curve initialization
|
|
const curves = machine.showCurve();
|
|
this.assert(
|
|
curves.powerCurve && curves.flowCurve,
|
|
'Should properly initialize power and flow curves'
|
|
);
|
|
|
|
// Test 2: Test reverse curve creation
|
|
const reversedCurve = machine.reverseCurve(this.machineCurve.nq);
|
|
this.assert(
|
|
reversedCurve["1"].x[0] === this.machineCurve.nq["1"].y[0] &&
|
|
reversedCurve["1"].y[0] === this.machineCurve.nq["1"].x[0],
|
|
'Should correctly reverse x and y values in curve'
|
|
);
|
|
|
|
// Test 3: Update curve dynamically
|
|
const newCurve = {
|
|
nq: {
|
|
"1": {
|
|
x: [0, 25, 50, 75, 100],
|
|
y: [0, 125, 250, 375, 500]
|
|
}
|
|
},
|
|
np: {
|
|
"1": {
|
|
x: [0, 25, 50, 75, 100],
|
|
y: [0, 75, 150, 225, 300]
|
|
}
|
|
}
|
|
};
|
|
machine.updateCurve(newCurve);
|
|
const updatedCurves = machine.showCurve();
|
|
this.assert(
|
|
updatedCurves.flowCurve["1"].y[2] === 250,
|
|
'Should update curve with new values'
|
|
);
|
|
|
|
// Test 4: Verify curve interpolation
|
|
machine.measurements.type("pressure").variant("measured").position("downstream").value(800);
|
|
const midpointCtrl = machine.calcCtrl(250); // Should interpolate between points
|
|
const calculatedFlow = machine.calcFlow(midpointCtrl);
|
|
this.assert(
|
|
Math.abs(calculatedFlow - 250) < 1, // Allow small numerical error
|
|
'Should accurately interpolate between curve points'
|
|
);
|
|
|
|
} catch (error) {
|
|
console.error('Test failed with error:', error);
|
|
this.failedTests++;
|
|
}
|
|
}
|
|
|
|
async runAllTests() {
|
|
console.log('Starting Machine Tests...\n');
|
|
|
|
await this.testBasicOperations();
|
|
await this.testPredictions();
|
|
await this.testSequenceExecution();
|
|
await this.testMeasurementHandling();
|
|
await this.testCurveHandling();
|
|
|
|
console.log('\nTest Summary:');
|
|
console.log(`Total Tests: ${this.totalTests}`);
|
|
console.log(`Passed: ${this.passedTests}`);
|
|
console.log(`Failed: ${this.failedTests}`);
|
|
|
|
process.exit(this.failedTests > 0 ? 1 : 0);
|
|
}
|
|
}
|
|
|
|
// Run the tests
|
|
const tester = new MachineTester();
|
|
tester.runAllTests().catch(console.error); |