ESP32 の WiFi 設定をアクセスポイント＋ Web サーバで行う

ESP8266用に作った大昔のプログラムが、ESP32用に直したら使えたので紹介します。

ESP32 の Wi-Fi パラメータ設定を、ESP32 をアクセスポイント化して内部の Web サーバの設定ページで行えるようにします。

GPIO16 を High にて起動するとアクセスポイントとなるのでスマホなどでアクセスして設定します。その後 GPIO16 を Lo にして起動すると設定した ESSID/PASSPHASE でWi-Fiに接続します。


# 環境

- Arduino 1.8.10 for Linux
- esp32 by Espressif System Version 1.0.3
- WEMOS LOLIN32

# 動作説明

## 設定の書き込みと読み込み

ESP32 内部の Webサーバ にアクセスし設定用ページを実行すると、指定した ESSID, PASSPHASE が SPIFFS 中の /wifi_settings.txt に保存されます。

保存された ESSID, PASSPHASE は次回以降の起動時に読み込まれます。
起動時に正常な /wifi_settings.txt が得られない場合は、ハードコードされているデフォルトセッティングを使って  /wifi_settings.txt を上書きします。


## 通常起動

GPIO16が、GNDレベルなら通常起動します。
保存された ESSID, PASSPHASE を使って Wi-Fi に接続します。

## アクセスポイントとして起動

GPIO16が、HIGH になったままで起動したならハードコードされているデフォルトセッティングで Wi-Fi アクセスポイントとして起動します。

# 問題点

スマホの機種によっては、うまく表示できない場合があるようです。プロキシ的な何か？

# スケッチ

```

#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <SPIFFS.h>

const int WiFiSetPin = 16; // GPIO16  push with boot : AP mode on
const char* settings = "/wifi_settings.txt";
// AP mode WiFi Setting
const char* defaultWifiMode = "APMode";
const char* defaultSsid = "ORION";
const char* defaultEssKey = "11111111";
String wifiMode;
String ssid;
String essKey;
String channel;
char *sensorModeStr;
int WiFiSet = 0;  // 0 ... normal operation / 1 ... WiFi Setting Mode
WebServer server(80);

void handleRoot(){
  char temp[500];
  snprintf ( temp, 500,
"<html>\
<head>\
<title>WiFiSetting Demo</title>\
<style>\
body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
</style>\
</head>\
<body>\
<h1> WiFiSetting Demo</h1>\
<br> (something contents is here.)\
<hr> \
<a href=\"\/wifiInput\">wifi settings</a> \
</body>\
</html>");
  server.send ( 200, "text/html", temp );
}

void wifiInput() {
  String html = "";
  html += "<h1>WiFi Settings</h1>";
  html += "<form method='post' action='/wifiSet'>";
  html += "  <br>";
  html += "  <input type='text' name='essid' >ESSID<br>";
  html += "  <input type='text' name='key' >KEY(pass)<br>";
  html += "  <br>";
  html += "  <input type='submit'><br>";
  html += "</form>";
  server.send(200, "text/html", html);
}

void wifiSet() {
  String wifiMode = "clientMode";
  String setSsid = server.arg("essid");
  String setKey = server.arg("key");
  String setChannel = server.arg("0");

  File f = SPIFFS.open(settings, "w");
  f.println(wifiMode);
  f.println(setSsid);
  f.println(setKey);
  f.println(channel);
  f.close();

  String html = "";
  html += "<h1>WiFi Settings</h1>";
  html += "ESSID:" + setSsid + "<br>";
  html += "key(pass):" + setKey + "<br>";
  html += "<hr>";
  html += "<h1>Please Reset!</h1>";
  
  server.send(200, "text/html", html);
}

void handleNotFound(){
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  server.send(404, "text/plain", message);
}

void setup(void){
  Serial.begin(115200);
  Serial.println("");
  Serial.println("ESXAR Program Start");
  delay(1000);
  pinMode ( WiFiSetPin, INPUT_PULLUP );
  WiFiSet=digitalRead(WiFiSetPin);
//   init filesystem
  bool res = SPIFFS.begin(true); // FORMAT_SPIFFS_IF_FAILED
  if (!res) {
      Serial.println("SPIFFS.begin fail");
  }
  // check port
  int i;
  delay(1000);
  // settings read
  if ((1 ==digitalRead(WiFiSetPin)) && (1 ==WiFiSet)){
    WiFiSet=1; // boot on default  
  } else {
    WiFiSet=0;
  }
  // set file read
  File fp = SPIFFS.open(settings, "r");
  if (!fp) {
      Serial.println("open error");
  }
  wifiMode = fp.readStringUntil('\n'); // always "clientMode"
  ssid = fp.readStringUntil('\n');
  essKey = fp.readStringUntil('\n');
  channel = fp.readStringUntil('\n');  // no use
  Serial.print("wifiMode:");
  Serial.println(wifiMode);
  Serial.print("ssid:");
  Serial.println(ssid);
  Serial.print("essKey:");
  Serial.println(essKey);
  fp.close();
  wifiMode.trim();
  ssid.trim();
  essKey.trim();
  channel.trim();
  if ( 0 == wifiMode.compareTo("clientMode") ){
  } else if ( 0 == wifiMode.compareTo("APMode") ) {
  } else {
       Serial.print("SPIFFS data seems clash. Default load...");
       wifiMode=defaultWifiMode;
       ssid=defaultSsid;
       essKey=defaultEssKey;
       File f = SPIFFS.open(settings, "w");
       f.println(wifiMode);
       f.println(ssid);
       f.println(essKey);
       f.close();
  }
  if ( 0 == WiFiSet ) { 
    Serial.println("WiFiMode is ON");
    //----------WiFi access point---------
    Serial.println();
    Serial.print("Configuring access point...");
  /* You can remove the password parameter if you want the AP to be open. */
    if ( 0 == wifiMode.compareTo("APMode") ){
      WiFi.softAP(ssid.c_str(), essKey.c_str());
      IPAddress myIP = WiFi.softAPIP();
      Serial.print("AP IP address: ");
      Serial.println(myIP);
    }
    //----- WiFi client --------------
    if ( 0 == wifiMode.compareTo("clientMode") ){
      WiFi.begin(ssid.c_str(), essKey.c_str());
      Serial.println("");
    // Wait for connection
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("");
      Serial.print("Connected to ");
      Serial.println(ssid);
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
    }
  }
  if (1 == WiFiSet) { 
    Serial.println("WiFiMode default boot");
    //----------WiFi access point---------
    Serial.println();
    Serial.print("Configuring access point...");
  /* You can remove the password parameter if you want the AP to be open. */
    WiFi.softAP(defaultSsid, defaultEssKey);
    IPAddress myIP = WiFi.softAPIP();
    Serial.print("AP IP address: ");
    Serial.println(myIP);
  }
  server.on("/",     handleRoot);
  server.on("/wifiInput",  wifiInput);
  server.on("/wifiSet", wifiSet);
  server.onNotFound(handleNotFound);
  server.begin();
  Serial.println("HTTP server started");  
}
void loop(void){
  // Handle incoming connections 
   server.handleClient();
   delay(100);
}
```

2021/02/09追記

シリアルモニタに以下のエラーが出ることがありました。

```

E (462) SPIFFS: mount failed, -10025
```
以下追加すると解消しました。

```

#include <FS.h>
```