"基于提供的代码差异,本次提交构建了一个完整的IoT项目结构,包含了PlatformIO配置、IDE集成、Web服务器和WiFi管理模块的实现。项目包括但不限于.gitignore文件的配置、PlatformIO环境设置、杂项配置、测试目录结构、发布配置、代码实现等。此次提交确保了项目的初始化设置完整,为后续的物联网应用开发提供了基础。"
This commit is contained in:
commit
9a8162228d
|
@ -0,0 +1 @@
|
|||
.pio
|
|
@ -0,0 +1,8 @@
|
|||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PublishConfigData" remoteFilesAllowedToDisappearOnAutoupload="false">
|
||||
<serverData>
|
||||
<paths name="远程主机 (97a516d3-2dd7-4dd4-a0c4-22619a1f5cc5)">
|
||||
<serverdata>
|
||||
<mappings>
|
||||
<mapping local="$PROJECT_DIR$" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/AsyncUDP/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/WiFiProv/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/Update/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/FS/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/SD/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/FFat/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/ESPmDNS/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/BluetoothSerial/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/WiFiClientSecure/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/HTTPClient/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/Preferences/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/Insights/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/USB/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/HTTPUpdate/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/Ticker/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/NetBIOS/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/I2S/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/LittleFS/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/EEPROM/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/Ethernet/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/DNSServer/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/SD_MMC/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/RainMaker/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/SimpleBLE/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src" web="/" />
|
||||
</mappings>
|
||||
</serverdata>
|
||||
</paths>
|
||||
<paths name="远程主机 (c485ee5d-dc3e-4b5a-b69c-8f964aca0b62)">
|
||||
<serverdata>
|
||||
<mappings>
|
||||
<mapping local="$PROJECT_DIR$" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/AsyncUDP/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/WiFiProv/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/Update/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/FS/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/SD/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/FFat/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/ESPmDNS/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/BluetoothSerial/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/WiFiClientSecure/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/HTTPClient/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/Preferences/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/Insights/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/USB/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/HTTPUpdate/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/Ticker/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/NetBIOS/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/I2S/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/LittleFS/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/EEPROM/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/Ethernet/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/DNSServer/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/SD_MMC/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/RainMaker/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/SimpleBLE/src" web="/" />
|
||||
<mapping local="$USER_HOME$/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src" web="/" />
|
||||
</mappings>
|
||||
</serverdata>
|
||||
</paths>
|
||||
</serverData>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="PlatformIOSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<PlatformioProjectSettings>
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</PlatformioProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
<component name="PlatformIOWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,98 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-cn">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>ESP32-wifi配置页面</title>
|
||||
<style>* {
|
||||
color: #475347;
|
||||
text-shadow: 2px 2px 8px #FFF;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #F3F3F3;
|
||||
padding: 0;
|
||||
margin: 0
|
||||
}
|
||||
|
||||
td {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #FFF;
|
||||
}</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="display: flex;justify-content: center;align-items: center;height: 100vh;width: 100vw;">
|
||||
<div style="text-align: center;position: absolute;top: 15px;left: 0;right: 0;">
|
||||
<h1>ESP32 AP</h1>
|
||||
<h2>wifi配置页面</h2>
|
||||
</div>
|
||||
<div id="content"
|
||||
style="margin-block: 150px;border: none;border-radius: 8px;background-color: #93B874;padding: 10px;">
|
||||
<div style="display: flex;justify-content: space-between;">
|
||||
<h3>选择WIFI:</h3>
|
||||
<button onclick="refresh()" style="height: 40px;margin-top: 10px">刷新
|
||||
<svg style="width: 24px;height: 24px;" viewBox="0 0 1024 1024"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M928 416l-256-6.4 114.688-114.112A347.776 347.776 0 0 0 512 160a352 352 0 1 0 311.872 512H896a416 416 0 1 1-62.016-423.232L923.072 160z"
|
||||
fill="#000"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<table style="width: 450px;max-width: 80vw;border: #475347 1px solid;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>名称</th>
|
||||
<th>信号(RSSI)</th>
|
||||
<th>是否需要密码</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody">
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
const tbody = document.getElementById('tbody');
|
||||
const content = document.getElementById('content');
|
||||
const tableRow = (name, rssi, password_required) => `<tr><td>${name}</td><td>${rssi}</td><td>${password_required ? '是' : '否'}</td><td><button onclick="
|
||||
{
|
||||
if (${password_required}) {
|
||||
const password = prompt('请输入密码');
|
||||
if (password) {
|
||||
fetch('/set?ssid=' + '${name}' + '&password=' + password).then(res => {
|
||||
if (res.ok) {
|
||||
return res.text();
|
||||
}
|
||||
throw new Error('网络请求失败');
|
||||
}).then(async data => {
|
||||
content.innerHTML = await data;
|
||||
}).catch(error => {
|
||||
console.error('网络请求失败:', error)
|
||||
})
|
||||
} else {
|
||||
alert('禁止使用无密码连接!!!');
|
||||
}
|
||||
}
|
||||
}">连接</button></td></tr>`;
|
||||
const refresh = () => {
|
||||
tbody.innerHTML = '<tr><td colspan="4">刷新中...</td></tr>';
|
||||
const controller = new AbortController();// 不超时
|
||||
fetch('/scan', {signal: controller.signal}).then(res => res.json()).then(data => {
|
||||
tbody.innerHTML = '';
|
||||
data.forEach(item => {
|
||||
tbody.innerHTML += tableRow(item.ssid, item.rssi, item.password_required)
|
||||
})
|
||||
}).catch(error => {
|
||||
tbody.innerHTML = '<tr><td colspan="4">请求错误请刷新</td></tr>';
|
||||
})
|
||||
}
|
||||
refresh();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
|
@ -0,0 +1,14 @@
|
|||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:esp32dev]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
framework = arduino
|
|
@ -0,0 +1,13 @@
|
|||
//
|
||||
// Created by wuqiyang on 24-8-9.
|
||||
//
|
||||
#include "nonBlocking.h"
|
||||
|
||||
void runEveryInterval(void (*function)(), unsigned long *previousMillis, long interval) {
|
||||
// 判断当前时间与上一次调用的时间间隔是否达到了设定的间隔时间
|
||||
if (nowMillis - *previousMillis >= interval) {
|
||||
// 如果达到了间隔时间,更新上一次调用的时间为当前时间
|
||||
*previousMillis = nowMillis;
|
||||
function();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
//
|
||||
// Created by wuqiyang on 24-8-9.
|
||||
//
|
||||
|
||||
#ifndef ESPT0_NONBLOCKING_H
|
||||
#define ESPT0_NONBLOCKING_H
|
||||
#include "config.h"
|
||||
|
||||
void runEveryInterval(void (*function)(), unsigned long *previousMillis, long interval);
|
||||
|
||||
#endif //ESPT0_NONBLOCKING_H
|
|
@ -0,0 +1,243 @@
|
|||
//
|
||||
// Created by wuqiyang on 24-8-9.
|
||||
//
|
||||
#include "wifi.h"
|
||||
|
||||
/**
|
||||
* 初始化WiFi连接
|
||||
*/
|
||||
void wifi_init() {
|
||||
#if WIFI_CONFIG_SETUP
|
||||
WiFiClass::mode(WIFI_STA);
|
||||
// 连接到指定的WiFi网络
|
||||
WiFi.begin(ssid, password);
|
||||
// 不断重试
|
||||
while (WiFiClass::status() != WL_CONNECT){
|
||||
delay(1000);
|
||||
Serial.print(".");
|
||||
}
|
||||
#else
|
||||
Preferences preferences;
|
||||
preferences.begin("app-wifi", true);
|
||||
String ssid = preferences.getString("ssid", "");
|
||||
String password = preferences.getString("password", "");
|
||||
preferences.end();
|
||||
|
||||
if (ssid.length() == 0) {
|
||||
// 如果没有设置WiFi信息 打开AP模式
|
||||
wifi_ap_setup();
|
||||
}
|
||||
WiFiClass::mode(WIFI_STA);
|
||||
// 连接到指定的WiFi网络
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
// 重试20次,如果依旧无法连接,则重新初始化Wi-Fi
|
||||
// 循环直到WiFi连接成功
|
||||
for (int i = 0; i < 20; i++) {
|
||||
// 每3秒检查一次WiFi状态,以减少CPU资源消耗
|
||||
delay(3000);
|
||||
Serial.printf("尝试连接WiFi: %s 第%d次\n", ssid.c_str(), i + 1);
|
||||
if (WiFiClass::status() == WL_CONNECTED) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (WiFiClass::status() != WL_CONNECTED) {
|
||||
// 设置WiFi信息为空串
|
||||
wifi_set_ssid_password("", "");
|
||||
// 重启
|
||||
ESP.restart();
|
||||
}
|
||||
#endif
|
||||
Serial.println("\nWiFi connected");
|
||||
IPAddress ip = WiFi.localIP();
|
||||
Serial.printf("IP address: %s \n", ip.toString().c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* wifi_loop函数用于确保Wi-Fi连接状态为已连接。
|
||||
* 如果Wi-Fi连接断开,将重新初始化Wi-Fi。
|
||||
*/
|
||||
void wifi_loop() {
|
||||
// 检查当前Wi-Fi连接状态,如果不处于连接状态,则调用wifi_init函数重新初始化Wi-Fi
|
||||
if (WiFiClass::status() != WL_IDLE_STATUS) {
|
||||
if (WiFiClass::status() != WL_CONNECTED) {
|
||||
wifi_init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前连接情况
|
||||
* 如果没有连接,则返回等待连接成功并返回
|
||||
*/
|
||||
void wifi_get_status() {
|
||||
while (WiFiClass::status() != WL_CONNECTED) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
#if WIFI_CONFIG_SETUP
|
||||
#else
|
||||
|
||||
const byte DNS_PORT = 53;
|
||||
DNSServer dnsServer;
|
||||
WebServer server(80);
|
||||
|
||||
// AP模式下,等待用户输入WiFi信息
|
||||
void wifi_ap_setup() {
|
||||
Serial.println("WiFi AP Mode");
|
||||
WiFiClass::mode(WIFI_AP);
|
||||
WiFi.softAP("ESP_AP", "12345678");
|
||||
IPAddress apIP = WiFi.softAPIP();
|
||||
dnsServer.start(DNS_PORT, "*", apIP);
|
||||
|
||||
server.on("/", []() {
|
||||
server.send(200, "text/html", "<!DOCTYPE html>\n"
|
||||
"<html lang=\"zh-cn\">\n"
|
||||
"<head>\n"
|
||||
" <meta charset=\"UTF-8\">\n"
|
||||
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"
|
||||
" <title>ESP32-wifi配置页面</title>\n"
|
||||
" <style>* {\n"
|
||||
" color: #475347;\n"
|
||||
" text-shadow: 2px 2px 8px #FFF;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" body {\n"
|
||||
" background-color: #F3F3F3;\n"
|
||||
" padding: 0;\n"
|
||||
" margin: 0\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" td {\n"
|
||||
" text-align: center;\n"
|
||||
" vertical-align: middle;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" button {\n"
|
||||
" background-color: #FFF;\n"
|
||||
" }</style>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
"<div style=\"display: flex;justify-content: center;align-items: center;height: 100vh;width: 100vw;\">\n"
|
||||
" <div style=\"text-align: center;position: absolute;top: 15px;left: 0;right: 0;\">\n"
|
||||
" <h1>ESP32 AP</h1>\n"
|
||||
" <h2>wifi配置页面</h2>\n"
|
||||
" </div>\n"
|
||||
" <div id=\"content\"\n"
|
||||
" style=\"margin-block: 150px;border: none;border-radius: 8px;background-color: #93B874;padding: 10px;\">\n"
|
||||
" <div style=\"display: flex;justify-content: space-between;\">\n"
|
||||
" <h3>选择WIFI:</h3>\n"
|
||||
" <button onclick=\"refresh()\" style=\"height: 40px;margin-top: 10px\">刷新\n"
|
||||
" <svg style=\"width: 24px;height: 24px;\" viewBox=\"0 0 1024 1024\"\n"
|
||||
" xmlns=\"http://www.w3.org/2000/svg\">\n"
|
||||
" <path d=\"M928 416l-256-6.4 114.688-114.112A347.776 347.776 0 0 0 512 160a352 352 0 1 0 311.872 512H896a416 416 0 1 1-62.016-423.232L923.072 160z\"\n"
|
||||
" fill=\"#000\"></path>\n"
|
||||
" </svg>\n"
|
||||
" </button>\n"
|
||||
" </div>\n"
|
||||
" <table style=\"width: 450px;max-width: 80vw;border: #475347 1px solid;\">\n"
|
||||
" <thead>\n"
|
||||
" <tr>\n"
|
||||
" <th>名称</th>\n"
|
||||
" <th>信号(RSSI)</th>\n"
|
||||
" <th>是否需要密码</th>\n"
|
||||
" <th>操作</th>\n"
|
||||
" </tr>\n"
|
||||
" </thead>\n"
|
||||
" <tbody id=\"tbody\">\n"
|
||||
" </tbody>\n"
|
||||
"\n"
|
||||
" </table>\n"
|
||||
" </div>\n"
|
||||
"</div>\n"
|
||||
"<script>\n"
|
||||
" const tbody = document.getElementById('tbody');\n"
|
||||
" const content = document.getElementById('content');\n"
|
||||
" const tableRow = (name, rssi, password_required) => `<tr><td>${name}</td><td>${rssi}</td><td>${password_required ? '是' : '否'}</td><td><button onclick=\"\n"
|
||||
" {\n"
|
||||
" if (${password_required}) {\n"
|
||||
" const password = prompt('请输入密码');\n"
|
||||
" if (password) {\n"
|
||||
" fetch('/set?ssid=' + '${name}' + '&password=' + password).then(res => {\n"
|
||||
" if (res.ok) {\n"
|
||||
" return res.text();\n"
|
||||
" }\n"
|
||||
" throw new Error('网络请求失败');\n"
|
||||
" }).then(async data => {\n"
|
||||
" content.innerHTML = await data;\n"
|
||||
" }).catch(error => {\n"
|
||||
" console.error('网络请求失败:', error)\n"
|
||||
" })\n"
|
||||
" } else {\n"
|
||||
" alert('禁止使用无密码连接!!!');\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\">连接</button></td></tr>`;\n"
|
||||
" const refresh = () => {\n"
|
||||
" tbody.innerHTML = '<tr><td colspan=\"4\">刷新中...</td></tr>';\n"
|
||||
" const controller = new AbortController();// 不超时\n"
|
||||
" fetch('/scan', {signal: controller.signal}).then(res => res.json()).then(data => {\n"
|
||||
" tbody.innerHTML = '';\n"
|
||||
" data.forEach(item => {\n"
|
||||
" tbody.innerHTML += tableRow(item.ssid, item.rssi, item.password_required)\n"
|
||||
" })\n"
|
||||
" }).catch(error => {\n"
|
||||
" tbody.innerHTML = '<tr><td colspan=\"4\">请求错误请刷新</td></tr>';\n"
|
||||
" })\n"
|
||||
" }\n"
|
||||
" refresh();\n"
|
||||
"</script>\n"
|
||||
"</body>\n"
|
||||
"</html>");
|
||||
});
|
||||
server.on("/scan", []() {
|
||||
String json = "[";
|
||||
for (int i = 0; i < WiFi.scanNetworks(); i++) {
|
||||
if (i) {
|
||||
json += ",";
|
||||
}
|
||||
json += R"({"ssid":")" + WiFi.SSID(i) + R"(","rssi":")" + WiFi.RSSI(i) + R"(","password_required":)" +
|
||||
(WiFi.encryptionType(i) != WIFI_AUTH_OPEN ? "true" : "false") + "}";
|
||||
}
|
||||
json += "]";
|
||||
server.send(200, "application/json", json);
|
||||
});
|
||||
server.on("/set", []() {
|
||||
String ssid = server.arg("ssid");
|
||||
String password = server.arg("password");
|
||||
if (ssid.length() > 0 && password.length() > 0) {
|
||||
wifi_set_ssid_password(ssid, password);
|
||||
server.send(200, "text/html", "<h1>WiFi设置成功</h1><p>重新启动ESP32中</p>");
|
||||
delay(500);
|
||||
ESP.restart();
|
||||
} else {
|
||||
server.send(200, "text/html", "<h1>WiFi设置失败</h1><p>请重新输入WiFi信息。</p>");
|
||||
}
|
||||
});
|
||||
server.onNotFound([]() {
|
||||
server.sendHeader("Location", "/", true); // true参数表示进行301永久重定向
|
||||
server.send(302, "text/plain", "Redirecting to /");
|
||||
});
|
||||
|
||||
server.begin();
|
||||
Serial.println("HTTP server started");
|
||||
while (true) {
|
||||
dnsServer.processNextRequest();
|
||||
server.handleClient();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置wifi的ssid和password
|
||||
*/
|
||||
void wifi_set_ssid_password(const String &ssid, const String &password) {
|
||||
Preferences preferences;
|
||||
preferences.begin("app-wifi", false);
|
||||
preferences.putString("ssid", ssid);
|
||||
preferences.putString("password", password);
|
||||
preferences.end();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Created by wuqiyang on 24-8-9.
|
||||
//
|
||||
|
||||
#ifndef ESPT0_WIFI_H
|
||||
#define ESPT0_WIFI_H
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <Preferences.h>
|
||||
#include "config.h"
|
||||
|
||||
void wifi_init();
|
||||
|
||||
void wifi_loop();
|
||||
|
||||
void wifi_get_status();
|
||||
|
||||
// 根据编译条件配置WIFI设置
|
||||
#if WIFI_CONFIG_SETUP
|
||||
#else
|
||||
|
||||
#include <DNSServer.h>
|
||||
#include <WebServer.h>
|
||||
|
||||
void wifi_set_ssid_password(const String &ssid, const String &password);
|
||||
|
||||
// 初始化Wi-Fi AP模式的设置
|
||||
void wifi_ap_setup();
|
||||
|
||||
#endif
|
||||
|
||||
#endif //ESPT0_WIFI_H
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// Created by wuqiyang on 24-8-9.
|
||||
//
|
||||
#include <WebServer.h>
|
||||
#include <DNSServer.h>
|
||||
#include "config.h"
|
||||
|
||||
// 当前毫秒数
|
||||
unsigned long nowMillis;
|
||||
|
||||
// 串口
|
||||
const int serialBaud = 9600;
|
||||
|
||||
// wifi
|
||||
unsigned long wifiLoopMillis;
|
||||
#if WIFI_CONFIG_SETUP
|
||||
const String ssid = "debian-wqy";
|
||||
const String password = "qwq@wuqiyang";
|
||||
#endif
|
||||
void setupParameter() {
|
||||
Serial.begin(serialBaud);
|
||||
Serial.println("Hallo");
|
||||
wifiLoopMillis = millis();
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// Created by wuqiyang on 24-8-9.
|
||||
//
|
||||
|
||||
// wifi 设置默认信息 固定配网=1 动态配网=0
|
||||
#define WIFI_CONFIG_SETUP 0
|
||||
|
||||
#ifndef ESPT0_CONFIG_H
|
||||
#define ESPT0_CONFIG_H
|
||||
|
||||
#include <WString.h>
|
||||
#include "main.h"
|
||||
|
||||
extern unsigned long nowMillis;
|
||||
extern const int serialBaud;
|
||||
|
||||
// wifi
|
||||
extern unsigned long wifiLoopMillis;
|
||||
// 根据WIFI_CONFIG_SETUP宏的定义情况,声明全局常量字符串ssid和password
|
||||
#if WIFI_CONFIG_SETUP
|
||||
extern const String ssid;
|
||||
extern const String password;
|
||||
#endif
|
||||
|
||||
|
||||
void setupParameter();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,15 @@
|
|||
#include "main.h"
|
||||
#include "config.h"
|
||||
#include "component/nonBlocking.h"
|
||||
#include "component/wifi.h"
|
||||
|
||||
void setup() {
|
||||
setupParameter();
|
||||
// wifi
|
||||
wifi_init();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
nowMillis = millis();
|
||||
runEveryInterval(wifi_loop, &wifiLoopMillis, 1000);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
//
|
||||
// Created by wuqiyang on 24-8-9.
|
||||
//
|
||||
|
||||
#ifndef ESPT0_MAIN_H
|
||||
#define ESPT0_MAIN_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#endif //ESPT0_MAIN_H
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
This directory is intended for PlatformIO Test Runner and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
Loading…
Reference in New Issue