ESP32のデータ設定モード作成

こんにちは政井です。今日はESP32の設定についてやっていきます。

ESP32で最初に立ち上げる際に接続先データ等が設定されていないので、それを設定する方法を考えます。

普通は携帯やPCからwifiのアクセスポイントにアクセスして、データを書き換えますね。それを実現しようと思います。

ESP32はアクセスポイントになることができます。

  WiFi.softAP("ESP32_Config");
  IPAddress ip = WiFi.softAPIP();
  Serial.println("AP Mode IP: " + ip.toString());

  server.on("/", handleRoot);
  server.begin();

これを設定がないときに起動させればいいのです。

//APテスト
#include <WiFi.h>
#include <WebServer.h>
#include <DNSServer.h>
#include <Preferences.h>
#include <PubSubClient.h>

Preferences prefs;
DNSServer dnsServer;
WebServer server(80);
WiFiClient espClient;
PubSubClient mqttClient(espClient);

TaskHandle_t webTaskHandle;
TaskHandle_t mqttTaskHandle;
TaskHandle_t ledTaskHandle;

const byte DNS_PORT = 53;
const int LED_PIN = 2; // 内蔵LED

String ssid, pass, mqttServer, devName;

// ===== Webサーバタスク (APモード用) =====
void webTask(void *pvParameters) {
  for (;;) {
    dnsServer.processNextRequest();
    server.handleClient();
    vTaskDelay(10 / portTICK_PERIOD_MS);
  }
}

// ===== MQTTタスク (STAモード用) =====
void mqttTask(void *pvParameters) {
  for (;;) {
    if (!mqttClient.connected()) {
      if (mqttClient.connect(devName.c_str())) {
        Serial.println("MQTT接続成功");
      }
    }
    mqttClient.loop();

    // データ送信例
    String payload = "Hello from " + devName;
    mqttClient.publish("esp32/test", payload.c_str());

    vTaskDelay(5000 / portTICK_PERIOD_MS); // 5秒ごと送信
  }
}

// ===== LEDタスク =====
void ledTask(void *pvParameters) {
  for (;;) {
    if (WiFi.getMode() == WIFI_AP) {
      // APモード → 速い点滅
      digitalWrite(LED_PIN, HIGH);
      vTaskDelay(200 / portTICK_PERIOD_MS);
      digitalWrite(LED_PIN, LOW);
      vTaskDelay(200 / portTICK_PERIOD_MS);
    } else if (WiFi.status() != WL_CONNECTED) {
      // STAモードだが未接続 → ゆっくり点滅
      digitalWrite(LED_PIN, HIGH);
      vTaskDelay(800 / portTICK_PERIOD_MS);
      digitalWrite(LED_PIN, LOW);
      vTaskDelay(800 / portTICK_PERIOD_MS);
    } else {
      // Wi-Fi接続済み → 常時点灯
      digitalWrite(LED_PIN, HIGH);
      vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
  }
}

// ===== APモード起動 (Captive Portal + UTF-8) =====
void startAPMode() {
  WiFi.softAP("ESP32_Config");
  IPAddress ip = WiFi.softAPIP();
  dnsServer.start(DNS_PORT, "*", ip);

  server.on("/", []() {
    String page = "<!DOCTYPE html><html><head><meta charset='UTF-8'></head><body>"
                  "<h1>ESP32 設定ポータル</h1>"
                  "<form action='/set' method='POST'>"
                  "SSID:<input name='ssid'><br>"
                  "PASS:<input name='pass'><br>"
                  "MQTT:<input name='mqtt'><br>"
                  "Device:<input name='dev'><br>"
                  "<button type='submit'>保存</button></form>"
                  "</body></html>";
    server.send(200, "text/html; charset=UTF-8", page);
  });

  server.on("/set", []() {
    ssid = server.arg("ssid");
    pass = server.arg("pass");
    mqttServer = server.arg("mqtt");
    devName = server.arg("dev");

    prefs.begin("config", false);
    prefs.putString("ssid", ssid);
    prefs.putString("pass", pass);
    prefs.putString("mqtt", mqttServer);
    prefs.putString("dev", devName);
    prefs.end();

    server.send(200, "text/plain; charset=UTF-8", "保存しました。再起動してください。");
  });

  server.begin();

  // Webサーバタスク起動
  xTaskCreatePinnedToCore(webTask, "WebTask", 4096, NULL, 1, &webTaskHandle, 1);
}

// ===== STAモード起動 =====
void startSTAMode() {
  WiFi.begin(ssid.c_str(), pass.c_str());
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi接続完了: " + WiFi.localIP().toString());

  mqttClient.setServer(mqttServer.c_str(), 1883);

  // MQTTタスク起動
  xTaskCreatePinnedToCore(mqttTask, "MQTTTask", 4096, NULL, 1, &mqttTaskHandle, 1);
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);

  prefs.begin("config", true);
  ssid = prefs.getString("ssid", "");
  pass = prefs.getString("pass", "");
  mqttServer = prefs.getString("mqtt", "");
  devName = prefs.getString("dev", "esp32");
  prefs.end();

  if (ssid == "" || pass == "") {
    Serial.println("WiFi未設定 → APモード");
    startAPMode();
  } else {
    Serial.println("WiFi設定あり → STAモード");
    startSTAMode();
  }

  // LEDタスクは常時起動
  xTaskCreatePinnedToCore(ledTask, "LedTask", 2048, NULL, 1, &ledTaskHandle, 0);
}

void loop() {
  // メインループは空でOK
}

タイトルとURLをコピーしました