【OBS連携】心拍数表示 (#185)

Redmine: #185(親 #162

概要

OBS オーバーレイに心拍数(現在 BPM + 直近数分の推移グラフ)を表示します。beatoraja 本体が BLE 心拍計(CooSpo HW706 等、標準 GATT Heart Rate Service 0x180D / Measurement 0x2A37)にネイティブブリッジ経由で直接接続し、/state.json に乗せて overlay が表示します(クラウド非経由)。obsEnabled=false 時はゼロ影響。

構成

HW706 →(BLE notify)→ hrm-bridge (Rust+btleplug, natives/ に同梱)
   →(stdout NDJSON {"bpm":N})→ HeartRateService → ObsState → /state.json
   →(約1秒ポーリング)→ overlay (#heartrate 値+グラフ)

主な変更

  • tools/hrm-bridge: Rust + btleplug の BLE ブリッジ(0x180D スキャン→接続→0x2A37 購読→フラグバイト解析(UINT8/UINT16 LE)→{"bpm":N} 出力、バックオフ再接続、stdin EOF/SIGINT/SIGTERM で終了)。Windows バイナリ natives/hrm-bridge-win-x64.exe を同梱(既存 natives/*.dll と同方式)。
  • HeartRateService: ブリッジ子プロセスの起動/stdout 解析/1秒サンプリング/バックオフ再起動、バイナリ不在時は警告ログのみで no-op。
  • ObsState / /state.json: heartRate{bpm, zone, zoneIndex, min, max, sampleSec, history[]}(null/stale 復帰、リングバッファ 3分、ゾーン算出)。snapshot の read-modify-write を単一ロックで直列化し、非同期心拍スレッドと changeState スレッドの lost-update を防止。
  • Config / 設定UI: heartRateEnabled / heartRateMaxHr / heartRateDeviceFilterPlayConfigurationView + i18n 日英)。
  • overlay: #heartrate に現在 BPM + MIN/MAX + inline SVG 折れ線グラフ(差分再描画、null/空で例外なし)。配色は他ブロックと同一テーマ色。README / state.sample.json 更新。

テスト

  • xvfb-run -a ./gradlew testBUILD SUCCESSFUL(Java 単体: heartRate JSON 形・ゾーン境界・リングバッファ上限/min/max・stale→null・bpm 行パース)。
  • Rust: 0x2A37 フラグ解析の単体テスト(UINT8 / UINT16-LE / 短すぎるパケット)。
  • overlay: node --check + DOM シム契約テスト(bpm/zone/polyline/null/単一点/空 history)。
  • 実機(CooSpo HW706 + Windows)でブリッジ接続・overlay 表示を確認済み

補足

  • Windows バイナリは btleplug の WinRT 依存のため実機 Windows でビルドしコミット済み。Linux/Mac 版は未同梱(将来対応)。
  • heartRate.zone/zoneIndex/state.json に残置(将来のテーマで色分けに利用可能、現 overlay の見た目には不使用)。

マージリクエストレポート

読み込み中