快速开始

本指南介绍如何定义协议、生成代码以及将 bleRPC 集成到您的项目中。

1. 定义协议

创建一个 .proto 文件来定义 RPC 消息。每个命令是一个请求/响应对:

syntax = "proto3";
package blerpc;

message EchoRequest {
  string message = 1;
}

message EchoResponse {
  string message = 1;
}

message FlashReadRequest {
  uint32 address = 1;
  uint32 length = 2;
}

message FlashReadResponse {
  uint32 address = 1;
  bytes data = 2;
}

命令从匹配的 *Request / *Response 对中自动发现。例如,EchoRequest + EchoResponse 会生成 echo 命令。

2. 代码生成

generate-handlers 工具为所有支持的语言生成处理器桩代码和客户端代码。

构建生成器

cd tools/generate-handlers
go build -o generate-handlers .

运行代码生成

./generate-handlers -root /path/to/blerpc

这将生成以下文件:

输出描述
peripheral_fw/src/generated_handlers.hC 处理器声明 + 查找表
peripheral_fw/src/generated_handlers.cC 弱引用处理器桩
peripheral_py/generated_handlers.pyPython 处理器桩
central_py/blerpc/generated/generated_client.pyPython 客户端 mixin
central_android/.../GeneratedClient.ktKotlin 抽象客户端
central_ios/.../GeneratedClient.swiftSwift 客户端协议扩展
central_flutter/.../generated_client.dartDart 客户端 mixin
central_rn/.../GeneratedClient.tsTypeScript 抽象客户端(React Native)
central_fw/src/generated_client.hC central 客户端声明
central_fw/src/generated_client.cC central 客户端实现

3. 平台集成

iOS (Swift)

依赖

通过 Swift Package Manager 添加到您的 Xcode 项目:

// Package.swift or Xcode > File > Add Package Dependencies
https://github.com/tdaira/blerpc-protocol-swift  (from: 0.5.0)
https://github.com/apple/swift-protobuf.git      (from: 1.28.0)

生成 Protobuf 类型

brew install swift-protobuf
protoc --swift_out=YourApp/Proto/ \
  --swift_opt=Visibility=Public \
  -I proto/ proto/blerpc.proto

使用方法

let client = BlerpcClient()

// Scan for peripherals
let devices = try await client.scan()
try await client.connect(device: devices[0])

// Type-safe RPC call
let response = try await client.echo(message: "hello")
print(response.message)  // "hello"

// Read flash data
let flash = try await client.flashRead(address: 0, length: 8192)
print(flash.data.count)  // 8192

client.disconnect()

Android (Kotlin)

依赖

添加到您的 build.gradle.kts

repositories {
    maven {
        url = uri("https://maven.pkg.github.com/tdaira/blerpc-protocol-kt")
        credentials { /* GitHub token */ }
    }
}

dependencies {
    implementation("com.blerpc:blerpc-protocol-kt:0.5.0")
}

使用方法

val client = BlerpcClient(context)

// Scan for peripherals
val devices = client.scan()
client.connect(devices[0])

val response = client.echo(message = "hello")
println(response.message)  // "hello"

client.disconnect()

Python (macOS / Linux)

依赖

pip install bleak protobuf
pip install git+https://github.com/tdaira/blerpc-protocol.git

生成 Protobuf 类型

protoc --python_out=central_py/blerpc/generated/ \
  -I proto/ proto/blerpc.proto

使用方法

from blerpc.client import BlerpcClient

client = BlerpcClient()

# Scan for peripherals
devices = await client.scan()
await client.connect(devices[0])

resp = await client.echo(message="hello")
print(resp.message)  # "hello"

flash = await client.flash_read(address=0, length=8192)
print(len(flash.data))  # 8192

await client.disconnect()

Flutter (Dart)

依赖

添加到您的 pubspec.yaml

dependencies:
  blerpc_protocol: ^0.6.0
  flutter_blue_plus: ^1.35.0
  protobuf: ^6.0.0

生成 Protobuf 类型

dart pub global activate protoc_plugin
protoc --dart_out=lib/proto/ \
  -I proto/ proto/blerpc.proto

使用方法

final client = BlerpcClient();

// Scan for peripherals
final devices = await client.scan();
await client.connect(devices[0]);

