はじめに
このガイドでは、プロトコルの定義、コード生成、およびbleRPCのプロジェクトへの統合方法を説明します。
1. プロトコルの定義
RPCメッセージを定義する.protoファイルを作成します。各コマンドはRequest/Responseのペアです:
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.h | Cハンドラー宣言 + ルックアップテーブル |
peripheral_fw/src/generated_handlers.c | C weakハンドラースタブ |
peripheral_py/generated_handlers.py | Pythonハンドラースタブ |
central_py/blerpc/generated/generated_client.py | Pythonクライアントmixin |
central_android/.../GeneratedClient.kt | Kotlin抽象クライアント |
central_ios/.../GeneratedClient.swift | Swiftクライアントプロトコル拡張 |
central_flutter/.../generated_client.dart | Dartクライアントmixin |
central_rn/.../GeneratedClient.ts | TypeScript抽象クライアント(React Native) |
central_fw/src/generated_client.h | C centralクライアント宣言 |
central_fw/src/generated_client.c | C 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()
// ペリフェラルをスキャン
let devices = try await client.scan()
try await client.connect(device: devices[0])
// 型安全なRPC呼び出し
let response = try await client.echo(message: "hello")
print(response.message) // "hello"
// フラッシュデータの読み取り
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)
// ペリフェラルをスキャン
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()
# ペリフェラルをスキャン
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();
// ペリフェラルをスキャン
final devices = await client.scan();
await client.connect(devices[0]);
// 型安全なRPC呼び出し
final response = await client.echo(message: 'hello');
print(response.message); // "hello"
// フラッシュデータの読み取り
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]);
// 型安全なRPC呼び出し
const response = await client.echo({ message: 'hello' });
console.log(response.message); // "hello"
// フラッシュデータの読み取り
const flash = await client.flashRead({ address: 0, length: 8192 });
console.log(flash.data.length); // 8192
client.disconnect();
Zephyr Central (C)
生成されたクライアント
コードジェネレーターは、すべてのコマンドに対する型付きラッパー関数を持つgenerated_client.hとgenerated_client.cを生成します。3つのトランスポート関数(blerpc_rpc_call、blerpc_stream_receive、blerpc_stream_send)を実装し、生成されたAPIを呼び出します:
#include "generated_client.h"
// 型安全なRPC呼び出し — protobufのエンコード/デコードは自動的に処理されます
blerpc_EchoResponse resp;
int ret = blerpc_echo("Hello from central!", &resp);
if (ret == 0) {
LOG_INF("Echo: %s", resp.message);
}
// フラッシュデータの読み取り(FT_CALLBACKフィールドは自動的に処理されます)
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ストリーミング
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でのテスト
ペリフェラルの動作確認に最も簡単な方法:
# ペリフェラルファームウェアを書き込み
west flash
# Python統合テストを実行
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())
"