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:
103
scripts/fix-initial-volume.js
Normal file
103
scripts/fix-initial-volume.js
Normal file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Add initial volume calibration inject nodes to the demo flow.
|
||||
*
|
||||
* Problem: All 3 pumping stations start with initial volume = minVol,
|
||||
* which is below the dryRun safety threshold. This causes the safety
|
||||
* guard to trigger immediately on every tick, preventing normal control.
|
||||
*
|
||||
* Fix: Add inject nodes that fire once at deploy, sending
|
||||
* calibratePredictedVolume to each PS with a reasonable starting volume.
|
||||
*
|
||||
* PS West: 500m3 basin, startLevel=2.5m → start at 200m3 (level 1.6m)
|
||||
* Below startLevel, pumps stay off. q_in fills basin naturally.
|
||||
* PS North: 200m3 basin, flowbased → start at 100m3 (50% fill)
|
||||
* PS South: 100m3 basin, manual → start at 50m3 (50% fill)
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const flowPath = path.join(__dirname, '..', 'docker', 'demo-flow.json');
|
||||
const flow = JSON.parse(fs.readFileSync(flowPath, 'utf8'));
|
||||
|
||||
// Check if calibration nodes already exist
|
||||
const existingCalib = flow.filter(n => n.id && n.id.startsWith('demo_inj_calib_'));
|
||||
if (existingCalib.length > 0) {
|
||||
console.log('Calibration nodes already exist:', existingCalib.map(n => n.id));
|
||||
console.log('Removing existing calibration nodes first...');
|
||||
for (const node of existingCalib) {
|
||||
const idx = flow.findIndex(n => n.id === node.id);
|
||||
if (idx !== -1) flow.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Find the WWTP tab for positioning
|
||||
const wwtpTab = flow.find(n => n.id === 'demo_tab_wwtp');
|
||||
if (!wwtpTab) {
|
||||
console.error('WWTP tab not found!');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Calibration configs: { ps_id, name, volume, x, y }
|
||||
const calibrations = [
|
||||
{
|
||||
id: 'demo_inj_calib_west',
|
||||
name: 'Cal: PS West → 200m3',
|
||||
target: 'demo_ps_west',
|
||||
volume: 200,
|
||||
x: 100, y: 50,
|
||||
},
|
||||
{
|
||||
id: 'demo_inj_calib_north',
|
||||
name: 'Cal: PS North → 100m3',
|
||||
target: 'demo_ps_north',
|
||||
volume: 100,
|
||||
x: 100, y: 100,
|
||||
},
|
||||
{
|
||||
id: 'demo_inj_calib_south',
|
||||
name: 'Cal: PS South → 50m3',
|
||||
target: 'demo_ps_south',
|
||||
volume: 50,
|
||||
x: 100, y: 150,
|
||||
},
|
||||
];
|
||||
|
||||
let added = 0;
|
||||
|
||||
calibrations.forEach(cal => {
|
||||
const injectNode = {
|
||||
id: cal.id,
|
||||
type: 'inject',
|
||||
z: 'demo_tab_wwtp',
|
||||
name: cal.name,
|
||||
props: [
|
||||
{
|
||||
p: 'payload',
|
||||
vt: 'num',
|
||||
},
|
||||
{
|
||||
p: 'topic',
|
||||
vt: 'str',
|
||||
},
|
||||
],
|
||||
repeat: '',
|
||||
crontab: '',
|
||||
once: true,
|
||||
onceDelay: '0.5',
|
||||
topic: 'calibratePredictedVolume',
|
||||
payload: String(cal.volume),
|
||||
payloadType: 'num',
|
||||
x: cal.x,
|
||||
y: cal.y,
|
||||
wires: [[cal.target]],
|
||||
};
|
||||
|
||||
flow.push(injectNode);
|
||||
added++;
|
||||
console.log(`Added ${cal.id}: ${cal.name} → ${cal.target} (${cal.volume} m3)`);
|
||||
});
|
||||
|
||||
fs.writeFileSync(flowPath, JSON.stringify(flow, null, 2) + '\n');
|
||||
console.log(`\nDone. ${added} calibration node(s) added.`);
|
||||
Reference in New Issue
Block a user