1 接入点模式(Access Point)
ESP8266自已做为一个WIFI热点向外界发出WIFI信号,其它无线终端设备(手机,笔记本电脑等)可以连入该WIFI网络
#include <ESP8266WiFi.h> // 本程序使用ESP8266WiFi库
const char *ssid = "WIFI-AP"; // 要建立的WiFi名称
const char *password = "12345678"; // 这里定义将要建立的WiFi密码
// 初始化程序
void setup() {
Serial.begin(9600); // 启动串口通讯(波频率9600 bit/s)
WiFi.softAP(ssid, password); // 重点。用于启动NodeMCU的AP模式(接入点模式)
// 这两个参数具体内容在setup函数之前的位置进行定义。
// 如果只有单参数.softAP(ssid)返回bool值,表示开启AP是否成功
Serial.print("Access Point: "); // 打印信息
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.softAPIP()); // 可以得到NodeMCU的IP地址(默认是192.168.4.1)
}
// 主循环程序(类似while(true))
void loop() {
}
2 无线终端模式(Wireless Station)
ESP8266可以像其它无线终端设备一样,连入WIFI网络(只可以连接2.4G网络,不能连接5G网络)
2.1 单点无线模式
#include <ESP8266WiFi.h> // 本程序使用ESP8266WiFi库
const char* ssid = "WIFI-WS"; // 连入的WIFI名称
const char* password = "12345678";
void setup() {
Serial.begin(9600); // 启动串口通讯
WiFi.begin(ssid, password); // 重点,连接到WIFI网络
Serial.print("Connecting to ");
Serial.print(ssid); Serial.println(" ...");
int i = 0;
while (WiFi.status() != WL_CONNECTED) { // WiFi.status()返回连接状态信息,成功返回"WL_CONNECTED"
delay(1000); // delay(1000)延迟1秒
Serial.print(i++); Serial.println("秒");
}
Serial.println("");
Serial.println("Connection established!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP()); // 返回被分配的局域网IP地址
}
void loop() {
}
2.2 多点无线模式
如果开发板在多个场景切换,需要在不同场景下连入对应WIFI,就需要设置多个密码,让开发板连入WIFI新号最强的WIFI网络
#include <ESP8266WiFi.h> // 本程序使用ESP8266WiFi库
#include <ESP8266WiFiMulti.h> // 本程序使用ESP8266WiFiMulti库
ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象
void setup() {
Serial.begin(9600); // 启动串口通讯
//通过addAp函数存储 WiFi名称 WiFi密码
wifiMulti.addAP("WIFI-WS1", "12345678"); // addAP记录多个不同的WiFi信息
wifiMulti.addAP("WIFI-WS2", "12345678");
wifiMulti.addAP("WIFI-WS3", "12345678");
Serial.println("Connecting ...");
while (wifiMulti.run() != WL_CONNECTED) { // 连接最强WIFI。连接成功返回“WL_CONNECTED”
delay(1000);
Serial.print('.');
}
Serial.println('\n');
Serial.print("Connected to ");
Serial.println(WiFi.SSID()); // 连接的WiFI名称
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
}
void loop() {
}
3 混合开发模式
即使采用多点无线模式连入WIFI网络,其底层原理也还是将WIFI帐号密码写死在程序中,这种方式始终是不够灵活; 混合开发模式,顾名思义,将ESP8266的两种模式结合,通过网络配置的方式动态输入WIFI帐号密码
3.1 自定义配置WIFI流程图
3.2 向闪存文件系统上传基础数据(网页,txt文件)
wifiLogin.html
<!DOCTYPE html>
<html lang='zh-CN'>
<head>
<meta charset='UTF-8'>
<title>wifi</title>
</head>
<body>
<form name='input' action='/wifiLogin' method='POST'>
wifi名称: <br>
<input type='text' name='wifiAccount'><br>
wifi密码:<br>
<input type='password' name='wifiPassword'><br>
<input type='submit' value='保存'>
</form>
</body>
</html>
3个txt文件(account,password,ip分别保存WIFI帐号,WIFI密码,被分配的IP)
3.3 开发板代码
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WebServer.h>
#include <FS.h>
const char *apAccount = "ESP8266-AP";
const char *apPassword = "12345678";
boolean wifiLoginFlag = 0; // 用于标记wifi是否已经连接成功
String wifiLoginName = "CY-ESP8266";
ESP8266WiFiMulti wifiMulti;
ESP8266WebServer esp8266_server(80);
String wifi_ip_add = "/wifi/wifi_ip.txt";
String wifi_account_add = "/wifi/wifi_account.txt";
String wifi_password_add = "/wifi/wifi_password.txt";
void setup() {
Serial.begin(9600);
// 读取"闪存文件系统",获取WIFI帐号,WIFI密码
SPIFFS.begin();
// 开启AP模式
WiFi.softAP(apAccount, apPassword);
Serial.println(apAccount);
Serial.println(WiFi.softAPIP()); // 可以得到NodeMCU的IP地址(默认是192.168.4.1)
esp8266_server.begin(); // 启动"网络服务器"
esp8266_server.on("/", handleRoot);
esp8266_server.on("/wifiLogin", handleWifiLogin);
esp8266_server.on("/readWifiStatus", handleReadWifiStatus);
esp8266_server.onNotFound(handleNotFound);
// 检查闪存文件系统中保存的WIFI连接信息,用 这些信息连接WIFI
if (SPIFFS.exists(wifi_ip_add)&&SPIFFS.exists(wifi_account_add)&&SPIFFS.exists(wifi_password_add)){
String wifiAccount = readFile(wifi_account_add).c_str(); // String转换为const char*之间的转化 str.c_str()
// const char*转换为String用.toString()方法
String wifiPassword = readFile(wifi_password_add).c_str();
WiFi.hostname(wifiLoginName); // 连入WIFI网络后,开发板自己的名字
WiFi.begin(wifiAccount, wifiPassword);
Serial.print("Connecting to "); Serial.println(wifiAccount);
// 连接WIFI最多10秒
for(int i=1;i<=10;i++){
if(WiFi.status() == WL_CONNECTED){
wifiLoginFlag = 1;
break;
}
delay(1000);
Serial.print(i); Serial.println("秒");
}
} else {
Serial.println("文件不存在");
}
// 如果连接WIFI成功,将wifiIp写入闪存文件系统
if(WiFi.status()==WL_CONNECTED){
wifiLoginFlag = 1;
writeFile(wifi_ip_add,WiFi.localIP().toString());
} else {
Serial.println("首次启动Wifi连接失败");
}
}
void loop() {
esp8266_server.handleClient();
}
void handleRoot(){
// 默认访问WIFI登录页面wifiLogin.html
String path = "/wifiLogin.html";
String contentType = getContentType(path);
if(SPIFFS.exists(path)){
File file = SPIFFS.open(path,"r");
esp8266_server.streamFile(file, contentType);
file.close();
} else {
esp8266_server.send(404, "text/plain", "404 Not Found");
}
}
void handleWifiLogin(){
// 获取页面传来的参数,连接WIFI
// 如果成功就将WIFI帐号秘密写入闪存文件系统,返回成功提示,如果失败访问handleRoot
String wifiAccount = esp8266_server.arg("wifiAccount");
String wifiPassword = esp8266_server.arg("wifiPassword");
WiFi.hostname(wifiLoginName);
WiFi.begin(wifiAccount, wifiPassword);
esp8266_server.send(200, "text/plain", "连接中"); // 要先给浏览器响应,否则浏览器会一直发起访问
for(int i=1;i<=10;i++){
if(WiFi.status() == WL_CONNECTED){
wifiLoginFlag = 1;
break;
}
delay(1000);
Serial.print("新连接"); Serial.print(i); Serial.println("秒");
}
if(WiFi.status() == WL_CONNECTED){
wifiLoginFlag = 1;
// 将新的WIFI帐号,密码,路由器分配的IP地址写入闪存文件系统,向网页返回成功提示
writeFile(wifi_ip_add,WiFi.localIP().toString());
writeFile(wifi_account_add,wifiAccount);
writeFile(wifi_password_add,wifiPassword);
Serial.println("连接成功");
} else {
Serial.println("连接失败");
}
}
// 读取当前wifi连接状态,以及闪存文件系统中储存的wifi信息
void handleReadWifiStatus(){
String wifiStatus = "";
wifiStatus += "wifi连接状态:";
wifiStatus += wifiLoginFlag;
wifiStatus += "\r\n开发板被分配的IP地址:";
wifiStatus += readFile(wifi_ip_add);
wifiStatus += "\r\nwifi帐号";
wifiStatus += readFile(wifi_account_add);
wifiStatus += "\r\nwifi密码";
wifiStatus += readFile(wifi_password_add);
esp8266_server.send(200, "text/plain", wifiStatus);
}
void handleNotFound(){
esp8266_server.send(404, "text/plain", "404: Not found");
}
// 根据文件地址,读取文件中的字符串String
String readFile(String fileAddress){
File file = SPIFFS.open(fileAddress, "r");
String readStrings;
for(int i=0; i<file.size(); i++){
readStrings+=(char)file.read();
}
return readStrings;
}
// 根据文件地址和文字内容,向文件中的写入字符串String
String writeFile(String fileAddress,String fileContent){
File wifiIpFile = SPIFFS.open(fileAddress, "w");
wifiIpFile.print(fileContent);
}
// 获取文件类型
String getContentType(String filename){
if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
else if(filename.endsWith(".xml")) return "text/xml";
else if(filename.endsWith(".pdf")) return "application/x-pdf";
else if(filename.endsWith(".zip")) return "application/x-zip";
else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
3.4 使用示例
WIFI登录界面(/接口)
查询WIFI状态(/readWifiStatus接口)