在看到众多文章中,可以看到SmartCofig程序,很多都是完成一键配网后,下次开机,还需要手机进行配网,在实际应用中程序设计是不合理的。
程序设计主要是为了,当设备在一个新的环境下时,我们能更方便的连接网络。
本程序具体思路:
首先读取esp8266内部eeprom中保存的wifi信息,如果连接成功,则不进行SmartCofig,如果连接不成功则需要使用手机进行SmartCofig,通过SmartConfig完成esp8266配网,获取到wifi名称、密码后在保存到eeprom中,完成新环境的wifi配置。
**20210813更新当wifi名称为十位数时,不能正常配网的的bug。**
/*
通过一键配网后把连接到的wifi名称 密码保存到EEPROM中 esp32
*/
//#include <WiFi.h>
#include <ESP8266WiFi.h>
#include <EEPROM.h>
String smart_data = "";
int size_data = 0; //WIFI数据长度
String wifiname;
String wifipsw;
bool flag; //读取EEPROM联网,是否成功标志位
int wifiname_len; // wifi名的长度
void Config_wifi(const char *wifiname, const char *psw) //函数用于直接读取eeprom中的数据,直接完成后直接联网
{
int i = 0;
WiFi.begin(wifiname, psw);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
if (i == 0)
{
Serial.print("正在配置网络");
}
Serial.print(".");
i++;
if (i == 15)
{
Serial.println("连接失败请使用APP一键配网");
flag = true;
break;
}
}
if (WiFi.isConnected())
{
Serial.println("网络连接成功");
Serial.print("Local IP:");
Serial.println(WiFi.localIP());
}
}
void read_eeprom()
{
wifiname = "";
wifipsw = "";
int a = (int(EEPROM.read(0)) - int('0')) * 10 + (int(EEPROM.read(1)) - int('0')); //读数据,地址0和地址1分别保存wifi名称的长度的十位和个位
int b = (int(EEPROM.read(2)) - int('0')) * 10 + (int(EEPROM.read(3)) - int('0')) ; //读数据,地址2和地址3分别保存wifi密码的长度的十位和个位
Serial.println();
Serial.println(a);//打印出wifi名的长度,看是否正确
Serial.println(b);//打印出整个保存在eeprom中字符串的长度
for (int addr = 4; addr < b + 1; addr++)//地址3开始则是wifi的名称,然后依次是wifi密码
{
int data = EEPROM.read(addr); //读数据
// Serial.print(char(data));
if (addr < a + 4)
{
wifiname = wifiname + char(data);
}
else
{
wifipsw = wifipsw + char(data);
}
delay(2);
}
Serial.print("SSID:");
Serial.println(wifiname);
Serial.print("PASSWORD:");
Serial.println(wifipsw);
}
void smartConfig()
{
WiFi.mode(WIFI_STA);
Serial.println("\r\nWait for Smartconfig");
delay(2000);
// 等待配网
WiFi.beginSmartConfig();
while (1)
{
Serial.print(".");
delay(500);
if (WiFi.smartConfigDone())
{
Serial.println("SmartConfig Success");
Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
WiFi.setAutoConnect(true); // 设置自动连接
wifiname_len = String(WiFi.SSID().c_str()).length(); //获取wifi名的长度
if (wifiname_len < 9) {//判断wifi名是否为个位数,是则在前面补零
smart_data = String("0") + String(wifiname_len) + String(size_data) + String (WiFi.SSID().c_str()) + String(WiFi.psk().c_str());
size_data = String(smart_data).length();
smart_data = String("0") + String(wifiname_len) + String(size_data) + String (WiFi.SSID().c_str()) + String(WiFi.psk().c_str());
} else {
smart_data = String(wifiname_len) + String(size_data) + String (WiFi.SSID().c_str()) + String(WiFi.psk().c_str());
size_data = String(smart_data).length();
smart_data = String(wifiname_len) + String(size_data) + String (WiFi.SSID().c_str()) + String(WiFi.psk().c_str());
}
Serial.println(size_data);
Serial.println(smart_data); //打印出保存在eeprom数据
Serial.println(String(smart_data).length());//打印出保存在eeprom中的数据长度
for (int addr = 0; addr < size_data + 1; addr++)
{
//int data = addr%256; //在该代码中等同于int data = addr;因为下面write方法是以字节为存储单位的.
//String(smart_data).charAt(addr);
EEPROM.write(addr, toascii(String(smart_data).charAt(addr))); //写数据
}
EEPROM.commit(); //保存更改的数据
Serial.println("End write");
break;
}
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void setup()
{
Serial.begin(115200);
EEPROM.begin(50); //
flag = false;
read_eeprom();
Config_wifi(wifiname.c_str(), wifipsw.c_str());
if (flag)
{
smartConfig();
}
}
void loop()
{
}
烧录完成后串口打印的数据出现wait for samrtcofig后,使用手机一键配网
完成配网后,下次开机,会直接从esp8266内部EEPROM中读取wifi信息,进行联网。