# StreamHub — User Guide StreamHub turns signals streamed by MARTe2 `UDPStreamer` DataSources into a multi-user oscilloscope. One hub process aggregates any number of sources and serves up to 16 simultaneous clients: a browser SPA and/or the native ImGui desktop client. ``` MARTe2 app (UDPStreamer) ──UDP 44500──▶ StreamHub ──WebSocket 8090──▶ browser / ImGui ``` ## 1. Quick start (demo stack) ```bash source env.sh ./run_streamhub.sh -w -g ``` This builds everything, starts a demo MARTe2 application with three streamers (scalars over multicast, two array streamers), a StreamHub on port 8090, the web UI server on port 8080 (`-w`) and the ImGui client (`-g`). Then open: ``` http://localhost:8080/?hub=localhost:8090 ``` Useful flags: `-p ` WS port, `-n ` ring size, `-s` skip rebuild, `-h` full help (including the list of ports used). ## 2. Running against your own application 1. Add a `UDPStreamer` DataSource to your MARTe2 configuration (see [UDPStreamer.md](UDPStreamer.md)). 2. Write a hub configuration, e.g. `hub.cfg`: ``` WSPort = 8090 Sources = { MyApp = { Label = "MyApp" Addr = "192.168.0.10" Port = 44500 } } ``` For multicast streamers add `MulticastGroup = "239.0.0.1"` and `DataPort = 44503`. All keys and defaults: [StreamHub-Developer.md](StreamHub-Developer.md) §6. 3. Run the hub and a client: ```bash source env.sh ./Build/x86-linux/StreamHub/StreamHub.ex -cfg hub.cfg # web UI cd Client/webui && go build -o streamhub-webui . && ./streamhub-webui # then browse http://localhost:8080/?hub=:8090 # or native client ./Client/streamhub/build/StreamHubClient -host -port 8090 ``` Sources can also be added at runtime from either client ("Add source": label + `host:port`, optional multicast group/data port). "Save sources" persists the runtime list to `streamhub_sources.json` so the hub reloads it on restart. ## 3. Using the oscilloscope (web UI and ImGui) Both clients offer the same workflow: - **Plotting** — drag signals from the source sidebar onto a plot. Choose a grid layout (1×1 … 4×1 / 2×2 / 1×4). Live plots scroll with wall-clock time; pick the time window (1/5/10/30/60 s). - **Zoom** — scroll/drag to zoom. When zoomed in, the client automatically fetches high-resolution data from the hub for the visible window. *Back* steps through the zoom history, *Fit* frames the data, *Reset/Live* returns to the scrolling live view. - **Cursors** — enable cursors A/B and drag them; the readout shows ΔT and the value of each trace at both cursors. - **V-scale modes** — *normal*, *digital* (booleans stacked as logic traces), *mixed*. - **Signal styling** — per-trace colour, line width, markers. - **Stats** — per source: packet rate ± std, lost packets, fragments and bytes per cycle, cycle-time min/avg/max/std and a 20-bin cycle-time histogram. ## 4. Trigger The trigger runs **in the hub**, so a capture is identical in every connected client and uses full-rate ring data (not the decimated live stream). 1. Pick the trigger **signal** (for array signals: a specific element), the **edge** (rising/falling/both) and the **threshold**. 2. Pick the capture **window** (100 µs … 10 s) and the **pre-trigger** percentage (how much of the window precedes the trigger instant). 3. Mode **normal** re-arms automatically ~200 ms after each capture (*Stop* pauses re-arming); mode **single** captures once and waits for *Rearm*. 4. Press **Arm**. Badge states: `IDLE → ARMED → COLLECTING → TRIGGERED`. On capture, the trigger view shows all plotted signals relative to the trigger instant (marker at t = 0) over `[-pre, +post]`. ## 5. Troubleshooting | Symptom | Check | |---------|-------| | Source stuck in *connecting* | Streamer host/port reachable? For multicast: group/data port match the streamer, and routing allows IGMP | | No data but source *streaming* | `getStats` rate ≈ RT cycle rate? Firewall on UDP data port? | | Web UI loads but no signals | Did you pass `?hub=host:8090` (the SPA talks WS directly to the hub, not the web server)? | | Trigger never fires | Threshold inside the signal's actual range? Edge direction correct? | | Time axis jumps once at start | Normal: first-packet wall-clock calibration; it also re-anchors after a source restart | Hub-side logs go to stdout; the demo scripts write `/tmp/streamhub_e2e_{marte,hub}.log`. ## 6. Further reading - [StreamHub-API.md](StreamHub-API.md) — WebSocket protocol (write your own client) - [StreamHub-Developer.md](StreamHub-Developer.md) — internals, build, tests - [UDPStreamer.md](UDPStreamer.md) — configuring the MARTe2 DataSource - [Protocol.md](Protocol.md) — UDPS wire format