Sinus inflow: 54-270 m³/h (base 0.015 + amplitude 0.06 m³/s), 4 min
period. Peak needs 1-2 pumps, never all 3 = realistic headroom.
PS control: continuous proportional demand when level > stopLevel, not
just when > startLevel && filling. Pumps now ramp down smoothly as
basin drains toward stopLevel instead of staying stuck at last setpoint.
pumpingStation e8dd657: dead zone elimination
build_flow.py: sinus tuned for gradual pump scaling visibility
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three fixes:
1. PS outflow triple-counted (pumpingStation c62d8bc): MGC registered
twice + individual pumps registered alongside MGC + dual event
subscription per child. Now: one registration per aggregation level,
one event per child. Volume integration tracks correctly.
2. All 3 pumps always on: minFlowLevel was 1.0 m but startLevel was
2.0 m, so at the moment pumps started the percControl was already
40% → MGC mapped to 356 m³/h → all 3 pumps. Fixed: minFlowLevel
= startLevel (2.0 m) so percControl starts at 0% and ramps
linearly. Now pumps graduate: 1-2 pumps at low level, 3 at high.
3. Generalizable registration rule added as code comments: when a group
aggregator exists (MGC), subscribe to it, not its children. Pick
one event name per measurement type per child.
E2E verified: 2/3 pumps active at 56% fill, volume draining correctly,
pump C at 5.2% ctrl delivering 99 m³/h while pump A stays off.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
generalFunctions 29b78a3 -> 086e5fe:
Schema default machineCurve.nq had a dummy pressure slice at key "1"
with fake data. Deep merge injected it alongside real curve data,
pulling the pressure-dimension spline negative at low pressures.
Fix: default to empty {nq: {}, np: {}}.
rotatingMachine 26e253d -> 510a423:
Tests updated for corrected fValues.min (70000 vs old 1).
Trace instrumentation removed. 91/91 green.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Architecture change: demo is now driven by a sinusoidal inflow into the
pumping station basin, rather than a random demand generator. The basin
fills from the sinus, and PS's levelbased control should start/stop
pumps via MGC when level crosses start/stop thresholds.
Changes:
- Demo Drivers tab: sinus generator (period 120s, base 0.005 + amp 0.03
m³/s) replaces the random demand. Sends q_in to PS via link channel.
- PS config: levelbased mode, 10 m³ basin, startLevel 1.2 m / stopLevel
0.6 m. Volume-based safeties on, time-based off.
- MGC scaling = normalized (was absolute) so PS's percent-based level
control maps correctly.
- Dashboard mode toggle now drives PS mode (levelbased ↔ manual) instead
of per-pump setMode. Slider sends Qd to PS (only effective in manual).
- PS code (committed separately): _controlLevelBased now calls
_applyMachineGroupLevelControl + new Qd topic + forwardDemandToChildren.
KNOWN ISSUE: Basin fills correctly (visible on dashboard), but pumps
don't start when level exceeds startLevel. Likely cause: _pickVariant
for 'level' in _controlLevelBased may not be resolving the predicted
level correctly, or the safetyController is interfering despite
time-threshold being 0. Needs source-level tracing of the PS tick →
_safetyController → _controlLogic → _controlLevelBased path with
logging enabled. To be debugged in the next session.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each node repo now has a CLAUDE.md that declares its S88 hierarchy
level (Control Module / Equipment Module / Unit / Process Cell), the
associated S88 colour, and the placement lane per the superproject's
flow-layout rule set (.claude/rules/node-red-flow-layout.md).
The rule set lives in the superproject only (single source of truth).
Per-node repos reference it. When Claude Code opens a node repo, it
reads the local CLAUDE.md and knows which lane / colour / group to
use when building a multi-node demo or production flow.
Submodule pointer bumps for all 11 nodes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New top-level examples/ folder for end-to-end demos that show how multiple
EVOLV nodes work together (complementing the per-node example flows under
nodes/<name>/examples/). Future end-to-end demos will live as siblings.
First demo: pumpingstation-3pumps-dashboard
- 1 pumpingStation (basin model, manual mode for the demo so it observes
rather than auto-shutting pumps; safety guards disabled — see README)
- 1 machineGroupControl (optimalcontrol mode, absolute scaling)
- 3 rotatingMachine pumps (hidrostal-H05K-S03R curve)
- 6 measurement nodes (per pump: upstream + downstream pressure mbar,
simulator mode for continuous activity)
- Process demand input via dashboard slider (0-300 m3/h) AND auto random
generator (3s tick, [40, 240] m3/h) — both feed PS q_in + MGC Qd
- Auto/Manual mode toggle (broadcasts setMode to all 3 pumps)
- Station-wide Start / Stop / Emergency-Stop buttons
- Per-pump setpoint slider, individual buttons, full status text
- Two trend charts (flow per pump, power per pump)
- FlowFuse dashboard at /dashboard/pumping-station-demo
build_flow.py is the source of truth — it generates flow.json
deterministically and is the right place to extend the demo.
Bumps:
nodes/generalFunctions 43f6906 -> 29b78a3
Fix: childRegistrationUtils now aliases the production
softwareType values (rotatingmachine, machinegroupcontrol) to the
dispatch keys parent nodes check for (machine, machinegroup). Without
this, MGC <-> rotatingMachine and pumpingStation <-> MGC wiring
silently never matched in production even though tests passed.
Demo confirms: MGC reports '3 machine(s) connected'.
Verified end-to-end on Dockerized Node-RED 2026-04-13: pumps reach
operational ~5s after deploy, MGC distributes random demand across them,
basin tracks net flow direction, all dashboard widgets update each second.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
generalFunctions: e50be2e -> 43f6906
Fixes the bug where picking a supplier and then a type left the model
dropdown stuck on "Awaiting Type Selection". Affects every node that
uses the shared assetMenu (measurement, rotatingMachine, pumpingStation,
monster, …). The chained dropdowns now use an explicit downward
cascade with no synthetic change-event dispatch, so the parent handler
can no longer wipe a child after the child was populated.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
measurement: d6f8af4 -> <new>
Fixes a regression in the previous measurement editor commit where a
const Temporal Dead Zone error in oneditprepare aborted the function
before the asset / logger / position menu init ran. Menus are now
kicked off first, mode logic is guarded with try/catch and null-checks.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
measurement: 495b4cf -> d6f8af4
Makes Input Mode the top-level hierarchy in the editor: analog-only and
digital-only field blocks toggle visibility live based on the dropdown,
legacy nodes default to 'analog', channels JSON gets live validation,
and runtime logs an actionable warning when the payload shape doesn't
match the selected mode.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bumps:
- nodes/generalFunctions 75d16c6 -> e50be2e (permissive unit check + measurement schema additions)
- nodes/measurement f7c3dc2 -> 495b4cf (digital mode + dispatcher fix + 59 new tests + rewritten README + UI)
Wiki:
- wiki/manuals/nodes/measurement.md — new user manual covering analog and
digital modes, topic reference, smoothing/outlier methods, unit policy,
and the pre-fix dispatcher bug advisory.
- wiki/sessions/2026-04-13-measurement-digital-mode.md — session note with
findings, fix scope, test additions, and dual-mode E2E results.
- wiki/index.md — links both pages and adds the missing 2026-04-13
rotatingMachine session entry that was omitted from the earlier commit.
Status: measurement is now trial-ready in both analog and digital modes.
71/71 unit tests green (was 12), dual-mode E2E on live Dockerized
Node-RED verifies analog regression and a three-channel MQTT-style
payload (temperature/humidity/pressure) dispatching independently with
per-channel smoothing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bumps:
- nodes/generalFunctions 024db55 -> 75d16c6 (FSM abort recovery + schema sync)
- nodes/rotatingMachine 07af7ce -> 17b8887 (interruptible sequences, dual-curve tests, rewritten README)
Wiki:
- wiki/manuals/nodes/rotatingMachine.md — new user manual covering inputs,
outputs, state machine, supported curves, and troubleshooting.
- wiki/sessions/2026-04-13-rotatingMachine-trial-ready.md — session note
with findings, fixes, test additions, and dual-curve E2E results.
- wiki/index.md — link both and bump updated date.
Status: rotatingMachine is now trial-ready. 91/91 unit tests green, live
Docker E2E verifies shutdown/emergency-stop during ramps and prediction
behaviour across both shipped pump curves (hidrostal-H05K-S03R,
hidrostal-C5-D03R-SHN1).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
rotatingMachine:
- Safety fixes: async input handler, emergencyStop case fix, null guards,
listener cleanup, tick loop race condition, editor timeout
- Prediction: remove efficiency rounding (was breaking NCog/BEP), fix
variant reads, curve anomaly detection
- 43 new tests (76 total)
machineGroupControl:
- Critical: fix flowmovement unit mismatch (m³/s sent where m³/h expected,
pumps never moved from minimum)
- Fix absolute scaling comparison bug, empty Qd block, empty-machines guards
- Add marginal-cost refinement loop: reduces gap to brute-force optimum
from 2.1% to <0.1%
- 2 new test files with NCog distribution and power comparison tests
generalFunctions:
- Fix 3 anomalous power values in hidrostal-H05K-S03R curve data
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- generalFunctions: fix infinite recursion in validateSchema when version string is in schema
- rotatingMachine: fix missing closing brace in emergencystop case block
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix Dockerfile.e2e to install EVOLV properly in Node-RED /data/
- Add measurement node E2E test flow with scaling (4-20mA to 0-5m)
- Add Grafana health check to run-e2e.sh
- Guard pumpingStation demo IIFE with require.main check
- All 10 EVOLV nodes load successfully in containerized Node-RED
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>