> 技术文档 > ESP8266开发板Web配网代码实现指南_esp8266 web配网

ESP8266开发板Web配网代码实现指南_esp8266 web配网

网上看到类似用web页面实现esp8266AP热点实现wifi配网,先将代码分享大家交流学习,已测试可用

功能特点

  1. 完整的Web配网功能

    • 自动创建配置AP

    • 手机连接后自动跳转配置页面

    • WiFi网络扫描与选择

    • 配置保存与自动连接

  2. 多页面导航

    • WiFi配置页面

    • 设备信息页面(实时显示状态

    • 重置设置页面

  3. LED状态指示

    • 未配置:亮1秒,灭3秒

    • 已配置未连接:0.5秒快速闪烁

    • 已连接:常亮

  4. 中文支持

    • 完整的中文界面

    • 解决乱码问题

  5. 设备信息显示

    • 实时显示设备状态

    • 显示网络连接信息

    • 显示运行时间和固件版本

注意事项

  1. 需要添加DNSServer库(通常随ESP8266核心一起安装)

  2. 某些手机可能需要手动打开浏览器才能触发自动跳转

  3. 对于iOS设备,可能需要用户点击\"登录网络\"提示才能打开配置页面

  4. 成功连接WiFi后,可以通过串口监视器查看设备获取的IP地址,用于后续访问

这个优化版本实现了类似视频中的自动跳转功能,大大提升了用户体验,使配网过程更加直观和便捷。

===========以下为源代码部分======================================== 

//2025-4-11 东边日出 web实现配wifi#include #include #include #include #include #include #define LED_PIN 2#define EEPROM_SIZE 512ESP8266WebServer server(80);DNSServer dnsServer;struct WiFiConfig { char ssid[32]; char password[64];};enum WiFiConfigState { CONFIG_NOT_SET, CONFIG_SET_BUT_NOT_CONNECTED, CONFIG_SET_AND_CONNECTED};WiFiConfigState configState = CONFIG_NOT_SET;unsigned long lastScanTime = 0;String wifiScanResults;const char* htmlHeader = R\"=====(   ESP8266 配置页面  body { font-family: Arial, sans-serif; margin: 0; padding: 0; background-color: #f5f5f5; } .container { max-width: 600px; margin: 20px auto; padding: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } h1 { text-align: center; color: #444; margin-bottom: 30px; } .nav { display: flex; justify-content: space-around; margin-bottom: 20px; } .nav button { padding: 10px 15px; border: none; border-radius: 4px; background: #4CAF50; color: white; cursor: pointer; font-size: 16px; } .nav button:hover { background: #45a049; } .form-group { margin-bottom: 15px; } label { display: block; margin-bottom: 5px; font-weight: bold; } input, select { width: 100%; padding: 10px; box-sizing: border-box; border: 1px solid #ddd; border-radius: 4px; } button[type=\"submit\"] { background: #2196F3; color: white; padding: 12px 15px; border: none; border-radius: 4px; cursor: pointer; width: 100%; font-size: 16px; } button[type=\"submit\"]:hover { background: #0b7dda; } .status { margin-top: 20px; padding: 15px; border-radius: 4px; } .success { background: #dff0d8; color: #3c763d; } .error { background: #f2dede; color: #a94442; } .info { background: #d9edf7; color: #31708f; } .hidden { display: none; } #wifiList { margin-bottom: 15px; } #manualSSID { margin-top: 15px; } .device-info p { margin: 10px 0; } .reset-btn { background: #f44336 !important; } .reset-btn:hover { background: #d32f2f !important; }  

ESP8266 设备配置

)=====\";const char* htmlFooter = R\"=====(
function showTab(tabId) { document.querySelectorAll(\'.tab-content\').forEach(tab => { tab.classList.add(\'hidden\'); }); document.getElementById(tabId).classList.remove(\'hidden\'); } function scanWifi() { fetch(\'/scan\') .then(response => response.json()) .then(data => { const select = document.getElementById(\'wifiList\'); select.innerHTML = \'选择WiFi网络...\'; data.forEach(wifi => { const option = document.createElement(\'option\'); option.value = wifi.ssid; option.textContent = wifi.ssid + \' (\' + wifi.rssi + \'dBm)\'; select.appendChild(option); }); }); } function toggleManualSSID() { const manualDiv = document.getElementById(\'manualSSID\'); const wifiList = document.getElementById(\'wifiList\'); if(wifiList.value === \'\') { manualDiv.style.display = \'block\'; } else { manualDiv.style.display = \'none\'; document.getElementById(\'ssid\').value = wifiList.value; } } // 初始显示WiFi配置页 window.onload = function() { showTab(\'wifiConfig\'); scanWifi(); }; )=====\";const char* wifiConfigPage = R\"=====(
)=====\";const char* deviceInfoPage = R\"=====()=====\";const char* resetPage = R\"=====()=====\";void setup() { Serial.begin(115200); delay(10); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); EEPROM.begin(EEPROM_SIZE); WiFiConfig config; EEPROM.get(0, config); if (config.ssid[0] != \'\\0\') { Serial.println(\"读取到保存的WiFi配置:\"); Serial.print(\"SSID: \"); Serial.println(config.ssid); connectToWiFi(config.ssid, config.password); } else { Serial.println(\"没有找到保存的WiFi配置\"); configState = CONFIG_NOT_SET; } if (WiFi.status() != WL_CONNECTED) { startConfigPortal(); } setupServer(); Serial.println(\"HTTP服务器已启动\");}void loop() { server.handleClient(); if (configState != CONFIG_SET_AND_CONNECTED) { dnsServer.processNextRequest(); } handleLED();}void setupServer() { server.on(\"/\", HTTP_GET, []() { String page = htmlHeader; page += wifiConfigPage; page += generateDeviceInfoPage(); page += resetPage; page += htmlFooter; server.send(200, \"text/html; charset=UTF-8\", page); }); server.on(\"/scan\", HTTP_GET, []() { scanWiFiNetworks(); server.send(200, \"application/json\", wifiScanResults); }); server.on(\"/config\", HTTP_POST, []() { String ssid = server.arg(\"ssid\"); String password = server.arg(\"password\"); WiFiConfig config; strncpy(config.ssid, ssid.c_str(), sizeof(config.ssid)); strncpy(config.password, password.c_str(), sizeof(config.password)); EEPROM.put(0, config); EEPROM.commit(); String response; if (connectToWiFi(config.ssid, config.password)) { response = \"配置保存成功,已连接到WiFi!\"; } else { configState = CONFIG_SET_BUT_NOT_CONNECTED; response = \"配置保存成功,但连接WiFi失败,请检查网络设置。\"; } String page = htmlHeader; page += wifiConfigPage; page += generateDeviceInfoPage(); page += resetPage; page += htmlFooter; page += \"document.getElementById(\'status\').className = \'status \"; page += WiFi.status() == WL_CONNECTED ? \"success\' style=\'display:block\'>\" + response : \"error\' style=\'display:block\'>\" + response; page += \"\"; server.send(200, \"text/html; charset=UTF-8\", page); }); server.on(\"/reset\", HTTP_POST, []() { resetDevice(); String page = htmlHeader; page += wifiConfigPage; page += generateDeviceInfoPage(); page += resetPage; page += htmlFooter; page += \"document.getElementById(\'resetStatus\').className = \'status success\' style=\'display:block\'>设备已重置成功!\"; server.send(200, \"text/html; charset=UTF-8\", page); }); server.on(\"/info\", HTTP_GET, []() { String page = htmlHeader; page += wifiConfigPage; page += generateDeviceInfoPage(); page += resetPage; page += htmlFooter; server.send(200, \"text/html; charset=UTF-8\", page); }); server.onNotFound([]() { server.sendHeader(\"Location\", \"http://192.168.4.1\", true); server.send(302, \"text/plain\", \"\"); }); server.begin();}String generateDeviceInfoPage() { String infoPage = deviceInfoPage; WiFiConfig config; EEPROM.get(0, config); infoPage.replace(\"%DEVICE_ID%\", String(ESP.getChipId(), HEX)); infoPage.replace(\"%CONFIG_STATE%\", getConfigStateString()); infoPage.replace(\"%WIFI_STATUS%\", getWiFiStatusString()); infoPage.replace(\"%CONFIG_SSID%\", config.ssid[0] == \'\\0\' ? \"未配置\" : String(config.ssid)); infoPage.replace(\"%IP_ADDRESS%\", WiFi.localIP().toString()); infoPage.replace(\"%MAC_ADDRESS%\", WiFi.macAddress()); infoPage.replace(\"%UPTIME%\", String(millis() / 1000)); return infoPage;}bool connectToWiFi(const char* ssid, const char* password) { Serial.print(\"正在连接WiFi: \"); Serial.println(ssid); WiFi.begin(ssid, password); int attempts = 0; while (WiFi.status() != WL_CONNECTED && attempts 10000 || wifiScanResults.length() == 0) { Serial.println(\"开始扫描WiFi网络...\"); int n = WiFi.scanNetworks(); Serial.println(\"扫描完成\"); wifiScanResults = \"[\"; for (int i = 0; i = (ledState ? 3000 : 1000)) { ledState = !ledState; digitalWrite(LED_PIN, ledState ? HIGH : LOW); lastBlinkTime = millis(); } break; case CONFIG_SET_BUT_NOT_CONNECTED: if (millis() - lastBlinkTime >= 500) { ledState = !ledState; digitalWrite(LED_PIN, ledState ? HIGH : LOW); lastBlinkTime = millis(); } break; case CONFIG_SET_AND_CONNECTED: digitalWrite(LED_PIN, LOW); break; }}String getConfigStateString() { switch (configState) { case CONFIG_NOT_SET: return \"未配置\"; case CONFIG_SET_BUT_NOT_CONNECTED: return \"已配置但未连接\"; case CONFIG_SET_AND_CONNECTED: return \"已配置并连接\"; default: return \"未知状态\"; }}String getWiFiStatusString() { switch (WiFi.status()) { case WL_IDLE_STATUS: return \"空闲\"; case WL_NO_SSID_AVAIL: return \"SSID不可用\"; case WL_SCAN_COMPLETED: return \"扫描完成\"; case WL_CONNECTED: return \"已连接\"; case WL_CONNECT_FAILED: return \"连接失败\"; case WL_CONNECTION_LOST: return \"连接丢失\"; case WL_DISCONNECTED: return \"未连接\"; default: return \"未知状态\"; }}