- Add FFI wrappers for all EskinDeviceFunc trait methods: eskin_read_hdw_version, eskin_read_matrix_row/col, eskin_read_device_config1/2, eskin_write_device_config1/2, eskin_write_matrix_row/col - Extract sdk_error_to_code() helper for SdkError -> SdkErrorCode conversion - Update C header (include/eskin_ffi.h) with new function declarations - Update Python FFI bindings (example/python/eskin_ffi.py) with new methods - Update README with Python usage instructions and full FFI interface table
235 lines
6.0 KiB
Markdown
235 lines
6.0 KiB
Markdown
# 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
|
||
# 将生成的 .so 文件复制到 python 示例目录下
|
||
cp target/release/libeskin_finger_sdk.so example/python/
|
||
cd example/python
|
||
python3 example.py
|
||
```
|
||
|
||
> **注意:** Python 示例默认从当前目录加载 `libeskin_finger_sdk.so`,请确保 `.so` 文件已复制到 `example/python/` 目录下,或修改 `example.py` 中的 `LIB_PATH` 指向正确的路径。
|
||
|
||
```python
|
||
from eskin_ffi import EskinDevice
|
||
|
||
with EskinDevice("libeskin_finger_sdk.so") as dev:
|
||
dev.open("/dev/ttyUSB0")
|
||
|
||
# 读取硬件版本
|
||
print(f"Hardware version: {dev.read_hdw_version()}")
|
||
|
||
# 读取矩阵尺寸
|
||
print(f"Matrix: {dev.read_matrix_row()} x {dev.read_matrix_col()}")
|
||
|
||
# 读寄存器
|
||
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)` | 写寄存器原始字节 |
|
||
| `eskin_read_hdw_version(handle, buf, buf_len, actual_len)` | 读取硬件版本号 |
|
||
| `eskin_read_matrix_row(handle, out)` | 读取矩阵行数 |
|
||
| `eskin_read_matrix_col(handle, out)` | 读取矩阵列数 |
|
||
| `eskin_read_device_config1(handle, out)` | 读取设备配置寄存器1 |
|
||
| `eskin_read_device_config2(handle, out)` | 读取设备配置寄存器2 |
|
||
| `eskin_write_device_config1(handle, enable, return_count)` | 写入设备配置寄存器1 |
|
||
| `eskin_write_device_config2(handle, enable, return_count)` | 写入设备配置寄存器2 |
|
||
| `eskin_write_matrix_row(handle, row, return_count)` | 写入矩阵行数 |
|
||
| `eskin_write_matrix_col(handle, col, 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` — 序列化(可选) |