見出し画像

古いクルマ(フィアットパンダ)向けにスマートキーを開発した話

新型コロナの影響でオンライン開催となったiOSDC 2020ですが、「CryptoKitとCoreBluetoothを利用したスマートキー開発」と題してLT枠で登壇させていただきました。(時間配分ミスって途中でドラ鳴ってしまいました。。。)

iOSDCではアプリ側の内容に寄せた内容になりましたが、質問でも車載器側の話をいくつかいただいたので、ここでは今回開発したスマートキーのシステム全般の話を書いていこうかと思います。

フィアットパンダ

画像1

今回の対象となるクルマですが、初代フィアットパンダです。1980年に巨匠ジョルジェット・ジウジアーロが開発・デザインしたフィアット製の小型ハッチバックで、今年40周年を迎えました。曲面といえる部分はほとんどなく、ボディはほぼ全て直線と平面で構成されています。すべての窓ガラスも板ガラスであるなど、徹底的なコスト削減が行われていますが、その優れたデザイン製・スペース効率などから、今でも高い人気を誇っています。この初代モデルは1980年から2003年まで20年近く製造されたロングセラーモデルで、その後2代目(2003年-2011年)、3代目(2011年-)のモデルも発売されています。

画像2

最近だとアイフルのCMで板前の人が乗ってましたね。

そんな初代フィアットパンダですが、イタリア車の宿命と言えるのか結構壊れます。走る、止まるといった基本的な部分は問題ないのですが、ミラーが折れたり(ミラー調整しようとして骨がボキっといったり)、スイッチが壊れたり(空調の風量調節スイッチは今もガタガタ)、細かい部品が壊れやすい印象です。ドアロック部分も壊れやすいパーツらしく、自分が購入した時点で運転席側は交換されていました。キーシリンダー部分がスイッチになっていて、鍵を差し込んでドアロックを解除してからこの部分を押してドアを開きます。合理的でシンプルなデザインで個人的には大好きなのですが、ここが壊れるとキーシリンダーごと交換のため鍵が変わります。なので、ここが壊れるたびに鍵が変わり鍵が増えていきます。

画像3

この部分にできるだけ負荷をかけないためにも、スマートキーが必要だったわけですね。

ドアを開けるには

クルマのドアは最近のクルマであれば集中ドアロック機構を標準で備えています。運転席側のドアと他のドアが連動しており、運転席側のドアのロックを解除すればすべてのドアのロックが解除され、ロックすればすべてのドアがロックされる仕組みです。今回のパンダも最終年型である98年製であるため、この機能を有しています。

クルマによって仕組みは様々だと思いますが、一般的にドアのロックを行うとドアロック線に信号が流れ、ロック解除を行うとドアアンロック線に信号が流れます。この信号はECUを通して各ドアに伝達し、各ドアに設置されているドアロックモーターが作動し、各ドアのロック・アンロックが行われる仕組みです。

つまりドアロック・アンロック線に対してそれぞれ信号を送ることができれば、外部からロック・アンロックすることができるわけですね。

システム構成

画像4

クルマの外からドアのロック・アンロックを指示するスマートキー(iPhone+専用アプリ)と、クルマの外から発信された指示を受け取ってドアロック・アンロック線に対して信号を送信する車載器(Arduino)の2つで構成されます。

車載器はクルマのバッテリーから電源を取得し、常時起動させておきます。バッテリー上がりを防ぎつつ、待機中ずっと動作させる必要があるため低消費電力で動作する必要があります。とはいえ、普段そんなに頻繁に乗るわけでもないので、ドラレコ用のバッテリー電圧が一定まで下がると自動的に電源をオフにする配線を利用しています。

この状態で車載器はBLEのPeripheralとして動作させて、常にAdvertise Packetを飛ばすようにします。そして車載器はスマートキーから接続されて指示を受けたらドアロック・アンロック線に対して信号を送信しドアのロック・アンロックを行います。

スマートキーはBLEのCentralとして動作させ、周囲に車載器がないか探索させます。車載器の発信するAdvertisePacketを検知したら接続を行い、ユーザの指示に従ってロック・アンロック指示を行います。

車載器

車載する端末は低消費電力でBluetoothLEが利用でき、Arduinoで開発ができるAdafruit Feather nRF52 Bluefruit LE nRF52832を使用することにしました。車載器側で表示や操作等を行いたいため、OLEDディスプレイと3つのボタンがついた拡張モジュールのAdafruit FeatherWing OLEDを利用できることも選択した理由の一つです。

公開されているライブラリやサンプルプログラムをわかりやすく、組込み初心者の自分でもかんたんに開発を進めることができました。

Adafruit Feather nRF52はUSBから供給される5V電圧で動作しますが、ドアロック・アンロック線に対しては12V電圧で信号を送る必要があります。そのため、Adafruit FeatherのGPIO端子から送った信号を12V電圧に変換するためにリレーモジュールを別途用意しています。

