Skip to content

v1.2.0 — Real data

Choose a tag to compare

@goldbarth goldbarth released this 15 Jun 13:52
· 12 commits to main since this release
73592d8

port-tidewatch v1.2.0

Release date: 2026-06-15

Real data (M7). v1.1 made the pipeline demonstrable with a scripted surge; v1.2
feeds it from the live PEGELONLINE Elbe gauges alongside that simulator,
behind a source-selection switch — without touching the Reading contract or
the consumer path.

Highlights

  • Live PEGELONLINE Elbe feed — a source adapter polls the public WSV REST-API
    for four Hamburg gauges (St. Pauli, Bunthaus, Over, Zollenspieker) and emits the
    same Reading records the simulator does. Centimetres-above-gauge-zero are
    converted to metres NHN in an explicit mapping layer (W/100 + PNP offset);
    conditional GET (If-None-Match) means a 304 emits no duplicate reading, and
    transient API failures are logged and retried without crashing the host.
  • Source-selection switch — a single ReadingSource config value
    (Simulator | Pegelonline) chooses the active source at startup, so the same
    build serves the scripted demo or the real feed without recompiling. A bad or
    empty value fails fast at startup, consistent with the threshold-options
    validation.
  • Producer renamed to Tidewatch.Source — the simulator project became a
    Generic Host that hosts interchangeable reading sources behind IReadingSource;
    the simulator is now one source among others, so the name and the deployed
    workload (reading-source) are source-neutral.

What's seen on the dashboard

Four live Hamburg Elbe gauges, all normal

Live dashboard on real WSV/PEGELONLINE data — the public Hamburg Elbe gauges (St. Pauli, Zollenspieker, Over, Bunthaus), all normal.

The scripted-surge demo (video and screenshots) from
v1.1
still tells the alerting story best — real Elbe levels normally sit well below the
4.50 m NHN warning boundary, so the live feed reads calm normal. The live feed's
value is the real-data integration: cm → PNP → NHN mapping and conditional polling
against the public WSV API.

What's changed

Reading-source host (was Tidewatch.Simulator)

  • Moved to a Generic Host (Microsoft.NET.Sdk.Worker): DI, Options, graceful
    shutdown. The publish path is the IReadingPublisher seam; sources depend on
    intent, not transport.
  • SimulatorSource holds the scripted surge (behaviour unchanged — same Reading,
    exchange, routing key; SURGE_PEAK_M / SURGE_PERIOD_S / RABBITMQ_HOST still
    honoured).
  • PegelonlineSource + PegelonlineClient + PegelMapper: latest value, window
    backfill on start, live gaugeZero lookup, and the cm → m / PNP → NHN mapping.
    Stations are configured by UUID. HPA tidal gauges expose no gaugeZero, so their
    PNP is set explicitly (Hamburg PNP = NHN −5.00 m); the live lookup remains for
    other WSV stations.
  • ReadingSourceOptions + validator select the active source at startup
    (ValidateOnStart); only the chosen source and its dependencies are registered.

Deploy

  • The deployed producer runs the live feed: ReadingSource=Pegelonline is set via
    env var on the k8s reading-source Deployment and the Container Apps app; the
    local appsettings default stays Simulator for the documented demo.
  • The producer workload was renamed simulatorreading-source across the k8s
    manifests, kustomization, azure.yaml, and the bicep (resource, name,
    azd-service-name), plus the runbook.

Tests

  • PegelMapper cm → m / PNP → NHN pinned end to end against a known St. Pauli
    value; ReadingSource validator (known / missing / unknown / numeric).

Known limitations (by design)

  • Live feed reads calm — real Elbe levels stay below the storm-surge
    thresholds, so the live source shows normal; the simulator remains the
    dramatic demo. The two are not run side by side (single source per run).
  • Dashboard remains read-only and polling-based.
  • No notification delivery — alert events are published but acting on them is
    still out of scope.

What's next (v1.3)

Observability made visible — see M8 in
docs/ISSUES.md:
surface the existing OpenTelemetry path in the dashboard (a pipeline latency pulse,
a Jaeger deep-link, and an optional self-rendered trace waterfall).