S

SUT1 Replay Server

archived
Academic

Real-time telemetry decoder (Swinburne capstone, HD 90/100).

Cohort lead engineer2025Multi-cohort handoverSwinburne (industry-client capstone)Real-time systems / networking
Python
FastAPI
asyncio
WebSockets
Academic project. Source kept in a private org.

Overview

A real-time bridge between sailboat simulators and browser dashboards. It takes in binary UDP and TCP telemetry, decodes it, and streams it to web clients over WebSockets. I inherited a stalled multi-cohort codebase and shipped it to the industry client's requirements.

I led the codebase through a multi-cohort handover and did the bulk of the shipped work: the TCP layer, session identity, graceful shutdown, the frontend, and the docs. The original UDP scaffold and base protocol decoders came from a prior cohort.

How it works

1

Simulator

Binary UDP and TCP packets

2

Decoder

Struct-aligned byte parsing

3

Session manager

One stream per session hash

4

WebSocket fan-out

Batched to dashboards

Simulators send binary telemetry over UDP and TCP. The server decodes it and fans it out to browser dashboards over WebSockets, one stream per session.

Showcase

Sail Simulation Race Display capstone poster: problem, FastAPI proxy solution, five-layer architecture, and team — shown at the Swinburne Capstone Exhibition.
Capstone exhibition poster — the problem, the FastAPI proxy solution, and the five-layer architecture. Shown at the Swinburne Capstone Exhibition (CdSESS 2025 People's Choice voting).
Live demo of the race-display dashboards running on the physical sailing simulator at the Swinburne Capstone Exhibition.
The race-display dashboards running live on the real simulator equipment at the exhibition.
The sailing simulator hardware that emits the binary UDP/TCP telemetry the server decodes.
The sailing simulator that produces the binary telemetry the server decodes.

Engineering challenges

01Picking up a stalled codebase from earlier cohorts

Problem. I joined a project several student cohorts had already touched. There were multiple half-finished branches, abandoned attempts, and no clear working version, with an industry client still expecting something.

Approach. I took ownership properly: pulled the scattered branches together, then made decisions I could defend and undo. Where earlier work didn't fit the requirements I reverted it with a written reason instead of quietly deleting it. I got the main path working first and hardened it after, and at the end I wrote a proper docs folder and kept the old readme around so the next person wasn't stuck where I had been.

Outcome. The project reached a working, documented state and the next cohort member picked it up cleanly, which to me was the real proof it worked. It was graded HD, 90 out of 100.

02Decoding a binary protocol with no hardware to test on

Problem. The telemetry came as raw binary packets laid out to match a C++ struct, and I didn't have the actual simulator to test against.

Approach. I built the TCP side of the decoding and extended the packet formats, parsing with byte-for-byte struct layouts, padding included, and added a small safety net that cleans NaN and infinity values out of malformed packets. To test without the real simulator, I wrote a mock that packs the exact same byte layout, plus an offline decoder to replay captured logs.

Outcome. I could build and check the whole decode path without the physical simulator, and it held up against messy real packets.

03Streaming to many browsers without melting

Problem. Lots of browser clients subscribing to live, high-frequency telemetry, with sessions whose network address keeps changing, and a server that has to shut down cleanly without cutting off active sessions.

Approach. I built the TCP client and manager layer and wired it into the existing UDP and WebSocket flow, sending updates to browsers in small batches instead of one message at a time. I swapped the shaky address-based session key for a stable hash, and made shutdown wait for a second interrupt while sessions were live so it wouldn't yank the rug out.

Outcome. Steady multi-session streaming under load, with clean start-up and shutdown.

External links

What I'd do differently

  • There aren't automated tests in the tree; I leaned on the mock simulator and manual runs. A small suite around the decoders would catch format regressions.
  • Sessions live in memory, so a restart wipes them. I'd persist session state if this needed to survive restarts.