至强ESP8266Web配网,利用FS闪存文件系统+EEPROM记录配网信息和相关参数设定
FS闪存文件系统和EEPROM的使用时二选一的,可以任意一种作为你的备选存储相关参数的方案来实施。
每个人的个性化需求不一样,可以根据个人的需求做相关的移植即可,已经相当精简,内容只涉及配网和存储案例参数设定的,移植也非常方便。
EEPROM读写函数都是现成写好的,直接拿来使用即可,比起自己来写的话,不一定能写出这么优秀无bug的代码,站在巨人的肩膀上实现自己的小目标要比一个人摸索要快捷省力,而且高效,容易得多。
注意事项:利用闪存文件系统配置,上传完程序后,再点击工具-esp8266 Sketch Date Upload上传配置后,才可以打开相关的Web配置页面,进行配置,
本代码已经成功验证,并且反复断电,验证读取FS和EEPROM是否正确。
配网页面大同小异,如下图:
配置完成后,串口打印信息:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <FS.h> //闪存文件系统
#include <ArduinoJson.h>//json数据处理库(第三方)
#include <EEPROM.h>
#define button D8 //设置手动清除FS闪存内容按键,loop里面已注释,未开启。
String ssid,password,location0,apikey0;
ESP8266WebServer server(80); //创建Web服务端口为80
void setup() {
pinMode(LED_BUILTIN, OUTPUT);//板载led
pinMode(button,INPUT);
digitalWrite(button,HIGH);
Serial.begin(115200);
EEPROM.begin(1024);
Serial.println("以下为EEPROM读取的信息:");
String count=Read_String(EEPROM.read(800),816);
delay(50);
Serial.println(count);
String pass=Read_String(EEPROM.read(804),856);
delay(50);
Serial.println(pass);
String loca= Read_String(EEPROM.read(808),884);
delay(50);
Serial.println(loca);
String api=Read_String(EEPROM.read(812),932);
delay(50);
Serial.println(api);
//Serial.println("");
if (SPIFFS.begin()) { // 打开闪存文件系统,记得在你连接板子下载的过程中选Flash Size的时候不要选no SPIFFS,你可以选1M、2M、3M都无所谓,因为两个文件都很小
Serial.println("闪存文件系统打开成功");
} else {
Serial.println("闪存文件系统打开失败");
}
if (SPIFFS.exists("/config.json")) { // 判断有没有config.json这个文件
Serial.println("存在配置信息,正在自动连接");
const size_t capacity = JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + 156; //分配一个内存空间
DynamicJsonDocument doc(capacity);// 声明json处理对象
File configJson = SPIFFS.open("/config.json", "r");
deserializeJson(doc, configJson); // json数据序列化
const char* ssid = doc["ssid"];
Serial.println(ssid);
const char* password = doc["password"];
Serial.println(password);
const char* location = doc["location0"];
Serial.println(location);
const char* apikey = doc["apikey0"];
Serial.println(apikey);
WiFi.mode(WIFI_STA); // 更换wifi模式
//WiFi.mode(WIFI_AP_STA);//设置模式为AP+STA
digitalWrite(LED_BUILTIN, HIGH);
WiFi.begin(ssid, password); // 连接wifi
Serial.println("AP设置完成");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
configJson.close();
Serial.println(WiFi.localIP());
} else {
Serial.println("不存在配置信息,正在打开web配网模式");
IPAddress softLocal(192, 168, 1, 1);
IPAddress softGateway(192, 168, 1, 1);
IPAddress softSubnet(255, 255, 255, 0);
WiFi.softAPConfig(softLocal, softGateway, softSubnet);
WiFi.softAP("esp8266", "12345678"); //这里是配网模式下热点的名字和密码
Serial.println(WiFi.softAPIP());
}
server.on("/", handleRoot);//web首页监听
server.on("/set", handleConnect); // 配置ssid密码监听,感觉跟express的路由好像
server.begin();
}
void loop() {
server.handleClient();
// if (digitalRead(button) == 0) { //按键扫描,开启后,会监测按键是否按下,按下后,将会清楚FS闪存,下次重启将进入配网。
// removeConfig();
// }
}
void handleRoot() { //展示网页的关键代码
if (SPIFFS.exists("/index.html")) {
File index = SPIFFS.open("/index.html", "r");
server.streamFile(index, "text/html");
index.close();
}
}
void handleConnect() { //处理配置信息的函数
ssid = server.arg("ssid"); //arg是获取请求参数
password = server.arg("password");
location0 = server.arg("location"); //从JavaScript发送的数据中找laction的值
apikey0 = server.arg("apikey"); //从JavaScript发送的数据中找apikey的值
EEPROM.begin(1024);
Serial.println(ssid);
Write_String(800,816,ssid);
delay(30);
Serial.println(password);
Write_String(804,856,password);
delay(30);
Serial.println(location0);
Write_String(808,884,location0);
delay(30);
Serial.println(apikey0);
Write_String(812,932,apikey0);
delay(30);
server.send(300, "text/plain", "OK");
WiFi.mode(WIFI_STA); //改变wifi模式
WiFi.begin(ssid.c_str(), password.c_str());//String类型直接用会报错,不要问为什么,转成char *就行了。
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(WiFi.localIP());
removeConfig(); // 不管有没有配置先删除一次再说。
String payload; // 拼接构造一段字符串形式的json数据长{"ssid":"xxxxx","password":"xxxxxxxxxxx"}
payload += "{\"ssid\":\"";
payload += ssid;
payload += "\",\"password\":\"";
payload += password;
payload += "\",\"location0\":\"";
payload += location0;
payload += "\",\"apikey0\":\"";
payload += apikey0;
payload += "\"}";
File wifiConfig = SPIFFS.open("/config.json", "w");
wifiConfig.println(payload);//将数据写入config.json文件中
wifiConfig.close();
}
void removeConfig() {
if (SPIFFS.exists("/config.json")) { // 判断有没有config.json这个文件
if (SPIFFS.remove("/config.json")) {
Serial.println("删除旧配置");
} else {
Serial.println("删除旧配置失败");
}
}
}
//a写入字符串长度,b是起始位,str为要保存的字符串
void Write_String(int a,int b,String str){
EEPROM.write(a, str.length());//EEPROM第a位,写入str字符串的长度
//把str所有数据逐个保存在EEPROM
for (int i = 0; i < str.length(); i++){
EEPROM.write(b + i, str[i]);
}
EEPROM.commit();
}
//a位是字符串长度,b是起始位
String Read_String(int a, int b){
String data = "";
//从EEPROM中逐个取出每一位的值,并链接
for (int i = 0; i < a; i++){
data += char(EEPROM.read(b + i));
}
return data;
}
配网.html代码:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WIFI配网</title>
</head>
<body>
<div class="main">
<h2>WIFI配网</h2>
<br>
<input class="input ssid" type="text" placeholder="SSID" name="ssid">
<input class="input password" type="password" placeholder="密码" name="password">
<button class="button" onclick="sendData()">配置</button>
</div>
</body>
<script>
function sendData(){
let ssid = document.querySelector(".ssid").value
let password = document.querySelector(".password").value
if(ssid == "" || password == ""){
return
}
console.log(ssid,password)
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log("配置成功")
alert("配置成功");
}
};
xhttp.open("GET", "set?ssid="+ssid+"&password="+password, true);
xhttp.send();
}
</script>
<style>
html,body{
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.main{
width: 100%;
height: 100%;
margin: 0;
padding: 0;
text-align: center;
}
.button{
outline: none;
box-sizing: border-box;
background: #f5f5f5;
border: 1px solid#bdbdbd;
border-radius: 18px;
color: #434343;
cursor: pointer;
display: block;
font-family: inherit;
font-size: 16px;
font-variant: normal;
font-weight: 400;
height: 2.14285714em;
line-height: 1.42857143;
margin: 18px auto;
padding: 4px 30px;
text-decoration: none;
white-space: nowrap;
}
.input{
resize: none;
outline: none;
margin: 4px auto;
height: 45px;
width: 80%;
border: 1px solid #d0d1ce;
padding-left: 15px;
font-size: 14px;
color: #000;
margin-left: 10px;
border-radius: 10px;
border: 1px solid #dcdfe6;
background-color: #fff;
}
</style>
</html>