授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力。希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石。。。
一、基础篇
- ESP8266开发之旅 基础篇① 走进ESP8266的世界
- ESP8266开发之旅 基础篇② 如何安装ESP8266的Arduino开发环境
- ESP8266开发之旅 基础篇③ ESP8266与Arduino的开发说明
- ESP8266开发之旅 基础篇④ ESP8266与EEPROM
- ESP8266开发之旅 基础篇⑤ ESP8266 SPI通信和I2C通信
- ESP8266开发之旅 基础篇⑥ Ticker——ESP8266定时库
二、网络篇
- ESP8266开发之旅 网络篇① 认识一下Arduino Core For ESP8266
- ESP8266开发之旅 网络篇② ESP8266 工作模式与ESP8266WiFi库
- ESP8266开发之旅 网络篇③ Soft-AP——ESP8266WiFiAP库的使用
- ESP8266开发之旅 网络篇④ Station——ESP8266WiFiSTA库的使用
- ESP8266开发之旅 网络篇⑤ Scan WiFi——ESP8266WiFiScan库的使用
- ESP8266开发之旅 网络篇⑥ ESP8266WiFiGeneric——基础库
- ESP8266开发之旅 网络篇⑦ TCP Server & TCP Client
- ESP8266开发之旅 网络篇⑧ SmartConfig——一键配网
- ESP8266开发之旅 网络篇⑨ HttpClient——ESP8266HTTPClient库的使用
- ESP8266开发之旅 网络篇⑩ UDP服务
- ESP8266开发之旅 网络篇⑪ WebServer——ESP8266WebServer库的使用
- ESP8266开发之旅 网络篇⑫ 域名服务——ESP8266mDNS库
- ESP8266开发之旅 网络篇⑬ SPIFFS——ESP8266 Flash文件系统
- ESP8266开发之旅 网络篇⑭ web配网
- ESP8266开发之旅 网络篇⑮ 真正的域名服务——DNSServer
- ESP8266开发之旅 网络篇⑯ 无线更新——OTA固件更新
三、应用篇
- ESP8266开发之旅 应用篇① 局域网应用 ——炫酷RGB彩灯
- ESP8266开发之旅 应用篇② OLED显示天气屏
- ESP8266开发之旅 应用篇③ 简易版WiFi小车
四、高级篇
- ESP8266开发之旅 进阶篇① 代码优化 —— ESP8266内存管理
- ESP8266开发之旅 进阶篇② 闲聊Arduino IDE For ESP8266配置
- ESP8266开发之旅 进阶篇③ 闲聊 ESP8266 Flash
- ESP8266开发之旅 进阶篇④ 常见问题 —— 解决困扰
- ESP8266开发之旅 进阶篇⑤ 代码规范 —— 像写文章一样优美
- ESP8266开发之旅 进阶篇⑥ ESP-specific APIs说明
在前面的博文中,博主介绍到ESP8266WiFi库是包含了很多功能的一个超级库。ESP8266WiFi库不仅仅局限于 ESP8266WiFi.h 和 ESP8266WiFi.cpp 这两个文件,只不过它们是最核心的统一入口。
而在这些库中,有个8266模块通用库 ESP8266WiFiGeneric库,ESP8266WiFiSTA/ESP8266WiFiAP/ESP8266WiFiScan都会在它的基础上去做一些自己的逻辑(也就是会用到它的一些方法),所以算是比较重要的一个基础库,它包括处理程序来管理wi-fi事件,如连接,断开连接或获得ip,wi-fi模式的变化,管理模块睡眠模式的功能,以ip地址解析的hostName等;
ESP8266在使用过程中并非会一直如希望般稳定运行的,为了应对这些情况就需要能够了解WiFi状态,并对WiFi突发事件作出响应。
首先,我们先看一下它的头文件源码:
class ESP8266WiFiGenericClass {
// ----------------------------------------------------------------------------------------------
// -------------------------------------- Generic WiFi function ---------------------------------
// ----------------------------------------------------------------------------------------------
public:
ESP8266WiFiGenericClass();
// Note: this function is deprecated. Use one of the functions below instead.
void onEvent(WiFiEventCb cb, WiFiEvent_t event = WIFI_EVENT_ANY) __attribute__((deprecated));
// Subscribe to specific event and get event information as an argument to the callback
WiFiEventHandler onStationModeConnected(std::function<void(const WiFiEventStationModeConnected&)>);
WiFiEventHandler onStationModeDisconnected(std::function<void(const WiFiEventStationModeDisconnected&)>);
WiFiEventHandler onStationModeAuthModeChanged(std::function<void(const WiFiEventStationModeAuthModeChanged&)>);
WiFiEventHandler onStationModeGotIP(std::function<void(const WiFiEventStationModeGotIP&)>);
WiFiEventHandler onStationModeDHCPTimeout(std::function<void(void)>);
WiFiEventHandler onSoftAPModeStationConnected(std::function<void(const WiFiEventSoftAPModeStationConnected&)>);
WiFiEventHandler onSoftAPModeStationDisconnected(std::function<void(const WiFiEventSoftAPModeStationDisconnected&)>);
WiFiEventHandler onSoftAPModeProbeRequestReceived(std::function<void(const WiFiEventSoftAPModeProbeRequestReceived&)>);
// WiFiEventHandler onWiFiModeChange(std::function);
int32_t channel(void);
bool setSleepMode(WiFiSleepType_t type);
WiFiSleepType_t getSleepMode();
bool setPhyMode(WiFiPhyMode_t mode);
WiFiPhyMode_t getPhyMode();
void setOutputPower(float dBm);
void persistent(bool persistent);
bool mode(WiFiMode_t);
WiFiMode_t getMode();
bool enableSTA(bool enable);
bool enableAP(bool enable);
bool forceSleepBegin(uint32 sleepUs = 0);
bool forceSleepWake();
protected:
static bool _persistent;
static WiFiMode_t _forceSleepLastMode;
static void _eventCallback(void *event);
// ----------------------------------------------------------------------------------------------
// ------------------------------------ Generic Network function --------------------------------
// ----------------------------------------------------------------------------------------------
public:
int hostByName(const char* aHostname, IPAddress& aResult);
int hostByName(const char* aHostname, IPAddress& aResult, uint32_t timeout_ms);
bool getPersistent();
protected:
friend class ESP8266WiFiSTAClass;
friend class ESP8266WiFiScanClass;
friend class ESP8266WiFiAPClass;
};
这里出现了友元类(friend class),意味着 ESP8266WiFiSTAClass 、ESP8266WiFiScanClass 、ESP8266WiFiAPClass 可以访问 ESP8266WiFiGenericClass的private和protected成员。
讲解之前,先浏览一下博主整理的百度脑图,以便有个整体认识:
整体上来说,方法可以分为两类:
首先我们需要了解一下有哪些WiFi事件,请打开源码中的 ESP8266WiFiType.h 文件,里面有关于WiFi事件的定义:
typedef enum WiFiEvent
{
WIFI_EVENT_STAMODE_CONNECTED = 0,//STA模式下连接上网络
WIFI_EVENT_STAMODE_DISCONNECTED,//STA模式下断开网络
WIFI_EVENT_STAMODE_AUTHMODE_CHANGE,//STA模式下校验模式改变
WIFI_EVENT_STAMODE_GOT_IP,//STA模式下模块获取到IP地址
WIFI_EVENT_STAMODE_DHCP_TIMEOUT,//STA模式下DHCP分配IP超时
WIFI_EVENT_SOFTAPMODE_STACONNECTED,//AP模式下有station连接进来
WIFI_EVENT_SOFTAPMODE_STADISCONNECTED,//AP模式下有station断开连接
WIFI_EVENT_SOFTAPMODE_PROBEREQRECVED,//AP模式下收到探针请求
WIFI_EVENT_MAX,
WIFI_EVENT_ANY = WIFI_EVENT_MAX,
WIFI_EVENT_MODE_CHANGE //源码中已经去掉
} WiFiEvent_t;
知道了有哪些事件(WiFiEvent),然后针对性去监听这些事件。当事件发生的时候,我们注册事件处理者(WiFiEventHandler),然后可以获取事件信息。
使用WiFiEventHandler需要先声明,然后注册对应事件并加入事件触发时执行的操作:
//请注意,以下为伪代码,不能运行,注意理解思想即可
//声明事件
WiFiEventHandler event;
//事件触发时处理者
void handler(const WiFiEvent& event)
{
//TODO 在这里可以获取具体的事件信息
}
//注册事件
event = WiFi.onWiFiEvent(handler);
函数说明:
/**
* 注册事件处理器
* 事件类型:STA模式下连接上网络
* @param 事件处理回调函数(函数的入参是 WiFiEventStationModeConnected)
* @return WiFiEventHandler
*/
WiFiEventHandler onStationModeConnected(std::function<void(const WiFiEventStationModeConnected&)>);
注意点:
WiFiEventStationModeConnected 事件信息:
// WiFiEventStationModeConnected事件信息
struct WiFiEventStationModeConnected
{
String ssid;// station的ssid,理解为名字
uint8 bssid[6];//station的mac地址
uint8 channel;//station连到的信道
};
函数说明:
/**
* 注册事件处理器
* 事件类型:STA模式下断开网络
* @param 事件处理回调函数(函数的入参是 WiFiEventStationModeDisconnected)
* @return WiFiEventHandler
*/
WiFiEventHandler onStationModeDisconnected(std::function<void(const WiFiEventStationModeDisconnected&)>);
注意点:
WiFiEventStationModeDisconnected 事件信息:
// WiFiEventStationModeDisconnected 事件信息
struct WiFiEventStationModeDisconnected
{
String ssid;// station的ssid,理解为名字
uint8 bssid[6];//station的mac地址
WiFiDisconnectReason reason;//断开连接原因
};
//断开连接原因
enum WiFiDisconnectReason
{
WIFI_DISCONNECT_REASON_UNSPECIFIED = 1,
WIFI_DISCONNECT_REASON_AUTH_EXPIRE = 2,
WIFI_DISCONNECT_REASON_AUTH_LEAVE = 3,
WIFI_DISCONNECT_REASON_ASSOC_EXPIRE = 4,
WIFI_DISCONNECT_REASON_ASSOC_TOOMANY = 5,
WIFI_DISCONNECT_REASON_NOT_AUTHED = 6,
WIFI_DISCONNECT_REASON_NOT_ASSOCED = 7,
WIFI_DISCONNECT_REASON_ASSOC_LEAVE = 8,
WIFI_DISCONNECT_REASON_ASSOC_NOT_AUTHED = 9,
WIFI_DISCONNECT_REASON_DISASSOC_PWRCAP_BAD = 10, /* 11h */
WIFI_DISCONNECT_REASON_DISASSOC_SUPCHAN_BAD = 11, /* 11h */
WIFI_DISCONNECT_REASON_IE_INVALID = 13, /* 11i */
WIFI_DISCONNECT_REASON_MIC_FAILURE = 14, /* 11i */
WIFI_DISCONNECT_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, /* 11i */
WIFI_DISCONNECT_REASON_GROUP_KEY_UPDATE_TIMEOUT = 16, /* 11i */
WIFI_DISCONNECT_REASON_IE_IN_4WAY_DIFFERS = 17, /* 11i */
WIFI_DISCONNECT_REASON_GROUP_CIPHER_INVALID = 18, /* 11i */
WIFI_DISCONNECT_REASON_PAIRWISE_CIPHER_INVALID = 19, /* 11i */
WIFI_DISCONNECT_REASON_AKMP_INVALID = 20, /* 11i */
WIFI_DISCONNECT_REASON_UNSUPP_RSN_IE_VERSION = 21, /* 11i */
WIFI_DISCONNECT_REASON_INVALID_RSN_IE_CAP = 22, /* 11i */
WIFI_DISCONNECT_REASON_802_1X_AUTH_FAILED = 23, /* 11i */
WIFI_DISCONNECT_REASON_CIPHER_SUITE_REJECTED = 24, /* 11i */
WIFI_DISCONNECT_REASON_BEACON_TIMEOUT = 200,
WIFI_DISCONNECT_REASON_NO_AP_FOUND = 201,
WIFI_DISCONNECT_REASON_AUTH_FAIL = 202,
WIFI_DISCONNECT_REASON_ASSOC_FAIL = 203,
WIFI_DISCONNECT_REASON_HANDSHAKE_TIMEOUT = 204,
};
函数说明:
/**
* 注册事件处理器
* 事件类型:STA模式下校验模式改变
* @param 事件处理回调函数(函数的入参是 WiFiEventStationModeAuthModeChanged)
* @return WiFiEventHandler
*/
WiFiEventHandler onStationModeAuthModeChanged(std::function<void(const WiFiEventStationModeAuthModeChanged&)>);
注意点:
WiFiEventStationModeAuthModeChanged 事件信息:
// WiFiEventStationModeAuthModeChanged 事件信息
struct WiFiEventStationModeAuthModeChanged
{
uint8 oldMode;
uint8 newMode;
};
验证模式:
typedef enum _auth_mode {
AUTH_OPEN = 0,
AUTH_WEP,
AUTH_WPA_PSK,
AUTH_WPA2_PSK,
AUTH_WPA_WPA2_PSK,
AUTH_MAX
} AUTH_MODE;
函数说明:
/**
* 注册事件处理器
* 事件类型:STA模式下模块获取到IP地址
* @param 事件处理回调函数(函数的入参是 WiFiEventStationModeGotIP)
* @return WiFiEventHandler
*/
WiFiEventHandler onStationModeGotIP(std::function<void(const WiFiEventStationModeGotIP&)>);
WiFiEventStationModeGotIP 事件信息:
// WiFiEventStationModeGotIP 事件信息
struct WiFiEventStationModeGotIP
{
IPAddress ip;//IP地址
IPAddress mask;//子网掩码
IPAddress gw;//网关
};
函数说明:
/**
* 注册事件处理器
* 事件类型:STA模式下DHCP分配IP超时
* @param 事件处理回调函数
* @return WiFiEventHandler
*/
WiFiEventHandler onStationModeDHCPTimeout(std::function<void(void)>);
注意点:
函数说明:
/**
* 注册事件处理器
* 事件类型:AP模式下有station连接进来
* @param 事件处理回调函数(函数的入参是 WiFiEventSoftAPModeStationConnected)
* @return WiFiEventHandler
*/
WiFiEventHandler onSoftAPModeStationConnected(std::function<void(const WiFiEventSoftAPModeStationConnected&)>);
WiFiEventSoftAPModeStationConnected 事件信息:
// WiFiEventSoftAPModeStationConnected 事件信息
struct WiFiEventSoftAPModeStationConnected
{
uint8 mac[6];//station mac地址
uint8 aid;// station 名字
};
函数说明:
/**
* 注册事件处理器
* 事件类型:AP模式下有station断开连接
* @param 事件处理回调函数(函数的入参是 WiFiEventSoftAPModeStationDisconnected)
* @return WiFiEventHandler
*/
WiFiEventHandler onSoftAPModeStationDisconnected(std::function<void(const WiFiEventSoftAPModeStationDisconnected&)>);
WiFiEventSoftAPModeStationDisconnected 事件信息:
// WiFiEventSoftAPModeStationDisconnected 事件信息
struct WiFiEventSoftAPModeStationDisconnected
{
uint8 mac[6];//station mac地址
uint8 aid;// station 名字
};
函数说明:
/**
* 注册事件处理器
* 事件类型:AP模式下收到探针请求
* @param 事件处理回调函数(函数的入参是 WiFiEventSoftAPModeProbeRequestReceived)
* @return WiFiEventHandler
*/
WiFiEventHandler onSoftAPModeProbeRequestReceived(std::function<void(const WiFiEventSoftAPModeProbeRequestReceived&)>);
WiFiEventSoftAPModeProbeRequestReceived 事件信息:
// WiFiEventSoftAPModeStationDisconnected 事件信息
struct WiFiEventSoftAPModeProbeRequestReceived
{
int rssi;//信号强度
uint8 mac[6];//mac地址
};
函数说明:
/**
* 是否保存wifi设置到flash中
* @param persistent 该参数设置是否将WiFi参数保存于Flash中,默认为true
*/
void persistent(bool persistent);
注意点:
函数说明:
/**
* 设置wifi工作模式
* @param WiFiMode_t wifi工作模式
* @return bool 是否设置成功
*/
bool mode(WiFiMode_t);
WiFi工作模式:
typedef enum WiFiMode
{
WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3
} WiFiMode_t;
读者是不是感觉上面的枚举很熟悉呢?
函数说明:
/**
* 获取当前wifi工作模式
* @return WiFiMode_t 当前wifi工作模式
*/
WiFiMode_t getMode();
函数说明:
/**
* 设置为STA模式
* @param enable true表示使能STA工作模式
* @return bool 是否设置成功
*/
bool enableSTA(bool enable);
注意点:
函数说明:
/**
* 设置为AP模式
* @param enable true表示使能AP工作模式
* @return bool 是否设置成功
*/
bool enableAP(bool enable);
注意点:
函数说明:
/**
* 设置睡眠模式
* @param WiFiSleepType_t 睡眠模式
* @return bool 是否设置成功
*/
bool setSleepMode(WiFiSleepType_t type);
WiFiSleepType_t 睡眠模式:
typedef enum WiFiSleepType
{
WIFI_NONE_SLEEP = 0,//非睡眠模式 WIFI_LIGHT_SLEEP = 1,//轻度睡眠 WIFI_MODEM_SLEEP = 2//深度睡眠
} WiFiSleepType_t;
注意点:
源码:
/*
This sketch shows how to use WiFi event handlers.
In this example, ESP8266 works in AP mode.
Three event handlers are demonstrated:
- station connects to the ESP8266 AP
- station disconnects from the ESP8266 AP
- ESP8266 AP receives a probe request from a station
*/
#include
#include
const char* ssid = "ap-ssid";
const char* password = "ap-password";
WiFiEventHandler stationConnectedHandler;
WiFiEventHandler stationDisconnectedHandler;
WiFiEventHandler probeRequestPrintHandler;
WiFiEventHandler probeRequestBlinkHandler;
bool blinkFlag;
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
// 不保存任何wifi配置到flash
WiFi.persistent(false);
// 建立一个AP
WiFi.mode(WIFI_AP);
WiFi.softAP(ssid, password);
// 注册事件处理器
// 回调函数会在事件发生时被调用
// onStationConnected函数会在每一次有station连接时调用
stationConnectedHandler = WiFi.onSoftAPModeStationConnected(&onStationConnected);
// onStationDisconnected函数会在每一次有station断开时调用
stationDisconnectedHandler = WiFi.onSoftAPModeStationDisconnected(&onStationDisconnected);
// onProbeRequestPrint和onProbeRequestBlink函数会在每一次收到探针请求时调用
// onProbeRequestPrint会打印station的mac地址和信号强度到串口监视器
// onProbeRequestBlink会闪烁LED
probeRequestPrintHandler = WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequestPrint);
probeRequestBlinkHandler = WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequestBlink);
}
void onStationConnected(const WiFiEventSoftAPModeStationConnected& evt) {
Serial.print("Station connected: ");
Serial.println(macToString(evt.mac));
}
void onStationDisconnected(const WiFiEventSoftAPModeStationDisconnected& evt) {
Serial.print("Station disconnected: ");
Serial.println(macToString(evt.mac));
}
void onProbeRequestPrint(const WiFiEventSoftAPModeProbeRequestReceived& evt) {
Serial.print("Probe request from: ");
Serial.print(macToString(evt.mac));
Serial.print(" RSSI: ");
Serial.println(evt.rssi);
}
void onProbeRequestBlink(const WiFiEventSoftAPModeProbeRequestReceived&) {
// 我们不能在事件处理函数中调用延时函数或者其他阻塞函数
// 因此这里设置一个标志位
blinkFlag = true;
}
void loop() {
if (millis() > 10000 && probeRequestPrintHandler) {
// 10s之后,禁止 onProbeRequestPrint
Serial.println("Not printing probe requests any more (LED should still blink)");
probeRequestPrintHandler = WiFiEventHandler();
}
if (blinkFlag) {
blinkFlag = false;
digitalWrite(LED_BUILTIN, LOW);
delay(100);
digitalWrite(LED_BUILTIN, HIGH);
}
delay(10);
}
String macToString(const unsigned char* mac) {
char buf[20];
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(buf);
}
源码:
#include
const char *ssid = "********";
const char *password = "********";
WiFiEventHandler STAConnected;
WiFiEventHandler STADisconnected;
WiFiEventHandler STAGotIP;
void ConnectedHandler(const WiFiEventStationModeConnected &event)
{
Serial.println(WiFi.status());
Serial.println("模块连接到网络");
}
void DisconnectedHandler(const WiFiEventStationModeDisconnected &event)
{
Serial.println(WiFi.status());
Serial.println("模块从网络断开");
}
void setup()
{
Serial.begin(115200);
Serial.println();
STAConnected = WiFi.onStationModeConnected(ConnectedHandler);
STADisconnected = WiFi.onStationModeDisconnected(DisconnectedHandler);
STAGotIP = WiFi.onStationModeGotIP([](const WiFiEventStationModeGotIP &event) {
Serial.println(WiFi.status());
Serial.println("模块获得IP");
});
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println(WiFi.status());
}
void loop()
{
delay(5000); //等待5秒
WiFi.disconnect(); //断开当前网络连接
}
本篇博文更注重于讲解WiFi通信过程中的一些事件以及配置,可以增加开发者对于设备的了解,这对于开发稳定的产品是比较有帮助的。