Files
rmon/docs/ui-spec.md
T
Martino Ferrari dca378b5ef initial commit
2026-04-11 16:30:18 +02:00

7.7 KiB

RMon UI Specification

Technology

  • Framework: egui + eframe (immediate-mode Rust GUI)
  • Render backend: glow (OpenGL 2.1+) — chosen for maximum Linux compatibility
  • Plotting: egui_plot for interactive panels; custom egui painter (line strip primitives) for high-throughput paths (>100k points/frame)
  • Async runtime: tokio (runs in a background thread; communicates with egui via std::sync::mpsc)
  • SSH tunnel management: spawns system ssh subprocess

Deployment

Single binary. On Linux, dynamically links only:

  • libGL (OpenGL driver, always present on any desktop Linux)
  • libX11 / libxcb (X11, or Wayland via libwayland-client with wayland feature)
  • libc (glibc, standard on all Linux distributions)

On Windows: fully static (links Win32 APIs and ANGLE for OpenGL ES via DirectX).

Pre-built agent binaries for all supported architectures are embedded in the UI binary at compile time using include_bytes!. This allows the UI to deploy the agent without any extra files.

Layout

┌─────────────────────────────────────────────────────────────────────┐
│ [Connect ▼]  [host: myserver]  [⏺ Record]  [⏹ Stop]  [Status: OK] │  ← Toolbar
├────────────────┬────────────────────────────────────────────────────┤
│ Signal Tree    │  Plot Panel 1                  │  Plot Panel 2     │
│                │                                │                   │
│ ▼ imu         │  [signal A] [signal B]  [✕]   │  [signal C]  [✕]  │
│   ▼ accel     │  ┌──────────────────────────┐  │  ┌─────────────┐  │
│     accel_x ══╪═►│ time-series plot          │  │ │             │  │
│     accel_y   │  │                           │  │ │             │  │
│     accel_z   │  │   ╭─╮   ╭──╮             │  │ │             │  │
│   ▼ gyro      │  │  ╯  ╰──╯  ╰─            │  │ │             │  │
│     gyro_x    │  │                           │  │ └─────────────┘  │
│     gyro_y    │  │  ┼────────────────────── │  │                   │
│ ▼ temps       │  └──────────────────────────┘  │  [+ Add Plot]     │
│   inlet       │  [cursor A: t=12.3s  val=1.2]  │                   │
│   outlet      │  [cursor B: t=15.1s  Δt=2.8s]  │                   │
│               │  [A-B: Δval=-0.3  mean=1.05]   │                   │
└───────────────┴────────────────────────────────┴───────────────────┘

Connection Dialog

Shown on startup (or via toolbar "Connect" button) when not connected.

Fields:

  • SSH Host: free text, matched against ~/.ssh/config Host entries (autocomplete offered)
  • Agent Port: numeric, default 7891
  • Agent Config: path on remote machine, default ~/.rmon/config.toml

On connect:

  1. Detect remote arch via ssh {host} uname -m
  2. Check / upload agent binary (see docs/architecture.md connection flow)
  3. Start agent if not running
  4. Establish port forward
  5. Perform protocol handshake
  6. Fetch signal list → populate signal tree

Connection errors are shown inline with a retry button.

Signal Tree Panel

  • Collapsible tree mirroring the path field of each SignalInfo
  • Each leaf shows: label, unit, last value (live-updated), colored dot (source status)
  • Drag-and-drop: drag a signal leaf onto a plot panel to add it
  • Right-click menu: "Add to plot 1 / 2 / new plot", "Signal info" (opens info popup), "Start recording", "Stop recording"
  • Search/filter bar at the top of the panel
  • Recording state shown with red ⏺ icon on the signal leaf

Plot Panels

Any number of plot panels can be open (horizontally tiled by default, resizable/detachable).

Axes

  • X axis: time (absolute UTC or relative to a reference point; toggled in toolbar)
  • Y axis: auto-range by default; can be locked manually
  • Zoom: scroll wheel (time axis), Ctrl+scroll (Y axis)
  • Pan: click-drag on the plot

Signals in a Plot

  • Each signal rendered as a colored line
  • Legend at top of plot (click to hide/show individual signals)
  • Color is auto-assigned, can be changed via right-click on the legend entry
  • Line style (solid/dashed/dotted) and width configurable per signal

Cursors

  • Add cursors via toolbar button or right-click on plot → "Add cursor"
  • Drag to position; snaps to nearest sample if within threshold
  • Measurement bar below the plot shows:
    • Per cursor: timestamp, value for each visible signal
    • Between two cursors: Δt, Δvalue, mean, min, max over the interval

Math Signals

  • Right-click plot → "Add math signal"
  • Expression editor (simple formula: a + b, a * 2.0, a - b, etc. where a, b are signal IDs)
  • Math signals appear in the legend with an f(x) icon and can be added to other plots

High-Throughput Rendering

When a signal has more points than pixels in the X direction, the renderer decimates using min-max downsampling (preserves peaks/troughs visually). This runs on the CPU in plot_panel.rs before passing vertices to egui's painter.

Toolbar

  • Connect / Disconnect dropdown (shows current host or "Not connected")
  • Time range selector: presets (last 10s / 1min / 10min / 1h) or custom range picker
  • Time display toggle: absolute UTC vs relative
  • Record button: opens signal selection dialog → starts recording for selected signals
  • Status indicator: green = connected, yellow = reconnecting, red = disconnected

Keyboard Shortcuts

Key Action
Space Pause / resume live scrolling
R Reset all plot zoom/pan to live view
C Add cursor to focused plot
Del Remove selected cursor
Ctrl+N Add new plot panel
Ctrl+W Close focused plot panel
Ctrl+F Focus signal tree search
Ctrl+S Save current layout to file

Session Persistence

On clean exit, the UI saves the current session to ~/.config/rmon/last_session.toml:

  • Connected host alias
  • Open plot panels and their signal assignments
  • Cursor positions
  • Time range and zoom state

On next launch with the same host, it offers to restore the session.

State Machine (connection)

Disconnected
    │ user clicks Connect
    ▼
Deploying          (copying/verifying agent binary)
    │ agent ready
    ▼
Tunneling          (SSH port-forward process running)
    │ port open
    ▼
Handshaking        (TCP open, sent Handshake, awaiting HandshakeAck)
    │ accepted
    ▼
Connected          (normal operation, DataBatch messages flowing)
    │ tunnel drops / error
    ▼
Reconnecting       (exponential backoff, max 30s, reuses same tunnel if still up)
    │ max retries exceeded
    ▼
Disconnected

Async / UI Thread Boundary

  • tokio runtime runs in a dedicated OS thread
  • The egui render loop runs on the main thread (required by most platform window systems)
  • Communication: std::sync::mpsc::channel — the tokio tasks push UiEvent variants (DataBatch, SignalList, Status, Error) to the UI; the UI pushes Command variants (Subscribe, QueryHistory, StartRecording) to tokio
  • eframe::App::update() drains the incoming event channel each frame before rendering