chore: clean up superproject structure
Some checks failed
CI / lint-and-test (push) Has been cancelled

Move content to correct locations:
- AGENTS.md → .agents/AGENTS.md (with orchestrator reference update)
- third_party/docs/ (8 reference docs) → wiki/concepts/
- manuals/ (12 Node-RED docs) → wiki/manuals/

Delete 23 unreferenced one-off scripts from scripts/ (keeping 5 active).
Delete stale Dockerfile.e2e, docker-compose.e2e.yml, test/e2e/.
Remove empty third_party/ directory.

Root is now: README, CLAUDE.md, LICENSE, package.json, Makefile,
Dockerfile, docker-compose.yml, docker/, scripts/ (5), nodes/, wiki/,
plus dotfiles (.agents, .claude, .gitea).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
znetsixe
2026-04-07 18:01:04 +02:00
parent bac6c620b1
commit 48f790d123
55 changed files with 21 additions and 5670 deletions

127
wiki/concepts/asm-models.md Normal file
View File

@@ -0,0 +1,127 @@
# Activated Sludge Models (ASM1, ASM2d, ASM3)
> **Used by**: `biological-process-engineer` agent, `reactor` node, `monster` node
> **Validation**: Verified against IWA publications, WaterTAP documentation, and peer-reviewed literature
## ASM1 — Activated Sludge Model No. 1
**Source**: Henze, M., Grady, C.P.L., Gujer, W., Marais, G.v.R., Matsuo, T. (1987). IAWPRC Task Group on Mathematical Modelling for Design and Operation of Biological Wastewater Treatment.
**Published**: IWA Scientific and Technical Report No. 1
### 13 Components (State Variables)
| Symbol | Description | Type |
|--------|-------------|------|
| S_I | Soluble inert organic matter | Soluble |
| S_S | Readily biodegradable substrate | Soluble |
| X_I | Particulate inert organic matter | Particulate |
| X_S | Slowly biodegradable substrate | Particulate |
| X_B,H | Active heterotrophic biomass | Particulate |
| X_B,A | Active autotrophic biomass | Particulate |
| X_P | Particulate products from biomass decay | Particulate |
| S_O | Dissolved oxygen | Soluble |
| S_NO | Nitrate and nitrite nitrogen | Soluble |
| S_NH | Ammonium nitrogen (NH₄⁺-N) | Soluble |
| S_ND | Soluble biodegradable organic nitrogen | Soluble |
| X_ND | Particulate biodegradable organic nitrogen | Particulate |
| S_ALK | Alkalinity (molar units) | Soluble |
### 8 Processes
1. **Aerobic growth of heterotrophs**: S_S + S_O + S_NH → X_B,H (Monod kinetics)
2. **Anoxic growth of heterotrophs**: S_S + S_NO + S_NH → X_B,H (denitrification)
3. **Aerobic growth of autotrophs**: S_NH + S_O → X_B,A + S_NO (nitrification)
4. **Decay of heterotrophs**: X_B,H → X_P + X_S (death-regeneration concept)
5. **Decay of autotrophs**: X_B,A → X_P + X_S
6. **Ammonification of soluble organic nitrogen**: S_ND → S_NH
7. **Hydrolysis of entrapped organics**: X_S → S_S
8. **Hydrolysis of entrapped organic nitrogen**: X_ND → S_ND
### Key Kinetic Parameters (default values at 20°C)
| Parameter | Symbol | Default | Unit | Description |
|-----------|--------|---------|------|-------------|
| Max. heterotrophic growth rate | μ_H | 6.0 | d⁻¹ | |
| Half-saturation (substrate) | K_S | 20.0 | g COD/m³ | |
| Half-saturation (oxygen, het.) | K_O,H | 0.2 | g O₂/m³ | |
| Half-saturation (nitrate) | K_NO | 0.5 | g NO₃-N/m³ | |
| Heterotrophic decay rate | b_H | 0.62 | d⁻¹ | |
| Max. autotrophic growth rate | μ_A | 0.8 | d⁻¹ | |
| Half-saturation (ammonia) | K_NH | 1.0 | g NH₃-N/m³ | |
| Half-saturation (oxygen, aut.) | K_O,A | 0.4 | g O₂/m³ | |
| Autotrophic decay rate | b_A | 0.05 | d⁻¹ | |
| Anoxic reduction factor | η_g | 0.8 | — | |
| Hydrolysis rate | k_h | 3.0 | g X_S/(g X_B,H · d) | |
| Yield (heterotrophic) | Y_H | 0.67 | g COD/g COD | |
| Yield (autotrophic) | Y_A | 0.24 | g COD/g N | |
| Fraction to X_P | f_P | 0.08 | — | |
### Temperature Correction
Arrhenius-type: k(T) = k(20) · θ^(T-20)
Common θ values:
- Heterotrophic growth: θ = 1.072
- Autotrophic growth: θ = 1.103 (nitrifiers are very temperature-sensitive)
- Decay: θ = 1.04
### Presentation Format
The model is presented in the **Petersen matrix** (also called Gujer matrix) format, where rows are processes and columns are components. Each cell contains the stoichiometric coefficient for how a process affects a component.
## ASM2d — Activated Sludge Model No. 2d
**Source**: Henze, M., Gujer, W., Mino, T., Matsuo, T., Wentzel, M.C., Marais, G.v.R., van Loosdrecht, M.C.M. (1999)
**Published**: IWA Scientific and Technical Report No. 3; also Water Science & Technology 39(1), 165-182
### Key Extensions over ASM1
- Adds **biological phosphorus removal** by phosphorus accumulating organisms (PAOs)
- Includes **denitrifying PAOs** (simultaneous P-removal and denitrification)
- 19 components, 21 processes
- Models storage of poly-hydroxy-alkanoates (PHA) and polyphosphate (poly-P) by PAOs
- Includes fermentation of readily biodegradable substrate
### Additional Components (beyond ASM1)
- S_F: Fermentable, readily biodegradable substrate
- S_A: Fermentation products (acetate)
- S_PO4: Soluble ortho-phosphate
- X_PAO: Phosphorus accumulating organisms
- X_PP: Poly-phosphate stored by PAOs
- X_PHA: Poly-hydroxy-alkanoates stored by PAOs
## ASM3 — Activated Sludge Model No. 3
**Source**: Gujer, W., Henze, M., Mino, T., van Loosdrecht, M.C.M. (1999); updated in Henze et al. (2001)
**Published**: IWA Scientific and Technical Report No. 9
### Key Differences from ASM1
- **Replaces death-regeneration** with endogenous respiration (conceptually simpler)
- **Introduces storage polymers** (X_STO) for heterotrophic biomass — substrate is first stored, then used for growth
- 13 state variables, 12 reactions
- More suitable for dynamic simulation and control applications
- Eliminates the problematic simultaneous storage/growth ambiguity in ASM1
### Storage-Based Metabolism
In ASM3, heterotrophs first store readily biodegradable substrate as internal storage products (X_STO), then grow on these stored products. This two-step process better reflects observed biological behavior.
## Choosing Between Models
| Criterion | ASM1 | ASM2d | ASM3 |
|-----------|------|-------|------|
| Carbon & nitrogen | Yes | Yes | Yes |
| Phosphorus removal | No | Yes | Via separate Bio-P module |
| Computational cost | Low | High | Medium |
| Calibration effort | Low | High | Medium |
| Best for | Carbon/N only WWTPs | Bio-P plants | Dynamic control |
## Authoritative References
1. Henze, M. et al. (1987). "Activated Sludge Model No. 1" — IAWPRC Scientific and Technical Report No. 1
2. Henze, M. et al. (1995). "Activated Sludge Model No. 2" — IAWQ Scientific and Technical Report No. 3
3. Henze, M. et al. (1999). "Activated Sludge Model No. 2d" — Water Sci. Technol. 39(1), 165-182
4. Gujer, W. et al. (1999). "Activated Sludge Model No. 3" — Water Sci. Technol. 39(1), 183-193
5. Henze, M. et al. (2000). "Activated Sludge Models ASM1, ASM2, ASM2d and ASM3" — IWA Publishing, ISBN 9781900222242
6. Jeppsson, U. (1996). "Modelling Aspects of Wastewater Treatment Processes" — Lund University PhD thesis (comprehensive ASM1 parameter listing)

View File

