#include <WiFiProv.h>
#include <U8g2lib.h>
// --- OLED設定 ---
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
// --- I2Cピン設定 ---
#define I2C_SDA 21
#define I2C_SCL 22
// --- リセットボタンピン ---
#define RESET_BUTTON_PIN 0 // BOOTボタン(GPIO 0)
// --- プロビジョニング設定 ---
const char* service_name = "PROV_ESP32"; // BLEデバイス名
const char* service_key = NULL; // BLEでは不要
const char* pop = "abcd1234"; // Proof of Possession
uint8_t uuid[16] = {0}; // カスタムUUID(0=デフォルト使用)
// --- 状態変数 ---
bool isProvisioningDone = false;
bool isWiFiConnected = false;
bool isBLEActive = false;
// -----------------------------------------------------
// -----------------------------------------------------
void resetWiFiSettings() {
Serial.println("\n=== Resetting WiFi Settings ===");
showStatus("Resetting...");
delay(100);
WiFi.disconnect(true, true);
delay(1000);
Serial.println("WiFi settings cleared!");
Serial.println("Restarting ESP32...");
showStatus("Restarting...");
delay(2000);
ESP.restart();
}
// -----------------------------------------------------
// 画面表示ヘルパー関数
// -----------------------------------------------------
void showStatus(const char* message) {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_7x13_tf);
const int lineHeight = 14;
int y = lineHeight;
u8g2.drawStr(0, y, "--- Status ---");
y += lineHeight;
u8g2.drawStr(0, y, message);
y += lineHeight;
y += 2;
if(isBLEActive) {
u8g2.drawStr(0, y, "BLE: Active");
y += lineHeight;
u8g2.drawStr(0, y, service_name);
} else if(isWiFiConnected) {
u8g2.drawStr(0, y, "WiFi: OK");
y += lineHeight;
String ip = "IP:" + WiFi.localIP().toString();
u8g2.drawStr(0, y, ip.c_str());
} else {
u8g2.drawStr(0, y, "Waiting...");
}
u8g2.sendBuffer();
}
// -----------------------------------------------------
// -----------------------------------------------------
void SysProvEvent(arduino_event_t *sys_event) {
switch (sys_event->event_id) {
Serial.println(">>> Provisioning initialized");
break;
Serial.println("\n========================================");
Serial.println(">>> BLE PROVISIONING STARTED!");
Serial.println("========================================");
Serial.print("Device Name: ");
Serial.println(service_name);
Serial.print("PoP (Proof of Possession): ");
Serial.println(pop);
Serial.println();
Serial.println("Instructions:");
Serial.println("1. Open 'ESP BLE Provisioning' app");
Serial.println("2. Tap 'Provision New Device'");
Serial.println("3. Select 'I don't have a QR code'");
Serial.println("5. Select 'PROV_ESP32'");
Serial.println("6. Enter PoP: abcd1234");
Serial.println("7. Select your WiFi network");
Serial.println("========================================\n");
isBLEActive = true;
showStatus("BLE Active!");
break;
Serial.println(">>> Credentials received!");
Serial.println(WiFi.localIP());
Serial.print(" RSSI: ");
Serial.print(WiFi.RSSI());
Serial.println(" dBm");
isWiFiConnected = true;
showStatus("Connected!");
break;
default:
break;
}
}
// -----------------------------------------------------
// Setup
// -----------------------------------------------------
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n\n");
Serial.println("========================================");
Serial.println(" ESP32 BLE WiFi Provisioning");
Serial.println("========================================");
Serial.println();
// リセットボタンの設定
pinMode(RESET_BUTTON_PIN, INPUT_PULLUP);
// I2C初期化
Wire.begin(I2C_SDA, I2C_SCL);
// OLED初期化
if (!u8g2.begin()) {
Serial.println("ERROR: OLED initialization failed!");
while(1) delay(1000);
}
u8g2.setFlipMode(0);
showStatus("Booting...");
delay(1000);
// BOOTボタン長押しでリセット(起動後5秒以内)
Serial.println("Press BOOT button (3 sec) to reset WiFi");
showStatus("BOOT=Reset");
unsigned long checkStart = millis();
while(millis() - checkStart < 5000) {
if(digitalRead(RESET_BUTTON_PIN) == LOW) {
unsigned long pressStart = millis();
while(digitalRead(RESET_BUTTON_PIN) == LOW) {
if(millis() - pressStart > 3000) {
Serial.println("\n>>> Reset button pressed!");
resetWiFiSettings();
}
delay(50);
}
}
delay(50);
}
WiFi.onEvent(SysProvEvent);
Serial.println("--- WiFi Diagnostic Info ---");
Serial.print("WiFi Mode: ");
Serial.println(WiFi.getMode());
Serial.print("Saved SSID: '");
Serial.println("'");
Serial.print("SSID Length: ");
Serial.println("---------------------------\n");
// 既存の設定があるかチェック
Serial.println("!!! Found saved WiFi credentials !!!");
Serial.println("Press BOOT button to reset (3 sec)");
showStatus("Old WiFi Found");
// リセットの機会を与える(3秒)
checkStart = millis();
while(millis() - checkStart < 3000) {
if(digitalRead(RESET_BUTTON_PIN) == LOW) {
unsigned long pressStart = millis();
while(digitalRead(RESET_BUTTON_PIN) == LOW) {
if(millis() - pressStart > 3000) {
resetWiFiSettings();
}
delay(50);
}
}
delay(50);
}
Serial.println("Connecting with saved credentials...");
showStatus("Connecting WiFi");
isProvisioningDone = true;
} else {
// BLEプロビジョニング開始
Serial.println("No saved credentials found");
Serial.println("\n========================================");
Serial.println(" STARTING BLE PROVISIONING");
Serial.println("========================================\n");
showStatus("Init BLE...");
delay(500);
delay(500);
Serial.println("Initializing BLE provisioning...");
// ★重要: NETWORK_PROV_SCHEME_HANDLER_FREE_BTDMを使用
WiFiProv.beginProvision(
NETWORK_PROV_SCHEME_HANDLER_NONE, // ここを変更
NETWORK_PROV_SECURITY_1,
pop,
service_name,
service_key,
NULL // uuidはデフォルトを使用するためNULL推奨
// uuid
);
Serial.println(">>> BLE provisioning initiated!");
Serial.println(">>> Waiting for PROV_START event...\n");
}
}
// -----------------------------------------------------
// Loop
// -----------------------------------------------------
void loop() {
// BOOTボタン監視(常時)
static unsigned long buttonPressStart = 0;
if(digitalRead(RESET_BUTTON_PIN) == LOW) {
if(buttonPressStart == 0) {
buttonPressStart = millis();
} else if(millis() - buttonPressStart > 3000) {
Serial.println("\n>>> Resetting WiFi (BOOT pressed)...");
resetWiFiSettings();
}
} else {
buttonPressStart = 0;
}
// BLE待機中のステータス表示
if(isBLEActive) {
static unsigned long lastMsg = 0;
if(millis() - lastMsg > 10000) {
Serial.println("\n[BLE] Waiting for smartphone...");
Serial.print(" Device: ");
Serial.println(service_name);
Serial.print(" PoP: ");
Serial.println(pop);
Serial.println();
lastMsg = millis();
}
}
if(isProvisioningDone && isWiFiConnected) {
static unsigned long lastUpdate = 0;
if(millis() - lastUpdate > 5000) {
showStatus("Connected!");
lastUpdate = millis();
}
}
delay(100);
}