NodeMCU(ESP8266) WIFI配网及保存WiFi密码信息

背景

在我们使用智能设备时经常会看到很多设备是接入WiFi的,刚买来的时候是需要连接WiFi的,配WiFi的方式有很多种,我遇到的比较多的是smartConfig声纹配网,如果是有触摸屏的话很多都是屏幕上直接输入WiFi密码即可。配置完网络后我们后续的使用时都是无需再次配WiFi信息。

WiFi配网原理

关于配网的原理我也是看别人的文章的,所以就不做搬运,如需了解请阅读下面这篇文章。

IoT】物联网之 WIFI 一键配网 smartConfig 浅析(ESP32)

demo视频

原本想这么一个简单的东西就没必要拍视频来展示,但是代码和文字都是很枯燥的,我这种学渣看到完全提不起兴趣,驱动个人去做的更多的可能还是看到别人的创意视频吧,所以我便想着用视频的方式来展示,希望也能驱动和我一样的小白玩家不断前行。

功能讲解

  1. 先从EEPROM中获取WiFi的SSID和密码
  2. 如果已经有了SSID和密码,则直接使用SSID密码连接WIFI
  3. 如果是没有SSID和密码,则进入到配网模式
  4. 配网完成后将WiFi的SSID和密码存储到EEPROM存储器中
  5. 最后进入主程序,判断清除EEPROM存储器的功能键是否按下
  6. 如果按下则清空WiFi的SSID和密码信息,重置后回到步骤1

大致流程如下

代码

这里代码推荐使用多文件的方式来写,第一复用性会比较高(拿到其他项目也能用),第二不会被很长的代码看迷糊。

  • smartconfig.h

这个主要就是将WiFi的SSID和密码存储起来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

#include <EEPROM.h>

#ifndef _SMART_CONFIG_
// 声明
#define _SMART_CONFIG_

#define EEPROM_START 1024

struct WifiPwd {
char ssid[32];
char pwd[64];
};

/*
保存参数到eeprom
*/
void saveConfig(WifiPwd *wifipwd) {
EEPROM.begin(EEPROM_START);
uint8_t *p = (uint8_t*)(wifipwd);
for (int i = 0; i < sizeof(*wifipwd); i++) {
EEPROM.write(i, *(p + i));
}
EEPROM.commit();
// 释放内存
delete wifipwd;
}

/*
获取wifi账号密码信息
*/
WifiPwd* loadConfigs() {
// 为变量请求内存
WifiPwd *pvalue = new WifiPwd;
EEPROM.begin(EEPROM_START);
uint8_t *p = (uint8_t*)(pvalue);
for (int i = 0; i < sizeof(*pvalue); i++) {
*(p + i) = EEPROM.read(i);
}
EEPROM.commit();
return pvalue;
}

/**
清空wifi账号和密码
*/
void clearConfig() {
EEPROM.begin(EEPROM_START);
// 这里为啥是96 ,因为在结构体声明的长度之和就是96
for (int i = 0; i < 96; i++) {
EEPROM.write(i, 0);
}
EEPROM.commit();
}

#endif
  • smart-config-demo.ino

主程序,说明注释里面都有

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

#include <ESP8266WiFi.h>
#include <cstring>
#include "smartconfig.h"

// 功能按键
#define POWERKEY 5


/**
一键配网
*/
void smartConfig() {
// 先从flash中加载账号密码
WifiPwd* wifipwd = loadConfigs();
if (strlen(wifipwd->pwd) > 0 ) {
Serial.println("\n\ruse password connect wifi");
// 如果说有账号密码信息,那就直接用账号密码连接wifi
WiFi.mode(WIFI_STA);
WiFi.begin(wifipwd->ssid, wifipwd->pwd);
while (WiFi.status() != WL_CONNECTED) {
// 直到wifi连接成功为止
blinkled();
}
// 删除内存
delete wifipwd;
// 设置自动连接
WiFi.setAutoConnect(true);
} else {
Serial.println("\n\rwait smart config wifi");
WiFi.beginSmartConfig();
while (1) {
blinkled();
if (WiFi.smartConfigDone()) {
WifiPwd *wifipwd = new WifiPwd;
strcpy(wifipwd->ssid, WiFi.SSID().c_str());
strcpy(wifipwd->pwd, WiFi.psk().c_str());
// 记住wifi账号密码
saveConfig(wifipwd);
// 设置自动连接
WiFi.setAutoConnect(true);
break;
}
}
}
Serial.println("\n\rWiFi Connected IP address: ");
Serial.println(WiFi.localIP());
}

/**
指示灯闪烁
*/
void blinkled() {
digitalWrite(LED_BUILTIN, LOW);
delay(200);
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
}

/**
按键
*/
int keywords() {
// 获取按键的值
int keyValue = digitalRead(POWERKEY);
// 目前是直接返回的,todo 后续需要对按键除抖和长按处理等
return keyValue;
}


void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(POWERKEY, OUTPUT);
smartConfig();
digitalWrite(LED_BUILTIN, LOW);
Serial.println("wifi connected");
}

void loop() {
if (WiFi.status() != WL_CONNECTED) {
// 如果wifi断开的话就重连
WiFi.reconnect();
}
// 判断是否按下重置按钮
if (keywords() == 1) {
// 如果按键按下则清空eeprom和重置单片机
clearConfig();
Serial.println("wifi账号密码已经清除");
}
}