ESP8266 (ESP-WROOM-02) でWi-Fi使用時のSSID/パスワードをブラウザで設定できるように

## 概要
ESP8266(以下 WROOM02) で Wi-Fi 使用時に、SSID / Password をブラウザで設定できるように。

## はじめに
サンプルコードでは、Wi-Fi の SSID と パスワード をハードコーディングしている場合がほとんどです。
その状態では、Wi-Fi を切り替えるために、再コンパイルが必要になってしまいます。

ブラウザで、SSID と パスワード を設定できるようにしたいですが、そもそもブラウザで接続するためには Wi-Fi につながっている必要があります。(あぁ、卵が先か鶏が先か。。)

そこで、Wi-Fi の設定時は、WROOM02 自身が アクセスポイント兼 Webサーバ になって、ブラウザを使った設定の変更をサービスするようにします。（サーバモード）
設定後に再起動すると、設定された SSID に 接続するようになります。（クライアントモード）

（なお、サーバモードでのアクセスポイントは、SSID は WROOM02 の macアドレス、パスワードは「thereisnospoon」にしています。）


## モード切り替え

利便性のため、GPIO0 と リセット は、タクトスイッチ を使って実装して下さい。
詳細は、以下を参照して下さい。
http://qiita.com/exabugs/items/9ca4093813db71278b39

なお、ハード的な WROOM02 の起動モードは、以下になります。

|モード|IO15|IO2|IO0|EN|
|----|:----:|:----:|:-----:|:-----:|
|書き込み|Low|High|Low|High|
|実行|Low|High|High|High|

書き込みを行う際は、IO0 を Low (ボタン押下) にした状態で、リセットボタンをクリック。(起動の瞬間に IO0 が Low なら大丈夫です)


今回はさらに、実行モードでの起動後に、サーバモードかクライアントモードのどちらになるかを、IO0 の状態で決定しています。

|モード|再起動|
|----|-------|
|クライアント|リセットボタンを押すだけ|
|サーバ|リセットボタンを押して、直ぐ(1秒以内)に IO0 を押し続ける|




## スケッチ
スケッチは以下になります。

```cpp
#include <ESP8266WiFi.h>
#include <WiFiClient.h> 
#include <ESP8266WebServer.h>
#include <FS.h>


// モード切り替えピン
const int MODE_PIN = 0; // GPIO0

// Wi-Fi設定保存ファイル
const char* settings = "/wifi_settings.txt";

// サーバモードでのパスワード
const String pass = "thereisnospoon";


ESP8266WebServer server(80);

/**
 * WiFi設定
 */
void handleRootGet() {
  String html = "";
  html += "<h1>WiFi Settings</h1>";
  html += "<form method='post'>";
  html += "  <input type='text' name='ssid' placeholder='ssid'><br>";
  html += "  <input type='text' name='pass' placeholder='pass'><br>";
  html += "  <input type='submit'><br>";
  html += "</form>";
  server.send(200, "text/html", html);
}

void handleRootPost() {
  String ssid = server.arg("ssid");
  String pass = server.arg("pass");

  File f = SPIFFS.open(settings, "w");
  f.println(ssid);
  f.println(pass);
  f.close();

  String html = "";
  html += "<h1>WiFi Settings</h1>";
  html += ssid + "<br>";
  html += pass + "<br>";
  server.send(200, "text/html", html);
}

/**
 * 初期化(クライアントモード)
 */
void setup_client() {
  
  File f = SPIFFS.open(settings, "r");
  String ssid = f.readStringUntil('\n');
  String pass = f.readStringUntil('\n');
  f.close();

  ssid.trim();
  pass.trim();

  Serial.println("SSID: " + ssid);
  Serial.println("PASS: " + pass);

  WiFi.begin(ssid.c_str(), pass.c_str());

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");

  Serial.println("WiFi connected");
  
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

/**
 * 初期化(サーバモード)
 */
void setup_server() {
  byte mac[6];
  WiFi.macAddress(mac);
  String ssid = "";
  for (int i = 0; i < 6; i++) {
    ssid += String(mac[i], HEX);
  }
  Serial.println("SSID: " + ssid);
  Serial.println("PASS: " + pass);

  /* You can remove the password parameter if you want the AP to be open. */
  WiFi.softAP(ssid.c_str(), pass.c_str());

  server.on("/", HTTP_GET, handleRootGet);
  server.on("/", HTTP_POST, handleRootPost);
  server.begin();
  Serial.println("HTTP server started.");
}

/**
 * 初期化
 */
void setup() {
  Serial.begin(115200);
  Serial.println();

  // 1秒以内にMODEを切り替える
  //  0 : Server
  //  1 : Client
  delay(1000);

  // ファイルシステム初期化
  SPIFFS.begin();

  pinMode(MODE_PIN, INPUT);
  if (digitalRead(MODE_PIN) == 0) {
    // サーバモード初期化
    setup_server();
  } else {
    // クライアントモード初期化
    setup_client();
  }
}

void loop() {
  server.handleClient();
}
```

## 使い方

1. サーバモードで起動(リセットボタンを押して、IO0を押し続ける)後、シリアルモニタに表示されるSSID/パスワードのネットワークに接続します。

```
SSID: 18fe34eexx92  ←  ここはチップ(WROOM02)毎に異なります
PASS: thereisnospoon
HTTP server started.
```

2. http://192.168.4.1/ にアクセス。Wi-Fi 設定画面を開きます。

![スクリーンショット 2016-01-03 18.00.58.png](https://qiita-image-store.s3.amazonaws.com/0/69410/e02866ae-2fec-e665-dab9-a0d939e42f2b.png)

3. SSID と パスワード を設定します。

4. WROOM02 を再起動(リセットボタンを押下)します。

## まとめ

ESP8266(以下 WROOM02) で Wi-Fi 使用時に、SSID / Password をブラウザで設定できるようにしました。