Files
xserial/README_en.md

12 KiB
Raw Permalink Blame History

pipeview

Cross-platform serial / TCP / UDP data inspection tool with configurable framing, protocol decoding, multi-session management, and real-time waveform plotting — all in a single binary.

Built with Rust + egui, scriptable with Lua.

中文文档


Table of Contents


Features

Transport

Type Description Options
Serial Serial port communication Port name, baud rate (30012M), data bits (5/6/7/8), parity (None/Odd/Even), stop bits (1/2), flow control (None/Software/Hardware), DTR/RTS control
TCP TCP client Target address host:port
UDP UDP communication Bind address host:port, optional remote address

Framers

Framers split raw byte streams into discrete frames. Each session supports multiple independent pipelines — the same byte stream feeds multiple framer→decoder chains in parallel.

Framer Description Parameters
Line Split by \n strip_cr, max_line_len
Fixed Fixed-length frames frame_len
Length Length-prefixed protocol len_bytes (1/2/4/8), endian, length_includes_self, max_payload
COBS Consistent Overhead Byte Stuffing max_frame
MixedTextPlot Hybrid text lines + COBS-encoded plot frames on one stream strip_cr, max_line_len, max_plot_frame
Lua User-defined framer script script_path

Decoders

Decoders parse framed data into displayable content.

Decoder Output Parameters
Text Text encoding (UTF-8 / Latin1 / ASCII)
Hex Hexadecimal uppercase, separator, bytes_per_group, endian
Plot Waveform sample_type (i8f64), endian, channels (164), format (Interleaved / Block / XY)
MixedTextPlot Hybrid text + waveform encoding
Lua Custom script_path

Plot sample formats:

Format Description Byte layout
Interleaved Channels interleaved [ch0_s0, ch1_s0, ch2_s0, ch0_s1, ch1_s1, …]
Block Channel-contiguous blocks [ch0_s0, ch0_s1, …, ch1_s0, ch1_s1, …]
XY 2-channel x/y pairs [x0, y0, x1, y1, …]

Supported sample types: i8, u8, i16, u16, i32, u32, i64, u64, f32, f64

Views

  • Text View — formatted text with timestamps, direction markers ([IN]/[OUT]), and pipeline labels. Built-in search (Ctrl+F) with case-sensitive toggle, match counter, and highlighting.
  • Hex View — hex dump alongside ASCII sidebar. Configurable byte grouping and endianness.
  • Plot View — real-time waveforms via egui_plot. Auto-fit, box zoom, axis locking, follow-latest, detached window, channel legend.

Sessions

  • Multi-session — tabbed interface, each session independently configured
  • Connection control — Connect / Disconnect / Reconnect with auto-reconnect on drop
  • Live reconfiguration — change framer/decoder settings without restarting
  • Data sending — Text mode (UTF-8, configurable line endings) and Hex mode (raw bytes). Four line ending options: None / LF / CR / CRLF
  • Ring buffer — default 10,000 entries, configurable 1001,000,000
  • Log to file — background writer thread with 1 KB buffer, non-blocking
  • SearchCtrl+F search bar, case-sensitive toggle, F3/Shift+F3 navigation

Lua Scripting

Built-in LuaJIT runtime:

  • Custom framers — implement feed(bytes), flush(), reset(), pending_len()
  • Custom decoders — implement decode(frame), return text/hex/plot/binary
  • Session APIpipeview.open() to create sessions, session:on_data() for event callbacks, session:send() to transmit data
  • Utilitiespipeview.list_ports(), pipeview.sleep(ms), pipeview.poll(limit), pipeview.log(msg)

Keyboard Shortcuts

Shortcut Action
Ctrl+N New session
Ctrl+E Edit current session
Ctrl+W Delete current session
Ctrl+F5 Toggle connection
Ctrl+T / Ctrl+H / Ctrl+P Switch to Text / Hex / Plot view
Ctrl+Tab / Ctrl+Shift+Tab Next / Previous tab
Ctrl+L Clear output
Ctrl+F Search
F3 / Shift+F3 Next / Previous match
Ctrl+, UI settings
Esc Close overlay

Quick Start

Prerequisites

Platform Dependencies
Linux libudev-dev (apt install libudev-dev)
macOS None
Windows None
All Rust ≥ 1.85, C compiler (GCC / Clang / MSVC)

Build & Run

git clone https://github.com/your-org/pipeview.git
cd pipeview

cargo run -p pipeview-gui

# Run tests
cargo test --workspace           # ~308 tests
cargo clippy --workspace --all-targets -- -D warnings

Release Build

cargo build -p pipeview-gui --release
# Binary: target/release/pipeview-gui (Linux/macOS)
#         target/release/pipeview-gui.exe (Windows)

Walkthrough: Drone Telemetry

Parse Betaflight/INAV flight controller telemetry in the format:

AHRS q:1.0000,0.0998,0.0499,0.0200|YPR:8.87,4.44,2.96|Gyro:14.78,8.87,5.92|RC:1559,1544,1500,1519|M:1612,1588,1603,1597|L:0 F:1 C:0

Step 1: Start the data source

python tools/test_drone.py --rate 10 --port 8091

Step 2: Configure the session

In pipeview-gui, create a session with two pipelines:

Setting Value
Transport TCP 127.0.0.1:8091
Pipeline 1 Framer: Line → Decoder: Luaexamples/drone_text.lua
Pipeline 2 Framer: Line → Decoder: Luaexamples/drone_plot.lua

Step 3: View the results

  • Text View — formatted sensor readouts
  • Plot View — real-time gyroscope curves (gz/gy/gx)

