ラズパイを使ってプラレールをシミュレータにする

# きっかけ
今年で3歳になる私の息子は電車が大大大好きです。
先月の誕生日に息子が大好きな大宮の鉄道博物館に行ってきました。
が、、コロナ対策で全部のシミュレータが営業停止になっていました。かわいそうに、彼の大好きな蒸気機関車も新幹線も通勤列車も運転ができなかったわけです。

不完全燃焼の彼を見て、私は思い立ちました。
よし、おうちシミュレータを作ってあげよう、と。

# どうやって作ろう
先日行われた[TwilioSIGNAL2020](https://cloudapi.kddi-web.com/magazine/twilio-event/twilio-signal-2020-day1-keynote "SIGNAL2020 Day1 Keynote")で発表されたTwilioVideo WebRTC Goを使えばVideoチャットの部分は無料で実現できそうだなと思いました。
あとはどんなデバイスを使うかですが、ちょうど最近[この記事](https://japan.techrepublic.com/article/35139151.htm)を見たのでラズパイ4を使ってみることにしました。

# さぁ調達だ
## ラズパイ
ラズパイを扱うのは初めてなので、どこから購入するのかなどを調べてたところ

- [Amazon](https://www.amazon.co.jp/)
- [アールエスコンポーネンツ](https://jp.rs-online.com/web/)
- [KSY](https://raspberry-pi.ksyic.com/)

といった選択肢があるようです。
Amazonが最安のようですが、届いたラズパイが初期ロットで不具合が存在する型番だったという[口コミ](https://www.amazon.co.jp/gp/customer-reviews/R1RPLR4AM9LEGA)もあったので、アールエスコンポーネンツから購入することにしました。

RAM 4GBと8GBで悩みましたが、そこまで高性能のものにしてもしょうがないので4GBにしました。あわせて、カメラモジュールも購入しました。

## ケース
ラズパイは4になって格段に性能があがったものの、それに伴い放熱対策が必須になったようです。今回はWebRTCを使うため放熱対策はしておくべきと考え、ファン付きのケースを探しました。
お手頃な値段でAC電源もついていたので[こちら](https://www.amazon.co.jp/-/ja/gp/product/B07VC3RWYZ)にしました。
なお、電源は5V/3Aもしくは5.1V/3Aのものを使う必要があります。
> This product should only be connected to an external power supply rated at 5V/3A DC or 5.1V/ 3A DC minimum.

[Raspberry Pi 4 Product Brief](https://static.raspberrypi.org/files/product-briefs/Raspberry-Pi-4-Product-Brief.pdf)より引用

## microSDカード
ラズパイはハードディスクやSSDではなく、microSDを記憶媒体として使っています。
OSのインストールにもmicroSDが必要ですので、PCから書き込みを行うカードリーダーと合わせて購入します。
microSDのRead/Write速度がラズパイの性能に直結するようです。とりあえず、A1(Application Performance Class 1)と記載されているmicroSDを選べば良いみたいなので、[こちら](https://www.amazon.co.jp/gp/product/B07VT3M4GM)にしました。あわせて[カードリーダー](https://www.amazon.co.jp/gp/product/B08KD55RNF)も購入しました。

## 変換アダプター
ラズパイは4で映像出力がMicro HDMIになったようです。
私が愛用しているモニターには常時HDMIケーブルを接続しているので、[こちら](https://www.amazon.co.jp/gp/product/B00JDRHQ58)の変換アダプターを購入しました。

## ケーブル
USB Type-CケーブルとHDMIケーブルはすでにあるものを使います。

## 入力機器
キーボード、マウスもすでにあるものを使います。

## モバイルバッテリー
プラレールに搭載した際の電源を確保するため、5V/3Aに対応したモバイルバッテリーが必要です。
少しオーバースペックですが[こちら](https://www.amazon.co.jp/gp/product/B07Z632WQ1)を購入しました。

## Twilioアカウント
[こちら](https://cloudapi.kddi-web.com/signup)でTwilioアカウントを作ります。
TwilioVideo WebRTC Goは無料で使えるので、トライアルアカウントのままで大丈夫です。

## プラレール
世間にはリチウムイオン電池を接続して、プラレールの操縦も遠隔操作している猛者がいらっしゃるようです。
が、今回は去年の誕生日に購入した[E5系はやぶさコントロールセット](
https://www.takaratomy.co.jp/products/plarail/tettei/set/e5hayabusa/index.htm)を使用します。
ほら、かっこいい運転台があったほうがさまになるし、バックもできるし。

# いくらかかった？
合計で¥18,425でした。意外といったな。。

| 商品                  | 税込価格 | 購入元                      |
|:--------------------:|:-------:|:--------------------------:|
| ラズパイ4本体          | ¥6,549  | RSコンポーネンツ             |
| カメラモジュール        | ¥2,736  | RSコンポーネンツ             |
| ケース & AC電源        | ¥2,059  | Amazon                     |
| microSD              | ¥1,999  | Amazon                     |
| SDカードリーダー       | ¥684    | Amazon                     |
| Micro HDMI変換ケーブル | ¥999    | Amazon                     |
| モバイルバッテリー      | ¥3,399  | Amazon                     |
| Twilioアカウント       | ¥0      | KDDIウェブコミュニケーションズ |

# そして2時間格闘した結果がこちらです
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/8a74452f-fcd3-884f-e5c1-5a966c407596.jpeg" width=50%>

カメラモジュールの接続は[こちら](https://www.pc-koubou.jp/magazine/17276#section02)の記事を参考にさせていただきました。

# Raspberry Pi OSをインストール
[公式ドキュメント](https://www.raspberrypi.org/documentation/installation/installing-images/README.md)を参考にしつつ、Raspberry Pi OSイメージをRaspberry ImagerからmicroSDカードに書き込みます。
あとはmicroSDをラズパイに差し込むだけです。簡単！

# Videoアプリケーションを構築
Twilio公式の[Gitリポジトリ](https://github.com/twilio/twilio-video-app-react)を使って、Videoアプリケーションを構築します。
Twilioアカウントに紐づくサーバレス環境に構築するためどこからでもいいのですが、今回はせっかくなのでラズパイから操作します。

## パッケージのインストール
### パッケージ更新
パッケージ一覧とインストール済みパッケージを更新します。

```bash
pi@raspberrypi:~ $ sudo apt update
pi@raspberrypi:~ $ sudo apt upgrade
```

### Node.jsをインストール
Twilio CLIのインストールやVideoアプリケーションのデプロイにNPMを使用するため、Node.jsをインストールします。

```bash
pi@raspberrypi:~ $ curl -sL https://deb.nodesource.com/setup_current.x | sudo bash -
pi@raspberrypi:~ $ sudo apt install nodejs
```

### Twilio CLIをインストール
ラズパイにTwilio CLIが対応しているkeyringがなく、後の[クレデンシャル情報の設定](#クレデンシャル情報の設定)でエラーが発生するため、このタイミングで`gnome-keyring`もインストールします。

```bash
pi@raspberrypi:~ $ sudo apt install gnome-keyring
pi@raspberrypi:~ $ sudo npm install -g twilio-cli
```

## Twilio CLIの設定
### Account SIDとAuth Tokenの取得
Twilioアカウントでログイン後、Account SIDとAuth Tokenを[こちら](https://jp.twilio.com/console/project/settings)から取得します。

### クレデンシャル情報の設定
Twilio CLIのクレデンシャル情報を設定します。
`Account SID`と`Auth Token`を聞かれるので、それぞれ入力します。
`Shorthand identifier for your profile`には"Plarail Simulator"などの文字列を入力します。
keyringのパスワード入力が求められます。

```bash
pi@raspberrypi:~ $ twilio login
You can find your Account SID and Auth Token at https://www.twilio.com/console
 » Your Auth Token will be used once to create an API Key for future CLI access to your Twilio Account or Subaccount, and then forgotten.
? The Account SID for your Twilio Account or Subaccount: ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
? Your Twilio Auth Token for your Twilio Account or Subaccount: [hidden]
? Shorthand identifier for your profile: Plarail Simulator
Created API Key SKxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx and stored the secret using libsecret. See: https://www.twilio.com/console/runtime/api-keys/SKxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
twilio-cli configuration saved to "/home/pi/.twilio-cli/config.json"
Saved Plarail Simulator.
```

## Twilio CLI RTCプラグインのインストール
リアルタイムコミュニケーションアプリのデプロイ時に利用するプラグインをインストールします。

```bash
pi@raspberrypi:~ $ twilio plugins:install @twilio-labs/plugin-rtc
```

## Videoアプリケーションの構築
### リポジトリの取得
GitHubリポジトリをクローンします。

```bash
pi@raspberrypi:/usr $ chmod 777 /usr/src
pi@raspberrypi:/usr $ cd /usr/src
pi@raspberrypi:/usr/src $ git clone https://github.com/twilio/twilio-video-app-react
```

### Videoアプリケーションのデプロイ
依存するパッケージをインストールし、Twilio CLIでVideoアプリケーションをデプロイします。
デフォルトだと`ROOM Type`が"group"なので"go"を指定します。

```bash
pi@raspberrypi:/usr/src $ cd twilio-video-app-react/
pi@raspberrypi:/usr/src/twilio-video-app-react $ npm install --production
pi@raspberrypi:/usr/src/twilio-video-app-react $ npm run deploy:twilio-cli -- --room-type=go
```

# Videoアプリケーションに接続
## ラズパイから接続
さぁ、ついにVideoアプリケーションが構築できました！
デプロイが完了すると、`Web App URL`と`Passcode`が表示されるのでブラウザからアクセスします。
以下のコマンドでも確認ができます。

```bash
pi@raspberrypi:/usr/src/twilio-video-app-react $ twilio rtc:apps:video:view
```

名前とルーム名を入力して
![login.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/c901cb66-e37b-b177-0314-5fbdf2b1e057.png)

カメラの使用を許可して
![camera_permission.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/4b11ba7a-40a2-94c9-c22e-6f765c710166.png)

正しく映像が表示されました。
![raspi_camera.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/e5adfd37-edd5-c133-bb29-5a88cebc3549.png)


## スマホブラウザから接続
次に、シュミレータ画面代わりの私のおふるのスマホからChromeで接続してみます。
![smartphone_chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/2a43fae3-97ac-24e5-a5d3-4fb797a36e77.png)


たしかにこれでVideoチャットは実現できましたが、これじゃない感…!!
横幅はまだしも縦幅の半分くらいがChromeのアドレスバーやメニューに占領されて画面がものすごく小さくなっています。

# スマホアプリを構築
もうここまできたらスマホアプリも構築してしまいましょう。
Twilio公式の[Gitリポジトリ](https://github.com/twilio/twilio-video-app-android)を使って、Videoアプリを構築します。
ビルドである程度のメモリを使うので、手持ちのMacBookProから行います。

## AndroidStudioをインストール
[AndroidStudio](https://developer.android.com/studio)をインストールします。

## AndroidStudioからスマホにデプロイ
`Get from Version Control`をクリック後、`URL`にGitリポジトリのURLを指定し`Clone`します。
![AndroidStudio_git_clone.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/361574bd-5260-7924-9bf1-07d47cef62ee.png)

スマホをUSBでつなげると、上部メニューの`Running devices`に端末名(今回だと"Sony 701SO")が表示されます。
デプロイ先の端末名を選択して、その右の`▶`を押してデプロイします。
スマホへのデプロイ方法は[こちら](https://techacademy.jp/magazine/2433)に詳しく記載されています。
![AndroidStudio_deploy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/021c7df5-cc84-5c13-c976-6b371e43c0ad.png)

# スマホアプリから接続
さぁ！今度はどうでしょうか。

`Passcode`には[ラズパイから接続](#ラズパイから接続)で表示されていた数字を入力し、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/1993251d-9943-ff18-fa14-43c2fb776a63.png" width=50%>

ラズパイと同じルーム名を入れて`JOIN`します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/24d401d1-ae89-abf3-5581-fc423c131282.png" width=50%>

すばらしい！！フルスクリーンでラズパイのカメラを表示することができました。
![Android_commando.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/461f882d-3d30-7164-e58b-a8d0dcddb884.png)

# プラレールに搭載
ラズパイとモバイルバッテリーをプラレールに搭載します。
自宅には貨物列車セットがあったので、コンテナを外してそれぞれを輪ゴムで装着しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/a0c85758-a77a-4abd-7174-8e146d0c3612.jpeg" width=50%>

運転台はこんな感じです。
![PXL_20201110_053355487.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/0ee5c8fa-f577-ea13-b197-90917b05ff8e.jpeg)

# 息子にお披露目
ついにお披露目です！
モバイルバッテリーが予想以上に重いので、先頭車をフル充電した電池に差し替えます。
重すぎて動かなかった時用に、貨物列車も待機。プラレールの世界でも貨物列車は少しパワフルな(気がする)んです。

モーターを唸らせながらもなんとか動いてくれました。
息子も「出発進行！次は品川〜」と言いながら大興奮！とても喜んでくれました！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157189/aafa5b74-5254-8482-6778-0de0011ff8a8.jpeg" width=50%>

彼が寝る前にお披露目したせいで、なかなか寝ついてくれませんでした。ごめん。。

# 最後に
TwilioVideo WebRTC Goは1:1のP2Pだからか遅延が気になりませんでした。おかげで思った以上にしっかりしたシミュレータになりました。
というか、よくよく考えるとこれはシミュレータじゃなくて前面展望ですよね。まぁ喜んでくれたしいいか。
もし次を作る機会があれば、「軽量/小型化」と「セルフビューの非表示」にトライしたいと思います。