feat: add FFI layer, protocol tests, mock transport, README

- FFI: eskin_open/close/read_register/write_register for C/C++/Python
- Protocol: encode/decode tests with golden bytes verification
- Stream: implement PollingSampleCollector producing FingerSample
- Register: add parse_combined_forces/parse_module_errors
- Transport: add MockSerialTransport for testing
- Include: add C header file eskin_ffi.h
- Examples: C++ and Python usage examples
- README: full usage guide for Rust/C++/Python
- Exclude docs/ from repo (internal only)
This commit is contained in:
lenn
2026-05-06 00:54:44 +08:00
parent 60f9ad15e7
commit a7b7192341
13 changed files with 721 additions and 1915 deletions

214
README.md
View File

@@ -1,2 +1,214 @@
# eskin-finger-sdk
# Eskin Finger SDK
E-Skin 手指力传感器 Rust SDK提供串口通信、寄存器读写、流式采集能力支持 Rust / C/C++ / Python 调用。
## 目录结构
```text
src/
lib.rs — Rust 库入口
device.rs — 设备管理open/close/read/write
stream.rs — 流式采集PollingSampleCollector
protocol.rs — 协议帧编解码CRC-8/X25
register.rs — 寄存器地址定义与解析
transport.rs — 串口传输抽象
channel.rs — 线程间 Channel
config.rs — 配置与设备信息
error.rs — 错误类型
types.rs — 数据类型定义
ffi/mod.rs — C FFI 导出函数
include/
eskin_ffi.h — C/C++ 头文件
example/
cpp/main.cpp — C++ 使用示例
python/ — Python 使用示例
```
---
## 快速开始Rust
```rust
use eskin_finger_sdk::config::DeviceConfig;
use eskin_finger_sdk::device::{EskinDevice, EskinDeviceInner};
use eskin_finger_sdk::transport::SerialPortTransport;
let transport = SerialPortTransport::new("/dev/ttyUSB0", 921600);
let config = DeviceConfig::default();
let mut device = EskinDeviceInner::new(config, Box::new(transport));
device.open().unwrap();
// 读寄存器(原始字节)
let data = device.read_register(0x0000, 4).unwrap();
println!("Serial: {:?}", data);
// 写寄存器
let count = device.write_register(0x0030, &[0x01, 0x00, 0x00, 0x00]).unwrap();
println!("Wrote {} bytes", count);
device.close().unwrap();
```
---
## 使用 C/C++
### 构建动态库
```bash
# 安装依赖Ubuntu
sudo apt install pkg-config libudev-dev
# 构建
cargo build --release
# 输出: target/release/libeskin_finger_sdk.so
```
### 编译 C++ 示例
```bash
g++ example/cpp/main.cpp -I include -L target/release -leskin_finger_sdk -o example_cpp
LD_LIBRARY_PATH=target/release ./example_cpp
```
### C++ 代码示例
```cpp
#include "eskin_ffi.h"
#include <cstdio>
int main() {
EskinDeviceHandle dev = eskin_open("/dev/ttyUSB0", nullptr);
if (!dev) return 1;
uint8_t buf[256];
uint32_t actual;
if (eskin_read_register(dev, 0x0000, 4, buf, sizeof(buf), &actual) == ESkinSuccess) {
printf("Serial: %02X %02X %02X %02X\n", buf[0], buf[1], buf[2], buf[3]);
}
eskin_close(dev);
return 0;
}
```
---
## 使用 Python
```bash
cargo build --release
cd example/python
LD_LIBRARY_PATH=../../target/release python3 example.py
```
```python
from eskin_ffi import EskinDevice
with EskinDevice("target/release/libeskin_finger_sdk.so") as dev:
dev.open("/dev/ttyUSB0")
# 读寄存器
data = dev.read_register(0x0000, 4)
print(f"Serial: {data.hex()}")
# 写寄存器
dev.write_register(0x0030, bytes([0x01, 0x00, 0x00, 0x00]))
```
---
## FFI 接口一览
| 函数 | 说明 |
|------|------|
| `eskin_version()` | 获取 SDK 版本 |
| `eskin_open(path, config)` | 打开串口设备,返回 handle |
| `eskin_close(handle)` | 关闭设备,释放 handle |
| `eskin_read_register(handle, addr, length, buf, buf_len, actual_len)` | 读寄存器原始字节 |
| `eskin_write_register(handle, addr, data, data_len, return_count)` | 写寄存器原始字节 |
---
## 协议格式
### Request 帧
```text
[start:2B] [data_len:2B LE] [dev_addr:1B] [reserved:1B] [func:1B]
[start_addr:4B LE] [read/write_len:2B LE] [payload:NB] [crc:1B]
start = [0x55, 0xAA]
func: READ=0xFB, WRITE=0x79
```
### Response 帧
```text
[start:2B] [data_len:2B LE] [dev_addr:1B] [reserved:1B] [func:1B]
[start_addr:4B LE] [read/write_len:2B LE] [payload:NB] [status:1B] [crc:1B]
start = [0x55, 0xAA] (注: 0xAA55 LE)
func: RESPONSE_READ=0xFF, RESPONSE_WRITE=0xF9
status: 0x00=Success
```
---
## 错误码
| 名称 | 值 | 说明 |
|------|----|------|
| `Success` | 0 | 成功 |
| `InvalidPointer` | 1 | 空指针 |
| `DeviceNotFound` | 2 | 设备未找到 |
| `DeviceAlreadyOpen` | 3 | 设备已打开 |
| `NotInitialized` | 4 | 未初始化 |
| `AlreadyStreaming` | 5 | 已在采集中 |
| `NotStreaming` | 6 | 未在采集 |
| `Timeout` | 9 | 读超时 |
| `ChannelClosed` | 10 | 通道断开 |
| `CrcError` | 14 | CRC 校验失败 |
| `FrameError` | 15 | 帧格式错误 |
| `DeviceError` | 17 | 设备返回错误 |
---
## 测试
```bash
cargo test # 全部测试
cargo test protocol::tests # 仅协议层
```
---
## 架构
```text
User / C / Python
↓ FFI
DeviceWrapper (handle)
EskinDeviceInner
↓ read_register / write_register
EskinProtocolCodec (encode/decode + CRC8)
SerialTransport (write/read bytes)
Hardware (UART)
```
详细设计见 `docs/PROGRESS.md``docs/ARCHITECTURE.md`
---
## 依赖
- `serialport` — 串口访问(需要 `pkg-config` + `libudev-dev`
- `crc` — CRC-8/X25 校验
- `crossbeam-channel` — 高性能线程间通信
- `chrono` — 时间戳
- `serde` / `serde_json` — 序列化(可选)