- Update all submodule URLs from gitea.centraal.wbd-rd.nl to gitea.wbd-rd.nl - Add settler as proper submodule in .gitmodules - Add agent skills, function anchors, decisions, and improvements - Add Docker configuration and scripts - Add manuals and third_party docs - Update .gitignore with secrets and build artifacts - Remove stale .tgz build artifact Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
139 lines
5.6 KiB
JavaScript
139 lines
5.6 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Comprehensive runtime analysis of the WWTP demo flow.
|
|
* Captures process debug output, pumping station state, measurements,
|
|
* and analyzes filling/draining behavior over time.
|
|
*/
|
|
|
|
const http = require('http');
|
|
|
|
const NR_URL = 'http://localhost:1880';
|
|
|
|
function fetchJSON(url) {
|
|
return new Promise((resolve, reject) => {
|
|
http.get(url, res => {
|
|
const chunks = [];
|
|
res.on('data', c => chunks.push(c));
|
|
res.on('end', () => {
|
|
try { resolve(JSON.parse(Buffer.concat(chunks))); }
|
|
catch (e) { reject(new Error('Parse error from ' + url + ': ' + e.message)); }
|
|
});
|
|
}).on('error', reject);
|
|
});
|
|
}
|
|
|
|
// Inject a debug-capture subflow to intercept process messages
|
|
async function injectDebugCapture() {
|
|
const flows = await fetchJSON(NR_URL + '/flows');
|
|
|
|
// Find all nodes on WWTP tab
|
|
const wwtp = flows.filter(n => n.z === 'demo_tab_wwtp');
|
|
|
|
console.log('=== WWTP Node Inventory ===');
|
|
const byType = {};
|
|
wwtp.forEach(n => {
|
|
if (!byType[n.type]) byType[n.type] = [];
|
|
byType[n.type].push(n);
|
|
});
|
|
|
|
Object.entries(byType).sort().forEach(([type, nodes]) => {
|
|
console.log(type + ' (' + nodes.length + '):');
|
|
nodes.forEach(n => {
|
|
const extra = [];
|
|
if (n.simulator) extra.push('sim=ON');
|
|
if (n.model) extra.push('model=' + n.model);
|
|
if (n.basinVolume) extra.push('basin=' + n.basinVolume + 'm3');
|
|
if (n.basinHeight) extra.push('h=' + n.basinHeight + 'm');
|
|
if (n.positionVsParent) extra.push('pos=' + n.positionVsParent);
|
|
if (n.control) extra.push('ctrl=' + JSON.stringify(n.control));
|
|
console.log(' ' + n.id + ' "' + (n.name || '') + '" ' + (extra.length ? '[' + extra.join(', ') + ']' : ''));
|
|
});
|
|
});
|
|
|
|
// Analyze pumping station configurations
|
|
console.log('\n=== Pumping Station Configs ===');
|
|
const pss = wwtp.filter(n => n.type === 'pumpingStation');
|
|
pss.forEach(ps => {
|
|
console.log('\n' + ps.id + ' "' + ps.name + '"');
|
|
console.log(' Basin: vol=' + ps.basinVolume + 'm3, h=' + ps.basinHeight + 'm');
|
|
console.log(' Inlet: h=' + ps.heightInlet + 'm, Outlet: h=' + ps.heightOutlet + 'm');
|
|
console.log(' Simulator: ' + ps.simulator);
|
|
console.log(' Control mode: ' + (ps.controlMode || 'not set'));
|
|
|
|
// Check q_in inject wiring
|
|
const qinInject = wwtp.find(n => n.id === 'demo_inj_' + ps.id.replace('demo_ps_', '') + '_flow');
|
|
if (qinInject) {
|
|
console.log(' q_in inject: repeat=' + qinInject.repeat + 's, wired to ' + JSON.stringify(qinInject.wires));
|
|
}
|
|
|
|
// Check what's wired to this PS (port 2 = parent registration)
|
|
const children = wwtp.filter(n => {
|
|
if (!n.wires) return false;
|
|
return n.wires.some(portWires => portWires && portWires.includes(ps.id));
|
|
});
|
|
console.log(' Children wired to it: ' + children.map(c => c.id + '(' + c.type + ')').join(', '));
|
|
});
|
|
|
|
// Analyze inject timers
|
|
console.log('\n=== Active Inject Timers ===');
|
|
const injects = wwtp.filter(n => n.type === 'inject');
|
|
injects.forEach(inj => {
|
|
const targets = (inj.wires || []).flat();
|
|
console.log(inj.id + ' "' + (inj.name || '') + '"');
|
|
console.log(' topic=' + inj.topic + ' payload=' + inj.payload);
|
|
console.log(' once=' + inj.once + ' repeat=' + (inj.repeat || 'none'));
|
|
console.log(' → ' + targets.join(', '));
|
|
});
|
|
|
|
// Analyze q_in function nodes
|
|
console.log('\n=== q_in Flow Simulation Functions ===');
|
|
const fnNodes = wwtp.filter(n => n.type === 'function' && n.name && n.name.includes('Flow'));
|
|
fnNodes.forEach(fn => {
|
|
console.log(fn.id + ' "' + fn.name + '"');
|
|
console.log(' func: ' + (fn.func || '').substring(0, 200));
|
|
const targets = (fn.wires || []).flat();
|
|
console.log(' → ' + targets.join(', '));
|
|
});
|
|
|
|
// Analyze measurement nodes
|
|
console.log('\n=== Measurement Nodes ===');
|
|
const meas = wwtp.filter(n => n.type === 'measurement');
|
|
meas.forEach(m => {
|
|
console.log(m.id + ' "' + (m.name || '') + '"');
|
|
console.log(' type=' + m.assetType + ' sim=' + m.simulator + ' range=[' + m.o_min + ',' + m.o_max + '] unit=' + m.unit);
|
|
console.log(' pos=' + (m.positionVsParent || 'none'));
|
|
// Check port 2 wiring (parent registration)
|
|
const port2 = m.wires && m.wires[2] ? m.wires[2] : [];
|
|
console.log(' port2→ ' + (port2.length ? port2.join(', ') : 'none'));
|
|
});
|
|
|
|
// Analyze rotating machines
|
|
console.log('\n=== Rotating Machine Nodes ===');
|
|
const machines = wwtp.filter(n => n.type === 'rotatingMachine');
|
|
machines.forEach(m => {
|
|
console.log(m.id + ' "' + (m.name || '') + '"');
|
|
console.log(' model=' + m.model + ' mode=' + m.movementMode);
|
|
console.log(' pos=' + m.positionVsParent + ' supplier=' + m.supplier);
|
|
console.log(' speed=' + m.speed + ' startup=' + m.startup + ' shutdown=' + m.shutdown);
|
|
const port2 = m.wires && m.wires[2] ? m.wires[2] : [];
|
|
console.log(' port2→ ' + (port2.length ? port2.join(', ') : 'none'));
|
|
});
|
|
|
|
// Check wiring integrity
|
|
console.log('\n=== Wiring Analysis ===');
|
|
pss.forEach(ps => {
|
|
const psPort0 = ps.wires && ps.wires[0] ? ps.wires[0] : [];
|
|
const psPort1 = ps.wires && ps.wires[1] ? ps.wires[1] : [];
|
|
const psPort2 = ps.wires && ps.wires[2] ? ps.wires[2] : [];
|
|
console.log(ps.id + ' wiring:');
|
|
console.log(' port0 (process): ' + psPort0.join(', '));
|
|
console.log(' port1 (influx): ' + psPort1.join(', '));
|
|
console.log(' port2 (parent): ' + psPort2.join(', '));
|
|
});
|
|
}
|
|
|
|
injectDebugCapture().catch(err => {
|
|
console.error('Analysis failed:', err);
|
|
process.exit(1);
|
|
});
|