Raspberry Piを野外で使う際のコンソールの検討

2020/11/11追記: Androidのバージョンアップにより、オプション2(USBテザリング)とオプション3(WiFiホットスポット)のネットワークアドレスが可変となり、この方法はそのまま使えなくなった。対処方法は[続報](https://qiita.com/tomoto335/items/7d087060d8a563e94bbd)を参照。

前回の記事「[Raspberry Piで天体写真用オートガイダーを制御する](https://qiita.com/tomoto335/items/0870704707e6373d784b)」では、自宅WiFiの届く範囲でテストを行っており、実際に野外にRPiを持ち出した際にどんなコンソールを用いて操作するか？という課題が据え置きであった。今回はそれについて検討する。

# 要件

- GUIが使え、PHD2(オートガイディングソフトウェア)が操作できること。
- 信頼性が高い(reliable & robust)こと。
    - 撮影に出た先で動作しなかった場合、夜の屋外でトラシューなんてやりたくないし、そもそも何もできず即終了であろう。
- 機材が少なく済むこと。
- 接続が簡単で確実な(間違いが起こりにくい)こと。
- 消費電力が少ないこと。
- 道具としてAndroidスマフォを使ってもよい。iPhoneは知らん。
    - 筆者はPixel 4を使っているので、評価結果はスマフォに高いスペックを要求する側にバイアスがかかっている可能性がある。

# 本命: スマフォVNC方式

これはRPiでVNCサーバを立ち上げてスマフォから操作する方法である。前回のテストでは自宅WiFiの中でこの方法を用いたが、思いのほか快適であった。1024x768の画面サイズでVNCサーバを立ち上げ、スマフォ上で拡大縮小しながらの操作でPHD2は十分快適に使える。何故かShift+クリックが効かないという問題があるが、回避策はあるので特に深刻ではない。

これを自宅WiFiの外でやろうと思ったら、(1)RPiとスマフォをIPで接続する (2)スマフォからRPiのIPアドレスがわかる(＝スマフォ上のVNCクライアントから接続先のRPi上のVNCサーバを指差せる) という2条件を満たせばよいはずである。検討してみると実現方法のオプションが幾つかあったので、以下順に挙げていく。

## オプション1: RPiのWiFiアクセスポイント化

真っ先に思い付くのは「RPiをWiFiアクセスポイントにし、スマフォのWiFiをそちらにつなぎに行く」というよくある方式である。この場合、普段自宅WiFiにステーションとしてぶら下がっているRPiを、外に行ったときにはアクセスポイントに「切り替える」必要があり、この方法が自明ではない。コンソールの接続前に切り替えコマンドを叩くとかはできないからである。というわけで、以下のような情報をいろいろ漁ってみた。

- RPiアクセスポイント化の基本: https://thepi.io/how-to-use-your-raspberry-pi-as-a-wireless-access-point/
- RPiのWiFiをステーション・アクセスポイント間で切り替えたい！というまさに同じ動機の議論: https://www.raspberrypi.org/forums/viewtopic.php?f=36&t=249482
- 切り替え手段1 autoAP: https://github.com/gitbls/autoAP
- 切り替え手段2 WiFi Connect: https://github.com/balena-io/wifi-connect

この中で autoAP というのが面白そうだと思ったのだが、ネットワーク管理を systemd-networkd に切り替えなきゃいけない→( ﾟДﾟ)ﾏﾝﾄﾞｸｾとなり、結局スマフォ側をアクセスポイントにする方が楽だということに気付き、この方式の検討は中断した。

なお「WiFiドングルをもう一個させばいいじゃない」というのも事実だが、電力消費増えそう且つリソースの無駄(本来切り替えで済むものを2台のハードウェアで賄う)なので、「RPiがアクセスポイント・スマフォがステーション」という先入観はここで一旦捨てて考えることにする。

## オプション2: USB接続

いわゆる「USBテザリング」の仕組みを使うのだが、インターネットに接続するわけではない。RPiとスマフォをUSBで接続し、スマフォ側でUSBテザリングをONにすると、内部的には両者の間にIPネットワークが確立されてスマフォが外界に対するルーターとなる。ここでローカルネットワーク内でRPiとスマフォとを通信させるわけだ。

まず普通にRPiとスマフォをUSBで接続してUSBテザリングをONにしてみよう。するとRPi上に `usb0` という名前のネットワークインタフェースが現れ、IPアドレスはスマフォ側のDHCPサーバによって割り当てられる。このままだとスマフォ側からRPiのIPアドレスを知る方法がなく困るので(RPi上でmDNSを有効にしてもスマフォ側からルックアップしてくれるわけでもない)、 `/etc/dhcpcd.conf` に次のようなエントリーを追加し、IPアドレスを固定する。現在のAndroidの仕様だとUSBテザリングの内部ネットワークは192.168.42.0/24というアドレスに固定になっているようなので、その下で適当なアドレス(この例では99)を選ぶ。192.168.42.129はスマフォ側が取るようなので避けること。ルーターやDNSは指定しなくて構わない。

```
interface usb0
static ip_address=192.168.42.99/24
```

この設定で再びUSBテザリングをONにすると、スマフォ上のVNCから192.168.42.99に接続してRPiを操作できる。

本方式の特徴まとめ:

- 接続手順: USBケーブルで接続 → スマフォのUSBテザリングをON → VNCで192.168.44.xxに接続
- 利点: ケーブルでつないだらほぼ確実につながるので、信頼性は高い。
- 欠点: ケーブルが必要。スマフォが充電されてしまい、RPiのバッテリーから電力が吸い取られる。

## オプション3: WiFiホットスポット接続

スマフォをWiFiホットスポットにし、RPiからWiFiステーションとして接続する方法である。USBがWiFiになっただけで、スマフォがルーターとなりローカルなIPネットワークにRPiが参加するという原理は変わらない。このためにRPi側には次の2つの設定を行う。

(1) 接続先WiFiアクセスポイントのリスト(`/etc/wpa_supplicant/wpa_supplicant.conf`)にスマフォのWiFiホットスポットを追加する。

```
network={
    ssid="<スマフォのホットスポット名>"
    psk="<パスフレーズ>"
}
```

(2) USB接続と同様、`/etc/dhcpcd.conf` にIPアドレス固定のためのエントリーを追加する。ネットワークアドレスが192.168.**43**.0/24に代わるので注意。(アドレス129はやはりスマフォに取られているので避ける。また `arp -a` すると1～3あたりは取られていたのであまり小さい値は避けた方がよい。この例のように99あたりはちょうどよいと思われる。)

```
ssid <スマフォのホットスポット名>
static ip_address=192.168.43.99/24
```

この設定でスマフォのWiFiホットスポットをONにすると、RPiが自動的に接続に行き、スマフォ側から192.168.43.99でRPiにアクセスできるようになる。

本方式の特徴まとめ:

- 接続手順: スマフォのWiFiホットスポットをON → スマフォ上でRPiからの接続を確認 → VNCで192.168.43.xxに接続。
- 利点: WiFiホットスポットは枯れた機能であり、信頼性はそこそこあると言えよう。
- 欠点: スマフォのバッテリーを食う(と言われている)。自宅の外など自宅WiFiの電波が微妙にあるところでは接続先がふらふらとぶれる可能性がある。

## オプション4: Bluetooth接続

USBやWiFiの代わりに「Bluetoothテザリング」(あるいはPersonal Area Network)という機能を使うもので、やはり原理は変わらない。ただ接続はBluetoothなので、スマフォとRPiをペアリングしておき、スマフォ側でBluetoothテザリングをONにし、RPiの方でBluetooth PANクライアントとして接続する、という手順を実行する必要がある。

手順が少々ややこしいので、下記ページの "Bluetooth Tethering with all devices" の章に従うとよい:
https://raspiproject.altervista.org/usb-and-bluetooth-tethering-with-raspberry-pi/amp/

例によってデフォルトではIPアドレスが一定にならないので、`/etc/dhcpcd.conf` でアドレスを固定する。Bluetoothテザリングのネットワークインタフェース名は `bnep0`、ネットワークアドレスは192.168.**44**.0/24である。アドレスの決め方や記述方法は先述した方式と変わらない。これでスマフォから固定IPアドレスでRPiにアクセスできるようになる。

```
interface bnep0
static ip_address=192.168.44.99/24
```

一度手作業での接続に成功したら、同ページで紹介されている RaspberryPi_BTPAN_AutoConnect というスクリプトを使って、RPiからの接続を自動的に行うようにする。ちなみに筆者は起動直後に待たずに接続が確立されるよう次の行をcrontabに追加している。

```
@reboot sleep 10 && /usr/local/sbin/check-and-connect-bt-pan.sh
```

スマフォ側でBluetoothテザリングをONにするのは通常の設定画面からでも可能である(執筆時点のAndroidではアクセスポイント設定の下、USBテザリングと並んでスイッチがある)が、これを簡単にするアプリがいろいろとあるのでお勧めである。筆者はホーム画面からワンクリックでONにできるこれを使っている。
https://play.google.com/store/apps/details?id=jp.co.nicumaru.bluetoothtetheronoff

なお、Bluetoothの通信帯域幅はWiFiに比べてかなり劣るはずだが、PHD2を操作する分には特に問題は感じなかった。

本方式の特徴まとめ:

- 接続手順: スマフォのBluetoothテザリングをON → スマフォ上でRPiからの接続を確認 → VNCで192.168.44.xxに接続
- 利点: バッテリーの消耗が少ない(と言われている)。WiFiと独立なので自宅周辺でも安定して使える。
- 欠点: 特になし。設定に手順が必要であるが、一度クリアしてしまえば問題ない。

## スマフォVNC方式の全体評価

試してみたところBluetooth接続方式が最も良さそうであるが、他の2方式も設定はしておき、バックアップとしていつでも使えるようにする。方法を3つも用意しておけばどれか動くだろう、という考えである。今後実際に使ってみて現場でどうなるか見てみたいと思う。

# 次点: RPiスタンドアロン化

上記のスマフォVNC方式はすなわち「RPiをヘッドレスで使う」方式であるが、こちらはRPiにディスプレイを付けてスタンドアロンで使えるようにしようという試みである。本気でやるならタブレット並みのディスプレイを付けるべきだと思うが、あまり大きくしたくはない・電力消費も増やしたくないので、この480x320の小型TFTディスプレイを試してみることにした。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465152/06e9e828-d11a-3b05-6e50-1e2a9d141bb6.jpeg" width="480">

結論から言うと、かっこよくてテンションは上がるが、実用性はスマフォVNC方式にはるかに及ばずとりあえず却下せざるを得ず。

- PHD2は一応使える。画面は小さいものの、必要な機能はなんとか使える。
- 必要なボタン、例えば「閉じる」ボタンが画面外に出ると文字通りお手あげで、電源コードを抜くしかない。
- タッチスクリーンは今主流の静電容量式ではなく抵抗式で、PalmOS時代を彷彿とさせる懐かしさであるが、ちゃちくて使い物にならない。
    - 指での操作はほぼ無理。スタイラスを使ってなんとか可能だが、誤操作も増える。
    - gtkの問題か、タッチスクリーンだとPHD2のメニューが選択できず、肝心の必要な操作が行えない。
- USBやBluetoothでキーボード＆マウスを接続すればまともに操作できるようになり、スマフォをBluetoothキーボード＆マウスにするアプリケーションもあるが、そんならスマフォVNCでいいじゃん！と本末転倒である: https://play.google.com/store/apps/details?id=io.appground.blek
- HDMI出力をディスプレイに転送する `fbcp` (frame buffer copy)というプロセスがCPUを常時10%近く食う。
- 電力消費を抑えるためGPIO18でバックライトを制御できるはずなのだが、急に設定が変わったり、一筋縄ではいかない。
    - wiringPiを使う場合、RPi 4だとアップデートが必要: http://wiringpi.com/wiringpi-updated-to-2-52-for-the-raspberry-pi-4b/

結局「RPi単体で(スマフォや外部機器の接続なしに)一通りの操作が成立する」というレベルに到達する見込みがなく、ならば素直にヘッドレス＋スマフォVNCの方がよいという結論である。TFTディスプレイはそれだけでかっこいいのだが、わざわざ電力消費とCPU負荷を増やすのに見合ったメリットがあるとは考えにくい。残念ながら何かいいアイディアが出るまで保留である。