Waterschap Brabantse Delta · R&D-lab · uitleg
settler is in EVOLV de digitale twin van een secundaire nabezinktank
(clarifier). Uit één influentstroom (debiet F_in + een 13-species
concentratievector) splitst hij drie stromen: gezuiverd effluent, spuislib
(surplus) en retourslib. Dat gebeurt met één instantane TSS-massabalans —
niet met een bezinkmodel. De node is stateless en event-driven: geen klok,
geen slibvoorraad, geen toestandsmachine; hij herrekent de splitsing telkens als een
influent-commando, een upstream-reactor-stateChange of een TSS-meting
binnenkomt (src/nodeClass.js:6-16). Deze pagina volgt letterlijk wat de code
doet aan de hand van één voorbeeld-trigger, een interactieve console en één
splitsings-figuur die de kernformule getrouw naspeelt.
RnD/EVOLV, submodule
settler @ be671fa96872, na versheids-herverificatie tegen
origin/main (identiek; zie verantwoording onderaan).settler is een S88-Unit (lane L4, kleur #50a8d9;
nodes/settler/CLAUDE.md, S88-tabel). Hij registreert zich typisch als kind
softwareType: 'settler' met positionVsParent: 'downstream' tegen
een reactor, en is zélf parent van drie soorten kinderen: een upstream reactor (die
stateChange vuurt en zo het influent levert), een TSS-meting (die de
target-concentratie C_TS zet) en een downstream retourpomp (die bepaalt
hoeveel slib retour gaat) (CONTRACT.md §Children; src/specificClass.js:27-30).
De node is expliciet een stateless transform — static tickInterval = null:
er is geen periodieke loop, geen interne slibvoorraad en geen tijdsintegrator. Output
verschijnt op het domein-event 'output-changed' via
notifyOutputChanged(); alleen de statusbadge wordt elke 1000 ms gepolld
(src/nodeClass.js:6-17; docs/functional.html:51).
Rode draad door de hele pagina: één nabezinktank op werkpunt
F_in = 120 m³/h, influent-TSS X_TS,in = 4000 mg/L
(index 12 van de 13-species-vector), target retourconcentratie
C_TS = 8000 mg/L (via een TSS-meting gezet; de code-default is 2500) en
een geregistreerde retourpomp op 40 m³/h. Alle getallen in de rode draad zijn met
node tegen de échte Settler-domeincode doorgerekend
(scratchpad/settler-verify.js; testgevallen als commentaar onderaan de
pagina-JS): F_s = 60, effluent 60, spui 20, retour 40 m³/h
(ΣF = F_in).
Het I/O-contract in één oogopslag: kies een verb, stel de velden in,
kopieer het exacte injecteerbare msg, en klik Injecteer ▸ om te zien wat
er uit de drie poorten komt — met live doorgerekende splitsing op de voorbeeld-context
van de rode draad (C_TS 8000 mg/L via TSS-meting, retourpomp 40 m³/h). Elke bewering draagt
een pad:regel-chip. Poortlabels ["process","dbase","parent"].
Er zijn maar twee injecteerbare berichten: het influent-verb (envelope)
en het legacy child.register-topic.
["process","dbase","parent"],
settler.html:26-28). Let op: settler overschrijft
_emitOutputs() (src/nodeClass.js:23-30) — poort 0 draagt de
rúwe 3-berichten-array uit getEffluent, níét door de process-formatter.| Poort | Label | Belangrijkste keys |
|---|---|---|
| 0 | process |
Array van drie Node-RED-berichten, elk
topic:'Fluent', payload:{ inlet, F, C }, timestamp
(src/specificClass.js:57-61): inlet=0 effluent
(F=F_eff, particulaten idx 7–12 op 0 als F_s>0);
inlet=1 spuislib/surplus (F=F_so, particulaten
geconcentreerd); inlet=2 retourslib (F=F_sr). |
| 1 | dbase |
Delta-gecomprimeerde scalar-snapshot via formatMsg(getOutput(), cfg,
'influxdb'); msg.topic = config.general.name. Velden
(src/specificClass.js:124-134): F_in, C_TS,
F_eff, F_surplus, F_return + de platte
metingen-snapshot. Omzetbaar naar frost/json/csv
(settler.html:84-91). |
| 2 | parent |
In _emitOutputs altijd null. De enige
Port-2-emit is de eenmalige startup-handshake
{ topic:'child.register', payload:node.id, positionVsParent, distance }
(BaseNodeAdapter.js:117-132; CONTRACT.md §Outputs). |
De settler staat centraal en is
parent van drie kinderen. Het influent komt binnen als in-process event: de
upstream reactor vuurt stateChange op zijn eigen emitter (niet de
measurements-emitter), waarna de settler reactor.getEffluent pullt. De
TSS-meting zet C_TS via een measurement-event; de retourpomp is een
object-referentie waarvan de settler de flow afleest. De drie Fluent-stromen en de
telemetrie gaan via draden naar downstream consumenten; registratie naar de eigen
parent loopt via poort 2.
Kinderen worden via de ChildRouter
gerouteerd op softwareType (src/specificClass.js:27-30): een
reactor moet upstream zijn (anders een warn) en levert bij
stateChange zijn getEffluent als nieuwe F_in/Cs_in
(src/specificClass.js:86-100); een measurement van type
quantity (tss) zet C_TS (src/specificClass.js:111-120);
een downstream machine wordt de returnPump en krijgt
upstreamSource = this (src/specificClass.js:102-109).
Klik een stap in de lijst (of gebruik ◀ ▶). Boven zie je waar in de massabalans je bent;
rechts wat er gebeurt, de waarde van het rode-draadvoorbeeld op dat punt (met node
tegen de échte Settler-code doorgerekend), en het codepad.
Dit is de complete kernlogica van get getEffluent
(src/specificClass.js:37-62) als één live figuur. Schuif het influentdebiet
F_in, de influent-TSS X_TS,in (= Cs_in[12]), de
target-concentratie C_TS en de retourpomp-flow; de gestapelde balk verdeelt
F_in in effluent / spui / retour volgens
F_s = min(F_in·Cs_in[12]/C_TS, F_in). Let op het
klem-gedrag: zodra X_TS,in > C_TS wordt F_s
begrensd door F_in en valt het effluent op nul.
F_s > 0 worden in het effluent de
particulaten (idx 7–12) op 0 gezet; in het slib worden ze geconcentreerd
met Cs_s[i] = F_in·Cs_in[i]/F_s. Oplosbare species (idx 0–6)
gaan onveranderd mee (src/specificClass.js:50-54).docs/functional.html is illustratief, niet gemodelleerd
(docs/functional.html:51,65; src/specificClass.js:37-62).X_TS,in > C_TS zou F_in·Cs_in[12]/C_TS
groter dan F_in worden; de min(…, F_in) voorkomt negatief
effluent — al het debiet gaat dan naar slib (src/specificClass.js:38;
tests specificClass.basic.test.js:39-47).C_TS = 2500 mg/L ligt onder
een typische influent-TSS; zonder een quantity (tss)-meting die C_TS
ophoogt, klemt het effluent al snel op 0. aanname: in bedrijf
wordt C_TS via meting gezet (src/specificClass.js:24,113-116).F_sr = min(returnPump.flow(measured, atEquipment), F_s) — de pomp
kan nooit méér trekken dan er slib bezinkt; de rest is spui F_so = F_s − F_sr.
Zónder geregistreerde pomp is F_sr = 0 en gaat al het slib naar spui
(src/specificClass.js:42-48).Cs_s[i] = F_in·Cs_in[i]/F_s draait alléén binnen
if (F_s > 0); bij F_s = 0 blijft Cs_s de
ongewijzigde kopie — geen NaN (src/specificClass.js:53-54).C is getypeerd any, dus een array van afwijkende
lengte wordt ongevalideerd overgenomen (handlers.js:28;
commands/index.js:19-22). aanname: een te korte
vector kan downstream problemen geven — geen guard gezien.Er is geen state-machine en geen AUTO/MAN-mode. De "toestand" is uitsluitend de
dataset F_in, Cs_in (13-vector), C_TS en de aangesloten
returnPump (src/specificClass.js:20-25). De statusbadge toont
idle('no influent') (blauw) zolang F_in ≤ 0, anders een groene dot
met F_in/eff/surplus
(src/specificClass.js:136-142). Drie triggers leiden via
notifyOutputChanged() tot nieuwe output: het influent-verb, een
upstream-reactor-stateChange, en een TSS-meting.
generalFunctions/src/configs/settler.json +
editor (settler.html:7-25). Opvallend: geen geometrie- of
slibmodel-parameters — geen tankoppervlak, oppervlaktebelasting of bezinkcoëfficiënten.
De enige "slibparameter" is de constante C_TS = 2500
(src/specificClass.js:24), overschrijfbaar via een TSS-meting, niet via config.| Veld | Default | Betekenis |
|---|---|---|
general.name | "Settler" | leesbare naam; wordt ook het Influx-topic (fallback <softwareType>_<id>). |
functionality.softwareType | "settler" | type voor parent-child-registratie. |
functionality.positionVsParent | "downstream" | positie t.o.v. de eigen parent (enum upstream/atEquipment/downstream). |
processOutputFormat / dbaseOutputFormat | "process" / "influxdb" | uitvoerformaat poort 0 / 1 (dbase ook frost/json/csv). |
general.logging.logLevel | "info" | enum debug/info/warn/error. |
| asset-blok | — | uuid/model/unit/assetTagNumber/frostServer/geoLat/geoLon (FROST-identiteit, settler.html:17-24). |
Alle punten zijn code-observaties d.d. 2026-07-17 (statisch, niet in runtime
geverifieerd); de submodule-tip be671fa96872 is identiek aan
origin/main (herverifieerd 2026-07-17).
ΣF = F_in) en particulaten-op-0 in het effluent, maar geen enkele test sluit
de solids-massa (F·C) over de drie stromen. De oplosbare species (idx 0–6) gaan
onverdund mee met álle stromen (src/specificClass.js:50-52).
aanname: mogelijk een bewuste vereenvoudiging.src/specificClass.js:24,38). aanname:
in bedrijf altijd via meting gezet.influent-commando met
een C-array van afwijkende lengte wordt ongevalideerd overgenomen
(src/commands/handlers.js:28); C is bewust getypeerd
any (commands/index.js:19-22). Geen guard gezien.package.json:19 draait alleen
test/basic, test/integration en test/edge; de
Jest-stijl test/specificClass.test.js in de test-root wordt NIET meegenomen.
aanname: mogelijk onbedoeld._output-manifest.md — vereist door
.claude/rules/output-coverage.md voor output-wijzigingen; nog niet gebackfilld
voor deze node.data.influent,
setInfluent, msg.payload) worden als "unknown" genegeerd
(test/basic/commands.basic.test.js:133-163); child.register blijft
transitioneel op msg.topic (src/commands/index.js:26-36).https://lab.wbd-rd.nl/rnd-lab/projects/evolv-settler.CONTRACT.md en de gedeelde bibliotheek
nodes/generalFunctions/CONTRACT.md.RnD/EVOLV (super-repo 74c4089, 2026-07-03) — submodule
settler geanalyseerd @ be671fa96872, plus het feitendossier van
deze analyse. Analysedatum 2026-07-17.git fetch
gedraaid; origin/main van settler = be671fa96872,
identiek aan de geanalyseerde tip. Geen open fix-branches relevant voor deze node.pad:regel-verwijzing. De interactieve figuur en de console zijn
getrouwe herimplementaties, vooraf met node tegen de échte
Settler-domeincode doorgerekend (testgevallen als commentaar in de pagina-JS);
illustratieve aannames zijn expliciet zo gelabeld.