Raspberry Piの無線LANをmicroSDで簡単に設定するためのツールを作った

以前に書いた[Raspberry Piの無線LANをmicroSDで設定する](https://qiita.com/mascii/items/0d1a280ac58ed8f6f999)という記事では、RaspbianのOSイメージが書き込まれた**microSDにあらかじめ`wpa_supplicant.conf`というファイルを作成しておくことで、無線LANの設定ができる**ことをご紹介しましたが、ブラウザ上でSSIDとパスフレーズを入力するだけで簡単に`wpa_supplicant.conf`を作成できるツールを作成しましたので、紹介します。
<img width="600" alt="wpa-supplicant-conf-tool.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/67e67a87-27f1-2aef-43a5-739d6e0755d7.png">

# 動作環境(確認済み)
- Raspberry Pi Zero W
    - Raspbian Stretch Lite 2017-09-07
        - イメージをMicroSDに書き込んだ直後の状態
- PC(macOS Sierra)
    - Google Chrome
    - Firefox
    - Safari
- PC(Windows 10)
    - Internet Explorer 11
    - Edge

Raspberry Piの内蔵の無線LAN機能では2.4GHz帯のアクセスポイントのみ利用できます。
ルーターのデフォルトの設定では、2.4GHz帯のアクセスポイントのSSIDにはgやGといった文字が含まれていることが多いです。

# 使用方法
`wpa_supplicant.conf`というファイルをmicroSDのルートディレクトリに作成していきます。
このファイルをmicroSDのルートディレクトリに作成すると、Raspberry Pi起動時に自動でRaspbian上の`/etc/wpa_supplicant/wpa_supplicant.conf`を上書きするようになっています(microSDのルートディレクトリに作成したファイルは削除されます)。

[https://mascii.github.io/wpa-supplicant-conf-tool/](https://mascii.github.io/wpa-supplicant-conf-tool/)にアクセスし、Raspbianで利用したいSSIDとPassphrase(WPAキー)を追加していきます。
WPAキーが設定されていないアクセスポイントにも対応しておりますが、自己責任でお願いします。

![wpa-supplicant-conf-tool.gif](https://qiita-image-store.s3.amazonaws.com/0/137045/1861a1f4-6cb7-6099-9cfa-b2f448976aec.gif)


Raspbianで利用したいSSIDとPassphrase(WPAキー)を追加し終えたら、「wpa_supplicant.conf作成」ボタンをクリック(またはIE11,Edge以外のブラウザの場合、右クリック > 保存)し、Raspbianイメージが書き込まれたmicroSDに`wpa_supplicant.conf`というファイル名で保存します。
ご一緒にいかがですか？的な感じで、「ssh.txt作成」ボタンで空の`ssh.txt`も作成できます。これを一度Raspbianイメージが書き込まれたmicroSDに保存しておかないとSSH接続ができませんので、ぜひご利用ください。

これら一連の操作は全てブラウザ上のJavaScriptで処理されていますので、サーバーへSSIDやパスフレーズが送信されるといったことはありません。

また、このツールで作成される`wpa_supplicant.conf`のPSKは平文ではなく、SSIDとパスフレーズの組をハッシュ化した256bitのキーを用いております。

```wpa_supplicant.conf
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="test"
    psk=899f089ca767f38265424c83ce83193ab145571c0a71e1aca4487d615c411f34
}
network={
    ssid="test2"
    key_mgmt=NONE
}
```

# SSH接続をする
macOSでZeroconf(Bonjour)を利用するケースを、[Raspberry Piの無線LANをmicroSDで設定する](https://qiita.com/mascii/items/0d1a280ac58ed8f6f999#ssh%E6%8E%A5%E7%B6%9A)で紹介しております

# ツールを作った理由
[Vue.js](https://jp.vuejs.org/index.html) + [webpack](https://webpack.js.org/)で何か実用性もあるMVP(Minimum Viable Product)を作ってみたかったことと、以前に書いた[Raspberry Piの無線LANをmicroSDで設定する](https://qiita.com/mascii/items/0d1a280ac58ed8f6f999)という記事の手順をもっと簡単にできそうだと感じていたからです。

npmパッケージの~~[pbkdf2](https://www.npmjs.com/package/pbkdf2)~~ [crypto-js](https://www.npmjs.com/package/crypto-js)をimportして使うことでパスフレーズのハッシュ化ができること、ブラウザ上のJavaScriptで指定したファイル名・内容のファイルをダウンロードできることがわかり、Vue.jsで作られたToDoアプリを参考にすれば実用性もあるツールが作れそうだ、と思いました。
そして急遽、[We Are JavaScripters! @11th【休日もくもく会】](https://wajs.connpass.com/event/65887/)という勉強会に申し込んで、もくもくと作ってみることにしました。
家でまったりしているよりも集中でき、普段からVue.js使っている方からアドバイスいただけたりするので、休日のもくもく会はとても良い感じでした。

今回作成したツールのビルド前のソースコードはこちらで公開しています:
https://github.com/mascii/vue-wpa-supplicant-conf

(2017/10/07追記)
Vue.jsの代わりに[React](https://reactjs.org/)を用いたバージョンを作ってみました。
Vue.jsからReactに変更するにあたり、まず[ESLint](https://eslint.org/)の設定とwebpackの設定を行う必要がありましたが、Vue.js版での経験のおかげで直ぐに設定できました。
React版を作っているときはひたすらESLintに怒られ続けたものの、Vue.jsで書いていたときには気づけなかったこともあり、とても良い勉強になりました。
また、Vue.jsの`v-bind`や`v-for`の便利さや、コードのシンプルさにも気付かされました。

React版のビルド前のソースコードはこちらで公開しています:
https://github.com/mascii/react-wpa-supplicant-conf

(2017/11/27追記)
webpackでビルドしたJavaScript, CSSをHTMLファイルに埋め込むようにしたため、**HTMLファイル単体をダウンロード**しておくだけでローカル(インターネットに繋がらない環境)で利用できるツールになりました。
<img width="133" alt="wpa_supplicant.conf作成_html_file.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/47b16dfb-9241-c663-861a-9999be8a7324.png">

詳しくはこちらの別記事を参照してください:
[JavaScript, CSS, 画像ファイルをHTMLに自動で埋め込む方法](https://qiita.com/mascii/items/c5e01f544267f8df5776)

(2018/02/24追記)
Vue.jsより軽量な[Hyperapp](https://hyperapp.js.org/)に変更し、ファイルサイズが62KBほど削減しました。

詳しくはこちらの別記事を参照してください:
[Hyperapp, React, Vue.jsで同じサンプルアプリを作ってサイズを比較してみた](https://qiita.com/mascii/items/149738ceb51fa9950008)

# LT発表
この設定ツールについて、[IoT縛りの勉強会! IoTLT vol.33 @ LINE](https://iotlt.connpass.com/event/67583/)で「あなたのお家に眠るラズパイを救出したい」([スライド](https://speakerdeck.com/mascii/anatafalseojia-nimian-rurasuhaiwojiu-chu-sitai))というタイトルで発表いたしました。
[<img width="480" alt="slide_0.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/137045/88193939-70fa-615f-9d50-5c45f290afa8.jpeg">](https://speakerdeck.com/mascii/anatafalseojia-nimian-rurasuhaiwojiu-chu-sitai)

Raspberry Piをヘッドレス(ディスプレイ、キーボード、マウスなし)で利用するための手順を、OSイメージ書き込みに[Etcher](https://etcher.io/)、無線LAN設定に本ページで紹介した設定ツール、SSH接続の際にZeroconfを用いる方法で、初心者の方々に向けて紹介いたしました。

# 参考サイト
* ファイルダウンロードについて
    * [JavaScriptでファイルダウンロード処理を実現する](https://qiita.com/wadahiro/items/eb50ac6bbe2e18cf8813)
* sshdの自動起動について
    * [Raspbian の起動時の仕掛け](https://qiita.com/kounoike/items/446bb1d9e0ee9b689c1e)
* Vue.js版
    * [Vue.jsを使って簡単なToDoリストを作成してみた - Qiita](https://qiita.com/hashimoto-1202/items/7fed2e8cd88f0e2ef276)
    * [Vue.jsとVuexとwebpackで単一ファイルコンポーネント化してTodoListを作ってみた - Qiita](https://qiita.com/tiwu_official/items/6a877bcdf2c3022f0ff6)
* React版
    * [React.js + ES6 + WebPack チュートリアル - Qiita](https://qiita.com/tfutada/items/fe55d1c1b0904b5ced2b)
    * [【React】ToDoアプリを作ってみよう【前編】 - Qiita](https://qiita.com/mikan3rd/items/20152cdd63a708264a9e)
    * [【React】ToDoアプリを作ってみよう【後編】 - Qiita](https://qiita.com/mikan3rd/items/0a1be8fa9f349735cf4a)
    * [Reactをes6で使う場合のbindの問題 - Qiita](https://qiita.com/cubdesign/items/ee8bff7073ebe1979936)
    * [[React.js] setStateしても直ちにstateは変更されない | Like@Lunatic](https://likealunatic.jp/2015/07/reactjs-setstate)
    * [javascript - Delete item from state array in react - Stack Overflow](https://stackoverflow.com/questions/36326612/delete-item-from-state-array-in-react)
    * [reactjs - React set focus on input after render - Stack Overflow](https://stackoverflow.com/questions/28889826/react-set-focus-on-input-after-render)
    * [static - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes/static)
        * staticメソッドの呼び出し方