Waterschap Brabantse Delta · R&D lab · research artifact

Data compression: the current sensor dataflow in EVOLV, and what happens to a value before it is stored

Mike Molekamp (intern, Avans Hogeschool) track Data compression date 2026-10-12 version 2.0 draft
Before sensor data can be compressed, it has to be clear which route it takes today and what already happens to it on the way. This artifact maps the current flow of sensor data in EVOLV, from the sensor in the field to the dashboard where the R&D lab analyses it, places every component in a block of the real-time data pipeline (RTDP), and records what each step does to a value, based on the EVOLV source code.[2][3][4] It answers the first part of sub-question 1: how is sensor data processed and stored today? Version 2.0 follows the latest EVOLV code (all nodes on main, generalFunctions 1.13.2), in which every node writes to FROST itself.

Dataflow

The flow has two paths: the write path runs for every measurement, the read path only when someone opens or queries the data. Use the toggle to show where the planned compression components go.

Show

1 · write path · for every measurement

field / digital twinSensorsmany types · fixed interval or irregular · simulated by the digital twin in developmentdata generation
→
at the sensorCleaning modulefilters noise before data goes onlineprocessing
→
edge · Node-REDEVOLV nodemeasurement node and every other node: own MeasurementContainer, full precision · used for controlprocessing
→
edge · generalFunctionsFROST writer of the nodesnapshot of Port 1 · device gate · buffer, backoff, metadataingestion
→
edge · generalFunctionsReducer (per series)change-heartbeat: every change + last value every 60 s · no compressionprocessing
→
centralFROST serverreceives observations over HTTP POSTstorage · access
→
centralDatabaseevery changed value + heartbeats as observationsstorage

2 · read path · on request

centralDatabaseobservationsstorage
→
centralFROST serverserves observations per datastream and period over HTTP GETstorage · access
→
on retrieval · location tbcDecoderrebuilds the series with monotone PCHIP, within the repeatability of the sensorprocessing · new
→
R&D labDashboarddraws straight lines between stored values · analysis, partly with AIvisualisation
existing component new in this research (planned)
The current dataflow of sensor data in EVOLV. Every node keeps its measurements in its own MeasurementContainer and sends a snapshot of its database output to its own FROST writer. Per series the reducer change-heartbeat passes every changed value and a heartbeat every 60 s to FROST, which stores them in the database. The dashboard reads them back through FROST. The mono label under each component is its RTDP block.

Components

Each component in one sentence, in the order a measurement passes them.[2][4]

Sensorsfield · data generation

Many different types of sensors deliver measurements, some at a fixed interval and some irregularly. In the development environment a digital twin generates the measurements inside the measurement nodes.

Cleaning moduleat the sensor · processing

Filters noise and unwanted values locally, at the sensor itself, so only cleaned data goes online.

EVOLV nodeNode-RED edge layer · processing

The measurement node converts to its unit, optionally smooths and clamps (or passes 1-to-1 in passthrough mode) and passes every accepted sample in full precision on. Every node (for example a pump) keeps its measurements in its own MeasurementContainer and controls with them.

FROST writergeneralFunctions · ingestion

Taps the node's database output (Port 1) behind the device gate, turns every numeric field into a point per series and handles the FROST metadata chain, buffer, backoff and batches. One client per FROST server is shared by the whole runtime.

ReducergeneralFunctions · processing

One per series (Datastream); decides which values go to FROST. Today change-heartbeat: every change plus a heartbeat every 60 s. It is the plug-in point for a compression.

FROST servercentral · storage access

Implements the OGC SensorThings API (Things, Datastreams, Observations); data is written with HTTP POST and retrieved with HTTP GET.[1]

Databasecentral · storage

Stores the Observations FROST receives: today one row per changed value plus heartbeats.

DashboardR&D lab · visualisation

Where the R&D lab views and analyses the data, partly with AI. Between two stored values it draws a straight line.

What happens to a value on the way

The steps in the edge layer change the data before it is stored. These facts set the starting point for the compression: what "the original data" is, where the compression plugs in, and what it has to beat.[4]

Behaviour of the measurement node and the FROST writer in the EVOLV source code (generalFunctions 1.13.2), with the file where it is implemented.
StepWhat happensConsequence for compressionSource
PrecisionThe measurement node no longer rounds: every accepted sample reaches the MeasurementContainer at its source time and in full precision. A passthrough mode passes values 1-to-1.Values are full float64; a PCHIP curve will practically never hit them exactly. The compression is therefore bounded by the sensor's repeatability, not exact.measurement/src/channel.js · _writeOutput
SnapshotOn every output the node hands its FROST writer a full snapshot of its database fields (Port 1). Only finite numbers become points; a few text fields become Thing properties.The compression works on this copy, never on the MeasurementContainer the node controls with (US-19).nodered/BaseNodeAdapter.js · frost/nodeWriter.js
TimestampSet to the writer's clock when the node sends its output (milliseconds), not the sensor's own measurement time."Original timestamp" means this processing timestamp.frost/nodeWriter.js · frostFormatter.js
Missing valuesNon-finite values are skipped. When a series disappears from the node's output, the reducer gets absent() and the heartbeat stops; no gap is recorded in FROST.A gap is only visible as missing heartbeats; the compression has to mark gaps itself (US-8, US-11).frost/nodeWriter.js · frost/reducer.js
Reductionchange-heartbeat sends a value when it differs from the last sent value, and repeats the last value every 60 s so standstill shows as a flat line. There is no tolerance band.Storage is not compressed: this is the new baseline. The old CoreSync route (angle mode, no fixed error bound) is the second reference; SDT with ε = repeatability is the fair competitor.frost/reducer.js
Plug-in pointA reducer is an object with offer(point), due(now), absent() and flush(); a factory gets the first point of the series (unit, repeatability, accuracy) and is registered with registerReducer(). The code names "the rewritten SDT" as the next reducer.The PCHIP compression becomes a reducer; buffer, backoff and metadata stay untouched.frost/reducer.js · frost/domain.js
One client per serverThe first node that connects to a FROST server sets the client options (heartbeat, reducer) for the whole runtime.The compression cannot yet be chosen per node; this has to be agreed with the R&D lab.frost/client.js · getClient
Observation parametersEach Observation carries parameters: the reduction reason, evolvFieldKey, evolvStreamKey, sourceMeasurement and, when relevant, the curve origin. The value itself is 8 bytes.Metadata still dominates storage per point; the size per Observation has to be measured again for the zero measurement.frost/frostRequests.js · observationParameters
FROST unavailableUp to 200 observations per series are buffered in memory (keep-first + rolling-latest); a failed observation goes back into the buffer. When full, points after the first are dropped. A restart empties the buffer.Data can still be lost on long outages and restarts (relevant for US-5).frost/domain.js

Mapping to the RTDP

Each component placed in a block of the real-time data pipeline, with the reason. The compression works on the processing block just before ingestion and lowers storage; on visualisation it only changes how the line between knots is drawn.[1]
RTDP blockComponentWhy this block
data generationSensorsProduce the measurements (or the digital twin simulates them).
processingCleaning moduleFilters the data before it is collected.
processingEVOLV nodeConverts, filters and uses the measurements for control.
processingReducerDecides which values are kept; the place where the compression runs.
ingestionFROST writerCollects the node's output and posts it to FROST, with buffer and retries.
storage · accessFROST serverStandard API in front of the database: receives observations (POST) and serves them (GET).
storageDatabasePersists the observations.
visualisationDashboardDashboarding and analysis.
assumption Open points. The RTDP mapping is the author's interpretation and still has to be checked with the R&D lab. Older flows may still route data through a CoreSync node (angle mode); CoreSync skips messages that a node already wrote itself (msg.frost.direct), so knots are not reduced twice. Which reducer runs is chosen per FROST server for the whole runtime, not per node. The protocol between sensor and edge layer, the database behind FROST and where the decoder will run are not yet recorded; the database is therefore shown generically.

Sources

  1. Compression_README.md — project description v2.1, sections 2, 9 and 15 (context, RTDP impact, FROST), M. Molekamp. consulted 2026-10-12
  2. Description of the current dataflow — M. Molekamp, internship Waterschap Brabantse Delta / Avans Hogeschool. recorded 2026-10-12
  3. Real-time data pipeline (RTDP) model — blocks data generation, ingestion, processing, storage, visualisation (figure data-pipeline-transparant.png). consulted 2026-10-08
  4. EVOLV source code — Waterschap Brabantse Delta R&D, git.wbd-rd.nl/RnD/EVOLV, all nodes on main: generalFunctions 2df4980 (1.13.2, src/frost/, src/nodered/BaseNodeAdapter.js), measurement eee2c6a, coresync 075a7d7 (0.2.5). consulted 2026-10-12
Data vintage Dataflow and EVOLV code as of 2026-10-12 (v1.2 described the CoreSync route of 2026-10-08)
Method Component inventory and source-code reading, mapped to the RTDP blocks
Track Data compression (prj_c388225ebbe9)
Contact Mike Molekamp · R&D lab · lab.wbd-rd.nl