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:
279
scripts/update-demo-flow.js
Normal file
279
scripts/update-demo-flow.js
Normal 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');
|
||||
Reference in New Issue
Block a user