Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
194 lines
5.8 KiB
Markdown
194 lines
5.8 KiB
Markdown
# xserial
|
||
|
||
**跨平台串口 / TCP / UDP 数据观测工具** — 可配置分帧、协议解码、多会话管理、实时波形绘图,单二进制零依赖。
|
||
|
||
基于 Rust + [egui](https://github.com/emilk/egui) 构建,支持 Lua 脚本扩展。
|
||
|
||
---
|
||
|
||
## 功能特性
|
||
|
||
### 传输层
|
||
|
||
- **串口** — 波特率 (300–12M)、数据位 (5/6/7/8)、校验位 (None/Odd/Even)、停止位 (1/2)、流控 (None/Software/Hardware)、DTR/RTS 控制
|
||
- **TCP** — 原始 TCP 客户端
|
||
- **UDP** — 绑定地址 + 可选远端地址
|
||
|
||
### 分帧与解码
|
||
|
||
每个 Session 可配置**多条独立管线** — 同一字节流并行送入多个 framer→decoder 链路。
|
||
|
||
| 分帧器 | 说明 |
|
||
|--------|------|
|
||
| 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 | 用户自定义解码脚本 |
|
||
|
||
### 视图
|
||
|
||
- **文本视图** — 带时间戳、方向标记、管线标签
|
||
- **十六进制视图** — hex dump + ASCII 侧栏
|
||
- **波形视图** — 实时波形:自适应、框选缩放、锁定坐标轴、浮动窗口
|
||
|
||
### 会话管理
|
||
|
||
- 多会话并发,标签页切换
|
||
- 连接 / 断开 / 重连,支持断线自动重连
|
||
- 运行时重配置(修改分帧器/解码器无需重启)
|
||
- 环形缓冲区历史记录(可配置上限)
|
||
- **日志到文件** — 后台线程写入,不阻塞 UI
|
||
- 配置自动持久化到 `gui-state.json`
|
||
|
||
### Lua 脚本
|
||
|
||
内置 LuaJIT 运行时,自定义分帧和解码逻辑:
|
||
|
||
```lua
|
||
local buffer = ""
|
||
return {
|
||
feed = function(bytes)
|
||
buffer = buffer .. bytes
|
||
local frames = {}
|
||
while true do
|
||
local i = buffer:find("\n", 1, true)
|
||
if not i then break end
|
||
frames[#frames + 1] = buffer:sub(1, i - 1)
|
||
buffer = buffer:sub(i + 1)
|
||
end
|
||
return frames
|
||
end,
|
||
flush = function()
|
||
if #buffer == 0 then return nil end
|
||
local frame = buffer; buffer = ""; return frame
|
||
end,
|
||
reset = function() buffer = "" end,
|
||
pending_len = function() return #buffer end,
|
||
}
|
||
```
|
||
|
||
会话 API:`xserial.open()`、`xserial.list_ports()`、`xserial.sleep()`、`xserial.poll()`、`xserial.log()`、`session:on_data()`、`session:send()`
|
||
|
||
### 快捷键
|
||
|
||
| 快捷键 | 操作 |
|
||
|--------|------|
|
||
| `Ctrl+N` | 新建会话 |
|
||
| `Ctrl+E` | 编辑当前会话 |
|
||
| `Ctrl+W` | 删除当前会话 |
|
||
| `Ctrl+F5` | 切换连接 |
|
||
| `Ctrl+T/H/P` | 切换到文本 / 十六进制 / 波形视图 |
|
||
| `Ctrl+Tab` / `Ctrl+Shift+Tab` | 下一个 / 上一个标签页 |
|
||
| `Ctrl+L` | 清空输出 |
|
||
| `Ctrl+,` | UI 设置 |
|
||
| `Esc` | 关闭浮层 |
|
||
|
||
---
|
||
|
||
## 快速开始
|
||
|
||
### 前置条件
|
||
|
||
- **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/` 或 `~/.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
|
||
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
|
||
```
|
||
|
||
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
|
||
XSERIAL_GUI_PROFILE_INTERVAL_MS=500 cargo run -p xserial-gui
|
||
```
|
||
|
||
### 日志
|
||
|
||
```bash
|
||
RUST_LOG=info cargo run -p xserial-gui
|
||
RUST_LOG=xserial_gui=debug cargo run -p xserial-gui
|
||
```
|
||
|
||
---
|
||
|
||
## 技术栈
|
||
|
||
- **运行时**: tokio (multi-thread)
|
||
- **串口**: `tokio-serial` + `serialport`
|
||
- **GUI**: egui + egui_plot
|
||
- **Lua**: mlua 0.11, LuaJIT (vendored), async/serde/send
|
||
- **事件**: `tokio::sync::broadcast` 多订阅者
|
||
- **零 feature flags**,零 build script,零条件编译
|
||
|
||
## License
|
||
|
||
MIT
|