// Type-safe RPC call
final response = await client.echo(message: 'hello');
print(response.message);  // "hello"

// Read flash data
final flash = await client.flashRead(address: 0, length: 8192);
print(flash.data.length);  // 8192

client.disconnect();

React Native (TypeScript)

依赖

添加到您的 package.json

{
  "dependencies": {
    "@blerpc/protocol-rn": "file:../blerpc-protocol-rn",
    "protobufjs": "^7.4.0",
    "react-native-ble-plx": "^3.2.1",
    "react-native-get-random-values": "^1.11.0",
    "buffer": "^6.0.3",
    "fast-text-encoding": "^1.0.6",
    "@noble/ciphers": "^1.3.0",
    "@noble/curves": "^1.9.7",
    "@noble/hashes": "^1.8.0"
  }
}

生成 Protobuf 类型

npx pbjs -t static-module -w commonjs \
  -o src/proto/blerpc.js ../proto/blerpc.proto
npx pbts -o src/proto/blerpc.d.ts src/proto/blerpc.js

使用方法

import { BlerpcClient } from './client/BlerpcClient';
import { BleTransport } from './ble/BleTransport';

const transport = new BleTransport();
const devices = await transport.scan();
const client = new BlerpcClient(transport);
await client.connect(devices[0]);

// Type-safe RPC call
const response = await client.echo({ message: 'hello' });
console.log(response.message);  // "hello"

// Read flash data
const flash = await client.flashRead({ address: 0, length: 8192 });
console.log(flash.data.length);  // 8192

client.disconnect();

Zephyr Central (C)

生成的客户端

代码生成器会创建 generated_client.hgenerated_client.c,其中包含所有命令的类型化包装函数。您需要实现三个传输函数(blerpc_rpc_callblerpc_stream_receiveblerpc_stream_send),然后调用生成的 API:

#include "generated_client.h"

// Type-safe RPC call — protobuf encode/decode is handled
blerpc_EchoResponse resp;
int ret = blerpc_echo("Hello from central!", &resp);
if (ret == 0) {
    LOG_INF("Echo: %s", resp.message);
}

// Read flash data (FT_CALLBACK fields handled automatically)
blerpc_FlashReadResponse flash;
uint8_t data_buf[8192];
size_t data_len;
ret = blerpc_flash_read(0, 8192, &flash, data_buf, sizeof(data_buf), &data_len);

// P2C streaming
blerpc_CounterStreamResponse results[20];
size_t count;
ret = blerpc_counter_stream(20, results, 20, &count);

构建

west build -b nrf54l15dk/nrf54l15/cpuapp central_fw

Zephyr Peripheral (C)

实现处理器

生成的处理器使用 __attribute__((weak))。在您自己的源文件中重写它们:

// handlers.c
#include "generated_handlers.h"
#include "blerpc.pb.h"

int handle_echo(const uint8_t *req_data, size_t req_len,
                pb_ostream_t *ostream) {
    blerpc_EchoRequest req = blerpc_EchoRequest_init_zero;
    pb_istream_t stream = pb_istream_from_buffer(req_data, req_len);
    if (!pb_decode(&stream, blerpc_EchoRequest_fields, &req))
        return -1;

    blerpc_EchoResponse resp = blerpc_EchoResponse_init_zero;
    strncpy(resp.message, req.message, sizeof(resp.message) - 1);
    if (!pb_encode(ostream, blerpc_EchoResponse_fields, &resp))
        return -1;
    return 0;
}

构建

# nRF54L15
west build -b nrf54l15dk/nrf54l15/cpuapp peripheral_fw

# EFR32xG22E
west build -b xg22_ek2710a peripheral_fw -- -DBOARD_ROOT=/path/to/blerpc

4. 使用 Python Central 进行测试

验证 peripheral 是否正常工作的最简单方法:

# Flash the peripheral firmware
west flash

# Run the Python integration tests
cd central_py
python -m pytest tests/test_integration.py -v

或者使用交互式客户端:

python -c "
import asyncio
from blerpc.client import BlerpcClient

async def main():
    client = BlerpcClient()
    devices = await client.scan()
    await client.connect(devices[0])
    resp = await client.echo(message='hello')
    print(f'Echo: {resp.message}')
    await client.disconnect()

asyncio.run(main())
"