Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Waggle

Waggle is the CU Robotics telemetry service: a Rust/Axum backend that buffers incoming telemetry frames and a React (Vite) dashboard that renders them in the browser. Producers POST JSON batches to `/batch`; connected clients receive live updates over `/ws`.

## Prerequisites
- Rust toolchain via [`rustup`](https://rustup.rs/).
- Node.js 20+ and npm. You can install Node with `./tools/install.sh` on Ubuntu-based hosts.
- Python 3 if you plan to use the replay/export utilities in `tools/`.

## Quick Start
```bash
# Install frontend dependencies and build the production bundle
npm install --prefix client
npm run build --prefix client

# Run the backend (serves the built dashboard at http://localhost:3000/)
cargo run
```

### Development Loop (hot reload)
```bash
# Terminal 1 – backend
cargo run

# Terminal 2 – frontend
cd client
npm run dev # Vite dev server on http://localhost:5173
```
The dev server proxies WebSocket traffic to `ws://localhost:3000/ws`, so keep the backend running.

## Publishing Telemetry
- **HTTP:** POST a `WaggleData` JSON object to `/batch`. The backend converts embedded PNGs to 500×500 JPG thumbnails and stores up to 10 recent frames while clients are disconnected.
- **WebSocket:** Connect to `/ws`, send any message to mark the client ready, and the server will start streaming JSON arrays of frames at up to 100 Hz.

Minimal example:
```jsonc
{
"sent_timestamp": 1728000000,
"graph_data": {
"Battery Voltage": [
{ "x": 1728000000.0, "y": 12.6 }
]
},
"string_data": {
"Mode": { "value": "Autonomous" }
}
}
```
See `docs/api.md` for the full schema (images, SVG overlays, robot pose data, etc.).

## Tooling
- `cargo run --example simulator` — generates fake telemetry to exercise the dashboard without hardware.
- `tools/replay.py` — replays saved telemetry into a live Waggle instance (requires Python 3).
- `tools/export_video.py` — exports replayed image streams as numbered JPG sequences.

## Testing & Linting
- Backend: `cargo fmt` and `cargo clippy --all-targets`.
- Frontend: `npm run lint --prefix client` and `npm run build --prefix client`.

## Contribution Checklist
- Run the formatting/linting commands above before opening a PR.
- Capture screenshots or short screencasts when changing UI behavior.
- Keep `docs/` in sync with new API fields or workflow changes.
- Coordinate schema or dashboard updates with team lead and the hive team so downstream consumers stay aligned.
64 changes: 64 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Waggle

Waggle is the CU Robotics telemetry service: a Rust/Axum backend that buffers incoming telemetry frames and a React (Vite) dashboard that renders them in the browser. Producers POST JSON batches to `/batch`; connected clients receive live updates over `/ws`.

## Prerequisites
- Rust toolchain via [`rustup`](https://rustup.rs/).
- Node.js 20+ and npm. You can install Node with `./tools/install.sh` on Ubuntu-based hosts.
- Python 3 if you plan to use the replay/export utilities in `tools/`.

## Quick Start
```bash
# Install frontend dependencies and build the production bundle
npm install --prefix client
npm run build --prefix client

# Run the backend (serves the built dashboard at http://localhost:3000/)
cargo run
```

### Development Loop (hot reload)
```bash
# Terminal 1 – backend
cargo run

# Terminal 2 – frontend
cd client
npm run dev # Vite dev server on http://localhost:5173
```
The dev server proxies WebSocket traffic to `ws://localhost:3000/ws`, so keep the backend running.

## Publishing Telemetry
- **HTTP:** POST a `WaggleData` JSON object to `/batch`. The backend converts embedded PNGs to 500×500 JPG thumbnails and stores up to 10 recent frames while clients are disconnected.
- **WebSocket:** Connect to `/ws`, send any message to mark the client ready, and the server will start streaming JSON arrays of frames at up to 100 Hz.

Minimal example:
```jsonc
{
"sent_timestamp": 1728000000,
"graph_data": {
"Battery Voltage": [
{ "x": 1728000000.0, "y": 12.6 }
]
},
"string_data": {
"Mode": { "value": "Autonomous" }
}
}
```
See `docs/api.md` for the full schema (images, SVG overlays, robot pose data, etc.).

## Tooling
- `cargo run --example simulator` — generates fake telemetry to exercise the dashboard without hardware.
- `tools/replay.py` — replays saved telemetry into a live Waggle instance (requires Python 3).
- `tools/export_video.py` — exports replayed image streams as numbered JPG sequences.

## Testing & Linting
- Backend: `cargo fmt` and `cargo clippy --all-targets`.
- Frontend: `npm run lint --prefix client` and `npm run build --prefix client`.

## Contribution Checklist
- Run the formatting/linting commands above before opening a PR.
- Capture screenshots or short screencasts when changing UI behavior.
- Keep `docs/` in sync with new API fields or workflow changes.
- Coordinate schema or dashboard updates with team lead and the hive team so downstream consumers stay aligned.
4 changes: 3 additions & 1 deletion docs/README_out_of_date.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Waggle Manual
# Waggle Manual (Archived)

> **Note:** This document has been superseded by the updated guides in `docs/README.md` and `docs/api.md`. It remains here for historical reference and may describe behavior from the legacy Go implementation.

## Table of Contents
- [Overview](#overview)
Expand Down
147 changes: 147 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Waggle API Reference

This document describes the network interfaces exposed by the Waggle backend. All routes are rooted at `http://<host>:3000/` unless configured otherwise.

## Table of Contents
- [Endpoints](#endpoints)
- [Telemetry Schema](#telemetry-schema)
- [Graph Settings](#graph-settings)
- [Versioning](#versioning)

## Endpoints

### `POST /batch`
Accepts a single telemetry batch encoded as JSON. The body must be valid UTF-8.

- **Headers:** `Content-Type: application/json`
- **Response:** `200 OK` on success, `4xx` on malformed input.
- **Rate:** Designed for up to 100 frames per second; higher rates may be dropped once the buffer fills.

Example:

```json
{
"sent_timestamp": 1730000000,
"graph_data": {
"Motor RPM": [
{ "x": 1730000000.0, "y": 123.4 }
],
"Battery Voltage": [
{ "x": 1730000000.0, "y": 12.7, "settings": { "clear_data": false } }
]
},
"images": {
"Front Camera": {
"image_data": "<base64 png string>",
"scale": 1,
"flip": false
}
},
"svg_data": {
"Field Overlay": {
"svg_string": "<svg>...</svg>"
}
},
"string_data": {
"Mode": { "value": "Autonomous" },
"Status": { "value": "Ready" }
},
"robot_position": {
"x": 1.25,
"y": 3.42,
"heading": 0.87
}
}
```

#### Error handling
- Invalid JSON results in `400 Bad Request`.
- Images that fail to decode are skipped; the response still returns `200 OK`. Backend logs contain details.
- Oversized payloads may be rejected by the reverse proxy if one is placed in front of Waggle.

### `GET /ws`
WebSocket endpoint used by dashboards and other consumers to receive live telemetry.

- **Protocol:** ws / wss (if proxied).
- **Messages:** JSON-encoded arrays of `WaggleData` objects.
- **Client responsibilities:**
- Send a message (any string) immediately after connecting to mark the socket ready to receive data.
- Handle `[]` (empty arrays) which are used as keep-alives.
- Reconnect if the socket closes; see `client/src/hooks/useWebSocket.ts` for a reference implementation.

Example message delivered to clients:

```json
[
{
"sent_timestamp": 1730001234,
"graph_data": {
"Motor RPM": [
{ "x": 1730001234.0, "y": 120.0 },
{ "x": 1730001234.1, "y": 119.4 }
]
},
"images": {},
"svg_data": {},
"string_data": {}
}
]
```

### Static assets
Any other HTTP request falls back to serving files from `client/dist`. This allows the React single-page application to be hosted on the same origin.

## Telemetry Schema

| Field | Type | Required | Notes |
| ----- | ---- | -------- | ----- |
| `sent_timestamp` | number | ✓ | Epoch in seconds or milliseconds. |
| `graph_data` | object | optional | Map of series name → array of [`GraphPoint`](#graphpoint). |
| `images` | object | optional | Map of name → [`ImageData`](#imagedata). |
| `svg_data` | object | optional | Map of name → [`SvgData`](#svgdata). |
| `string_data` | object | optional | Map of name → [`StringData`](#stringdata). |
| `robot_position` | object | optional | [`RobotPosition`](#robotposition). Stored by the frontend; UI components can visualize it. |

### `GraphPoint`
```json
{ "x": <number>, "y": <number>, "settings": { "clear_data": <bool> }? }
```

### `ImageData`
```json
{ "image_data": "<base64 png>", "scale": <number>, "flip": <bool> }
```
- Publish PNG data; the backend resizes to 500×500 and converts to JPG before sending to clients.
- `scale` controls the display size multiplier on the dashboard.
- `flip=true` indicates the UI should mirror the image horizontally and vertically.

### `SvgData`
```json
{ "svg_string": "<svg>...</svg>" }
```
- Provide valid inline SVG markup. The frontend injects it directly via `dangerouslySetInnerHTML`.

### `StringData`
```json
{ "value": "<string>" }
```
- Use for human-readable values (states, warnings, counters).

### `RobotPosition`
```json
{ "x": <number>, "y": <number>, "heading": <number> }
```
- Heading is measured in radians; consumers can convert as needed.

## Graph Settings
Each point accepts an optional `settings` object. Supported flags:

| Flag | Type | Description |
| ---- | ---- | ----------- |
| `clear_data` | boolean | If true, the frontend clears the series before pushing the next point. Useful for resetting integral plots without breaking continuity. |

Additional settings can be introduced in future versions; clients should ignore unknown fields.

## Versioning
The current payload format is equivalent to `"schema 1"` in replay files. Breaking changes will increment the schema and be documented here. Consumers should reject replays that do not start with `schema 1` as their first line.