125 lines
4.8 KiB
Markdown
125 lines
4.8 KiB
Markdown
# Telemetry Monitor
|
||
|
||
A Flutter application for visualizing real-time telemetry streams over WebSocket.
|
||
Targets: Linux desktop, Android, and Web browsers (Flutter 3.41+).
|
||
|
||
## What it does
|
||
|
||
Connects to a WebSocket server, decodes Protocol Buffer packets carrying up to
|
||
16 channels of `double` data plus 8 status integers and a pause flag, and renders
|
||
them as rolling time-series charts at 60 Hz. Also receives log packets with
|
||
severity, error number, timestamp, and description.
|
||
|
||
Key features:
|
||
|
||
- 4–16 simultaneous charts in a configurable grid.
|
||
- 1 kHz packet rate with batched per-frame rendering.
|
||
- Min/max decimation for smooth display at any zoom level.
|
||
- Hatched regions for missing-data gaps; thin markers for sub-pixel gaps.
|
||
- Scrollback through the configured packet buffer (default 10 minutes).
|
||
- Shared X-zoom across charts; per-chart Y-zoom.
|
||
- Two-tab UI: dashboard with errors-only mini log, plus a full filterable log.
|
||
- CSV export for both packet data and log entries.
|
||
- Pause from UI button or from a proto field.
|
||
- 8 named status indicators with 4-state color coding (gray / red / yellow / green).
|
||
|
||
## Quick start
|
||
|
||
### Prerequisites
|
||
|
||
- Flutter 3.41 or later.
|
||
- Protocol Buffers compiler (`protoc`) version 3.x.
|
||
- The Dart `protoc_plugin` package (installed automatically via `pubspec.yaml`).
|
||
|
||
### Generating Protobuf bindings
|
||
|
||
The `messages.proto` file lives in `proto/`. After cloning, run:
|
||
|
||
mkdir -p lib/proto
|
||
protoc --dart_out=lib/proto/ -Iproto/ proto/messages.proto
|
||
|
||
This produces `lib/proto/messages.pb.dart` and friends. The generated files are
|
||
gitignored; regenerate after any schema change.
|
||
|
||
### Running
|
||
|
||
flutter pub get
|
||
flutter run -d linux # Linux desktop
|
||
flutter run -d <device-id> # Android
|
||
flutter run -d chrome # Web (CanvasKit recommended)
|
||
|
||
For Web, prefer the CanvasKit renderer for chart performance:
|
||
|
||
flutter run -d chrome --web-renderer canvaskit
|
||
|
||
### First-run configuration
|
||
|
||
The app starts with a default WebSocket URL of `ws://localhost:9000`. Open
|
||
**Settings** to change it. Open **Layout** to assign channels to grid cells and
|
||
name them.
|
||
|
||
## Architecture overview
|
||
|
||
See [`ARCHITECTURE.md`](./ARCHITECTURE.md) for the full design. Brief summary:
|
||
|
||
- **Transport** owns the WebSocket and reconnection.
|
||
- **Decoder** turns raw frames into `Envelope` messages (isolate on native,
|
||
inline on Web).
|
||
- **Session** owns ring buffers for packets and logs, the view-state machine,
|
||
and the per-frame Ticker that drives all rendering.
|
||
- **Layout** owns the grid configuration, channel assignments, channel names,
|
||
and status indicator names. Persisted via `shared_preferences`.
|
||
- **Export** writes CSV files (path_provider on native, Blob download on Web).
|
||
- **UI** is a `CustomPainter`-based chart grid plus the toolbar, status bar,
|
||
tabs, and dialogs.
|
||
|
||
## Key invariants
|
||
|
||
These are the design rules that keep the app correct. Don't violate them
|
||
without re-reading `ARCHITECTURE.md`.
|
||
|
||
1. **Single source of truth.** Sample data lives only in the packet ring
|
||
buffer. Log entries live only in the log ring buffer. Status snapshots
|
||
are *derived* from the packet buffer each frame, not latched.
|
||
|
||
2. **Producer/consumer decoupling.** WebSocket packets write into ring buffers
|
||
eagerly. Charts repaint only on the per-frame Ticker. The two are decoupled
|
||
by design — never call repaint from a packet handler.
|
||
|
||
3. **Disabled channels still record.** Toggling a channel "off" hides it on
|
||
the dashboard but does not stop recording or change the CSV output.
|
||
|
||
4. **Buffer is authoritative for export.** CSV always reads from the buffer,
|
||
never from cached UI snapshots.
|
||
|
||
5. **Window state is shared, Y state is per-chart.** All charts share one
|
||
X-axis window (zoom + pan + anchor). Each chart owns its own Y-mode and
|
||
Y-range.
|
||
|
||
## Project layout
|
||
|
||
lib/
|
||
main.dart # Entry point
|
||
app.dart # MaterialApp, top-level wiring
|
||
proto/ # Generated from messages.proto
|
||
config/ # AppConfig, Settings (persisted)
|
||
transport/ # WebSocket abstraction
|
||
decoder/ # Protobuf decoding
|
||
session/ # Ring buffers, view state, controller
|
||
layout/ # Grid + chart config
|
||
export/ # CSV exporter
|
||
ui/ # Widgets, dialogs, painters
|
||
proto/
|
||
messages.proto # Protocol Buffer schema
|
||
|
||
## Build targets
|
||
|
||
| Target | Notes |
|
||
| ------- | -------------------------------------------------------- |
|
||
| Linux | Primary development target. Full feature set. |
|
||
| Android | Same code as Linux. Uses `IOWebSocketChannel`. |
|
||
| Web | Decoder runs inline (no isolates). CanvasKit recommended. CSV export uses Blob downloads. |
|
||
|
||
## License
|
||
|
||
(Add as appropriate.) |