Captive PortalをESP32やRaspberry Pi Pico WでSoftAPを使用して実装!

投稿者: | 8月 29, 2024

追記

ライブラリにまとめて、公開しました。
Arduino(ESP32,ESP8266,Raspberry Pi Pico W)にてCaptive Portalを利用してWiFiを設定するライブラリ
GitHub
ArduinoIDE_Captive_Portal_WiFi_configure

はじめに

ESP32でSoftAPモードで起動し、WebページでWiFiのSSIDとパスワードを入力すると、再起動して自動でそのWiFiに接続する、という物を作ろうとしたときの途中経過で発生した副産物です。

Captive Portalとは

フリーWiFiに接続すると、自動でログインページに飛ばされてメールアドレスの入力をさせられたりします。この、ログインページに飛ばす機能がCaptive Portalです。
すべてのDNSリクエストに対してAP(ESP32)のIPアドレスを返すことで実行できます。
ESP32のようなものだと、WiFiで接続して操作する感じのHtmlベースのコントローラや、WiFiネットワークに接続する際のSSIDの選択とパスワードの入力に使えると思います。

コード

ArduinoIDEでのコードです。

#include <WiFi.h>
#include <WebServer.h>
#include <DNSServer.h>

WebServer server(80);
DNSServer dnsServer;

const char* ssid = "Arduino-Access-Point";
//const char* password = "123456789";

const char* htmlResponse = "<!DOCTYPE html>\
<html>\
<head><title>Arduino SoftAP</title></head>\
<body>\
<h2>Welcome to Arduino SoftAP with Captive Portal!</h2>\
<p>This is a simple web page served by Arduino in Access Point mode.</p>\
<a href=\"https://unagidojyou.com/2024/03-22/esp32_captive-portal/\">Unagi Dojyou</a>\
</body>\
</html>";

void handleRoot() {
  server.send(200, "text/html", htmlResponse);
}

void handleNotFound() {
  String IPaddr = ipToString(server.client().localIP());
  server.sendHeader("Location", String("http://") + IPaddr, true);
  server.send(302, "text/plain", "");
  server.client().stop();
}

// https://qiita.com/dojyorin/items/ac56a1c2c620782d90a6
String ipToString(uint32_t ip) {
  String result = "";
  result += String((ip & 0xFF), 10);
  result += ".";
  result += String((ip & 0xFF00) >> 8, 10);
  result += ".";
  result += String((ip & 0xFF0000) >> 16, 10);
  result += ".";
  result += String((ip & 0xFF000000) >> 24, 10);
  return result;
}

void setup() {
  WiFi.softAP(ssid);
  //WiFi.softAP(ssid,password);
  server.on("/", HTTP_GET, handleRoot);
  server.onNotFound(handleNotFound);

  dnsServer.start(53, "*", WiFi.softAPIP());
  server.begin();
}

void loop() {
  server.handleClient();
  dnsServer.processNextRequest();
}

使い方

const char* ssid = "ESP32-Access-Point";

でSSIDを指定できます。
接続する際にパスワードを設定したい場合は

//const char* password = "123456789";
//WiFi.softAP(ssid,password);

のコメントアウトを外して、

WiFi.softAP(ssid);

をコメントアウトしてください。
const char* htmlResponseの内容を変えることで表示する内容を変更できます。
文章の入力や、ボタンの設置を行いたい場合は、WebServerのハンドルを増やせばできます。めんどいのでここには詳しい方法は書きません。WebServer.hの使い方を調べれば出てくると思います。

おわりに

比較的短くて簡単なコードですが、DNSServer.hとWebServer.hが激重でこれだけでフラッシュの55%も食います。他にいろいろ機能をつけるとフラッシュの容量が足りなくなりそうです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)