屋外など独立環境下での使用を想定したヘッドレス Raspberry Pi の作りかた 

# はじめに
　モニタやキーボードを必要としないコンピュータの運用形態をヘッドレスというそうです。ここでは、天体観測時に望遠鏡に取り付ける Raspberry Pi（以下ラズパイ）のような、ヘッドレスかつ広域インターネットに接続しない、独立型の実行環境の作り方について説明します。

# 目標
　ラズパイ自体を Wi-fi のアクセスポイントとして機能するようにします。アクセスポイント化したラズパイに、ノートパソコンから接続し、ウィンドウシステム経由でラズパイを操作できるようにします。この設定により、以下に示すような条件および操作方法にてラズパイが操作できるようになりますので、結果的にラズパイのヘッドレスな状況での運用が可能となります（天体撮影などでは、ノートパソコンとラズパイとバッテリだけ持っていけば良いので、持ち運ばなければならない荷物の量も少なくなります）：

* インターネットに接続できる環境がなくても（スマフォでテザリング等しなくても）、
* アクセスポイント化したラズパイにノートパソコンから VNC 接続し、
* GUI でラズパイを操作したり、
* Web カメラ画像などを確認するプログラムなどを、
* ノートパソコンより操作

　ラズパイにはバックアップされた時計が搭載されていないので、通常は NTP を活用して正しい時刻を保持するようにしています。インターネットに接続しない場合、正確な時刻が分からなくなってしまいます。もちろん、そもそも正確な時刻は要らない、という運用形態であれば何も問題はありませんが、例えば、撮影日時をファイル名として記録したい等、現在時刻をある程度正確に知りたい場合などは困ってしまいます。そこで、本稿では、**あくまでもオプションとして**ですが、バッテリーパックアップされたリアルタイムクロックモジュールを活用する方法についても記しておきます。

　なお、本稿では mac からラズパイに接続することを想定して、各種の設定について記しています。Windows マシンからの VNC 接続については、今後の更新にて追記される…かもしれません。

# Step 0　システムソフトウェアの更新
　まずはシステムを最新版にしておきます。

```
sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrad
```

# Step 1　必要なソフトウェアのインストール
　本稿の設定では、最終的にラズパイはインターネットには接続できない状況になります。なので、インターネットに接続できる標準設定の時に、必要となる各種のソフトウェアのインストールを済ませておきます。

## 1.1 VNC Server - Tight VNC Server
### 1.1.1 インストール
　今回は、ssh などのターミナルではなく、VNC 接続に対応します。標準の設定でも VNC 接続へは対応しているようですが、mac の場合、標準のソフトウェアで接続することができませんでした。そのため、Tight VNC Server をインストールしておきます。

```
sudo apt install tightvncserver
```

　無事インストールできたら、tightvncserver として、Tight VNC サーバーを起動します。するとパスワードを聞かれるので、入力します。このパスワードは mac から接続する時に入力するパスワードとなります。

　ちなみに、もし、パスワードの入力で何か失敗してしまったら、~/.vnc/passwd ファイルを削除して、再度 tighvncserver を起動します。するとパスワードを聞いてくれますので、今度は失敗しないように、パスワードを入力（設定）しましょう。

### 1.1.2 接続テスト
mac は標準で VNC クライアントを有していますので、ファインダーメニューの「移動」→「サーバへ接続」と移動し、

```
vnc://ラズパイのIPアドレス:5901
```

として接続してみます。もし、ラズパイのアドレスが 192.168.123.45 であれば、

```
vnc://192.168.123.45:5901
```

で接続できるハズです。<font color=red>ここで VNC 接続できないと、ヘッドレス設定を行ったラズパイにも接続できず、困ったこととなります。この段階で、しっかりテスト＆確認するようにしましょう</font>。…とはいえ、ネットワークの設定によっては、もしかすると VNC 接続できない場合もあるかもしれません。その場合は、全ての設定完了後に再度 VNC 接続を試みてみましょう。

