User manual — chapter list

The GDA bridge

The bridge is a small server in the GDA repo that streams reconstructed GB network state - and answers on-demand physics queries - over one WebSocket. GDA computes; GridSim renders. This chapter covers starting the server, connecting from the desktop and web apps, the stream controls, and the faults you will actually meet.

Running the server

cd D:\Work\GDA\v1
python Applications/GridSim-Bridge/bridge_server.py

It binds 127.0.0.1:8770 by default; override with the BRIDGE_HOST and BRIDGE_PORT environment variables. It is a FastAPI/uvicorn app and needs the GDA Python environment (pandas, numpy, scipy for the solver).

Sanity-check it with a browser or curl: GET http://127.0.0.1:8770/ returns the app name, the WebSocket path (/ws/bridge), the available cases and the current horizon cutoff; GET /meta adds the settled-scalar time bounds.

Cases are discovered at startup: gb-full, gb-spine, and every NetworkModel/zones/zone-* directory (e.g. zone-nged, zone-ukpn).

Connecting

Desktop app - set BridgeEndpoint in %LOCALAPPDATA%\GridSim\settings.json (default ws://127.0.0.1:8770/ws/bridge) and pick the Live bridge model source. The zone/start/SRC pickers then drive the stream - see 12-replaying-estimated-states.md.

Web console - set the GridSim:BridgeEndpoint configuration key to the same ws://.../ws/bridge URI. The home screen then shows the bridge cards, and /dashboard/bridge:<case>[@<source>] opens a bridge session.

Stream actions

The client sends JSON actions on /ws/bridge:

Action Fields Effect
start case, start (ISO timestamp), fps, source begin streaming the case from the historical start; fps clamped to 1-144
stop - stop the active stream
set_speed fps change playback speed without restarting
seek start (and optionally case, source) restart the stream at a new instant
query op, at, params, id on-demand physics; runs alongside the stream

The server replies with a topology message once (the network model), then one state message per settlement-period tick: the slim result block (buses and line flows), the system scalars (frequency, RoCoF, generation, demand, inertia, condition, RoCoF headroom), map overlays, operator/market series, and

  • on estimated streams - a per-frame estimate quality block. Stream-level failures arrive as type:"error" messages; the C# client surfaces them as a fault rather than dropping them silently.

Sources

source on start/seek selects the reconstruction. Each has a lake prerequisite:

Source What each tick is Requires
live the case solved once; only the system scalars vary per tick the case directory under NetworkModel/, plus the reconstructed scalar datasets (Derived/inertia_reconstructed, Derived/system_condition_index)
presolved a stored demand-scaled re-solve of each period - per-bus state varies tick to tick Derived/presolved_state/<case>/topology.json + the window's year=/week= partitions (built by NetworkModel/presolve_lake.py)
estimated a stored WLS estimate fitted to each period's real telemetry, with its quality block Derived/estimated_state/<case>/... (built by NetworkModel/build_estimated_state.py)

If a stored source is requested but the case's lake (or the requested window) does not exist, the server sends an info message naming the builder to run and falls back to the live stream - the view is never left blank, it just loses per-bus frame-by-frame replay until the window is built.

On-demand queries

{action:"query", op:..., at:"<iso>", params:{...}, id:"..."} runs physics at a historical instant without stopping the stream. The ops are:

Op Returns
inertia the reconstructed system-inertia scalars at at
condition the system-condition index at at
scenario a what-if solve (trip/scale) via the GDA sparse-NR + OLTC engine
feasibility a feasibility/limit check of a proposed state
post_event post-event replay around a disturbance
asset per-asset drill-down (envelopes, BESS, tap changers, consumers) for a clicked bus
propagation corridor propagation delays (tau map) from the lake product

Every reply echoes the request's op and id, so out-of-order completion is safe. An unknown op returns verdict:"ERROR" listing the available ops; a query at past the horizon returns verdict:"INFEASIBLE_HORIZON". The C# client (GridBridgeClient.Query) times a query out after 60 s by default.

The forward-inference horizon

The bridge is a replay tool and will not nowcast. Every emitted tick is masked to the horizon cutoff - now minus 169 hours (7 days + 1 hour) - and a start past the cutoff is rejected outright:

{"type":"error","message":"start 2026-07-13T00:00:00+00:00 is past the
 no-forward-inference horizon (cutoff 2026-07-07T07:00:00+00:00, now - 7d 1h).
 Rejected."}

Pick starts at least 8 days back. In the desktop app use the 2 weeks ago or 30 days ago start presets (the shorter presets predate the horizon's widening and are rejected); if you drive the socket yourself, compute the cutoff from GET /meta. The GridSim client enforces the same 169-hour horizon independently on every received tick (with a small clock-skew allowance) - a too-recent frame is a protocol violation and faults the stream.

Common faults

Symptom Message Cause and fix
Unknown case Unknown case 'x'. Available: ['gb-full', 'gb-spine', 'zone-enwl', ...] typo, or the case directory is not materialised under NetworkModel/. Use a listed name
Horizon rejection start ... is past the no-forward-inference horizon (cutoff ..., now - 7d 1h). Rejected. the requested start is too recent - pick one >= 8 days back
No settled data No settled scalar data at/after ... the reconstructed scalar datasets do not cover the window; the settled data lags "now" - start further back, or refresh the GDA derived datasets
Missing stored lake No estimated lake for 'zone-nged'; streaming the live on-demand solve instead (build with NetworkModel/build_estimated_state.py ...) the requested source lake does not exist for that case/window; the stream falls back to live. Build the window with the named script
Invalid start Invalid start date the start string did not parse as a timestamp - send ISO-8601

In the desktop app these surface on the bridge status pill: a stream error or socket fault shows BRIDGE FAULT * disconnected, a client-side horizon violation shows HORIZON REJECTION * stream stopped, and a failed initial connection shows CONNECT FAILED * ... - with the server's message logged in the event log in each case.

See also