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:
znetsixe
2026-03-04 21:07:04 +01:00
parent fbd9e6ec11
commit 6a6c04d34b
169 changed files with 21332 additions and 1512 deletions

279
scripts/update-demo-flow.js Normal file
View File

@@ -0,0 +1,279 @@
#!/usr/bin/env node
/**
* Script to update docker/demo-flow.json with Fixes 2-5 from the plan.
* Run from project root: node scripts/update-demo-flow.js
*/
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'));
// === Fix 2: Enable simulator on 9 measurement nodes ===
const simMeasIds = [
'demo_meas_flow', 'demo_meas_do', 'demo_meas_nh4',
'demo_meas_ft_n1', 'demo_meas_eff_flow', 'demo_meas_eff_do',
'demo_meas_eff_nh4', 'demo_meas_eff_no3', 'demo_meas_eff_tss'
];
simMeasIds.forEach(id => {
const node = flow.find(n => n.id === id);
if (node) {
node.simulator = true;
console.log('Enabled simulator on', id);
} else {
console.error('NOT FOUND:', id);
}
});
// === Fix 2: Remove 18 inject+function sim pairs ===
const removeSimIds = [
'demo_inj_meas_flow', 'demo_fn_sim_flow',
'demo_inj_meas_do', 'demo_fn_sim_do',
'demo_inj_meas_nh4', 'demo_fn_sim_nh4',
'demo_inj_ft_n1', 'demo_fn_sim_ft_n1',
'demo_inj_eff_flow', 'demo_fn_sim_eff_flow',
'demo_inj_eff_do', 'demo_fn_sim_eff_do',
'demo_inj_eff_nh4', 'demo_fn_sim_eff_nh4',
'demo_inj_eff_no3', 'demo_fn_sim_eff_no3',
'demo_inj_eff_tss', 'demo_fn_sim_eff_tss'
];
// === Fix 5: Remove manual pump startup/setpoint injectors ===
const removeManualIds = [
'demo_inj_w1_startup', 'demo_inj_w1_setpoint',
'demo_inj_w2_startup', 'demo_inj_w2_setpoint',
'demo_inj_n1_startup',
'demo_inj_s1_startup'
];
const allRemoveIds = new Set([...removeSimIds, ...removeManualIds]);
const before = flow.length;
const filtered = flow.filter(n => !allRemoveIds.has(n.id));
console.log(`Removed ${before - filtered.length} nodes (expected 24)`);
// Remove wires to removed nodes from remaining nodes
filtered.forEach(n => {
if (n.wires && Array.isArray(n.wires)) {
n.wires = n.wires.map(wireGroup => {
if (Array.isArray(wireGroup)) {
return wireGroup.filter(w => !allRemoveIds.has(w));
}
return wireGroup;
});
}
});
// === Fix 3 (demo part): Add speedUpFactor to reactor ===
const reactor = filtered.find(n => n.id === 'demo_reactor');
if (reactor) {
reactor.speedUpFactor = 1;
console.log('Added speedUpFactor=1 to reactor');
}
// === Fix 4: Add pressure measurement nodes ===
const maxY = Math.max(...filtered.filter(n => n.z === 'demo_tab_wwtp').map(n => n.y || 0));
const ptBaseConfig = {
scaling: true,
i_offset: 0,
smooth_method: 'mean',
count: 3,
category: 'sensor',
assetType: 'pressure',
enableLog: false,
logLevel: 'error',
positionIcon: '',
hasDistance: false
};
// Function to extract level from PS output and convert to hydrostatic pressure
const levelExtractFunc = [
'// Extract basin level from PS output and convert to hydrostatic pressure (mbar)',
'// P = rho * g * h, rho=1000 kg/m3, g=9.81 m/s2',
'const p = msg.payload || {};',
'const keys = Object.keys(p);',
'const levelKey = keys.find(k => k.startsWith("level.predicted.atequipment") || k.startsWith("level.measured.atequipment"));',
'if (!levelKey) return null;',
'const h = Number(p[levelKey]);',
'if (!Number.isFinite(h)) return null;',
'msg.topic = "measurement";',
'msg.payload = Math.round(h * 98.1 * 10) / 10; // mbar',
'return msg;'
].join('\n');
const newNodes = [
// Comment
{
id: 'demo_comment_pressure',
type: 'comment',
z: 'demo_tab_wwtp',
name: '=== PRESSURE MEASUREMENTS (per pumping station) ===',
info: '',
x: 320,
y: maxY + 40
},
// --- PS West upstream PT ---
{
id: 'demo_fn_level_to_pressure_w',
type: 'function',
z: 'demo_tab_wwtp',
name: 'Level\u2192Pressure (West)',
func: levelExtractFunc,
outputs: 1,
x: 370,
y: maxY + 80,
wires: [['demo_meas_pt_w_up']]
},
{
id: 'demo_meas_pt_w_up',
type: 'measurement',
z: 'demo_tab_wwtp',
name: 'PT-W-UP (West Upstream)',
...ptBaseConfig,
i_min: 0, i_max: 5000, o_min: 0, o_max: 5000,
simulator: false,
uuid: 'pt-w-up-001',
supplier: 'Endress+Hauser',
model: 'Cerabar-PMC51',
unit: 'mbar',
assetTagNumber: 'PT-W-UP',
positionVsParent: 'upstream',
x: 580,
y: maxY + 80,
wires: [['demo_link_process_out'], ['demo_link_influx_out'], ['demo_pump_w1', 'demo_pump_w2']]
},
// PS West downstream PT (simulated)
{
id: 'demo_meas_pt_w_down',
type: 'measurement',
z: 'demo_tab_wwtp',
name: 'PT-W-DN (West Downstream)',
...ptBaseConfig,
i_min: 0, i_max: 5000, o_min: 0, o_max: 5000,
simulator: true,
uuid: 'pt-w-dn-001',
supplier: 'Endress+Hauser',
model: 'Cerabar-PMC51',
unit: 'mbar',
assetTagNumber: 'PT-W-DN',
positionVsParent: 'downstream',
x: 580,
y: maxY + 140,
wires: [['demo_link_process_out'], ['demo_link_influx_out'], ['demo_pump_w1', 'demo_pump_w2']]
},
// --- PS North upstream PT ---
{
id: 'demo_fn_level_to_pressure_n',
type: 'function',
z: 'demo_tab_wwtp',
name: 'Level\u2192Pressure (North)',
func: levelExtractFunc,
outputs: 1,
x: 370,
y: maxY + 220,
wires: [['demo_meas_pt_n_up']]
},
{
id: 'demo_meas_pt_n_up',
type: 'measurement',
z: 'demo_tab_wwtp',
name: 'PT-N-UP (North Upstream)',
...ptBaseConfig,
i_min: 0, i_max: 5000, o_min: 0, o_max: 5000,
simulator: false,
uuid: 'pt-n-up-001',
supplier: 'Endress+Hauser',
model: 'Cerabar-PMC51',
unit: 'mbar',
assetTagNumber: 'PT-N-UP',
positionVsParent: 'upstream',
x: 580,
y: maxY + 220,
wires: [['demo_link_process_out'], ['demo_link_influx_out'], ['demo_pump_n1']]
},
{
id: 'demo_meas_pt_n_down',
type: 'measurement',
z: 'demo_tab_wwtp',
name: 'PT-N-DN (North Downstream)',
...ptBaseConfig,
i_min: 0, i_max: 5000, o_min: 0, o_max: 5000,
simulator: true,
uuid: 'pt-n-dn-001',
supplier: 'Endress+Hauser',
model: 'Cerabar-PMC51',
unit: 'mbar',
assetTagNumber: 'PT-N-DN',
positionVsParent: 'downstream',
x: 580,
y: maxY + 280,
wires: [['demo_link_process_out'], ['demo_link_influx_out'], ['demo_pump_n1']]
},
// --- PS South upstream PT ---
{
id: 'demo_fn_level_to_pressure_s',
type: 'function',
z: 'demo_tab_wwtp',
name: 'Level\u2192Pressure (South)',
func: levelExtractFunc,
outputs: 1,
x: 370,
y: maxY + 360,
wires: [['demo_meas_pt_s_up']]
},
{
id: 'demo_meas_pt_s_up',
type: 'measurement',
z: 'demo_tab_wwtp',
name: 'PT-S-UP (South Upstream)',
...ptBaseConfig,
i_min: 0, i_max: 5000, o_min: 0, o_max: 5000,
simulator: false,
uuid: 'pt-s-up-001',
supplier: 'Endress+Hauser',
model: 'Cerabar-PMC51',
unit: 'mbar',
assetTagNumber: 'PT-S-UP',
positionVsParent: 'upstream',
x: 580,
y: maxY + 360,
wires: [['demo_link_process_out'], ['demo_link_influx_out'], ['demo_pump_s1']]
},
{
id: 'demo_meas_pt_s_down',
type: 'measurement',
z: 'demo_tab_wwtp',
name: 'PT-S-DN (South Downstream)',
...ptBaseConfig,
i_min: 0, i_max: 5000, o_min: 0, o_max: 5000,
simulator: true,
uuid: 'pt-s-dn-001',
supplier: 'Endress+Hauser',
model: 'Cerabar-PMC51',
unit: 'mbar',
assetTagNumber: 'PT-S-DN',
positionVsParent: 'downstream',
x: 580,
y: maxY + 420,
wires: [['demo_link_process_out'], ['demo_link_influx_out'], ['demo_pump_s1']]
}
];
// Wire PS output port 0 to the level-to-pressure function nodes
const psWest = filtered.find(n => n.id === 'demo_ps_west');
const psNorth = filtered.find(n => n.id === 'demo_ps_north');
const psSouth = filtered.find(n => n.id === 'demo_ps_south');
if (psWest && psWest.wires[0]) psWest.wires[0].push('demo_fn_level_to_pressure_w');
if (psNorth && psNorth.wires[0]) psNorth.wires[0].push('demo_fn_level_to_pressure_n');
if (psSouth && psSouth.wires[0]) psSouth.wires[0].push('demo_fn_level_to_pressure_s');
// Combine and write
const result = [...filtered, ...newNodes];
console.log(`Final flow has ${result.length} nodes`);
fs.writeFileSync(flowPath, JSON.stringify(result, null, 2) + '\n');
console.log('Done! Written to docker/demo-flow.json');