### 1.1.3 Tight VNC Server 関連で参考にしたページ
　以下のページにお世話になりました。感謝。

<b>MacからRaspberry PiにVNCでリモートデスクトップ接続する方法</b>
https://darmus.net/raspberry-pi-mac-vnc/

<b>VNCで接続用パスワードを忘れたときは</b>
http://blogcdn.rutake.com/blog/techmemo/2007/09/vnc.html

<b>TightVNC：Mac から Raspberry Pi 3 を リモートデスクトップ</b>
https://homemadegarbage.com/mac-raspi3-vnc

## 1.2 アクセスポイント化ソフトウェア - hostapd
　ここではインストールだけを行います（設定は後ほど）。

```
sudo apt install hostapd
```

## 1.3 DNS 用ソフトウェア - dnsmasq
　同じくインストールだけを行います（設定は後ほど）。

```
sudo apt install dnsmasq
```

## 1.4 オプションその１ - バッテリーパックアップされたリアルタイムクロックモジュールを使う場合
　私の場合は、ある程度正確な時刻が必要でしたので、バッテリーパックアップ可能なリアルタイムクロックモジュール(RTC)を使用しました。RTC モジュールはスイッチサイエンスで売っている約 500 円の PiRTC (DS1307) を使用しました。https://www.switch-science.com/catalog/5334/

<details><summary>以下、DS1307 を用いた PiRTC の設定方法です（左側の三角形をクリックすると展開します）</summary><div>

### 1.4.1 正しい時刻の取得 - ntpdate
　RTC モジュールの情報を使うには、まず正しい時刻を RTC に保存しなければなりません。起動後、ある程度時間が経つと、いつの間にかラズパイの時刻が正確になっていますが、せっかちな私は ntpdate を用いて強制的に時刻を同期するようにしています。というわけで、ntpdate のインストールを行います。

```
sudo apt install ntpdate
```

　ntpdate の使い方は簡単で、「sudo ntpdate ntpサーバーのアドレス」とすれば時刻同期は完了です。ntp サーバーのアドレスですが、NICT が公開しているものがありますので、

```
sudo ntpdate -v ntp.nict.jp
```

とすれば十分です。オプション v をつけると、同期に関する情報を表示してくれるものです。無事に同期が完了すると、最後の出力の行頭に現在の時刻が表示されているはずです。

**参考資料**
Linux基本コマンドTips（315）：【 ntpdate 】コマンド――時刻をNTPサーバと同期する
https://www.atmarkit.co.jp/ait/articles/1906/21/news013.html

### 1.4.2 I2C の有効化
　PiRTC は I2C により通信を行うので、I2C を有効にします。

```
sudo raspi-config
```

として raspi-config を立ち上げ、"5 Interfacing Options" → "P5 I2C" へと進み、I2C を有効化しておきます。

### 1.4.3 RTC ドライバのインストール
　スイッチサイエンスのページからもドライバのインストールに関する説明がありますが、当方の環境では、さらに追加の設定が必要でしたので、それも合わせて記しておきます。まず、Seeed-Studio よりインストーラを入手します（今回、以下の作業はホームディレクトリで行うものとします）。<font color=red>この段階では、まだ RTC モジュールはラズパイに装着しません。</font>

```
cd ~
git clone https://github.com/Seeed-Studio/pi-hats.git
```

なお、Seeed-Studio の Seeed は Seed ではなく、See<font color=red>e</font>d （e が 3 つ）なので注意して下さい。

次に、pi-hats/tools ディレクトリに移動して、インストールスクリプトを実行します：

```
cd ~/pi-hats/tools
sudo ./install.sh -u rtc_ds1307
sync
```

RTC モジュールを装着するため、ラスパイの電源をオフにします：

```
sudo shutdown now
```