画像5

ケースは3Dプリンタで作成。2万円程度の安い3Dプリンタでも立派なケースが作成できます。

画像6

車載器はまだ開発中のため、フロントポケットに無造作に放り込まれていますが、将来的にはもう少し見えないところに配置する予定です。

実装はhttps://github.com/saiten/panda-smart-lockで公開しています。

スマートキー(iPhoneアプリ)

画像7

アプリはクルマの解錠・施錠操作と後述する車載器への鍵登録機能の2つの機能を持つシンプルな構成になっています。バックグラウンドでも動作し、車載器をバックグラウンドで検知した場合は通知を送信し、通知上から解錠・施錠操作を行うことも可能です。

MVVM+RxSwiftで実装しており、Bluetooth周りの実装もLTでお話したようにRxBluetoothKitを利用しています。非常に便利。

こちらもコードはhttps://github.com/saiten/panda-smart-lock-iosで公開しています。

解錠・施錠の流れ

車載器とアプリ間で実際の解錠・施錠操作を行うには、まず事前に鍵の登録を行う必要があります。今回のシステムでは鍵の操作を行う際にECDSAによる署名を含める必要があり、その署名の有効性を検証するための公開鍵を事前に車載器に登録させます。

そのため、車載器には鍵登録モードと待機モードの2つが存在します。鍵登録モードは車載器を直接操作して鍵登録モードに切り替えないと利用できません。ですのでクルマの中にアクセスできない第三者が勝手に公開鍵を登録する、というようなことはできません。

画像9

車載器を鍵登録モードにした状態で、アプリ側で鍵の登録機能を使って公開鍵を登録します。このとき、画面上に表示されたピンコードとアプリ側で表示されたピンコードが同じ値であることを確認し、誤った機器に接続していないことを確認します。(まぁこれ1台しかないのでありえませんが)

車載器に鍵の登録が完了したら、以降そのアプリから施錠・解錠を行うことができるようになります。

解錠シーケンス

画像8

車載器は待機モードでは1つのService(Main Service)の中に2つのCharacteristic(Challenge CharacteristicとOperation Characteristic)を公開しています。(Service、Characteristicとは何ぞやという方はBLEのGATTで調べてください。)

アプリからクルマのドアを解錠するには車載器に接続後、まず車載器のChallenge Characteristicからチャレンジコードを読み出します。チャレンジコードは読み出す毎、操作する毎に変わる8bytesの乱数値です。今回のシステムではBLE上の通信は一切暗号化されておらず(車載器で使ってるAdafruitのライブラリが当時非対応だった)、簡単に外部から傍受することができます。操作情報を傍受し、その後同じ操作データで解錠操作を行えないようにするため、毎回チャレンジコードの取得が必要な設計になっています。

チャレンジコードの取得ができたらこれに登録したキー名、操作コード(解錠または施錠)とRSSI(電波強度。これは将来的にMITBを防げるように入れてますが未使用)、チャレンジコードをつなげたペイロードをSHA-256でハッシュ化し、事前に登録した秘密鍵で署名しています。ここはLTでお話したとおりCryptoKitを利用しています。ハッシュ化と署名はわずか2行。とても簡単です。

let hash = SHA256.hash(data: payload)
let signature = try! privateKey.signature(for: hash)

作成したペイロードと署名をOperation Characteristicに書き込むと、車載器側でチャレンジコードの有効性と署名の検証を行います。Arduino側でのECDSAの署名の検証にはmicro-eccを利用しています。

署名が有効であれば、操作コマンドに応じてGPIO端子からロック線またはアンロック線に対して信号を送ります。この信号がリレーモジュールを通じてクルマ側に通じてドアがロックしたり、アンロックしたりするという流れになります。(一応アンサーバック用にウィンカーにも信号を送っていますが、ウィンカーの配線がまだ終わっておらず、こちらはまだ未完成)

画像11

最後に

今のところ、アプリを起ち上げての操作は問題ないのですが、バックグラウンドでの動作が不安定なのと(これはCoreBluetoothの問題な気もするが)、本来のところのスマートキー操作(近づくだけでアンロックする)はまだできていない状態です。RSSIを使えばいい感じで実装できると思うので近々取り組みたいと考えています。

それとパンダにはタコメーターがついていないのでこちらも手を付けたい部分です。パンダにはOBD2はついていないのですが、Fiat 3Pinという診断ポートがエンジンルームにあり、そこから回転数が取れるらしい(まだ見つけられてない)。タコメーター自体は作ったのであとで配線してデータ取るだけなんですけど、こちらの方でもしばらく楽しめそうです。

画像10

新しいクルマも楽しいですが、昔ながらのクルマも自分の手の届く範囲でいろいろ遊べるのでなかなか楽しいです。興味があればぜひ皆さんもやってみてください。