@@ -0,0 +1,122 @@
# InfluxDB Time-Series Best Practices
> **Used by**: `telemetry-database` agent, `dashboardAPI` node
> **Validation**: Verified against InfluxDB official documentation (v1, v2, v3)
## Tag vs. Field Decision Framework
| Criterion | Use Tag | Use Field |
|-----------|---------|-----------|
| Queried in WHERE clause frequently | Yes | No |
| Used in GROUP BY | Yes | No |
| Low cardinality (< 100 distinct values) | Yes | Acceptable |
| High cardinality (IDs, timestamps, free text) | **Never** | Yes |
| Numeric measurement values | No | Yes |
| Needs aggregation (mean, sum, etc.) | No | Yes |
| Node/station/machine identifier | Yes | No |
| Actual sensor reading | No | Yes |
| Setpoint value | No | Yes |
| Quality flag | Depends* | Yes |
*Quality flags: If you have ≤5 quality levels (good/uncertain/bad), a tag is acceptable. If quality is a numeric score, use a field.
## EVOLV Tag/Field Convention
### Standard Tags (low cardinality, indexed)
```
locationId — Site identifier (e.g., "wwtp-brabant-01")
nodeType — Node type (e.g., "rotatingMachine", "reactor")
nodeName — Instance name (e.g., "pump-01", "reactor-A")
machineType — Equipment type (e.g., "pump", "blower", "valve")
stationId — Parent station identifier
measurementType — Sensor type (e.g., "flow", "pressure", "temperature")
```
### Standard Fields (not indexed, high cardinality)
```
value — Primary measurement value
setpoint — Control setpoint
quality — Data quality score (0.0-1.0)
state — Machine state (numeric code)
power — Power consumption (W)
efficiency — Current efficiency (0.0-1.0)
speed — Rotational speed (RPM or fraction)
position — Valve position (0.0-1.0)
```
## Cardinality Management
### What Is Cardinality?
Series cardinality = unique combinations of (measurement_name × tag_key_1 × tag_key_2 × ... × tag_key_n)
### Cardinality Limits
- **InfluxDB v1/v2 (TSM engine)**: High cardinality degrades query performance and increases memory usage. Keep below ~1M series per database.
- **InfluxDB v3**: Supports infinite series cardinality (new storage engine), but keeping cardinality low still improves query speed.
### Anti-Patterns (NEVER do these)
- Encoding timestamps in tag values
- Using UUIDs or session IDs as tags
- Free-text strings as tags
- Unbounded enum values as tags
- One measurement per sensor (use tags to differentiate instead)
### Good Patterns
- Use a single measurement name per data category
- Differentiate by tags, not by measurement name
- Keep tag value sets bounded and predictable
- Document all tag values in a schema registry
## Retention Policies
### Three-Tier Strategy
| Tier | Retention | Resolution | Purpose |
|------|-----------|------------|---------|
| Hot | 7-30 days | Full resolution (1s-10s) | Real-time dashboards, control loops |
| Warm | 90-365 days | Downsampled (1min-5min) | Trending, troubleshooting |
| Cold | 2-10 years | Heavily aggregated (1h-24h) | Compliance reporting, long-term trends |
### EVOLV Recommended Defaults
- Port 1 data at full resolution: 30 days
- 1-minute aggregates: 1 year
- 1-hour aggregates: 5 years (matches regulatory retention requirements)
## Continuous Queries / Tasks (Downsampling)
### InfluxDB v1: Continuous Queries
```sql
CREATE CONTINUOUS QUERY "downsample_1m" ON "evolv"
BEGIN
SELECT mean("value") AS "value", max("value") AS "max", min("value") AS "min"
INTO "rp_warm"."downsampled_1m"
FROM "telemetry"
GROUP BY time(1m), *
END
```
### InfluxDB v2: Tasks
```flux
option task = {name: "downsample_1m", every: 1m}
from(bucket: "telemetry")
|> range(start: -task.every)
|> aggregateWindow(every: 1m, fn: mean, createEmpty: false)
|> to(bucket: "telemetry-warm")
```
## Query Performance Tips
1. **Always filter by time range first** — time is the primary index
2. **Use tag filters in WHERE** — tags are indexed, fields are not
3. **Avoid regex on tag values** — use exact matches when possible
4. **Limit series scanned** — filter by specific nodeType/nodeName
5. **Use aggregation** — let the database aggregate rather than fetching raw points
6. **Batch writes** — write in batches of 5,000-10,000 points for optimal throughput
## Authoritative References
1. InfluxDB Documentation — "Schema Design and Data Layout" (https://docs.influxdata.com/influxdb/v1/concepts/schema_and_data_layout/)
2. InfluxDB Documentation — "Schema Design Recommendations and Best Practices" (v2/v3)
3. InfluxData Blog — "Time Series Data, Cardinality, and InfluxDB"
4. InfluxDB Documentation — "Resolve High Series Cardinality" (https://docs.influxdata.com/influxdb/v2/write-data/best-practices/resolve-high-cardinality/)
5. InfluxData (2023). "InfluxDB Best Practices" — Official technical guides

View File

@@ -0,0 +1,149 @@
# OT Security Standards — IEC 62443 & NIST SP 800-82
> **Used by**: `ot-security-integration` agent
> **Validation**: Verified against IEC 62443 series, NIST SP 800-82, Dragos, and Rockwell Automation publications
## IEC 62443 Framework Overview
IEC 62443 "Industrial communication networks — IT security for networks and systems" is the primary international standard series for Industrial Automation and Control System (IACS) cybersecurity.
### Standard Structure
| Part | Title | Scope |
|------|-------|-------|
| 62443-1-x | General | Concepts, vocabulary, use cases |
| 62443-2-x | Policies & Procedures | Security management system, patch management |
| 62443-3-x | System | System security requirements, zones & conduits |
| 62443-4-x | Component | Secure development lifecycle, component requirements |
### Key Parts for EVOLV
- **62443-3-2**: Security risk assessment and system design
- **62443-3-3**: System security requirements and security levels
- **62443-4-2**: Technical security requirements for IACS components
## Zones and Conduits
### Security Zone
A **zone** is a logical or physical grouping of assets that share common security requirements. Assets within a zone have the same security level (SL) target.
### Conduit
A **conduit** is a logical or physical grouping of communication channels connecting two or more zones. Conduits require security controls appropriate for the traffic they carry.
### EVOLV Zone Architecture (typical WWTP deployment)
```
Zone 0: Enterprise IT Network (SL 1-2)
↕ [Conduit: Firewall/DMZ]
Zone 1: SCADA/Historian Network (SL 2-3)
↕ [Conduit: Data diode or filtered bridge]
Zone 2: Process Control Network (SL 3)
↕ [Conduit: Managed switch with ACLs]
Zone 3: Field Device Network (SL 2-3)
- PLCs, RTUs, I/O modules
- Node-RED edge runtime (EVOLV)
- Sensors and actuators
```
### Zone Design Rules
- A zone can contain sub-zones
- A conduit cannot contain sub-conduits
- A zone can have more than one conduit
- Every device must belong to exactly one zone
- Communication between zones must pass through a conduit
## Security Levels (SL)
| Level | Protection Against | Typical Measures |
|-------|-------------------|------------------|
| SL 0 | No specific requirements | — |
| SL 1 | Casual or coincidental violation | Basic authentication, logging |
| SL 2 | Intentional attack with low motivation, generic skills | Role-based access, encrypted communications |
| SL 3 | Intentional attack with moderate motivation, IACS-specific skills | Strong authentication, intrusion detection, hardened systems |
| SL 4 | Intentional attack with high motivation, IACS-specific skills, extended resources | Dedicated security team, continuous monitoring, zero-trust |
### SL Types
- **SL-T (Target)**: Required security level for the zone
- **SL-A (Achieved)**: Actual security level implemented
- **SL-C (Capability)**: Maximum security level a component can support
## NIST SP 800-82 — Guide to ICS Security
**Source**: NIST Special Publication 800-82 Revision 3 (2023). "Guide to Operational Technology (OT) Security"
### Key Recommendations
1. Develop and maintain an OT-specific security program
2. Segment OT networks from IT networks (defense in depth)
3. Apply least privilege access control
4. Monitor OT network traffic for anomalies
5. Maintain an accurate OT asset inventory
6. Implement secure remote access with MFA
7. Develop OT-specific incident response plans
8. Regularly assess and manage OT security risks
## OPC UA Security Model
### Authentication
- X.509 certificates for server and client authentication
- Username/password as fallback (less secure)
- Anonymous access (should be disabled in production)
### Encryption
- Security policies define algorithm suites:
- `None` — No security (testing only)
- `Basic128Rsa15` — Deprecated, avoid
- `Basic256` — Deprecated, avoid
- `Basic256Sha256` — Minimum recommended
- `Aes128_Sha256_RsaOaep` — Preferred
- `Aes256_Sha256_RsaPss` — Strongest
### Message Security Modes
- `None` — No signing or encryption
- `Sign` — Messages signed but not encrypted
- `SignAndEncrypt` — Full protection (recommended)
## Modbus Security Considerations
### Vulnerabilities (standard Modbus TCP)
- No authentication — any network client can read/write registers
- No encryption — all traffic is plaintext
- No integrity protection — commands can be modified in transit
- Predictable function codes — easy to craft malicious packets
### Mitigations
1. Network segmentation — isolate Modbus devices in dedicated VLANs
2. Firewall rules — whitelist only authorized master IP addresses
3. Application-layer filtering — deep packet inspection for Modbus function codes
4. Monitoring — detect unusual register access patterns
5. Modbus/TCP Security (TLS) — available in newer implementations (RFC 7878-based)
## EVOLV-Specific Security Considerations
### Node-RED Admin Endpoints
- `GET /<nodeName>/menu.js` — Serves configuration data to editor
- `GET /<nodeName>/configData.js` — Serves runtime config to editor
- **Risk**: Information disclosure if exposed beyond editor network
- **Mitigation**: Bind Node-RED to localhost or trusted network only
### msg.topic Input Validation
- All `msg.topic` handlers must validate topic format before processing
- Prevent topic injection: reject topics containing path separators, special characters
- Validate payload types and ranges before applying to control logic
### Dynamic Configuration
- Configuration loaded from files or received via MQTT
- Must validate schema, types, and value ranges before applying
- Reject configurations that would violate safety envelopes
### Control Message Safety
- Validate actuator commands against physical limits before sending
- Rate-limit control output changes (prevent rapid cycling)
- Log all control actions with timestamp, source, and reason
## Authoritative References
1. IEC 62443 series (2018-2024). "Industrial communication networks — IT security for networks and systems"
2. NIST SP 800-82 Rev 3 (2023). "Guide to Operational Technology (OT) Security"
3. Dragos Inc. — "Understanding ISA/IEC 62443: A Guide for OT Security Teams" (https://www.dragos.com/blog/isa-iec-62443-concepts)
4. ISA/IEC 62443-3-3 — "System Security Requirements and Security Levels"
5. OPC Foundation — "OPC UA Security Model" specification
6. Modbus Organization — "MODBUS/TCP Security" specification

View File

@@ -0,0 +1,168 @@
# PID Control for Process Applications
> **Used by**: `mechanical-process-engineer` agent, `node-red-runtime` agent, `generalFunctions/src/pid/`
> **Validation**: Verified against Astrom & Hagglund (ISA, 2006) and MATLAB/Simulink documentation
## Continuous PID Controller
### Standard (ISA/Ideal) Form
```
u(t) = K_p · [e(t) + (1/T_i) · ∫e(τ)dτ + T_d · de(t)/dt]
```
Where:
- u(t) = controller output
- e(t) = error = setpoint - process variable (SP - PV)
- K_p = proportional gain
- T_i = integral time (seconds)
- T_d = derivative time (seconds)
### Parallel Form
```
u(t) = K_p · e(t) + K_i · ∫e(τ)dτ + K_d · de(t)/dt
```
Where K_i = K_p/T_i and K_d = K_p · T_d
## Discrete PID Implementation
### Positional Form (absolute output)
```
u[k] = K_p · e[k] + K_i · Δt · Σe[j] + K_d · (e[k] - e[k-1]) / Δt
```
- Computes the absolute output value each cycle
- Requires tracking of the integral sum
- Subject to integral windup
- Used when the controller output directly sets an actuator position
### Velocity Form (incremental output)
```
Δu[k] = K_p · (e[k] - e[k-1]) + K_i · Δt · e[k] + K_d · (e[k] - 2·e[k-1] + e[k-2]) / Δt
u[k] = u[k-1] + Δu[k]
```
- Computes the **change** in output each cycle
- Inherently bumpless on mode transfers (auto→manual→auto)
- Less prone to windup (but still needs anti-windup for output limits)
- Preferred for incremental actuators (VFDs, variable valves)
## Anti-Windup Strategies
Integral windup occurs when the controller output saturates (hits actuator limits) but the integral term continues to accumulate, causing large overshoot when the error changes sign.
### 1. Clamping (Conditional Integration)
Stop integrating when the output is saturated **and** the error has the same sign as the integral term:
```
if (u_raw > u_max || u_raw < u_min) && sign(e) == sign(integral):
freeze integral (do not accumulate)
else:
integral += e * Δt
```
- Simple to implement
- Effective for most process control applications
- The approach used in the EVOLV generalFunctions PID implementation
### 2. Back-Calculation
When the output saturates, feed back the difference between the saturated and unsaturated output to "unwind" the integrator:
```
integral += (K_i · e + K_b · (u_saturated - u_raw)) · Δt
```
Where K_b = 1/T_t (tracking time constant, typically T_t = √(T_i · T_d) or T_t = T_d).
- More sophisticated than clamping
- Better performance for systems with large disturbances
- Recommended by Astrom & Hagglund for demanding applications
### 3. Integrator Reset
Reset the integrator to a value that would produce the saturated output:
```
if u_raw > u_max:
integral = (u_max - K_p · e) / K_i
```
- Simple but can be aggressive
- May cause discontinuities
## Derivative Filtering
The derivative term amplifies high-frequency noise. Always filter it:
### First-Order Low-Pass Filter on D-Term
```
D_filtered[k] = α · D_filtered[k-1] + (1-α) · D_raw[k]
```
Where α = T_f / (T_f + Δt) and T_f = T_d / N (N typically 5-20, default 10).
### Derivative on PV (not Error)
To avoid derivative kick on setpoint changes:
```
D = -K_d · (PV[k] - PV[k-1]) / Δt (instead of using error)
```
This is the standard approach for process control.
## Cascade PID
Two nested loops where the outer (master) loop's output is the setpoint for the inner (slave) loop.
```
[SP_outer] → [PID_outer] → [SP_inner] → [PID_inner] → [Actuator] → [Process]
↑ ↑
[PV_outer] ←──── [Process] ←── [PV_inner]
```
### Design Rules
- Inner loop must be **5-10x faster** than outer loop
- Tune inner loop first (with outer loop in manual)
- Then tune outer loop
- Anti-windup on outer loop essential (its output is bounded by inner loop's SP limits)
### EVOLV Application
- Outer: Level controller → outputs flow setpoint
- Inner: Flow controller → outputs pump speed
- pumpingStation node coordinates this cascade
## Tuning Methods
### Ziegler-Nichols (Ultimate Gain Method)
1. Set I and D to zero, increase K_p until sustained oscillation
2. Record ultimate gain K_u and ultimate period T_u
3. Apply: K_p = 0.6·K_u, T_i = T_u/2, T_d = T_u/8
### Cohen-Coon (Process Reaction Curve)
1. Apply step change, record process reaction curve
2. Identify: gain K, dead time L, time constant τ
3. Apply formulas based on K, L, τ
### Lambda Tuning (IMC-based)
1. Identify process as FOPDT: K, L, τ
2. Choose closed-loop time constant λ (typically λ = max(3·L, τ))
3. K_p = τ/(K·λ), T_i = τ
- **Preferred for process control** — gives non-oscillatory response
- Directly specifies desired closed-loop speed
- Robust to model uncertainty when λ is chosen conservatively
## Authoritative References
1. Astrom, K.J. & Hagglund, T. (2006). "Advanced PID Control." ISA — The Instrumentation, Systems, and Automation Society.
2. Astrom, K.J. & Hagglund, T. (1995). "PID Controllers: Theory, Design, and Tuning." 2nd ed., ISA.
3. Seborg, D.E. et al. (2011). "Process Dynamics and Control." 3rd ed., Wiley. (Chapter on PID control)
4. MATLAB/Simulink documentation — "Anti-Windup Control Using PID Controller Block"
5. Smith, C.A. & Corripio, A.B. (2005). "Principles and Practices of Automatic Process Control." 3rd ed., Wiley.

View File

@@ -0,0 +1,154 @@
# Pump Affinity Laws & Curve Theory
> **Used by**: `mechanical-process-engineer` agent, `rotatingMachine` node, `pumpingStation` node
> **Validation**: Verified against Engineering Toolbox, Hydraulic Institute standards, and ScienceDirect
## Affinity Laws
The affinity laws describe how centrifugal pump performance scales with changes in rotational speed (N) or impeller diameter (D). They are derived from dimensional analysis under the assumption of geometric similarity (velocity triangles at the impeller remain geometrically similar).
### Speed Variation (constant diameter)
```
Q₂/Q₁ = N₂/N₁
H₂/H₁ = (N₂/N₁)²
P₂/P₁ = (N₂/N₁)³
```
### Diameter Variation (constant speed)
```
Q₂/Q₁ = D₂/D₁
H₂/H₁ = (D₂/D₁)²
P₂/P₁ = (D₂/D₁)³
```
### Combined Variation
```
Q₂/Q₁ = (N₂/N₁) · (D₂/D₁)
H₂/H₁ = (N₂/N₁)² · (D₂/D₁)²
P₂/P₁ = (N₂/N₁)³ · (D₂/D₁)³
```
### Practical Example (validated against Engineering Toolbox)
A pump at 1750 rpm delivering 100 gpm at 100 ft head using 5 bhp:
- At 3500 rpm: **200 gpm** flow, **400 ft** head, **40 bhp** power
- A 10% speed increase yields: +10% flow, +21% head, +33% power
### Accuracy Limitations
- Affinity laws are **approximate** — accuracy decreases with large speed changes (>±30%)
- Efficiency shifts slightly with speed change (not captured by basic affinity laws)
- Trimming impeller diameter >15-20% significantly reduces accuracy
- Laws assume no significant change in Reynolds number effects
## Pump Curve Types
### Q-H Curve (Flow vs. Head)
- Primary performance curve
- Head decreases as flow increases (for centrifugal pumps)
- Shape depends on specific speed (Ns): flat, steep, or drooping
- **Monotonicity**: Should be monotonically decreasing for stable operation. Non-monotonic (drooping) curves can cause instability in parallel operation.
### Q-P Curve (Flow vs. Power)
- Power consumption as function of flow
- Shape varies by pump type:
- Radial: power increases with flow (non-overloading possible at shutoff)
- Mixed flow: relatively flat
- Axial: power **decreases** with flow (overload risk at low flow)
### Q-η Curve (Flow vs. Efficiency)
- Efficiency peaks at Best Efficiency Point (BEP)
- Falls off on both sides of BEP
- Operating far from BEP causes excessive vibration, cavitation risk, and energy waste
## Best Efficiency Point (BEP)
The BEP is the operating point where the pump converts the maximum fraction of input power to useful hydraulic work.
### BEP Tracking Under VFD Control
When speed changes via VFD, the BEP shifts along a **parabolic path** in the Q-H plane:
```
H_BEP ∝ Q_BEP²
```
This is because both Q and H scale with speed, but H scales as the square of Q's scaling factor.
### Preferred Operating Region
- Continuous operation: 80% 110% of BEP flow
- Allowable range: 70% 120% of BEP flow
- Outside this range: increased bearing loads, seal wear, cavitation risk
## System Curve Theory
The system curve describes the head required by the piping system as a function of flow:
```
H_system = H_static + k · Q²
```
Where:
- H_static = static head (elevation difference + tank pressure difference)
- k = system resistance coefficient (Pa·s²/m⁶ in SI)
- Q = volumetric flow rate
### Duty Point
The **duty point** (operating point) is the intersection of the pump curve and system curve:
```
H_pump(Q) = H_system(Q)
```
This is solved numerically — find Q where pump curve equals system curve.
## Parallel Pump Operation
### Flow Summation Rule
For pumps in parallel at equal head:
```
Q_total = Q₁ + Q₂ + ... + Qₙ (at each head value)
```
The combined curve is constructed by **horizontally adding** individual pump curves.
### Key Considerations
- Each pump must overcome the same system head
- Adding a pump shifts the combined curve right, moving the operating point
- Diminishing returns: each additional pump adds less incremental flow
- Risk of back-flow through stopped pumps (check valves required)
- Unstable operation if pump curves have a drooping characteristic
## Series Pump Operation
For pumps in series at equal flow:
```
H_total = H₁ + H₂ + ... + Hₙ (at each flow value)
```
The combined curve is constructed by **vertically adding** individual pump curves.
## Specific Energy
The key energy KPI for pumping systems:
```
SE = P / Q [W / (m³/s) = J/m³]
```
More commonly expressed as:
```
SE = P / Q [kWh/m³] (with appropriate unit conversion)
```
Where:
- P = electrical power input (kW)
- Q = volumetric flow rate (m³/h)
- SE = P / Q · (1/1000) for kWh/m³ when P in W and Q in m³/s
### Wire-to-Water Efficiency
```
η_total = η_motor · η_VFD · η_pump = (ρ · g · Q · H) / P_electrical
```
## Authoritative References
1. Karassik, I.J. et al. "Pump Handbook" 4th ed. — McGraw-Hill (comprehensive pump engineering reference)
2. Europump/Hydraulic Institute (2001). "Pump Life Cycle Costs: A Guide to LCC Analysis for Pumping Systems"
3. Engineering Toolbox — "Affinity Laws for Pumps" (https://www.engineeringtoolbox.com/affinity-laws-d_408.html)
4. Hydraulic Institute Standards (HI 9.6.1 — Rotodynamic Pumps Guideline for NPSH Margin)
5. Gülich, J.F. (2014). "Centrifugal Pumps" 3rd ed. — Springer (theoretical foundation)

View File

@@ -0,0 +1,130 @@
# Sludge Settling & Clarifier Models
> **Used by**: `biological-process-engineer` agent, `settler` node
> **Validation**: Verified against Takacs et al. (1991), Vesilind (1968), and Burger-Diehl framework publications
## Vesilind Model — Zone Settling Velocity
**Source**: Vesilind, P.A. (1968). "Design of Prototype Thickeners from Batch Settling Tests." Water Sewage Works, 115, 302-307.
### Equation
```
v_s = v_0 · exp(-k · X)
```
Where:
- v_s = settling velocity (m/h)
- v_0 = maximum initial settling velocity (m/h)
- k = settling parameter (m³/kg or L/g)
- X = suspended solids concentration (kg/m³ or g/L)
### Typical Parameter Ranges for Municipal Wastewater
| Parameter | Typical Range | Unit | Notes |
|-----------|---------------|------|-------|
| v_0 | 4 12 | m/h | ~7.8 m/h is a commonly observed average |
| k | 0.3 0.8 | m³/kg | Correlates with SVI; higher SVI → higher k |
### SVI Correlation
The settling parameter k can be estimated from Sludge Volume Index:
- k ≈ 0.16 + 0.003 · SVI (for SVI in mL/g, k in m³/kg)
- Better correlations use SSVI (Stirred SVI) or DSVI (Diluted SVI)
### Limitations
- Only describes **zone settling** (hindered settling of a blanket)
- Does not capture compression settling at high concentrations
- Does not model the clarification zone (low-concentration region above blanket)
## Takacs Model — Double-Exponential Settling
**Source**: Takacs, I., Patry, G.G., Nolasco, D. (1991). "A dynamic model of the clarification-thickening process." Water Research, 25(10), 1263-1271.
### Equation
```
v_s = v_0 · (exp(-r_h · (X - X_min)) - exp(-r_p · (X - X_min)))
```
Where:
- v_s = settling velocity (m/h)
- v_0 = maximum Vesilind settling velocity (m/h)
- r_h = hindered settling parameter (m³/kg)
- r_p = flocculent settling parameter (m³/kg)
- X = suspended solids concentration (kg/m³)
- X_min = non-settleable fraction (kg/m³)
### Key Innovation
The double-exponential form captures **both** the clarification zone (low concentrations, dominated by the r_p term) and the thickening zone (high concentrations, dominated by the r_h term). This allows simulation of the complete solids profile from effluent to underflow.
### Typical Parameter Values
| Parameter | Typical Range | Default | Unit |
|-----------|---------------|---------|------|
| v_0 | 4 12 | 7.5 | m/h |
| r_h | 0.3 0.8 | 0.576 | m³/kg |
| r_p | 2.0 6.0 | 2.86 | m³/kg |
| X_min | 0 0.1 | 0.01 | kg/m³ |
### Sensitivity
- **r_p** is the most sensitive parameter — it governs effluent suspended solids
- Takacs et al. recommend finding r_p by simulation/calibration
- v_0 and r_h primarily affect the sludge blanket position and underflow concentration
### 1D Layer Model Implementation
The settler is divided into N horizontal layers (typically 10-30). For each layer:
1. Calculate settling velocity from local concentration
2. Apply solids flux theory (gravity flux + bulk flux)
3. Update concentration via mass balance
4. Handle feed layer, overflow, and underflow boundary conditions
## Burger-Diehl Framework — PDE-Based 1D Settler
**Source**: Burger, R., Diehl, S. and various co-authors (2011-present). Multiple publications developing the framework.
### Key Characteristics
- Based on rigorous **partial differential equation** theory (hyperbolic-elliptic PDE)
- Accounts for hindered settling, compression settling, and inlet dispersion
- Every implementation detail is consistent with PDE theory (unlike ad-hoc layer models)
- More realistic prediction of underflow sludge concentration
- Essential for accurate wet-weather modelling
### Advantages Over Takacs Layer Model
- Proper handling of compression settling (important at high MLSS)
- Mathematically rigorous — convergence guaranteed
- Better sludge blanket dynamics during storm events
- Can be extended with reactive terms (ASM1 biokinetics inside settler)
### When to Use Which Model
| Scenario | Recommended Model |
|----------|-------------------|
| Steady-state design | Vesilind + flux theory |
| Dynamic simulation (standard) | Takacs 1D layer model |
| Wet-weather / high-MLSS dynamics | Burger-Diehl PDE model |
| Quick estimation | Vesilind with SVI correlation |
## Flux Theory for Clarifier Design
The solids flux approach combines the gravity settling flux with the bulk (underflow) flux:
```
J_total = J_gravity + J_bulk = v_s(X) · X + Q_u/A · X
```
Where:
- J_total = total solids flux (kg/m²/h)
- v_s(X) = settling velocity at concentration X (from Vesilind or Takacs)
- Q_u = underflow rate (m³/h)
- A = clarifier surface area (m²)
The **limiting flux** determines the maximum solids loading rate — operating above this causes blanket rise and eventual washout.
## Authoritative References
1. Vesilind, P.A. (1968). "Design of Prototype Thickeners from Batch Settling Tests." Water Sewage Works, 115, 302-307.
2. Takacs, I., Patry, G.G., Nolasco, D. (1991). "A dynamic model of the clarification-thickening process." Water Res. 25(10), 1263-1271.
3. Burger, R., Diehl, S., Nopens, I. (2011). "A consistent modelling methodology for secondary settling tanks in wastewater treatment." Water Res. 45(6), 2247-2260.
4. Torfs, E. (2015). "Different settling regimes in secondary settling tanks." PhD thesis, Ghent University.
5. Daigger, G.T. (1995). "Development of refined clarifier operating diagrams using an updated settling characteristics database." Water Environment Research, 67(1), 95-100.

View File

@@ -0,0 +1,157 @@
# Sensor Signal Conditioning & Data Quality
> **Used by**: `instrumentation-measurement` agent, `measurement` node
> **Validation**: Verified against IEC 61298, sensor manufacturer literature, and signal processing references
## Signal Conditioning Pipeline
```
Raw Signal → Scaling → Filtering → Outlier Rejection → Quality Flagging → Output
```
## Scaling: Engineering Unit Conversion
### 4-20 mA Standard
```
value = range_min + (I - 4) / (20 - 4) · (range_max - range_min)
```
Where I is the measured current in mA.
### Key Rules
- 0 mA = wire break (fault condition)
- < 4 mA = under-range or fault
- 4 mA = range minimum (0%)
- 20 mA = range maximum (100%)
- > 20 mA = over-range or fault
- NAMUR NE43 recommends 3.8 mA and 20.5 mA as fault thresholds
## Filtering Methods
### Moving Average
```
y[k] = (1/N) · Σ x[k-i] for i = 0 to N-1
```
- Simple, effective for white noise
- Introduces phase lag proportional to (N-1)/2 samples
- Good for steady-state signals, poor for fast transients
### Exponential Moving Average (EMA)
```
y[k] = α · x[k] + (1-α) · y[k-1]
```
Where α = 2/(N+1) or α = Δt/(τ + Δt) for time-constant-based tuning.
- Less memory than moving average
- Equivalent to first-order low-pass filter
- τ (time constant) sets the cutoff frequency: f_c = 1/(2π·τ)
### Savitzky-Golay Filter
- Fits a polynomial to a window of data points, uses the polynomial value as the filtered output
- Preserves higher-order moments (peaks, edges) better than moving average
- Configurable by window size and polynomial order
- Typical: window = 5-11 points, order = 2-3
## Outlier Detection
### Z-Score Method
```
z = |x - μ| / σ
outlier if z > threshold (typically 3.0)
```
- Assumes normal distribution
- Sensitive to the outliers themselves (they inflate σ)
### Modified Z-Score (MAD-based)
```
MAD = median(|x_i - median(x)|)
modified_z = 0.6745 · (x - median(x)) / MAD
outlier if |modified_z| > threshold (typically 3.5)
```
- Robust to outliers (uses median instead of mean)
- **Recommended for process measurements** where occasional spikes are common
- 0.6745 is the 75th percentile of the standard normal distribution
### IQR Method
```
Q1 = 25th percentile, Q3 = 75th percentile
IQR = Q3 - Q1
outlier if x < Q1 - 1.5·IQR or x > Q3 + 1.5·IQR
```
- Non-parametric, no distribution assumption
- Common in exploratory data analysis
- Less suitable for real-time streaming (needs window of data)
## NRMSE for Drift Detection
Normalized Root Mean Square Error compares a recent measurement window against a reference window to detect sensor drift.
### Calculation
```
RMSE = √(Σ(x_i - x_ref_i)² / N)
NRMSE = RMSE / (x_max - x_min) or RMSE / x_mean
```
### Thresholds (typical for process sensors)
| NRMSE Range | Quality | Action |
|-------------|---------|--------|
| 0 0.05 | Good | Normal operation |
| 0.05 0.15 | Uncertain | Flag for review, increase monitoring |
| 0.15 0.30 | Poor | Alarm, reduce weight in control loops |
| > 0.30 | Bad | Remove from control, maintenance required |
### Reference Window Selection
- Calibration data (gold standard)
- Post-maintenance baseline
- Rolling reference from a known-good period
- Multi-sensor cross-validation
## Sensor Accuracy Classes
### IEC 61298 Framework
IEC 61298 "Process measurement and control devices — General methods and procedures for evaluating performance" defines standardized test methods for evaluating sensor accuracy under reference and influence conditions.
### Key Performance Metrics
- **Accuracy**: Closeness of measured value to true value (includes systematic and random errors)
- **Repeatability**: Closeness of successive measurements under identical conditions
- **Hysteresis**: Maximum difference between upscale and downscale readings
- **Linearity**: Maximum deviation from a straight line between zero and span
- **Deadband**: Smallest change in input that produces a detectable output change
### Common Accuracy Specifications
| Sensor Type | Typical Accuracy | Response Time |
|-------------|-----------------|---------------|
| Pressure transmitter | ±0.04 0.1% FS | < 100 ms |
| Flow meter (electromagnetic) | ±0.2 0.5% of reading | 1-3 s |
| Temperature (RTD/Pt100) | ±0.1 0.3°C | 5-30 s (depends on housing) |
| Level (ultrasonic) | ±0.25% FS | 1-5 s |
| pH | ±0.02 0.1 pH | 10-60 s |
| Dissolved oxygen | ±1-2% of reading | 30-90 s (membrane) |
| Turbidity (nephelometric) | ±2% of reading | 5-15 s |
| Ammonia (ion-selective) | ±5-10% of reading | 60-180 s |
## Sensor States and Warmup
### State Machine
```
Maintenance → Warmup → Active → Cooldown → Maintenance
```
### Warmup Behavior
- **Duration**: Varies by sensor type (seconds for pressure, minutes for pH, hours for dissolved oxygen)
- **During warmup**: Measurements flagged as "uncertain" quality
- **Completion criterion**: Readings stabilize within defined tolerance for a minimum duration
- **EVOLV convention**: Warmup state prevents measurements from propagating to control loops
### Stabilization Detection
```
stable if std_dev(last_N_readings) < threshold for T_stable seconds
```
## Authoritative References
1. IEC 61298 series (2008). "Process measurement and control devices — General methods and procedures for evaluating performance"
2. IEC 61326-2-3. "Electrical equipment for measurement, control and laboratory use — EMC requirements — Part 2-3: Particular requirements — Transducers with integrated or remote signal conditioning"
3. NAMUR NE43 (2003). "Standardization of the Signal Level for the Failure Information of Digital Transmitters"
4. Bently Nevada / Baker Hughes. "Fundamentals of Rotating Machinery Diagnostics"
5. Oppenheim, A.V. & Willsky, A.S. (1997). "Signals & Systems" 2nd ed., Prentice Hall
6. Press, W.H. et al. (2007). "Numerical Recipes" 3rd ed., Chapter 14 (Savitzky-Golay filters)

View File

@@ -0,0 +1,21 @@
# Source Documents
Place actual scientific papers, standards, and technical manuals here. Reference them from the summary files in the parent directory.
## Suggested Sources to Add
- IWA Scientific and Technical Report No. 1 — ASM1 (Henze et al., 1987)
- IWA Scientific and Technical Report No. 3 — ASM2d (Henze et al., 1999)
- IWA Scientific and Technical Report No. 9 — ASM3 (Gujer et al., 1999)
- Takacs et al. (1991) "A dynamic model of the clarification-thickening process" Water Res. 25(10), 1263-1271
- Astrom & Hagglund (2006) "Advanced PID Control" ISA
- Karassik et al. "Pump Handbook" McGraw-Hill
- Europump/Hydraulic Institute "Pump Life Cycle Costs"
- IEC 62443 series (OT security)
- IEC 61298 series (process measurement)
- EU Directive 91/271/EEC (Urban Waste Water Treatment)
- NIST SP 800-82 Rev 3 (Guide to ICS Security)
## File Naming Convention
`<author-year>-<short-title>.pdf` — e.g., `takacs-1991-clarification-thickening.pdf`

View File

@@ -0,0 +1,117 @@
# Dutch Wastewater Regulations & Compliance
> **Used by**: `commissioning-compliance` agent, `biological-process-engineer` agent
> **Validation**: Verified against EU Directive 91/271/EEC, Activiteitenbesluit milieubeheer, and Dutch water authority publications
## Regulatory Framework
### European Level
- **EU Urban Waste Water Treatment Directive 91/271/EEC** — Primary directive governing collection, treatment, and discharge of urban wastewater across all EU member states
- **Water Framework Directive 2000/60/EC** — Establishes river basin management and environmental quality standards
- **Revised UWWTD (2024)** — Updated directive with stricter nutrient limits and energy neutrality targets
### Dutch National Level
- **Waterwet** (Water Act) — National water management framework
- **Waterschapswet** (Water Authority Act) — Governance of regional water authorities
- **Activiteitenbesluit milieubeheer** — General rules for environmental activities including wastewater discharge
- **Besluit lozing afvalwater huishoudens** — Rules for domestic wastewater discharge
### Regional Level
- **Waterschap Brabantse Delta** — Regional water authority managing the target WWTP
- Operates under national framework with site-specific discharge permits (watervergunning)
## EU UWWTD Effluent Standards (Annex I)
### Table 1: Secondary Treatment Requirements
| Parameter | Concentration | Min. Reduction |
|-----------|--------------|----------------|
| BOD₅ (at 20°C, without nitrification) | 25 mg/L O₂ | 70-90% |
| COD | 125 mg/L O₂ | 75% |
| TSS (Total Suspended Solids) | 35 mg/L | 90% (>10,000 p.e.) |
| TSS (Total Suspended Solids) | 60 mg/L | 70% (2,000-10,000 p.e.) |
### Table 2: Nutrient Requirements for Sensitive Areas
| Parameter | Concentration | Min. Reduction |
|-----------|--------------|----------------|
| Total Phosphorus (10,000-100,000 p.e.) | 2 mg/L P | 80% |
| Total Phosphorus (>100,000 p.e.) | 1 mg/L P | 80% |
| Total Nitrogen (10,000-100,000 p.e.) | 15 mg/L N | 70-80% |
| Total Nitrogen (>100,000 p.e.) | 10 mg/L N | 70-80% |
*Note: The Netherlands designated its entire territory as a "sensitive area" under the UWWTD, meaning nutrient requirements (Table 2) apply to all significant WWTPs.*
### Dutch Practice (Often Stricter)
Dutch water authorities commonly set stricter limits than the EU minimum:
| Parameter | Typical Dutch Permit Limit | EU Minimum |
|-----------|---------------------------|------------|
| N-total | 5-10 mg/L | 10-15 mg/L |
| P-total | 0.3-1.0 mg/L | 1-2 mg/L |
| BOD₅ | 5-10 mg/L | 25 mg/L |
| COD | 50-100 mg/L | 125 mg/L |
| TSS | 10-20 mg/L | 35 mg/L |
| NH₄-N | 1-2 mg/L | Not specified in UWWTD |
*Note: Actual permit limits are site-specific. The values above represent common ranges for Dutch WWTPs.*
## Monitoring and Reporting Obligations
### Sampling Requirements (UWWTD Annex I, Table 3)
| Plant Size | Min. Annual Samples |
|------------|-------------------|
| 2,000-9,999 p.e. | 12 |
| 10,000-49,999 p.e. | 12 |
| ≥50,000 p.e. | 24 |
### Compliance Assessment
- Based on **annual averages** for most parameters
- A defined number of samples may fail while still meeting compliance (concentration limits)
- Percentage reduction assessed against influent loading
### Reporting Chain
1. WWTP operator monitors and reports to water authority
2. Water authority (Waterschap) reports to Province
3. Province reports to national government (IenW)
4. National government reports to European Commission
## Waterschap Brabantse Delta Context
### Service Area
- Province of Noord-Brabant (western part)
- Multiple WWTPs of varying sizes
- Mixed urban/agricultural/industrial catchment
### Key Challenges
- Agricultural runoff contributing nutrient loading
- Seasonal variations in flow and temperature
- Emerging contaminants (pharmaceuticals, microplastics)
- Energy efficiency targets (energy-neutral WWTP goal)
### EVOLV Relevance
- Process automation targets: optimizing energy use while maintaining effluent quality
- Real-time monitoring: continuous measurement of key parameters (NH₄, NO₃, PO₄, DO, TSS)
- Predictive control: using ASM models to anticipate process changes
- Reporting support: automated telemetry data for compliance reporting
## Key Compliance Parameters for EVOLV
| Parameter | Measurement Method | EVOLV Node | Typical Control Strategy |
|-----------|-------------------|------------|-------------------------|
| NH₄-N | Ion-selective electrode | measurement | Aeration control (DO setpoint cascade) |
| NO₃-N | UV absorption / ISE | measurement | Anoxic zone recirculation control |
| PO₄-P | Colorimetric / ISE | measurement | Chemical dosing or Bio-P optimization |
| DO | Amperometric / optical | measurement | Blower/diffuser control |
| TSS/MLSS | Optical (turbidity) | measurement | Sludge wasting control |
| Flow | Electromagnetic | measurement | Hydraulic load monitoring |
| Temperature | RTD/Pt100 | measurement | Process rate compensation |
## Authoritative References
1. Council Directive 91/271/EEC (1991). "Concerning urban waste water treatment" — Official Journal L 135/40
2. Directive (EU) 2024/3019. "Concerning urban wastewater treatment (recast)"
3. Activiteitenbesluit milieubeheer — Dutch Activities Decree (environmental management)
4. Waterschapswet — Dutch Water Authority Act
5. STOWA (Stichting Toegepast Onderzoek Waterbeheer) — Dutch Foundation for Applied Water Research (various publications on WWTP optimization)
6. Waterschap Brabantse Delta — Regional water management plans and discharge permits

View File

@@ -20,6 +20,14 @@ updated: 2026-04-07
## Core Concepts
- [generalFunctions API](concepts/generalfunctions-api.md) — logger, MeasurementContainer, configManager, etc.
- [Pump Affinity Laws](concepts/pump-affinity-laws.md) — Q ∝ N, H ∝ N², P ∝ N³
- [ASM Models](concepts/asm-models.md) — activated sludge model kinetics
- [PID Control Theory](concepts/pid-control-theory.md) — proportional-integral-derivative control
- [Settling Models](concepts/settling-models.md) — secondary clarifier sludge settling
- [Signal Processing for Sensors](concepts/signal-processing-sensors.md) — sensor conditioning
- [InfluxDB Schema Design](concepts/influxdb-schema-design.md) — telemetry data model
- [OT Security (IEC 62443)](concepts/ot-security-iec62443.md) — industrial security standard
- [Wastewater Compliance NL](concepts/wastewater-compliance-nl.md) — Dutch regulatory requirements
## Findings
- [BEP-Gravitation Proof](findings/bep-gravitation-proof.md) — within 0.1% of brute-force optimum (proven)
@@ -28,21 +36,18 @@ updated: 2026-04-07
- [Pump Switching Stability](findings/pump-switching-stability.md) — 1-2 transitions, no hysteresis (proven)
- [Open Issues (2026-03)](findings/open-issues-2026-03.md) — diffuser, monster refactor, ML relocation, etc.
## Manuals
- [FlowFuse Dashboard Layout](manuals/node-red/flowfuse-dashboard-layout-manual.md)
- [FlowFuse Widget Catalog](manuals/node-red/flowfuse-widgets-catalog.md)
- [Node-RED Function Patterns](manuals/node-red/function-node-patterns.md)
- [Node-RED Runtime](manuals/node-red/runtime-node-js.md)
- [Messages and Editor Structure](manuals/node-red/messages-and-editor-structure.md)
## Sessions
- [2026-04-07: Production Hardening](sessions/2026-04-07-production-hardening.md) — rotatingMachine + machineGroupControl
## Other Documentation (outside wiki)
- `CLAUDE.md` — Claude Code project guide (root)
- `AGENTS.md` — agent routing table, orchestrator policy (root, used by `.claude/agents/`)
- `.agents/AGENTS.md` — agent routing table, orchestrator policy
- `.agents/` — skills, decisions, function-anchors, improvements
- `.claude/` — Claude Code agents and rules
- `manuals/node-red/` — FlowFuse dashboard and Node-RED reference docs
## Not Yet Documented
- Parent-child registration protocol (Port 2 handshake)
- Prediction health scoring algorithm (confidence 0-1)
- MeasurementContainer internals (chainable API, delta compression)
- PID controller implementation
- reactor / settler / monster / measurement / valve nodes
- pumpingStation node (uses rotatingMachine children)
- InfluxDB telemetry format (Port 1)

10
wiki/manuals/README.md Normal file
View File

@@ -0,0 +1,10 @@
# Manuals
Local reference manuals used by EVOLV agents while implementing and reviewing Node-RED behavior.
- `manuals/node-red/INDEX.md`: Node-RED manual index and quick usage map.
- `manuals/node-red/runtime-node-js.md`: Runtime custom node message handling (`send`, `done`, multi-output arrays).
- `manuals/node-red/function-node-patterns.md`: Function-node return/send patterns for output routing.
- `manuals/node-red/messages-and-editor-structure.md`: Message shape and HTML/editor/runtime contracts.
- `manuals/node-red/flowfuse-ui-chart-manual.md`: FlowFuse `ui-chart` data contract and runtime controls.
- `manuals/node-red/flowfuse-dashboard-layout-manual.md`: Compact FlowFuse dashboard layout guidance.

View File

@@ -0,0 +1,30 @@
# Node-RED Manual Index
This folder summarizes official Node-RED docs that are relevant to EVOLV node development.
## Official Sources
- Creating Nodes: JavaScript file and message handling
https://nodered.org/docs/creating-nodes/node-js
- Creating Nodes: Edit dialog and node definition in `.html`
https://nodered.org/docs/creating-nodes/edit-dialog
- Working with messages
https://nodered.org/docs/user-guide/messages
- Writing Functions (return arrays, multiple outputs, async send/done)
https://nodered.org/docs/user-guide/writing-functions
## What To Check First (EVOLV)
1. Runtime routing in `src/nodeClass.js`: use explicit output arrays for multi-output nodes.
2. Input handlers: use `send` + `done` pattern from Node-RED runtime docs.
3. Function nodes in example flows: return arrays with output-position alignment.
4. Editor/runtime parity: properties in `RED.nodes.registerType(...defaults...)` must map to runtime config parsing.
5. For FlowFuse dashboard reference, see:
- `flowfuse-widgets-catalog.md` — master index of all 22 widget types
- `flowfuse-ui-chart-manual.md` — chart widget (line, bar, scatter, pie, histogram)
- `flowfuse-ui-gauge-manual.md` — gauge widget (tile, battery, tank, half, 3/4 arc)
- `flowfuse-ui-text-manual.md` — text display widget
- `flowfuse-ui-template-manual.md` — custom Vue/Vuetify template widget
- `flowfuse-ui-button-manual.md` — button widget
- `flowfuse-ui-config-manual.md` — config nodes (ui-base, ui-page, ui-group, ui-theme)
- `flowfuse-dashboard-layout-manual.md` — layout patterns and sizing rules

View File

@@ -0,0 +1,47 @@
# FlowFuse Dashboard Layout Notes (EVOLV Reference)
Primary sources:
- https://dashboard.flowfuse.com/
- https://dashboard.flowfuse.com/nodes/widgets/ui-chart.html
## Compact Screen Guidelines
- Use a 12-column page grid and place charts in 4-column blocks for 3-up rows.
- Disable legends for single-series charts to reduce visual noise.
- Prefer concise text widgets under charts for state/timing/snapshot summaries.
- Use compact theme spacing:
- lower page padding
- lower group gap
- lower widget gap
## Time Window Guidelines
- For live demos, default chart history to 10-15 minutes.
- Keep axis labels short and unit-specific.
- Use one chart per KPI unless comparison is intentionally needed.
## Message Hygiene For Widgets
- Chart widgets: send minimal `{ topic, payload, timestamp }`.
- Text widgets: send plain string in `msg.payload`.
- Separate chart and text outputs by Function-node output index.
## Gauge Sizing in Groups
- **Tank gauge**: `width: 2, height: 4` — tall vertical fill indicator.
- **3/4 arc gauge**: `width: 2, height: 3` — fits beside tank in same group row.
- **Status text**: `width: 4, height: 1` — full group width, below gauges.
- In a 4-column group, two `width: 2` gauges sit side by side, text below spans full width.
- Set `order` on widgets: tank=2, arc=3, text=1 (text first = top, gauges below; or tank=1, arc=2, text=3 for gauges on top).
## Group Height Auto-sizing
- Set `height: "1"` on groups to auto-grow with content.
- A group with a `height: 4` tank + `height: 1` text will auto-expand to ~5 rows.
## References
- FlowFuse Dashboard docs root: https://dashboard.flowfuse.com/
- FlowFuse `ui-chart` docs: https://dashboard.flowfuse.com/nodes/widgets/ui-chart.html
- FlowFuse Widget catalog: [flowfuse-widgets-catalog.md](flowfuse-widgets-catalog.md)
- FlowFuse Config nodes: [flowfuse-ui-config-manual.md](flowfuse-ui-config-manual.md)

View File

@@ -0,0 +1,62 @@
# FlowFuse `ui-button` Manual (EVOLV Reference)
Source: https://dashboard.flowfuse.com/nodes/widgets/ui-button.html
## Purpose
Clickable button that sends a message on user interaction.
## Properties
| Property | Type | Dynamic | Notes |
|----------|------|---------|-------|
| `group` | ref | No | Parent ui-group |
| `width` | int | No | Columns |
| `height` | int | No | Row units |
| `label` | string | Yes | Button text |
| `icon` | string | Yes | Material Design icon name (no `mdi-` prefix) |
| `iconPosition` | string | Yes | `"left"` or `"right"` |
| `buttonColor` | string | Yes | Background color |
| `textColor` | string | Yes | Label color (auto-calculated if omitted) |
| `iconColor` | string | Yes | Icon color (matches text if omitted) |
| `tooltip` | string | No | Hover tooltip |
| `order` | int | No | Position in group |
| `emulateClick` | bool | No | Trigger click on any received msg |
## Events
| Event | Enabled By | Output |
|-------|-----------|--------|
| Click | `onclick: true` | `msg.payload` = configured value |
| Pointer Down | `onpointerdown: true` | `msg.payload` + `msg._event` with timestamp |
| Pointer Up | `onpointerup: true` | `msg.payload` + `msg._event` with timestamp |
Hold duration = `pointerup._event.timestamp - pointerdown._event.timestamp`.
## Input
`msg.payload` — sets button payload value. With `emulateClick: true`, any input msg triggers a click.
`msg.enabled``true` / `false` to enable/disable the button.
## Dynamic Properties (`msg.ui_update`)
```js
msg.ui_update = {
label: "Stop",
icon: "stop",
iconPosition: "left",
buttonColor: "#f44336",
textColor: "#ffffff",
iconColor: "#ffffff",
class: "my-btn-class"
};
```
## EVOLV Key Rules
1. Use buttons for operator actions (start/stop pump, acknowledge alarm).
2. Set `emulateClick: false` (default) — don't auto-trigger on incoming messages.
3. For toggle buttons, update label/color dynamically via `msg.ui_update` from downstream logic.
4. Pair with confirmation dialog (ui-notification or ui-template) for destructive actions.
5. Standard sizing: `width: 2, height: 1` for inline; `width: 4, height: 1` for full-width in 4-col group.

View File

@@ -0,0 +1,121 @@
# FlowFuse `ui-chart` Manual (EVOLV Reference)
Source: https://dashboard.flowfuse.com/nodes/widgets/ui-chart.html
## Chart Types
| Type | X-Axis Options | Notes |
|------|---------------|-------|
| Line | timescale, linear, categorical | Interpolation: linear, step, bezier, cubic, cubic-mono |
| Bar | categorical | Grouped (side-by-side) or stacked |
| Scatter | timescale, linear, categorical | Configurable point shape & radius |
| Pie / Doughnut | radial | Nested series for multi-layer |
| Histogram | auto-binned | Numerical bins or categorical counting |
## Properties
| Property | Type | Dynamic | Notes |
|----------|------|---------|-------|
| `group` | ref | No | Parent ui-group |
| `width` | int | No | Columns |
| `height` | int | No | Row units |
| `label` | string | No | Chart title |
| `chartType` | string | No | `"line"`, `"bar"`, `"scatter"`, `"pie"`, `"histogram"` |
| `showLegend` | bool | No | Show series legend |
| `action` | string | Yes | `"append"` or `"replace"` |
| `pointShape` | string | No | Point marker shape (scatter/line) |
| `xAxisLimit` | int | No | Max data points to keep |
| `textColor` | color | No | Override text color |
| `gridColor` | color | No | Override grid lines |
| `xAxisType` | string | No | `"time"`, `"linear"`, `"category"` |
## Series Configuration
| Source | How It Works |
|--------|-------------|
| `msg.topic` | Default — each unique topic creates a series |
| `key` | Uses a named property from data object |
| `JSON` | Array of keys for multi-series from single msg |
| (blank) | Auto-generates timestamp for x |
## Input Format
### Simple (recommended for EVOLV)
```js
{ topic: "PS West Level", payload: 2.34, timestamp: Date.now() }
```
### Object with x/y mapping
```js
{ payload: { time: 1700000000000, value: 2.34 } }
// Configure x → "time", y → "value"
```
### Nested access
X/Y keys support dot notation: `"nested.value"``payload.nested.value`
## Dynamic Properties
| Property | Path | Notes |
|----------|------|-------|
| Action | `msg.action` | `"append"` or `"replace"` |
| Chart Options | `msg.ui_update.chartOptions` | eCharts config merge |
| CSS Class | `msg.class` | Add custom class |
## eCharts Customization (`msg.ui_update.chartOptions`)
Deep-merges with existing config. Accumulates across messages.
```js
msg.ui_update = {
chartOptions: {
yAxis: { position: "right", name: "Level (m)" },
grid: { top: 60, right: 40 },
title: { text: "Basin Levels", textStyle: { fontSize: 14 } }
}
};
```
**Series colors** — must provide all series configs together:
```js
msg.ui_update = {
chartOptions: {
series: [
{ name: "PS West", type: "line", lineStyle: { color: "#2196f3" }, itemStyle: { color: "#2196f3" } },
{ name: "PS North", type: "line", lineStyle: { color: "#ff9800" }, itemStyle: { color: "#ff9800" } }
]
}
};
```
## Data Actions
| Action | How | Effect |
|--------|-----|--------|
| Append | `msg.action = "append"` (default) | Add points to existing data |
| Replace | `msg.action = "replace"` | Clear then add |
| Clear | `msg.payload = []` | Remove all data |
## Time Formatting Tokens
`{HH}:{mm}:{ss}``12:00:00`
`{yyyy}-{M}-{d}``2020-1-1`
Tokens: `{yyyy}`, `{MM}`, `{dd}`, `{HH}`, `{H}`, `{hh}`, `{h}`, `{mm}`, `{m}`, `{ss}`, `{s}`, `{eeee}` (day name)
## EVOLV Key Rules
1. Send minimal `{ topic, payload, timestamp }` — chart auto-uses topic for series.
2. Set `category: "topic"`, `categoryType: "msg"` in node config — blank category causes editor validation errors.
3. For timeseries: leave x-key blank → auto-timestamp. Supply ms timestamps if custom.
4. For multi-station overlay charts: each station sends with a different `msg.topic`.
5. Use `msg.action = "append"` (default) for streaming data; `"replace"` for snapshot updates.
6. Keep one topic per chart for simple KPIs; use multi-topic for comparison views.
7. Prefer explicit output-slot routing: `node.send([msgForChart, msgForText, ...]); return null;`
## Common Failure Modes
- Payload is not numeric (string/object without y-key config)
- Function node returns to wrong output index
- Topic churn creates unexpected series fragmentation
- Chart has stale data policy mismatch (`append` vs `replace`)
- Blank `category` field causes red node on deploy

View File

@@ -0,0 +1,103 @@
# FlowFuse Config Nodes Manual (EVOLV Reference)
Sources:
- https://dashboard.flowfuse.com/nodes/config/ui-base.html
- https://dashboard.flowfuse.com/nodes/config/ui-page.html
- https://dashboard.flowfuse.com/nodes/config/ui-group.html
- https://dashboard.flowfuse.com/nodes/config/ui-theme.html
---
## `ui-base` — Dashboard Root
| Property | Type | Notes |
|----------|------|-------|
| `path` | string | URL path after host, e.g. `/dashboard` |
| `appIcon` | string | URL to square icon (192512px) for PWA |
| `includePagePath` | bool | Show page paths in side nav |
| `navigationStyle` | string | `"default"`, `"fixed"`, `"icon"`, `"temporary"`, `"none"` |
| `headerStyle` | string | `"default"` (scrolls), `"fixed"` (sticky), `"hidden"` |
| `headerContent` | string | `"page"`, `"dashboard"`, `"both"`, `"none"` |
---
## `ui-page` — Dashboard Page
| Property | Type | Notes |
|----------|------|-------|
| `name` | string | Displayed in nav and header |
| `ui` | ref | Parent ui-base |
| `path` | string | URL path segment, e.g. `/influent` |
| `icon` | string | Material Design icon (no `mdi-` prefix) |
| `theme` | ref | ui-theme reference |
| `layout` | string | `"grid"`, `"fixed"`, `"notebook"`, `"tabs"` |
| `order` | int | Position in navigation |
| `breakpoints` | array | See breakpoints table |
### Layout Types
| Layout | Description |
|--------|-------------|
| `grid` | Responsive grid, widgets flow into columns |
| `fixed` | Absolute positioned, no responsive reflow |
| `notebook` | Single-column stacked groups |
| `tabs` | Each group becomes a tab |
### Default Breakpoints (grid/notebook/tabs)
| Name | Min Width | Columns |
|------|-----------|---------|
| Mobile | 0 px | 3 |
| Medium | 576 px | 6 |
| Tablet | 768 px | 9 |
| Desktop | 1024 px | 12 |
---
## `ui-group` — Widget Container
| Property | Type | Notes |
|----------|------|-------|
| `name` | string | Group title (shown if `showTitle: true`) |
| `page` | ref | Parent ui-page |
| `width` | string/int | Column span (e.g. `"4"` = 4 of 12 columns) |
| `height` | string/int | Minimum row height (`"1"` = auto-grow) |
| `order` | int | Render order on page |
| `showTitle` | bool | Show name as header |
| `className` | string | Custom CSS class |
| `groupType` | string | `"default"` (visible) or `"dialog"` (triggered) |
### Sizing Rules
- Group `width` sets column span out of page's total columns (default 12).
- Group `height` is a **minimum** — group grows to fit content.
- Widget `width` within a group is relative to the group's width.
- Widget `height` is in row units (1 unit = theme's Row Height setting).
---
## `ui-theme` — Appearance
| Property | Type | Default | Notes |
|----------|------|---------|-------|
| `colors.surface` | color | — | Header & nav background |
| `colors.primary` | color | — | Buttons, sliders, focus rings |
| `colors.bgPage` | color | — | Page background |
| `colors.groupBg` | color | — | Group background |
| `colors.groupOutline` | color | — | Group border color |
| `sizes.rowHeight` | string | `"default"` | `"default"` (48px), `"comfortable"` (36px), `"compact"` (32px) |
| `sizes.pagePadding` | string | `"12px"` | CSS shorthand (e.g. `"12px 6px"`) |
| `sizes.groupGap` | string | `"12px"` | Space between groups |
| `sizes.groupBorderRadius` | string | `"4px"` | Group corner rounding |
| `sizes.widgetGap` | string | `"12px"` | Space between widgets in group |
---
## EVOLV Key Rules
1. **12-column grid** with 4-col groups gives a clean 3-column layout at desktop.
2. Set `height: "1"` on groups to let them auto-size (content determines height).
3. Use `order` on groups to control left-to-right placement within a row.
4. For compact dashboards: theme `rowHeight: "compact"`, `pagePadding: "6px"`, `groupGap: "6px"`, `widgetGap: "6px"`.
5. Widget `order` within a group determines top-to-bottom flow (lower = higher).
6. Gauge sizing guide: tank gauge `width:2, height:4` + 3/4 gauge `width:2, height:3` fits well in a 4-col group alongside a status text `width:4, height:1`.

View File

@@ -0,0 +1,108 @@
# FlowFuse `ui-gauge` Manual (EVOLV Reference)
Source: https://dashboard.flowfuse.com/nodes/widgets/ui-gauge.html
## Gauge Types
| `gtype` value | Visual | Best For |
|---------------|--------|----------|
| `gauge-tile` | Compact square with value | KPI tiles |
| `gauge-battery` | Horizontal battery bar | Charge / capacity |
| `gauge-tank` | Vertical tank with fill gradient | Liquid levels |
| `gauge-half` | 180° arc | Setpoint / range display |
| `gauge-34` | 270° arc | Primary process gauge |
## Properties
| Property | Type | Dynamic | Notes |
|----------|------|---------|-------|
| `group` | ref | No | Parent ui-group |
| `width` | int | No | Columns (max = group width) |
| `height` | int | No | Row units |
| `gtype` | string | Yes | See table above |
| `gstyle` | string | Yes | `"Needle"` or `"Rounded"` (half/3-4 only) |
| `min` | number | Yes | Range minimum |
| `max` | number | Yes | Range maximum |
| `segments` | array | Yes | `[{color: "#hex", from: number}, …]` |
| `title` | string | Yes | Label above gauge |
| `prefix` | string | Yes | Before value (half/3-4 only) |
| `suffix` | string | Yes | After value (half/3-4 only) |
| `units` | string | Yes | Small text below value (half/3-4 only) |
| `icon` | string | Yes | Material Design icon (half/3-4 only) |
| `sizeGauge` | int | No | Arc thickness px |
| `sizeGap` | int | No | Gap between arc & segments px |
| `sizeSegments` | int | No | Segment ring thickness px |
## Input
`msg.payload` — numeric value to display.
## Dynamic Properties (`msg.ui_update`)
```js
msg.ui_update = {
label: "Tank A",
gtype: "gauge-tank",
gstyle: "Rounded",
min: 0, max: 100,
segments: [{color:"#f44336", from:0}, {color:"#4caf50", from:25}, {color:"#f44336", from:90}],
prefix: "", suffix: "%", units: "fill"
};
```
## Segments
Array of `{color, from}` objects sorted ascending by `from`. Each segment colors the range from its `from` up to the next segment's `from` (or `max`).
**Tank default segments** (auto-applied when switching to tank type):
```json
[{"color":"#A8F5FF","from":0},{"color":"#55DBEC","from":15},
{"color":"#53B4FD","from":35},{"color":"#2397D1","from":50}]
```
## CSS Selectors
| Selector | Target |
|----------|--------|
| `.nrdb-ui-gauge-value span` | Central value text |
| `.nrdb-ui-gauge-value label` | Unit label |
| `.nrdb-ui-gauge-value i` | Icon |
| `.nrdb-ui-gauge #limits` | Min/max labels |
## EVOLV Key Rules
1. **Tank gauge** for basin level: set `gtype:"gauge-tank"`, `min:0`, `max:<basin height>`, custom segments by safety thresholds.
2. **3/4 gauge** for fill %: set `gtype:"gauge-34"`, `gstyle:"Rounded"`, `min:0`, `max:100`, segments for low/normal/high.
3. Recommended sizing: tank `width:2, height:4`; 3/4 arc `width:2, height:3`.
4. Send plain numeric `msg.payload` — no topic needed (gauge has no series concept).
5. Segments must be provided as array even for a single color range.
## Node JSON Example (tank)
```json
{
"id": "demo_gauge_tank_west",
"type": "ui-gauge",
"z": "demo_tab_dashboard",
"group": "demo_ui_grp_ps_west",
"name": "West Tank Level",
"gtype": "gauge-tank",
"gstyle": "Rounded",
"title": "Level",
"units": "m",
"prefix": "",
"suffix": "m",
"min": 0, "max": 4,
"segments": [
{"color":"#f44336","from":0},
{"color":"#ff9800","from":0.3},
{"color":"#2196f3","from":1.0},
{"color":"#ff9800","from":2.5},
{"color":"#f44336","from":3.2}
],
"width": 2, "height": 4,
"order": 2,
"x": 700, "y": 400,
"wires": []
}
```

View File

@@ -0,0 +1,112 @@
# FlowFuse `ui-template` Manual (EVOLV Reference)
Source: https://dashboard.flowfuse.com/nodes/widgets/ui-template.html
## Purpose
Custom Vue 3 / Vuetify / HTML widget. Full scripting, scoped CSS, send/receive messages.
## Scopes
| Scope | Renders | Use Case |
|-------|---------|----------|
| Widget (Group) | Inside a ui-group | Custom gauges, tables, controls |
| Widget (Page) | On page, outside groups | Floating overlays, full-width banners |
| Widget (UI) | On every page | Global headers, footers |
| CSS (All Pages) | N/A — injects `<style>` | Global CSS overrides |
| CSS (Single Page) | N/A — injects `<style>` | Page-specific CSS |
## Properties
| Property | Type | Dynamic | Notes |
|----------|------|---------|-------|
| `group` | ref | No | Parent ui-group (Group scope) |
| `page` | ref | No | Parent ui-page (Page scope) |
| `width` | int | No | Columns |
| `height` | int | No | Row units |
| `format` | string | Yes | Vue template string |
| `storeOutMessages` | bool | No | Persist last output for late joiners |
| `passthru` | bool | No | Forward input to output |
| `templateScope` | string | No | `"widget:group"`, `"widget:page"`, `"widget:ui"`, `"page:style"`, `"site:style"` |
## Template Structure
```html
<template>
<v-btn @click="send({payload: 'clicked'})">Click</v-btn>
<p>Value: {{ msg.payload }}</p>
</template>
<script>
export default {
data() { return { local: 0 }; },
watch: {
msg(val) { this.local = val.payload; }
},
methods: {
doSend() { this.send({payload: this.local}); }
},
mounted() { /* one-time setup */ },
unmounted() { /* cleanup */ }
};
</script>
<style scoped>
p { color: #2196f3; }
</style>
```
## Built-in Variables
| Variable | Description |
|----------|-------------|
| `id` | This node's unique ID |
| `msg` | Latest received message (reactive) |
| `$socket` | Socket.io client for custom events |
## Sending Messages
```js
this.send({ payload: 42, topic: "my-topic" });
this.submit(); // sends FormData from <form>
```
## Receiving Messages
**Option A** — Vue `watch`:
```js
watch: { msg(newMsg) { /* react */ } }
```
**Option B** — Socket listener:
```js
mounted() {
this.$socket.on('msg-input:' + this.id, (msg) => { /* handle */ });
}
```
## Teleports (inject into dashboard chrome)
```html
<Teleport to="#app-bar-actions">
<v-btn>Custom Button</v-btn>
</Teleport>
```
Targets: `#app-bar-title`, `#app-bar-actions`.
## Vuetify Components
All Vuetify 3 components are available without import: `<v-btn>`, `<v-card>`, `<v-slider>`, `<v-data-table>`, etc.
## Dynamic Properties (`msg.ui_update`)
```js
msg.ui_update = { format: "<p>New template content</p>" };
```
## EVOLV Key Rules
1. Use templates sparingly — prefer built-in widgets when they fit.
2. For complex custom visualizations (SVG P&ID, animated schematics), template is the right choice.
3. Always use `<style scoped>` to avoid leaking CSS to other widgets.
4. Prefer `watch: { msg }` over socket listeners for simpler code.
5. Keep templates under 100 lines — split complex UIs into multiple template nodes.

View File

@@ -0,0 +1,72 @@
# FlowFuse `ui-text` Manual (EVOLV Reference)
Source: https://dashboard.flowfuse.com/nodes/widgets/ui-text.html
## Purpose
Read-only text display widget. Shows a label + value. Supports HTML in payload.
## Properties
| Property | Type | Dynamic | Notes |
|----------|------|---------|-------|
| `group` | ref | No | Parent ui-group |
| `width` | int | No | Columns |
| `height` | int | No | Row units |
| `label` | string | Yes | Left-side label text |
| `format` | string | No | Template: `{{msg.payload}}` or `{{msg.myProp}}` |
| `layout` | string | Yes | See layout options below |
| `style` | bool | No | Enable custom font/size/color |
| `font` | string | Yes | Font family (when style enabled) |
| `fontSize` | string | Yes | e.g. `"16px"`, `"1.2rem"` |
| `color` | string | Yes | Text color (when style enabled) |
## Layout Options
| Value | Description |
|-------|-------------|
| `row-left` | Label and value left-aligned |
| `row-center` | Centered on row |
| `row-right` | Right-aligned |
| `row-spread` | Label left, value right |
| `col-center` | Stacked vertically, centered |
## Input
`msg.payload` — string or number. HTML is rendered if present.
## Dynamic Properties (`msg.ui_update`)
```js
msg.ui_update = {
label: "New Label",
layout: "row-spread",
font: "monospace",
fontSize: "14px",
color: "#ff5722"
};
```
Also: `msg.class` — add CSS class to the widget container.
## Value Formatting
The `format` field supports template syntax and JSONata:
- `{{msg.payload}}` — raw value
- `{{msg.myProp}}` — any msg property
- JSONata in Value property: `$round(payload, 1)`
## HTML Support
`msg.payload` can contain HTML tags. Useful for inline formatting:
```js
msg.payload = '<b>Active</b> — 3 pumps online';
```
## EVOLV Key Rules
1. Use `layout: "row-spread"` for status lines (label left, value right).
2. For multi-field status, build a formatted string in the Function node and send as single payload.
3. Keep text widgets `height: 1` for compact status rows.
4. Use `format: "{{msg.payload}}"` (the default) — keeps it simple.
5. For direction arrows and styled status, use HTML in payload: `↑ filling | 142 m³/h | 35 min`.

View File

@@ -0,0 +1,49 @@
# FlowFuse Dashboard 2.0 — Widget Catalog
Source: https://dashboard.flowfuse.com/
## Widgets (22 types)
| Widget | Type String | Description |
|--------|-------------|-------------|
| Audio | `ui-audio` | Play audio files or TTS in browser |
| Button | `ui-button` | Clickable button, sends msg on click/pointerdown/pointerup |
| Button Group | `ui-button-group` | Multiple buttons rendered together as toggle/selection |
| Chart | `ui-chart` | Line, bar, scatter, pie, histogram — backed by eCharts |
| Control | `ui-control` | Programmatic page navigation and group visibility control |
| Dropdown | `ui-dropdown` | Select one or many options from a dropdown list |
| Event | `ui-event` | Fires msg on browser-side events (page load, resize, etc.) |
| File Input | `ui-file-input` | File upload from browser to Node-RED |
| Form | `ui-form` | Multi-field input form with submit action |
| Gauge | `ui-gauge` | Numeric display as tile, battery, tank, half-arc, or 3/4-arc |
| Markdown | `ui-markdown` | Render markdown/HTML content |
| Notification | `ui-notification` | Toast / snackbar / alert popups |
| Number Input | `ui-number-input` | Numeric input field with optional range/step |
| Progress | `ui-progress` | Linear or circular progress bar |
| Radio Group | `ui-radio-group` | Select one option from radio buttons |
| Slider | `ui-slider` | Horizontal or vertical slider control |
| Spacer | `ui-spacer` | Empty cell for layout positioning |
| Switch | `ui-switch` | On/off toggle switch |
| Table | `ui-table` | Paginated data table with sorting/selection |
| Template | `ui-template` | Custom Vue/Vuetify/HTML with full scripting |
| Text | `ui-text` | Read-only text display, supports HTML |
| Text Input | `ui-text-input` | Editable text field (text, password, email, etc.) |
## Config Nodes (4 types)
| Node | Type String | Purpose |
|------|-------------|---------|
| Base | `ui-base` | Root dashboard instance — path, nav style, header |
| Theme | `ui-theme` | Colors, sizing, spacing, group styling |
| Page | `ui-page` | Dashboard page — path, layout (grid/fixed/notebook/tabs), breakpoints |
| Group | `ui-group` | Widget container — width, height, order within a page |
## See Also
- [ui-gauge manual](flowfuse-ui-gauge-manual.md)
- [ui-text manual](flowfuse-ui-text-manual.md)
- [ui-template manual](flowfuse-ui-template-manual.md)
- [ui-button manual](flowfuse-ui-button-manual.md)
- [ui-chart manual](flowfuse-ui-chart-manual.md)
- [ui-config manual](flowfuse-ui-config-manual.md)
- [Dashboard layout notes](flowfuse-dashboard-layout-manual.md)

View File

@@ -0,0 +1,29 @@
# Node-RED Function Node Patterns (EVOLV Summary)
Based on: https://nodered.org/docs/user-guide/writing-functions
## Return Semantics
- `return msg;` sends to output 1.
- `return [msg1, msg2, ...];` sends one message per output position.
- Use `null` for outputs that should not emit.
Examples:
- `return [msg, null, null];` -> output 1 only
- `return [null, msg, null];` -> output 2 only
## Message Mutation Pattern
- Start with the incoming `msg`, set fields (`msg.topic`, `msg.payload`), then return/send.
- This preserves message context unless there is a deliberate reason to create a new object.
## Async Function Pattern
- For asynchronous work, call `node.send(...)` and then `node.done()`.
- Avoid returning a message when output is sent asynchronously.
## EVOLV Practical Rule
- In example flows (including parsers), always align return-array position with downstream wiring.
- For dashboard parser functions, keep one stable output mapping per metric to avoid wire-level regressions.

View File

@@ -0,0 +1,27 @@
# Node-RED Messages and Editor/Runtime Structure (EVOLV Summary)
Sources:
- Messages: https://nodered.org/docs/user-guide/messages
- Edit dialog and node definition: https://nodered.org/docs/creating-nodes/edit-dialog
## Message Shape
- Standard message object is usually `msg`.
- `msg.payload` is the default value channel.
- `msg.topic` is used for routing/intent labeling.
## EVOLV Topic Routing
- EVOLV runtime wrappers route commands by `msg.topic` in `src/nodeClass.js`.
- Keep topic names stable unless a migration is defined (flow compatibility).
## Editor/Runtime Parity
- In `.html`, `RED.nodes.registerType(... defaults ...)` defines persisted config fields.
- Runtime parser in `src/nodeClass.js` must read and normalize the same fields.
- If a field is added/renamed in editor defaults, update runtime mapping and tests in the same change.
## Multi-Output Node Rule
- Runtime `node.send([out1, out2, out3])` must align with declared `outputs` in `.html`.
- If output meaning is `process`, `dbase`, `parent`, maintain stable index mapping across all message paths.

View File

@@ -0,0 +1,31 @@
# Node-RED Runtime Node JS Manual (EVOLV Summary)
Based on: https://nodered.org/docs/creating-nodes/node-js
## Input Handler Contract
- Node-RED calls runtime handlers as `function(msg, send, done)`.
- For compatibility, custom nodes should support fallback behavior when `send` is not provided.
- Use `done()` on successful completion and `done(err)` on failure.
## Output Routing Rules
- For single-output nodes: `send(msg)` sends on output 1.
- For multi-output nodes: pass an array with one slot per output, for example:
- `[msg, null, null]` => output 1 only
- `[null, msg, null]` => output 2 only
- Always construct the outbound message first, then send it.
## EVOLV Runtime Pattern
Recommended runtime input structure for `src/nodeClass.js`:
1. Normalize `send` fallback.
2. Wrap `switch(msg.topic)` in `try/catch`.
3. Route response messages to explicit output index with array format.
4. Call `done()`/`done(err)` consistently.
## Common Failure Mode
- Sending a bare object in a multi-output context can hide intended port routing.
- In EVOLV nodes with 3 outputs (`process`, `dbase`, `parent`), use explicit arrays for deterministic wiring behavior.