### 1.4.4 RTC モジュールの装着
　バックアップ用の電池をもジュルに入れて、Pi RTC DS1307 をラズパイに装着し、ラズパイの電源を入れます。

### 1.4.5 /dev/rtc の作成
/etc/modules に rtc-ds1307 を追加します。追加後は多分、以下のような状況になっているかと思います：

```
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.

i2c-dev
rtc-ds1307
```

<font color=red>書き込んだら一旦リブートします（sudo reboot now）</font>。その後、

```
ls /etc/r*
```

などとして、/dev に rtc というディレクトリがあるか確認します。/dev/rtc というファイルが確認できれば OK です。

### 1.4.5 DS1307 との通信の確認
　正しくドライバが動作していることを確認するために、今しがた取り付けた PiRTC の時刻を読み出してみます：

```
sudo hwclock -r
```

として、何か値が表示されれば OK です。渡しの場合は 2000 年 1 月 1 日である旨を示す表示が出てきました。

### 1.4.6 現在時刻を RTC に保存
　ntpdate などを用いて、ラズパイの時計を正しい時刻にしておきます。続いて、

```
sudo hwclock -w
```

として、DS1307 に現在のシステム時刻を書き込みます。これで、電池が有効である間、ラズパイの電源を切っても PiRTC は（ほぼ）正確な時刻を報告してくれるようになりました。

</div></details>

## 1.5 オプションその２ - その他必要なソフトのインストール（例：Python 関係）
　Step 2 ではアクセスポイント化してしまうため、広域インターネットへの接続が断たれてしまいます。その前に、必要なソフトウェアは全てインストールしておきましょう。私の場合は Python から OpenCV を使う必要があったので、libopencv-dev と python-opencv をインストールしておきました。

```
sudo apt install libopencv-dev
sudo apt install python-opencv
```

**参考：「Raspberry Pi B+にOpenCV-Python環境を構築する」**
https://qiita.com/jh3rox/items/be803f9171db8fe737de

あと、VideoForLinux も使うので、もしなかった場合はこの段階でインストールしておきます：

```
sudo apt-get install v4l-utils
```

**参考：Raspberry PiとPythonで複数のUSBカメラを取り扱う方法**
https://qiita.com/sudamasahiko/items/09c19addcbf23816390b

<font color=red>もちろん、インストールするだけでなく、念のため動作確認もしておきましょう。</font>

私の場合は、ロジクールの C270 という Web カメラを Python で操作したかったので、以下のプログラムを作って確認しました：

```python
import cv2

cap=cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    If ret==False:
        continue
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
capture.release()
cv2.destroyAllWindows()
```

## 1.6 オプションその３
　mac とラズパイを接続し、かつ、ファイルのやりとりを mac-ラズパイ間で行う場合には、netatalk をインストールしておきましょう。

```
sudo apt install netatalk
```

# Step 2 ラズパイのアクセスポイント化
　ここからはラズパイのアクセスポイント化を進めていきます。この作業を行うと、広域インターネットには接続できなくなりますので、必要なソフトのインストールなどは Step1 の段階で全て済ましておきましょう。

**※ なお、2.1 および 2.2 については以下のページを参考にしました…というか、ほぼそのままです。
一箇所にまとまっていた方が便利かと思い、本文書に記しております。**

**参考：Raspberry Pi3 wifiのAP/Clientを切り替え**
https://qiita.com/yamato225/items/4c17bfdbda6ce57104de


## 2.1 hostapd の設定を行う
　アクセスポイント化を担う hostapd の設定を行います。具体的には、/etc/hostapd/hostapd.conf に以下の内容を記述します：

```
interface=wlan0
driver=nl80211
ssid=AstroPi                ##SSID名
hw_mode=g
channel=6
ieee80211n=1
wmm_enabled=1
ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_passphrase=raspberry    ##SSIDパスワード
rsn_pairwise=CCMP
```

