起動時にジャンパ線が刺さっていたら WPS で wifi アクセスポイントの接続情報を受け取って全自動で wifi の設定をする Raspberry Pi の設定


#始めに
　Raspberry Pi を使うと、それまで高価な機器を買わなければできなかったような事が安価に実現できたりします。それを自分でつかっている間はいいのですが、誰かに提供する時に困ってしまうのが WiFi の設定で __「そちらのネットワーク環境に合わせて WiFi の設定をしてね」と言ってしまうと相手が困ってしまい__ ます。
　アクセスポイントへの接続を [wps](http://ja.wikipedia.org/wiki/Wi-Fi_Protected_Setup) で自動設定する事は可能なのですが、その wps の起動自身がデスクトップからの GUI にしろ、有線IP経由やシリアル経由（！）のコマンドラインにしろ少し大変だったりします。
　そこで、Raspberry Pi の起動シーケンスの中に wps による設定要求を組み込み、 __アクセスポイントの WPS ボタンを押して、Raspberry Pi はジャンパ線を刺して起動するだけで全自動で接続情報を受け取って設定し、すぐに WiFi が使えるように__ します。これだとだれでも自分で wifi の設定をして使ってくれそうですね

#復習：wps による Raspberry Pi の wifi 設定のおさらい
　本題に入る前に、理解のための整理として wps による wifi 設定をさっと俯瞰しておきます。興味のない方はファイルの変更点だけコピペして、以下は飛ばして直接「本題」にいっていただいても問題ないです

## 1. /etc/network/interfaces の変更
オリジナルの interfaces は

+ 有線 (eth0) は dhcp
+ 無線 (wlan0) は manual 

という設定なっています

```bash:/etc/network/interfaceオリジナル
auto lo

iface lo inet loopback
iface eth0 inet dhcp

allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp
```

manual というのは、端末の起動時は設定を行わないので、後で ifup コマンド等で手で設定しますね、という設定です。使い方によってはこれはこれで便利なのですが、アクセスポイントに接続して IP アドレスをもらって使いたいので、下のように __２カ所修正__ します

```bash:/etc/network/interfaces変更後
auto lo

iface lo inet loopback
iface eth0 inet dhcp

allow-hotplug wlan0
#iface wlan0 inet manual
iface wlan0 inet dhcp
#wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp
```

wlan0 の iface を __manual から dhcp に__、また __wpa-roam を wpa-conf に__変更します。ちなみに、アクセスポイントへの接続情報は文字列でこの /etc/wpa_supplicant/wpa_suplicant.conf に手で記載したり wps に編集されたりしたものが有効になります

## 2. wps による AP への設定情報の要求
### ディスクトップが使える場合
デスクトップが使える時は、wpagui を下図のようにメニューの "Internet" から選択して使います

![スクリーンショット 2015-04-23 16.12.07.png](https://qiita-image-store.s3.amazonaws.com/0/46544/0a44bb61-f515-c785-bc5c-3863a5738ec3.png "スクリーンショット 2015-04-23 16.12.07.png")

下図のようい WPS タブを開き、"PBC - push button" もしくは "Generate PIN" のどちらかを選択して wps を起動します

![スクリーンショット 2015-04-23 16.13.06.png](https://qiita-image-store.s3.amazonaws.com/0/46544/ccbd6e53-4740-672d-8726-080b2e89cfdc.png "スクリーンショット 2015-04-23 16.13.06.png")

尚、前述の interfaces で wlan0 を dhcp にする変更がしていない状態だと WPS タブはグレーアウトされていると思います

### コンソールによる設定
コンソールから wps を起動する場合は以下のように wpa_cli (コンソールアプリの wpagui と名前がにてますね)を以下のように利用します

```bash:プッシュボタンの場合
sudo wpa_cli wps_pbc
```

```bash:PIN生成の場合（例としてPIN=12345678）
sudo wpa_cli wps_pin any 12345678
```

# 本題：起動時にジャンパ線が刺さっていたら WPS で WiFi の自動設定をする設定

 wps の起動は wpa_cli コマンドでできるのですが、起動時に毎回そのへんの AP に wps で設定情報を要求するようでは少し迷惑ですし、そもそも悪意のある AP（も、Raspberry Pi で作れてしまいます）から騙されて掴まされる危険もあります。なにかトリガーが必要なのですが、ディスクトップやコンソールといった入出力機器がなくてもスタンドアロンで使えるように下図のように[ジャンパ線](http://www.aitendo.com/product/11178)を使うことにし、 __起動時にジャンパ線が刺さっていた時のみ、wps で AP の設定情報をとりにいく__ ことにします
ちなみにジャンパ線は青いケーブルです。輪ゴムも写ってますがこれはSDカードを固定してます（SDカードのフックの爪が壊れたので）。

![スクリーンショット 2015-04-24 20.07.53.png](https://qiita-image-store.s3.amazonaws.com/0/46544/ab8ae3a2-0dde-0198-f874-b614e88c4910.png "スクリーンショット 2015-04-24 20.07.53.png")

写真がちょっと不鮮明なのですが、ジャンパ線は Pin 1 と Pin 12 を下図のようにつないでいます。

![スクリーンショット 2015-04-23 11.19.15.png](https://qiita-image-store.s3.amazonaws.com/0/46544/8307c80e-6678-dba0-eab4-5080b39b1191.png "スクリーンショット 2015-04-23 11.19.15.png")

Pin 12 は gpio 18番です。Pin 1 は 3.3V の電源、つまり gpio の High 状態なので、起動時にジャンパ線でつながっていると gpio 18 の値は High、ジャンパ線がない普通の状態は Low になります

ということで、スクリプトの処理の内容は

1. gpio 18番を初期化
2. High なら wps で AP 情報を設定、Low ならなにもしない
3. gpio 18番を解放

この内容を下のように rc.local に追加します


```BASH:/etc/rc.localオリジナル
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

exit 0
```

```BASH:/etc/rc.local変更後
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

# gpio が on なら wps_pbc 及び wps_pin で AP の設定情報を要求
gpio=18
# gpio が初期化されていなければ初期化
if [ ! -d /sys/class/gpio/gpio${gpio} ]
then
  echo $gpio > /sys/class/gpio/export
fi
value=/sys/class/gpio/gpio${gpio}/value
current_value=`cat $value`
if [ $current_value -eq 1 ]
then
  `/sbin/wpa_cli wps_pbc`
  `/sbin/wpa_cli wps_pin any 12345678`
fi
echo $gpio > /sys/class/gpio/unexport

exit 0
```

Raspberry Pi が起動したら（gpio はもう解放しているので）ジャンパ線は抜いても大丈夫です。というか、そのままにしておくと想像もしてないような所にひっかけていろいろなトラブルの原因になりますのですぐに抜いたほうがいいです。一般にソフト屋さんは電気屋さんとか機構屋（筐体のギミックを設計する人）さん達からは「基盤を壊す人」と思われているようですが、確かに私も随分壊しました ^^;

#まとめ
以上、まとめますと下記の 2点の変更を行う事で、wps による wlan の自動設定が可能になります

1. /etc/network/interfaces を修正して dhcp を使うようにwlan0 を設定する
2. /etc/rc.local に、ジャンパ線が刺さっていたら wps による AP 情報を要求する処理を追加する 

使い方は

ジャンパ線をつないで Raspberry Pi を起動し
+ ルーターがボタンタイプの場合：ボタンを押す
+ ルーターが PIN タイプの場合：PIN 12345678 を受け付ける

になります

#余談
　あまりセキュアではないのでお行儀が悪いのですが、この wpa_suplicant.conf を /boot 領域に移動することも出来ます。この時、fstab の設定を変更して /boot 領域を[書き込み可能にしておく](http://qiita.com/UedaTakeyuki/items/2d57c8c7001e0bbaaef1)事が必要です。このようにしておく事のメリットは、この SD カードを Mac や Windows に刺して wpa_suplicant.conf に接続情報を追加したり変更したりする事ができます。デメリットとしてはセキュリティの問題がありすぎるので、基本的に個人的な利用に限定できる場合以外は使えない設定です 

#感想
　ちょっと自慢がはいってしまい申し訳ないのですが、自分で使っててもこれは結構べんりです

#参考URL
- [wps についての Wi-FI Alliance の解説](http://www.wi-fi.org/ja/discover-wi-fi/wi-fi-protected-setup)
- [Raspberry Pi Forum での議論](https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=77277)
- ブログ： [Linux で WPS を使う方法](http://3daysblog.blogspot.jp/2012/02/linux-wpawpa2.html)