From 367800a4265cab6f41dcccfeb4314f523e7f63c0 Mon Sep 17 00:00:00 2001 From: FallenSigh Date: Fri, 12 Jun 2026 21:15:48 +0800 Subject: [PATCH] update README.md Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- README.md | 383 +++++++++++++++--------------------------------------- 1 file changed, 105 insertions(+), 278 deletions(-) diff --git a/README.md b/README.md index b26bc6a..a750b46 100644 --- a/README.md +++ b/README.md @@ -1,159 +1,58 @@ # xserial -**跨平台串口 / TCP / UDP 数据观测工具** — 可配置分帧、协议解码、多会话管理,支持文本、十六进制和实时波形绘图。 +**跨平台串口 / TCP / UDP 数据观测工具** — 可配置分帧、协议解码、多会话管理、实时波形绘图,单二进制零依赖。 -基于 Rust workspace,GUI 使用 [egui](https://github.com/emilk/egui) + [egui_plot](https://github.com/emilk/egui/tree/master/crates/egui_plot),支持 Lua 脚本扩展分帧与解码逻辑。 +基于 Rust + [egui](https://github.com/emilk/egui) 构建,支持 Lua 脚本扩展。 --- -## 架构 - -``` -┌─────────────────────────────────────────────────────┐ -│ xserial-gui (egui) xserial-tui (ratatui) │ -│ 面板: sidebar, console, 占位实现 │ -│ hex_view, plot_view, │ -│ config │ -├─────────────────────────────────────────────────────┤ -│ xserial-client │ -│ SessionManager · Session · Config · History │ -│ Lua Runtime (mlua/LuaJIT) │ -│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ -│ │ LuaFramer│ │LuaDecoder│ │ Lua Session API │ │ -│ └──────────┘ └──────────┘ └──────────────────┘ │ -├─────────────────────────────────────────────────────┤ -│ xserial-core │ -│ Transport ──▶ Frame ──▶ Protocol ──▶ Pipeline │ -│ (Serial, (Line, (Text, Hex, (MultiPipeline) │ -│ TCP, UDP) Fixed, Plot, │ -│ Length, MixedTextPlot) │ -│ Cobs, │ -│ MixedTextPlot) │ -└─────────────────────────────────────────────────────┘ -``` - -| Crate | 类型 | 职责 | -|-------|------|------| -| `xserial-core` | library | 传输层、分帧器、协议解码器、Pipeline | -| `xserial-client` | library | 会话管理、配置持久化、事件分发、历史缓冲、Lua 运行时 | -| `xserial-gui` | binary | egui 桌面应用(主要入口) | -| `xserial-tui` | binary | ratatui 终端应用(占位,未达功能对等) | - -依赖方向: `core ← client ← {gui, tui}` - ---- - -## 构建 - -**前置条件**: - -- **Rust ≥ 1.85**(workspace 使用 `edition = "2024"`) -- **Linux**: `libudev-dev`(`serialport` 依赖) -- **所有平台**: C 编译器(`mlua` 使用 `vendored` 特性从源码编译 LuaJIT) - -```bash -# 编译检查 -cargo check --workspace - -# 运行测试(~266 个) -cargo test --workspace - -# 格式化 + Clippy -cargo fmt --all -cargo clippy --workspace --all-targets -- -D warnings -``` - ---- - -## 运行 - -### GUI(主要入口) - -```bash -cargo run -p xserial-gui -``` - -### TUI(占位实现) - -```bash -cargo run -p xserial-tui -``` - ---- - -## 功能 +## 功能特性 ### 传输层 -| 类型 | 配置项 | -|------|--------| -| **Serial** | 端口名、波特率、数据位 (5/6/7/8)、校验位 (None/Odd/Even)、停止位 (1/2)、流控 (None/Software/Hardware)、DTR、RTS | -| **TCP** | 目标地址 `host:port` | -| **UDP** | 绑定地址 `host:port`,可选远端地址 | +- **串口** — 波特率 (300–12M)、数据位 (5/6/7/8)、校验位 (None/Odd/Even)、停止位 (1/2)、流控 (None/Software/Hardware)、DTR/RTS 控制 +- **TCP** — 原始 TCP 客户端 +- **UDP** — 绑定地址 + 可选远端地址 -DTR/RTS 控制仅在 Serial 连接时可用。 +### 分帧与解码 -### 分帧器 +每个 Session 可配置**多条独立管线** — 同一字节流并行送入多个 framer→decoder 链路。 -| 分帧器 | 说明 | 配置 | -|--------|------|------| -| **Line** | 按换行符 `\n` 分割,可选去除 `\r` | `strip_cr`, `max_line_len` | -| **Fixed** | 固定字节数为一帧 | `frame_len` | -| **Length** | 长度前缀协议帧 | `len_bytes` (1/2/4/8), `endian`, `length_includes_self`, `max_payload` | -| **Cobs** | [COBS](https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing) 编码,`0x00` 分隔 | `max_frame` | -| **MixedTextPlot** | 单连接混合文本行 + COBS plot 帧 | `strip_cr`, `max_line_len`, `max_plot_frame` | -| **Lua** | 用户自定义 Lua 脚本 | `script_path` | +| 分帧器 | 说明 | +|--------|------| +| Line | 按 `\n` 分割,可选去除 `\r` | +| Fixed | 固定字节数为一帧 | +| Length | 长度前缀协议 (1/2/4/8 字节头) | +| COBS | [Consistent Overhead Byte Stuffing](https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing) | +| MixedTextPlot | 单连接混合文本行 + COBS plot 帧 | +| Lua | 用户自定义分帧脚本 | -### 协议解码器 +| 解码器 | 输出 | +|--------|------| +| Text | UTF-8 / Latin1 / ASCII | +| Hex | 可配置分组、大小端 | +| Plot | Interleaved / Block / XY 波形 (i8–f64) | +| MixedTextPlot | 混合文本 + 波形 | +| Lua | 用户自定义解码脚本 | -| 解码器 | 输出 | 配置 | -|--------|------|------| -| **Text** | UTF-8 / Latin1 文本 | `encoding` | -| **Hex** | 十六进制字符串 | `uppercase`, `separator`, `bytes_per_group`, `endian` | -| **Plot** | 数值波形数据 | `sample_type` (i8–f64), `endian`, `channels`, `format` (Interleaved / Block / XY) | -| **MixedTextPlot** | 混合流(文本 + 波形) | `encoding` | -| **Lua** | 用户自定义解码 | `script_path` | +### 视图 -#### Plot 采样格式 - -| 格式 | 说明 | -|------|------| -| **Interleaved** | 多通道交叉排列: `[ch0_s0, ch1_s0, ch0_s1, ch1_s1, …]` | -| **Block** | 按通道分块: `[ch0_s0, ch0_s1, …, ch1_s0, ch1_s1, …]` | -| **XY** | 2 通道,交替 x/y: `[x0, y0, x1, y1, …]` | - -支持的采样类型: `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `f32`, `f64` - -### Pipeline - -每个 Session 可配置多个 Pipeline。同一个字节流被送入所有 Pipeline,每个 Pipeline 独立分帧、解码,互不干扰。例如: - -- Pipeline "text": LineFramer → TextDecoder → 文本视图 -- Pipeline "hex": FixedFramer(16) → HexDecoder → 十六进制视图 -- Pipeline "plot": FixedFramer(256) → PlotDecoder → 波形视图 - -当数据到达时,只有成功解码的 Pipeline 产生输出。 +- **文本视图** — 带时间戳、方向标记、管线标签 +- **十六进制视图** — hex dump + ASCII 侧栏 +- **波形视图** — 实时波形:自适应、框选缩放、锁定坐标轴、浮动窗口 ### 会话管理 -- **多会话**: 同时运行多个独立 session -- **连接控制**: Connect / Disconnect / Reconnect -- **自动重连**: 断线后每秒自动重试 -- **动态重配置**: 运行时修改分帧器/解码器配置 -- **数据发送**: 通过 Console 面板发送原始字节到连接 -- **历史缓冲**: 环形缓冲区(默认 10,000 条),可配置上限 -- **状态持久化**: Session 配置自动保存到 `gui-state.json` +- 多会话并发,标签页切换 +- 连接 / 断开 / 重连,支持断线自动重连 +- 运行时重配置(修改分帧器/解码器无需重启) +- 环形缓冲区历史记录(可配置上限) +- **日志到文件** — 后台线程写入,不阻塞 UI +- 配置自动持久化到 `gui-state.json` -### Lua 脚本扩展 +### Lua 脚本 -内置 LuaJIT 运行时,支持: - -- **自定义分帧器**: 实现 `feed(bytes)`, `flush()`, `reset()`, `pending_len()` 四个函数 -- **自定义解码器**: 实现 `decode(frame)` 函数,返回 `{kind="text"|"hex"|"binary"|"plot", data=…}` -- **会话 API**: `xserial.open(config)` 创建 session,支持 `on_data(callback)` 事件回调 -- **辅助函数**: `xserial.list_ports()`, `xserial.sleep(ms)`, `xserial.poll(limit)`, `xserial.log(msg)` - -示例 Lua Line Framer: +内置 LuaJIT 运行时,自定义分帧和解码逻辑: ```lua local buffer = "" @@ -178,79 +77,99 @@ return { } ``` ---- - -## GUI - -### 面板 - -| 面板 | 功能 | -|------|------| -| **Sidebar** | Session 列表、创建/删除/编辑 session、连接切换 | -| **Config** | 传输参数、Pipeline 配置(分帧器 + 解码器类型及参数) | -| **Console** | 数据发送输入框,发送按钮 | -| **Text View** | 解码后的文本流,支持时间戳和方向标记 | -| **Hex View** | 十六进制字节展示,可配置分组和分隔符 | -| **Plot View** | 实时波形图,支持内嵌和浮动窗口两种模式 | +会话 API:`xserial.open()`、`xserial.list_ports()`、`xserial.sleep()`、`xserial.poll()`、`xserial.log()`、`session:on_data()`、`session:send()` ### 快捷键 | 快捷键 | 操作 | |--------|------| -| `Ctrl+Tab` | 下一个 Tab | -| `Ctrl+Shift+Tab` | 上一个 Tab | -| `Ctrl+T` | 切换到 Text 视图 | -| `Ctrl+H` | 切换到 Hex 视图 | -| `Ctrl+P` | 切换到 Plot 视图 | -| `Ctrl+N` | 新建 Session | -| `Ctrl+E` | 编辑当前 Session | -| `Ctrl+W` | 删除当前 Session | +| `Ctrl+N` | 新建会话 | +| `Ctrl+E` | 编辑当前会话 | +| `Ctrl+W` | 删除当前会话 | | `Ctrl+F5` | 切换连接 | +| `Ctrl+T/H/P` | 切换到文本 / 十六进制 / 波形视图 | +| `Ctrl+Tab` / `Ctrl+Shift+Tab` | 下一个 / 上一个标签页 | | `Ctrl+L` | 清空输出 | | `Ctrl+,` | UI 设置 | | `Esc` | 关闭浮层 | -### 状态持久化 +--- -GUI 状态(session 配置、活动 tab、显示选项)自动保存到: +## 快速开始 + +### 前置条件 + +- **Rust ≥ 1.85** +- **Linux**: `libudev-dev`(serialport 依赖) +- **所有平台**: C 编译器(mlua 从源码编译 LuaJIT) + +### 构建与运行 + +```bash +cargo run -p xserial-gui +``` + +### 测试 + +```bash +cargo test --workspace # ~308 个测试 +cargo clippy --workspace --all-targets -- -D warnings +``` + +### 配置文件位置 | 平台 | 路径 | |------|------| -| Linux | `$XDG_CONFIG_HOME/xserial/gui-state.json` 或 `~/.config/xserial/gui-state.json` | -| macOS | `~/Library/Application Support/xserial/gui-state.json` | -| Windows | `%APPDATA%\xserial\gui-state.json` | +| Linux | `$XDG_CONFIG_HOME/xserial/` 或 `~/.config/xserial/` | +| macOS | `~/Library/Application Support/xserial/` | +| Windows | `%APPDATA%\xserial\` | --- -## 开发工具 +## 架构 + +``` +┌──────────────────────────────────────────────────┐ +│ xserial-gui (egui) xserial-tui (ratatui) │ +├──────────────────────────────────────────────────┤ +│ xserial-client │ +│ SessionManager · Session · Config · History │ +│ Lua Runtime (mlua / LuaJIT) │ +├──────────────────────────────────────────────────┤ +│ xserial-core │ +│ Transport ──▶ Frame ──▶ Protocol ──▶ Pipeline │ +└──────────────────────────────────────────────────┘ +``` + +| Crate | 类型 | 职责 | +|-------|------|------| +| `xserial-core` | library | 传输层、分帧器、协议解码、管线 | +| `xserial-client` | library | 会话管理、事件分发、历史缓冲、Lua 运行时 | +| `xserial-gui` | binary | egui 桌面应用(主要入口) | +| `xserial-tui` | binary | ratatui 终端应用(占位) | + +依赖方向: `core ← client ← {gui, tui}` + +--- + +## 开发 ### Plot 测试服务器 ```bash -# 启动 TCP 波形数据源 python tools/test_plot.py --wire-format mixed --host 127.0.0.1 --port 8091 - -# XY 格式,2 通道 python tools/test_plot.py --wire-format mixed --format xy --channels 2 - -# 固定长度 raw plot 帧 -python tools/test_plot.py --wire-format raw --channels 2 --framelen 256 ``` -GUI 中配置: Transport `TCP 127.0.0.1:8091`, Framer `MixedTextPlot`, Decoder `MixedTextPlot` +GUI 中配置:Transport `TCP 127.0.0.1:8091`,Framer `MixedTextPlot`,Decoder `MixedTextPlot`。 ### 性能分析 ```bash -# 开启性能日志 RUST_LOG=xserial_gui::perf=info XSERIAL_GUI_PROFILE=1 cargo run -p xserial-gui - -# 自定义统计间隔(默认 1000ms) XSERIAL_GUI_PROFILE_INTERVAL_MS=500 cargo run -p xserial-gui ``` -日志输出: frame 耗时、事件 drain 耗时、text/hex/plot 渲染耗时、plot 点数统计 - ### 日志 ```bash @@ -258,109 +177,17 @@ RUST_LOG=info cargo run -p xserial-gui RUST_LOG=xserial_gui=debug cargo run -p xserial-gui ``` -使用 `tracing-subscriber` + `RUST_LOG` 环境变量控制日志级别。 - -### 测试 - -```bash -# 全部测试 -cargo test --workspace - -# 特定 crate -cargo test -p xserial-core -cargo test -p xserial-client - -# 集成测试 -cargo test -p xserial-core --test pipeline -cargo test -p xserial-client --test session_lifecycle -cargo test -p xserial-client --test lua_tests - -# 带输出 -cargo test -p xserial-core -- --nocapture -``` - -所有测试自包含(TCP/UDP 绑定 `127.0.0.1:0`,串口测试使用虚拟端口名),无外部依赖。 - --- -## 目录结构 +## 技术栈 -``` -crates/ - xserial-core/ # 传输、分帧、协议解码、Pipeline - src/ - transport/ # Serial, TCP, UDP - frame/ # Line, Fixed, Length, Cobs, MixedTextPlot - protocol/ # Text, Hex, Plot, MixedTextPlot - pipeline.rs # MultiPipeline - xserial-client/ # 会话管理、Lua 运行时 - src/ - session.rs # Session 事件循环 - manager.rs # SessionManager - config.rs # SessionConfig, FramerConfig, DecoderConfig - event.rs # DecodedEntry - history.rs # RingBuffer - cmd.rs # SessionCmd - lua/ # Lua 运行时、自定义 codec、会话 API - xserial-gui/ # egui 桌面应用 - src/ - main.rs - app.rs # XserialApp 主控制器 - panels/ # sidebar, config, console, hex_view, plot_view - shortcuts.rs # 键盘快捷键 - ui_fonts.rs # 字体加载 - perf.rs # 性能分析 - app_state.rs # 状态持久化 - buffers.rs # UI 缓冲管理 - xserial-tui/ # ratatui 终端应用 (占位) -tests/ # Lua 测试 fixture - lua_line_framer.lua - lua_text_decoder.lua -tools/ # 开发辅助工具 - test_plot.py # TCP 波形测试服务器 - test_plot_serial.c # C 串口 plot 测试客户端 - test_text_serial.c # C 串口文本测试客户端 - xs_mixed_plot.h # MixedTextPlot 线格式 C 参考头文件 -``` - ---- - -## MixedTextPlot 协议 - -单连接上混合传输文本行和波形数据的线格式。 - -**文本帧**: 普通文本行,以 `\n` 分隔。 - -**Plot 帧**: -``` -0x1E 'P' | COBS(plot_packet) | 0x00 -``` - -**Plot Packet** (13 字节头 + payload): -``` -'X' 'P' (magic) -version:u8 (固定 1) -format:u8 (0=Interleaved, 1=Block, 2=XY) -sample_type:u8 (F32=8) -endian:u8 (0=Little) -channels:u8 -samples_per_channel:u16le -payload_len:u32le -payload:bytes (channels × samples_per_channel × sample_byte_size) -``` - -参考实现: `tools/xs_mixed_plot.h`(C header) - ---- - -## 技术细节 - -- **异步运行时**: tokio (multi-thread) +- **运行时**: tokio (multi-thread) - **串口**: `tokio-serial` + `serialport` -- **分帧器特征**: `feed()`, `flush()`, `reset()`, `pending_len()` — 有状态字节流分帧 -- **解码器特征**: `name()`, `decode(&[u8]) -> Option` — 无状态帧解码 -- **Session 事件循环**: `tokio::select!` 多路复用命令、读取、重连定时器 -- **事件分发**: `tokio::sync::broadcast` — 多订阅者 -- **Lua**: `mlua` 0.11, LuaJIT (vendored 编译), 支持 async/serde/send -- **无 feature flags**: 零条件编译,无 build script -- **无 CI**: 本地自检 `cargo test --workspace` + `cargo clippy` +- **GUI**: egui + egui_plot +- **Lua**: mlua 0.11, LuaJIT (vendored), async/serde/send +- **事件**: `tokio::sync::broadcast` 多订阅者 +- **零 feature flags**,零 build script,零条件编译 + +## License + +MIT