## 2.2 dhcpcd の設定を行う
　DHCP 機能を担う dhcpcd の設定を行います。具体的には /etc/dhcpcd.conf を以下のように記述します。Step 1 の時にも補足しましたが、dhcpd.conf ではなく dhcp<font color=red>c</font>d.conf と最後の d の前に c がひとつ入りますので、間違えないようにしましょう。

```
interface eth0
fallback static_eth0
denyinterface wlan0
interface wlan0
static ip_address=192.168.123.1/24
static routers=192.168.123.123.1
static domain_name_servers=192.168.123.1
static broadcast 192.168.123.1.255
```

　この例では、アクセスポイント化したラズパイから渡される IP アドレスを 192.168.123.* にしています。123 では都合が悪い、という人は適当に該当部分を書き換えて下さい。

## 2.3 rc.local への追加
　起動時にアクセスポイントとしてラズパイが機能するように、いくつかのプログラムを起動時に実行するようにします。ここでは /etc/rc.local に以下の内容を記述する例を紹介します。/etc/rc.local の最後には exit 0 という記述があるので、その直前に以下の内容を記述します（なお、rc.local は root にて実行されるため sudo は不要です）。

```
# --- AstroPi - begin here ---
# hwclock -s
systemctl stop wpa_supplicant
systemctl stop dhcpcd
ifconfig wlan0 down && sudo ifconfig wlan0 up
hostapd /etc/hostapd/hostapd.conf &
sleep 5
systemctl start dhcpcd
systemctl start dnsmasq
sudo -u pi tightvncserver -geometry 1024x768 -depth 24
# --- AstroPi - end here ---
```

hostapd の起動の後、sleep しているのは、直後に dhcpcd を起動しても上手く動作しなかったためです。もしこの設定で上手くいかない場合はスリープする秒数を伸ばしてみて下さい（私の環境では 3 だと時々失敗してしまいます）。

　なお、下から 2 行目にて sudo していますが、これは root での実行のためではなく、ユーザー pi にて tightvncserver を起動するためです（-u pi）。tightvncserver の起動には環境変数の USER と HOME が必要とのことで、それらが設定された状況にて実行するようしています。

**参考**
【sudo】Linuxで指定したユーザーでコマンドを実行する
https://uxmilk.jp/53095

Raspberry Pi で TightVNC サーバ
https://raspberrypi.akaneiro.jp/archives/455

**オプション：Pi RTC DS1307 を使用している場合**
　2 行目の hwclock に関する行の行頭の # を削除し、hwclock -s を有効化して下さい。これにより、RTC が保持している日時がラズパイの日時として設定されます。

# Step 3 動作確認
　ここまでの設定を行ったら、一度ラズパイをリブートさせ（sudo reboot now）、アクセスポイント化したラズパイに接続（Wifi を AstroPi-AP に接続）できることを確認します。Wifi 経由でラズパイへの接続が無事終了したら、念のため

```
ping 192.168.123.1
```

を実行し、アクセスポイント化（AP 化）したラズパイと通信できていることを確認して下さい。

　次に、Mac の場合、ファインダ→移動→サーバーへ接続…、とし、

```
vnc://192.168.123.1:5901/
```

VNC にて、ラズパイのデスクトップ画面が表示されることを確認してみて下さい。

　以上にて、独立環境下でのヘッドレスなラズパイができあがりました。もし、アプリケーションプログラムのインストールし忘れなどに気がついた場合は、先にも記した @yamato225 さんの分かりやすい解説ページ 「Raspberry Pi3 wifiのAP/Clientを切り替え」https://qiita.com/yamato225/items/4c17bfdbda6ce57104de を参考に、一度クライアントモードにして再起動してみて下さい。

# おわりに
　当方の環境では、ここに示した設定で（いまのところ）問題なく動作しております。しかし、私自身は Linux に関してあまり詳しくはありませんので、誤解している部分や間違っているところがありましたらご指摘いただければ幸いです。