Migrate to new Gitea instance (gitea.wbd-rd.nl)
- 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>
This commit is contained in:
138
scripts/analyze-runtime.js
Normal file
138
scripts/analyze-runtime.js
Normal file
@@ -0,0 +1,138 @@
|
||||
#!/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);
|
||||
});
|
||||
Reference in New Issue
Block a user