The decoder in examples/drone_plot.lua:

return {
    decode = function(frame)
        local gz, gy, gx = frame:match("Gyro:([%d%.%-]+),([%d%.%-]+),([%d%.%-]+)")
        return {
            kind = "plot",
            channels = { { tonumber(gz) }, { tonumber(gy) }, { tonumber(gx) } },
            sample_type = "F64",
            format = "Block",
        }
    end,
}

Lua Scripting Guide

Framer API

A Lua framer splits raw bytes into frames. The script must return a table with these functions:

return {
    feed = function(bytes)
        -- bytes: Lua string (raw bytes)
        -- Returns: { frame1, frame2, ... } or nil
    end,

    flush = function()
        -- Returns: last buffered frame (string) or nil
    end,

    reset = function()
    end,

    pending_len = function()
        -- Returns: number of bytes pending in buffer
    end,
}

Reference: tests/lua_line_framer.lua (line-based framer splitting on \n).

Decoder API

A Lua decoder parses a frame into structured data. The script must return a table with a decode function:

return {
    decode = function(frame)
        -- frame: Lua string (one frame from the framer)
        -- Returns nil → skip this frame
        -- Returns string → treated as Text
        -- Returns table → must contain "kind" field
    end,
}

Return value formats:

kind Required Optional Purpose
"text" data: string Text view
"hex" data: string Hex view
"binary" data: string Raw bytes
"plot" channels: {{number,…},…} sample_type, format Plot view

Plot return value example:

return {
    kind = "plot",
    channels = {
        { 1.0, 2.0, 3.0 },  -- channel 0
        { 4.0, 5.0, 6.0 },  -- channel 1
    },
    sample_type = "F64",    -- default F64; also I8/U8/I16/U32/U64/F32
    format = "Block",       -- default Interleaved; also Block/XY
}

More examples in examples/.


Architecture

┌──────────────────────────────────────────────────┐
│  pipeview-gui (egui)       pipeview-tui (ratatui) │
├──────────────────────────────────────────────────┤
│  pipeview-client                                  │
│  SessionManager · Session · Config · History     │
│  Lua Runtime (mlua / LuaJIT)                     │
├──────────────────────────────────────────────────┤
│  pipeview-core                                    │
│  Transport ──▶ Frame ──▶ Protocol ──▶ Pipeline  │
└──────────────────────────────────────────────────┘
Crate Type Purpose
pipeview-core library Transport (Serial/TCP/UDP), framers (Line/Fixed/Length/COBS/Mixed/Lua), decoders (Text/Hex/Plot), MultiPipeline
pipeview-client library Session lifecycle, SessionManager, event broadcast (tokio broadcast), RingBuffer history, Lua runtime & session API
pipeview-gui binary egui desktop app: sidebar, config, console, text/hex/plot panels, keyboard shortcuts, font management, profiling
pipeview-tui binary ratatui terminal app (feature-incomplete, under development)

Dependency flow: core ← client ← {gui, tui}

Data flow:

[Transport] → read bytes → [MultiPipeline]
    → Pipeline 1: Framer → Decoder → DecodedEntry → broadcast → GUI buffers
    → Pipeline 2: Framer → Decoder → DecodedEntry → broadcast → GUI buffers
    → ...

Each pipeline frames and decodes independently. Only successful decodes produce output.


Configuration & Persistence

GUI state is saved automatically to platform-standard locations:

Platform Path
Linux $XDG_CONFIG_HOME/pipeview/gui-state.json or ~/.config/pipeview/gui-state.json
macOS ~/Library/Application Support/pipeview/gui-state.json
Windows %APPDATA%\pipeview\gui-state.json

Persisted data includes: session configurations (transport, pipelines), log settings, active tab, and display options.

Log files are written to logs/ under the config directory, named session_{id}_{timestamp}.log.


Development Tools

Test Data Generators

# Plot waveform test data
python tools/test_plot.py --wire-format mixed --host 127.0.0.1 --port 8091
python tools/test_plot.py --wire-format mixed --format xy --channels 2
python tools/test_plot.py --wire-format raw --channels 2 --framelen 256

# Drone telemetry test data
python tools/test_drone.py --rate 10 --port 8092

Profiling

RUST_LOG=pipeview_gui::perf=info XSERIAL_GUI_PROFILE=1 cargo run -p pipeview-gui
XSERIAL_GUI_PROFILE_INTERVAL_MS=500 cargo run -p pipeview-gui

Tracing

RUST_LOG=info cargo run -p pipeview-gui
RUST_LOG=pipeview_gui=debug cargo run -p pipeview-gui

Project Structure

crates/
  pipeview-core/        # Transport, framing, protocol
  pipeview-client/      # Session management, Lua runtime
  pipeview-gui/         # egui desktop application
  pipeview-tui/         # ratatui terminal application
examples/              # Lua script examples
  drone_plot.lua       # Drone telemetry plot decoder
  drone_text.lua       # Drone telemetry text decoder
tests/                 # Lua test fixtures
tools/                 # Development utilities
  test_plot.py         # Waveform test data generator
  test_drone.py        # Drone test data generator
  test_plot_serial.c   # C serial plot test client
  test_text_serial.c   # C serial text test client
  xs_mixed_plot.h      # MixedTextPlot protocol reference

Tech Stack

  • Runtime: tokio (multi-threaded)
  • Serial: tokio-serial + serialport
  • GUI: egui + egui_plot
  • Lua: mlua 0.11, LuaJIT (vendored), async/serde/send
  • Events: tokio::sync::broadcast (multi-subscriber)
  • Zero feature flags, zero build scripts, zero conditional compilation

License

MIT