Skip to content

feat: Raspberry Pi 限定の BLE ロジックを Transport 抽象層で汎用化 - #40

Merged
T3pp31 merged 3 commits into
masterfrom
feat/transport-abstraction
Sep 9, 2026
Merged

feat: Raspberry Pi 限定の BLE ロジックを Transport 抽象層で汎用化#40
T3pp31 merged 3 commits into
masterfrom
feat/transport-abstraction

Conversation

@T3pp31

@T3pp31 T3pp31 commented Sep 9, 2026

Copy link
Copy Markdown
Owner

背景

  • 現状の送受信ロジックは Raspberry Pi(BLE = bleak / PyBluez L2CAP / bluetoothctl)に固定されており、macOS 等の他環境では動かない
  • BLE 非対応環境でも同一パイプラインを動かせるよう、Transport 抽象層を導入する

変更内容

  • src/ble_blockchain/transport.py を新設
    • TransportService(Protocol: scan / start_discoverable / send_payload / receive_payload
    • BleTransportService(既存 BLE 実装を wrap。PyBluez / bleak は実行時 import に隔離し、モジュール import 時に解決しない)
    • load_transport(settings)config/transport.jsonmode で ble / file を選択)
  • src/ble_blockchain/transport_file.py を新設
    • FileTransportService(共有 inbox モデル: 送信は受信者 ID プレフィックスのファイルを書き、受信は自分の sender_id プレフィックスのファイルを読む。スキャン結果は scan_csv から読む)
  • config/transport.json を新設(mode: "ble"(既定)/ "file"
  • app/main.py の BLE 直結コード(scan / SEND / l2cap_server / start_discoverable の直 import)を transport 経由に書き換え
  • config/loader.pyTransportConfig / load_transport_config() 追加、device_settings.pysettings_path 追加、ble/start_discoverable.pyimport subprocess を実行時化
  • README / docs(Sphinx overview)を新構成に合わせて更新
  • テスト追加: tests/unit/test_transport.py / test_transport_file.py / test_main_transport.py(計 25 件)

影響範囲

領域 影響
src/ble_blockchain/ transport.py / transport_file.py 追加、main.py・loader.py・device_settings.py・start_discoverable.py 変更
config/(JSON) transport.json 追加(mode 切替)
settings*.json / keys/*.pem 変更なし(addr* キー互換維持。鍵もそのまま使用)
tests/ 新規 3 ファイル追加(合計 79 件 green)
docs/ / docs/diagrams/ README / overview.rst 更新。draw.io は今回未更新(機能追加が主のため見送り)
Raspberry Pi デプロイ 変更なし(mode: "ble" 既定で従来と同じ挙動。install_package.py も変更なし)

要件

  • config/transport.jsonmode に応じて load_transport(settings) が ble / file 実装を返す
  • file 方式: scan_csvbt_addrs / device_name の 2 列 CSV)からスキャン結果を読み、共有 inbox でペイロードを送受信できる
  • 既存 BLE 挙動は不変(PyBluez / bleak 依存は実行時 import に隔離。macOS でも import ble_blockchain.app.main が成功する)
  • 既存テスト 54 件が green のまま、新規テスト 25 件が追加される

セルフチェックリスト

共通

  • コミットメッセージに変更内容と理由が書かれていること
  • 不要なコードは削除していること(遅延 import は transport 側に集約)
  • 適切にエラーハンドリングされていること(未知 mode は ValueError、scan_csv 不在は空スキャン)
  • クラス名・メソッド名は意図が分かる名前であること(TransportService / FileTransportService 等)

本リポジトリ(BLE_Blockchain)

  • uv run pytest が通ること(79 passed)
  • 設定値をソースに直書きしていないこと(config/transport.json に集約)
  • keys/*.pem.env をコミットしていないこと
  • 公開 API を変えた場合、README と必要なら docs/ を更新したこと(README・overview.rst 更新済み)
  • アーキテクチャ・モジュール構成を変えた場合、docs/diagrams/ble-blockchain-architecture.drawio を更新したこと(今回は未更新)
  • Pi 向け手順に影響がある場合、README の実行例を更新したこと(BLE 方式は従来どおり)
  • L2CAP / PyBlueZ まわりを触った場合、Linux(Pi)での動作確認またはテストで代替していること(実行時 import 化のみで、実装は不変)

任意

  • uv run pylint(CI と同様)をローカルで確認したこと(10.00/10)
  • uv sync --group docscd docs && make html で Sphinx がビルドできること(build succeeded)

🤖 Generated with Claude Code

Made with Cursor

BLE(bleak / PyBluez L2CAP / bluetoothctl)に固定されていた送受信を
transport.py の TransportService(scan / start_discoverable / send_payload /
receive_payload)で抽象化し、config/transport.json の mode で「ble」と
「file」(共有 inbox + スキャン結果 CSV)を切り替えられるようにした。
PyBluez / bleak は実行時 import に隔離し、macOS 等でも import と
file 方式の実行が可能。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@dgxspark1

dgxspark1 Bot commented Sep 9, 2026

Copy link
Copy Markdown

🤖 AI Review

PR レビュー

1. 概要

本PRは、Raspberry Pi 限定だった BLE 通信ロジックを Transport 抽象層(transport.py)で汎用化し、config/transport.jsonmode 設定により BLE 方式file 方式 を切り替えられるようにする変更です。file 方式では Bluetooth を使わず共有 inbox ディレクトリとスキャン結果 CSV でペイロード交換を行うため、macOS 等の BLE 非対応環境でも同一パイプラインが動作します。README・ドキュメントの更新、単体テストの追加も含まれています。

2. 良い点

  • 抽象化の設計が適切: TransportService Protocol を定義し、BleTransportService / FileTransportService が同じインターフェースを実装する構成は拡張性が高く、将来の新方式追加も容易です。
  • 遅延 import の活用: BLE 依存ライブラリ(bleak, PyBlueZ)を実行時 import にすることで、file 方式利用時に不要な依存を回避しています。
  • テスト網羅性が高い: 正常系・異常系・境界値(空 CSV、sender_id 空文字、peers 0 件など)をカバーするテストが充実しており、特に file transport のラウンドトリップテストが良いです。
  • 後方互換性の維持: main.py のラッパーや既存の BLE 方式の動作を維持しつつ、抽象化を導入しています。

3. 懸念点・改善提案(重要度順)

【高】file 方式の受信が無限ループになる可能性
FileTransportService.receive_payload()while True でポーリングし続けます。受信ファイルが永遠に届かない場合、プロセスが終了しません。BLE 方式の l2cap_server() もブロッキングですが、タイムアウトやキャンセル手段がない点は同様です。タイムアウト設定(例: receive_timeout_sec)を追加するか、KeyboardInterrupt で graceful に終了できる設計を検討してください。

【高】file 方式のファイル名衝突リスク
send_payload()timestamp = int(time.time() * 1000) をファイル名に使用していますが、同一ミリ秒内に複数回送信するとファイル名が衝突し、上書きされる可能性があります。uuid4 や連番を追加するなど、一意性を保証してください。

【中】load_transport_config()data["mode"] が KeyError を投げる
config/transport.jsonmode キーが無い場合、KeyError が発生します。デフォルト値 "ble" を設定するか、明確なエラーメッセージ付きの ValueError に変換することを推奨します。

【中】file 方式の scan() が CSV の列欠落で KeyError
pd.read_csv() 後に df["bt_addrs"] を直接参照しており、列が無い場合 KeyError が発生します。テストでは異常系として検証されていますが、本番運用ではより明確なエラーメッセージ(例: "scan_csv に bt_addrs 列がありません")を出すと親切です。

【低】settings_path の追加が既存コードに影響
DeviceSettingssettings_path フィールドが追加されましたが、load_device_settings() 以外で DeviceSettings を直接構築している箇所(テスト含む)は全て更新されています。ただし、外部コードが DeviceSettings を直接インスタンス化している場合、破壊的変更になります。バージョン管理や互換性の考慮が必要です。

【低】start_discoverable.py の import 移動
subprocess を関数内 import に変更していますが、この変更は本PRの目的(Transport 抽象化)とは直接関係ありません。不要な変更を避け、PR のスコープを明確にすることを推奨します。

【低】README の file 方式の説明がやや冗長
config/transport.json の設定例と説明が README の複数箇所(システム概要、ファイル構成、Transport 方式の切替、処理の流れ)に重複して記載されています。ドキュメントの重複を避け、1 箇所に集約するか、相互参照にすると読みやすくなります。

4. セキュリティ・バグの可能性

  • シークレットの可能性: 差分に API キー、パスワード、トークンなどのシークレットらしき値は含まれていません。
  • file 方式のセキュリティ: file 方式では共有ディレクトリに平文のペイロードファイルが一時的に置かれます。ペイロード自体は AES-256-GCM で暗号化されていますが、ファイルの読み書き権限(パーミッション)が適切に設定されているか確認が必要です。inbox_dir の作成時に mkdir(parents=True, exist_ok=True) のみで、パーミッション指定がないため、デフォルトの umask に依存します。共有ディレクトリのパーミッションを明示的に設定(例: 0o700)することを推奨します。
  • シンボリックリンク攻撃: receive_payload()path.unlink() を実行しますが、inbox_dir 内にシンボリックリンクが置かれた場合、リンク先のファイルが削除される可能性があります。path.is_symlink() のチェックを追加することを推奨します。
  • ファイル名のパストラバーサル: send_payload()peer.replace(":", "_") により : を置換していますが、../ などのパス区切り文字が含まれる場合、inbox_dir 外にファイルが書き込まれる可能性があります。peer のサニタイズ(例: 英数字と _ 以外を除去)を強化してください。

T3pp31 and others added 2 commits September 9, 2026 11:19
CI の pylint(Python 3.9 で全 *.py を対象)で検出された
C0116 / C0415 / C1803 / C0301 / E1111 / E1128 / R0903 を修正。
併せて Python 3.9 互換のため PEP 604 記法(Path | None)を
Optional[Path] に変更した。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
AI レビューボットの生成失敗(NotFoundError)を受けて再実行を促す。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@T3pp31
T3pp31 merged commit 88e547c into master Sep 9, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant