Files
MARTe-Integrated-Components/Docs/StreamHub-API.md
T
2026-06-12 15:25:13 +02:00

232 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# StreamHub WebSocket API
StreamHub exposes a single WebSocket server (default port **8090**, any URL path).
Text frames carry JSON commands/events; binary frames carry data pushes and
trigger captures. The Go reference hub (`Client/udpstreamer`) implements the
identical protocol; both the browser SPA and the ImGui client work against either.
For the upstream UDPS wire format (source → hub) see [Protocol.md](Protocol.md).
All numbers in binary frames are **little-endian**. All timestamps are
**Unix wall-clock seconds** (float64) — see *Time base* in
[StreamHub-Developer.md](StreamHub-Developer.md).
---
## 1. Commands (client → hub, JSON text frames)
Every command is a JSON object with a `type` field.
### `ping`
```json
{"type":"ping"}
```
Reply (unicast): `{"type":"pong"}`.
### `addSource`
```json
{"type":"addSource","label":"PSU","addr":"192.168.0.10:44500",
"multicastGroup":"239.0.0.1","dataPort":44503}
```
- `addr``host:port` of the UDPStreamer control port.
- `multicastGroup` / `dataPort` — optional; if present the hub joins the
multicast group for DATA and keeps a TCP control connection for CONNECT/CONFIG.
- The hub assigns ids `s1`, `s2`, … and broadcasts an updated `sources` event.
### `removeSource`
```json
{"type":"removeSource","id":"s1"}
```
### `saveSources`
```json
{"type":"saveSources"}
```
Persists the current dynamically-added source list to the hub's `SourcesFile`
(JSON array of `{label,addr,multicastGroup,dataPort}`); it is reloaded at startup.
### `getSources` / `getConfig` / `getStats`
```json
{"type":"getSources"}
{"type":"getConfig","sourceId":"s1"}
{"type":"getStats"}
```
Force a broadcast of the corresponding event.
### `setTrigger`
```json
{"type":"setTrigger","signal":"s1:Sine","edge":"rising","threshold":0.0,
"windowSec":0.1,"prePercent":20,"mode":"normal"}
```
- `signal` — full key `src:sig`, or `src:sig[i]` to trigger on element *i* of a
multi-element PACKET signal.
- `edge``"rising"`, `"falling"` or `"both"`.
- `windowSec` — total capture window (clamped to 1e-4 … 10 s).
`preSec = windowSec * prePercent / 100`, `postSec = windowSec preSec`.
- `mode``"normal"` (auto-rearm ~200 ms after capture) or `"single"`
(stays TRIGGERED until `rearm`).
### `arm` / `disarm` / `rearm` / `trigStop`
```json
{"type":"arm"}
{"type":"disarm"}
{"type":"rearm"}
{"type":"trigStop","stopped":true}
```
- `arm` — IDLE → ARMED.
- `disarm` — any state → IDLE.
- `rearm` — TRIGGERED → ARMED (single mode).
- `trigStop` — sets the *stopped* flag suppressing auto-rearm in normal mode;
omit `stopped` to toggle.
Every transition is broadcast as a `triggerState` event.
### `zoom`
```json
{"type":"zoom","reqId":17,"t0":1765370000.123,"t1":1765370000.223,
"n":2400,"signals":"s1:Sine,s2:Wave[0]"}
```
- `reqId` — echoed in the reply; lets the client match request/response.
- `t0`/`t1` — Unix seconds window.
- `n` — target points per signal. Absent or `<10` → 2400; `n ≤ 0` → **no
decimation** (raw ring contents).
- `signals` — comma-separated full keys; absent → all signals of all sources.
- The reply is **unicast** to the requesting client only.
### `setMaxPoints`
```json
{"type":"setMaxPoints","maxPoints":50000}
```
Resizes all ring buffers (applied safely inside the push loop; push cursors are
reset). Broadcasts `maxPointsUpdated`.
---
## 2. Events (hub → client, JSON text frames)
### `sources`
```json
{"type":"sources","sources":[
{"id":"s1","label":"PSU","addr":"192.168.0.10:44500","state":"streaming"}]}
```
Sent on client connect, after add/remove/getSources, and when a source first
delivers its CONFIG.
### `config`
```json
{"type":"config","sourceId":"s1","publishMode":0,"signals":[
{"name":"Sine","typeCode":10,"quantType":0,"numDimensions":0,
"numRows":1,"numCols":1,"rangeMin":-1.0,"rangeMax":1.0,
"timeMode":0,"samplingRate":5000000.0,"timeSignalIdx":-1,"unit":"V"}]}
```
Field semantics follow the UDPS signal descriptor ([Protocol.md](Protocol.md)).
`numElements = numRows × numCols`.
### `stats`
Sent at `StatsRate` Hz (default 1 Hz):
```json
{"type":"stats","sources":{"s1":{
"state":"streaming","totalReceived":1234,"totalLost":0,
"rateHz":100.1,"rateStdHz":0.3,
"fragsPerCycle":3.0,"bytesPerCycle":4200.0,
"cycleAvgMs":10.0,"cycleStdMs":0.1,"cycleMinMs":9.8,"cycleMaxMs":10.4,
"cycleHistMin":9.8,"cycleHistMax":10.4,"cycleHist":[0,1,5,"…(20 bins)"]}}}
```
### `triggerState`
```json
{"type":"triggerState","state":"triggered","mode":"normal",
"stopped":false,"trigTime":1765370000.1234567}
```
`state``idle | armed | collecting | triggered`; `trigTime` present once a
trigger has fired.
### `zoom` (reply)
```json
{"type":"zoom","reqId":17,"signals":{
"s1:Sine":{"t":[1765370000.1230000,"…"],"v":[0.123456789,"…"]}}}
```
`t` is serialised with `%.17g` (full float64 precision — required for
µs windows at Unix-epoch magnitudes), `v` with `%.9g`.
### `maxPointsUpdated`
```json
{"type":"maxPointsUpdated","maxPoints":50000}
```
---
## 3. Binary frames (hub → client)
The first byte of every binary WS frame is a **version** discriminator.
### Version 1 — data push
Sent at `PushRate` Hz per source. Contains **only the samples that are new
since the previous push** (per-signal cursors hub-side), LTTB-decimated to at
most `MaxPushPoints` (default 50) per signal.
```
[1] version = 1
[1] sourceIdLen (L)
[L] sourceId (UTF-8, no NUL)
[4] numSignals (uint32)
per signal:
[2] keyLen (uint16) (K)
[K] key = signal name; "name[i]" per element for multi-element PACKET signals
[4] pairCount (uint32) (N)
[N×8] t (float64, Unix seconds)
[N×8] v (float64, physical units)
```
Clients must append samples verbatim — there is no overlap between pushes.
### Version 2 — trigger capture
Broadcast once per capture (FSM COLLECTING → TRIGGERED). Contains *all*
signals over `[trigTime preSec, trigTime + postSec]`, each LTTB-decimated
to ≤ 20 000 points.
```
[1] version = 2
[8] trigTime (float64, Unix seconds)
[8] preSec (float64)
[8] postSec (float64)
[4] numSignals (uint32)
per signal:
[2] keyLen (uint16) (K)
[K] fullKey = "src:sig" (UTF-8)
[4] pairCount (uint32) (N)
[N×8] t (float64, Unix seconds)
[N×8] v (float64)
```
---
## 4. Limits
| Limit | Value |
|-------|-------|
| Concurrent WS clients | 16 |
| UDPS source sessions | 32 |
| Max received WS payload | 64 KiB |
| Max sent WS payload | 4 MiB |