"基于提供的代码差异,本次提交构建了一个完整的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