const test = require('node:test'); const assert = require('node:assert/strict'); const Valve = require('../../../valve/src/specificClass'); const ValveGroupControl = require('../../src/specificClass'); function buildValve(name) { return new Valve( { general: { name, logging: { enabled: false, logLevel: 'error' }, }, asset: { supplier: 'binder', category: 'valve', type: 'control', model: 'ECDV', unit: 'm3/h', }, functionality: { positionVsParent: 'atEquipment', }, }, { general: { logging: { enabled: false, logLevel: 'error' }, }, movement: { speed: 1 }, time: { starting: 0, warmingup: 0, stopping: 0, coolingdown: 0 }, } ); } function primeValve(valve, position) { valve.updatePressure('measured', 500, 'downstream', 'mbar'); valve.updateFlow('predicted', 100, 'downstream', 'm3/h'); valve.state.movementManager.currentPosition = position; valve.updatePosition(); } function buildGroup() { return new ValveGroupControl({ general: { name: 'vgc-test', logging: { enabled: false, logLevel: 'error' }, unit: 'm3/h', }, functionality: { positionVsParent: 'atEquipment', }, }); } test('valveGroupControl distributes total flow according to supplier-curve Kv and keeps roundtrip balance', async () => { const valve1 = buildValve('valve-1'); const valve2 = buildValve('valve-2'); primeValve(valve1, 50); primeValve(valve2, 80); const group = buildGroup(); assert.equal(await group.childRegistrationUtils.registerChild(valve1, 'atEquipment'), true); assert.equal(await group.childRegistrationUtils.registerChild(valve2, 'atEquipment'), true); group.updateFlow('measured', 1000, 'atEquipment', 'm3/h'); const q1 = valve1.measurements.type('flow').variant('predicted').position('downstream').getCurrentValue('m3/h'); const q2 = valve2.measurements.type('flow').variant('predicted').position('downstream').getCurrentValue('m3/h'); const distributedTotal = q1 + q2; assert.ok(Math.abs(distributedTotal - 1000) < 0.001, `distributed flow mismatch: ${distributedTotal}`); const expectedRatio = valve1.kv / (valve1.kv + valve2.kv); const actualRatio = q1 / (q1 + q2); assert.ok(Math.abs(expectedRatio - actualRatio) < 0.001, `expected ratio ${expectedRatio}, got ${actualRatio}`); const expectedMaxDeltaP = Math.max( valve1.measurements.type('pressure').variant('predicted').position('delta').getCurrentValue('mbar'), valve2.measurements.type('pressure').variant('predicted').position('delta').getCurrentValue('mbar') ); assert.ok(Math.abs(group.maxDeltaP - expectedMaxDeltaP) < 0.001, `expected max deltaP ${expectedMaxDeltaP}, got ${group.maxDeltaP}`); group.destroy(); valve1.destroy(); valve2.destroy(); }); test('valveGroupControl rejects non-valve-like child payload', () => { const group = buildGroup(); const result = group.registerChild({ config: { functionality: { softwareType: 'valve' } } }, 'atEquipment'); assert.equal(result, false); assert.equal(Object.keys(group.valves).length, 0); group.destroy(); });