【ITニュース解説】I co-engineered a macOS Soundcore headphone controller with Claude over a weekend
2026年09月15日に「Dev.to」が公開したITニュース「I co-engineered a macOS Soundcore headphone controller with Claude over a weekend」について初心者にもわかりやすく解説しています。
ITニュース概要
macOSでSoundcoreヘッドホンを制御する公式アプリがないため、AIと週末で「SoundcoreBridge」を開発。Bluetoothプロトコルをリバースエンジニアリングし、デバイス通信の課題を解決した。AIはコード生成に役立ったが、実通信ログでの検証が成功の鍵だった。
ITニュース解説
SoundcoreヘッドホンをMacで利用する際、ノイズキャンセリングやイコライザーなどの設定変更には通常スマートフォンアプリが必要で、Macから直接操作できないという不便さがあった。この問題を解決するため、Macで動作するヘッドホンコントローラーアプリの開発が始まった。このプロジェクトでは、開発者は最新のAIであるClaudeと協力し、わずか週末の間にヘッドホンが使用する通信プロトコルをリバースエンジニアリングし、Macのメニューバーから操作できる「SoundcoreBridge」アプリとコマンドラインツールを構築することに成功した。
最初のステップは、ヘッドホンとの通信経路を見つけることだった。BluetoothデバイスはSDP(Service Discovery Protocol)を通じて提供サービスを公開しており、ヘッドホンを調べると「PaulWang-Spp」という項目が見つかった。このUUID(識別子)がSoundcoreヘッドホンの制御用と一致し、これが「チャンネル30」と呼ばれる通信路であることが判明した。誤ってヘッドホンを壊さないよう、ファームウェア更新用のチャンネルはコードで意図的にブロックされた。
次に、ヘッドホンとの具体的なデータ交換形式、つまり「フレーム形式」の解読が必要だった。先行研究を参考に、データが「マジックコード」「シーケンス番号」「コマンド」「データ長」「ペイロード(実際のデータ)」「チェックサム」で構成されていることが判明した。チェックサムは先行する全バイトの合計を8ビットに切り詰めたシンプルなものだったため、比較的容易に実装できた。このフレーム形式に基づき、データ変換を行うエンコーダーを実装し、既知のデータと比較することでその正確性を確認した。これにより、後で問題が発生した際に、エンコーダーの正確性を疑う必要がなくなり、問題特定の効率化に繋がった。
しかし、ここからが難関だった。Mac上でヘッドホンとの通信チャンネルを開こうとすると、関数は成功を返しても実際の通信は始まらない状態だった。他のBluetoothデバイスでも同様の失敗が続いたため、開発者は一時的にmacOSのプラットフォームに限界があると誤解してしまった。しかし、この時AIのClaudeが、macOS上で同様のBluetooth制御を実現している「SonyBridge」というオープンソースプロジェクトの存在を指摘してくれた。この情報が、開発者の誤った確信を打ち破る決定的なきっかけとなった。そのプロジェクトの実装を分析し、Claudeと共に試行錯誤を重ねた結果、チャンネルの開設に成功した。この過程で、IOBluetoothフレームワークの特殊な挙動が明らかになった。具体的には、初回呼び出しが失敗することがあり、再試行が必要なこと、通信応答が特定の実行ループで処理されるため、そのループを適切に動かし続ける必要があること、そして、失敗した通信チャンネルをすぐに閉じない方が良いこと、これら3点が判明した。
チャンネルの開設に成功し、ヘッドホンからファームウェアバージョンやモデル情報などのデータが読み取れるようになった。しかし、今度はヘッドホンにコマンドを「書き込む」ことができないという問題が発生した。コマンドを送ってもエラーも応答もなく、ヘッドホンの状態も変化しない「沈黙」が続いた。この問題の解決策は、Android版Soundcoreアプリの実際の通信内容をキャプチャして解析することだった。AndroidのBluetooth HCIスヌープログ機能を活用し、アプリ操作時の通信ログを収集した結果、ヘッドホンとアプリの間で接続時に特定の「ハンドシェイク」が行われていることが判明した。このハンドシェイクが完了しない限り、ヘッドホンはすべての書き込みコマンドを黙って無視することが明らかになった。このハンドシェイクはどこにも文書化されておらず、通信キャプチャがなければ発見は不可能だっただろう。さらに、ノイズキャンセリングモードの書き込みコマンドでも、読み出し時には「FF」となるバイトが、書き込み時には「02」でなければならないという、特定のバイトの異なる解釈が必要であることが判明した。この一つのバイトの差を見つけるのにも、多くの時間を費やした。
書き込みが機能するようになってからは、残りの設定項目(ANCモード、イコライザープリセット、バンド値など)のマッピングは比較的効率的に進んだ。Macからチャンネルを開いたまま、ヘッドホンの状態を定期的に読み取り、スマートフォンアプリで設定を一つ変更し、その変更によってヘッドホンのデータがどう変化したか(差分)を比較していく方法だ。これにより、ANCモードがヘッドホンデータの71バイト目で制御されていることや、イコライザー設定が23バイト目以降にあることなどが次々と解明された。
この開発過程で、公式のSoundcoreアプリにバグがあることも発見された。Macでヘッドホンの設定を変更した後、公式アプリを開くと、アプリはヘッドホンから現在の設定を正しく読み取るにもかかわらず、自身のキャッシュしていた古い値を表示してしまうというものだ。つまり、他のデバイスから設定を変更すると、公式アプリはユーザーに誤った情報を提供することになるが、今回開発したアプリは常にデバイスから直接最新の状態を読み取るため、この点ではより正確だった。
開発されたアプリは「Soundcore Space 2」向けだが、ヘッドホンとの基本的な通信フレーム形式は他のSoundcoreデバイスでも共通している。異なるのは、各種設定値(バッテリー、ANCモード、EQなど)がヘッドホンデータのどこに格納されているか(オフセット)や、特定の値の意味など「デバイス固有の情報」だけだ。そのため、新しいプロトコルコードを書くのではなく、モデルごとにこれらのオフセット値を定義したデータ構造を用意することで、他のモデルへの拡張性も考慮されている。
この開発プロジェクトからは、いくつかの重要な教訓が得られた。一つは、「エラーが報告されないことが成功を意味するわけではない」ということ。ヘッドホンは間違ったコマンドを無視するだけでエラーを返さなかったため、常に変更が正しく適用されたか「読み戻して確認する」ことが不可欠だった。二つ目は、対照実験の落とし穴。異なるデバイスで同じ失敗が起きたことで、原因がプラットフォームにあると誤解したが、実際はコードのバグを二重に測定していただけだった。三つ目は、先行事例の価値。行き詰まった時に、既に同様のことを実現しているプロジェクトの存在を知ることが、数日間の誤った結論を一瞬で正しい方向へと転換させる力を持っていた。そして最後に、AIと共同で開発する際には、実際のパケットキャプチャやログといった「生のデータ」を基盤とすることが極めて重要だ。AIはパターン認識やコード生成に優れているが、現実の裏付けがなければ、人間もAIも共に当てずっぽうの推測に陥りやすい。
こうして開発された「SoundcoreBridge」は、MITライセンスのオープンソースプロジェクトとして公開されており、SwiftとmacOS 13以降に対応している。リポジトリには、ヘッドホンの状態データのレイアウト、通信のハンドシェイク、22種類のイコライザープリセット値、そしてIOBluetoothフレームワークを扱う上での重要な知見など、プロトコルの詳細がすべて含まれている。これにより、他の開発者が独自のクライアントアプリを開発する際にも、最も困難な部分が既に解決されている。このプロジェクトはAnkerやSoundcoreとは無関係であり、開発者が所有するハードウェアの相互運用性を実現するためのリバースエンジニアリングの成果である。