授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力。希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石。。。
快速导航
单片机菜鸟的博客快速索引(快速找到你要的)
如果觉得有用,麻烦点赞收藏,您的支持是博主创作的动力。
现在,通常,为了让手机连上一个WiFi热点,基本上都是打开手机设置里面的WiFi设置功能,然后会看到里面有个WiFi热点列表,然后选择你要的连接上。 基本上你只要打开手机连接WiFi功能,都会发现附近有超级多的各种来路不明的WiFi热点(连接有风险需谨慎),那么手机是怎么知道附近的WiFi的呢?
通常,无线网络提供的WiFi热点,大部分都开放了SSID广播(记得之前博主讲过WiFi热点也可以隐藏的),Scan WiFi的功能就是扫描出所有附近的WiFi热点的SSID信息,这样一来,客户端就可以根据需要选择不同的SSID连入对应的无线网络中。
一般扫描网络需要几百毫秒才能完成。
而扫描WiFi过程包括:
那么Scan WiFi库提供了两种方式实现上面的扫描过程:
一般来说,学过多线程的读者应该都知道同步和异步的区别,这里就不细说,非本篇的重点内容。
有了前面的理论基础,那么我们开始详解一下ESP8266 scan wifi功能专用库——ESP8266WiFiScan库,大家使用的时候不需要
#include
只需要引入
#include
首先,对于Scan类库的描述,可以拆分为两个部分:
函数说明:
/**
* Start scan WiFi networks available
* @param async run in async mode(是否启动异步扫描)
* @param show_hidden show hidden networks(是否扫描隐藏网络)
* @param channel scan only this channel (0 for all channels)(是否扫描特定通道)
* @param max_ms_per_chan
* @return Number of discovered networks
*/
int8_t scanNetworks(bool async = false, bool show_hidden = false, bool passive = false, uint32_t max_ms_per_chan = 300)
{
if(WiFiGenericClass::getStatusBits() & WIFI_SCANNING_BIT) {
return WIFI_SCAN_RUNNING;
}
WiFiScanClass::_scanAsync = async;
WiFi.enableSTA(true);
scanDelete();
wifi_scan_config_t config;
config.ssid = 0;
config.bssid = 0;
config.channel = 0;
config.show_hidden = show_hidden;
if(passive){
config.scan_type = WIFI_SCAN_TYPE_PASSIVE;
config.scan_time.passive = max_ms_per_chan;
} else {
config.scan_type = WIFI_SCAN_TYPE_ACTIVE;
config.scan_time.active.min = 100;
config.scan_time.active.max = max_ms_per_chan;
}
if(esp_wifi_scan_start(&config, false) == ESP_OK) {
WiFiGenericClass::clearStatusBits(WIFI_SCAN_DONE_BIT);
WiFiGenericClass::setStatusBits(WIFI_SCANNING_BIT);
if(WiFiScanClass::_scanAsync) {
return WIFI_SCAN_RUNNING;
}
if(WiFiGenericClass::waitStatusBits(WIFI_SCAN_DONE_BIT, 10000)){
return (int16_t) WiFiScanClass::_scanCount;
}
}
return WIFI_SCAN_FAILED;
}
应用实例:
//实例代码 这只是部分代码 不能直接使用
//同步扫描
int n = WiFi.scanNetworks();//不需要填任何参数
Serial.println("scan done");
if (n == 0) {
Serial.println("no networks found");
} else {
Serial.println(" networks found");
}
函数说明:
/**
* Start scan WiFi networks available
* @param async run in async mode(是否启动异步扫描)
* @param show_hidden show hidden networks(是否扫描隐藏网络)
* @param channel scan only this channel (0 for all channels)(是否扫描特定通道)
* @param ssid* scan for only this ssid (NULL for all ssid's)(是否扫描特定的SSID)
* @return Number of discovered networks
*/
int8_t scanNetworks(bool async = false, bool show_hidden = false, uint8 channel = 0, uint8* ssid = NULL);
应用实例:
//实例代码 这只是部分代码 不能直接使用
//异步扫描
WiFi.scanNetworks(true);
// print out Wi-Fi network scan result uppon completion
int n = WiFi.scanComplete();
if(n >= 0){
Serial.printf("%d network(s) found\n", n);
for (int i = 0; i < n; i++){
Serial.printf("%d: %s, Ch:%d (%ddBm) %s\n", i+1, WiFi.SSID(i).c_str(), WiFi.channel(i), WiFi.RSSI(i), WiFi.encryptionType(i) == ENC_TYPE_NONE ? "open" : "");
}
//打印一次结果之后把缓存中的数据清掉
WiFi.scanDelete();
}
函数说明:
/**
* called to get the scan state in Async mode(异步扫描的结果函数)
* @return scan result or status
* -1 if scan not find
* -2 if scan not triggered
*/
int8_t scanComplete()
{
if(WiFiGenericClass::getStatusBits() & WIFI_SCAN_DONE_BIT) {
return WiFiScanClass::_scanCount;
}
if(WiFiGenericClass::getStatusBits() & WIFI_SCANNING_BIT) {
return WIFI_SCAN_RUNNING;
}
return WIFI_SCAN_FAILED;
}
函数说明:
/**
* delete last scan result from RAM(从内存中删除最近的扫描结果)
*/
void scanDelete()
{
WiFiGenericClass::clearStatusBits(WIFI_SCAN_DONE_BIT);
if(WiFiScanClass::_scanResult) {
delete[] reinterpret_cast<wifi_ap_record_t*>(WiFiScanClass::_scanResult);
WiFiScanClass::_scanResult = 0;
WiFiScanClass::_scanCount = 0;
}
}
注意点:
函数说明:
/**
* Return the SSID discovered during the network scan.
* @param i specify from which network item want to get the information
* @return ssid string of the specified item on the networks scanned list
*/
String SSID(uint8_t networkItem);
函数说明:
/**
* Return the RSSI of the networks discovered during the scanNetworks(信号强度)
* @param i specify from which network item want to get the information
* @return signed value of RSSI of the specified item on the networks scanned list
*/
int32_t RSSI(uint8_t networkItem);
函数说明:
/**
* Return the encryption type of the networks discovered during the scanNetworks(加密方式)
* @param i specify from which network item want to get the information
* @return encryption type (enum wl_enc_type) of the specified item on the networks scanned list
* ............ Values map to 802.11 encryption suites.....................
* AUTH_OPEN ----> ENC_TYPE_WEP = 5,
* AUTH_WEP ----> ENC_TYPE_TKIP = 2,
* AUTH_WPA_PSK ----> ENC_TYPE_CCMP = 4,
* ........... except these two, 7 and 8 are reserved in 802.11-2007.......
* AUTH_WPA2_PSK ----> ENC_TYPE_NONE = 7,
* AUTH_WPA_WPA2_PSK ----> ENC_TYPE_AUTO = 8
*/
uint8_t encryptionType(uint8_t networkItem);
函数说明:
/**
* return MAC / BSSID of scanned wifi (物理地址)
* @param i specify from which network item want to get the information
* @return uint8_t * MAC / BSSID of scanned wifi
*/
uint8_t * BSSID(uint8_t networkItem);
/**
* return MAC / BSSID of scanned wifi (物理地址)
* @param i specify from which network item want to get the information
* @return uint8_t * MAC / BSSID of scanned wifi
*/
String BSSIDstr(uint8_t networkItem);
函数说明:
/**
* loads all infos from a scanned wifi in to the ptr parameters
* @param networkItem uint8_t
* @param ssid const char**
* @param encryptionType uint8_t *
* @param RSSI int32_t *
* @param BSSID uint8_t **
* @param channel int32_t *
* @param isHidden bool *
* @return (true if ok)
*/
bool getNetworkInfo(uint8_t networkItem, String &ssid, uint8_t &encryptionType, int32_t &RSSI, uint8_t* &BSSID, int32_t &channel, bool &isHidden)
{
wifi_ap_record_t* it = reinterpret_cast<wifi_ap_record_t*>(_getScanInfoByIndex(i));
if(!it) {
return false;
}
ssid = (const char*) it->ssid;
encType = it->authmode;
rssi = it->rssi;
bssid = it->bssid;
channel = it->primary;
return true;
}
注意点:
函数说明:
/**
* return channel of scanned wifi(通道号)
*/
int32_t channel(uint8_t networkItem);
上面博主讲了一堆方法理论的知识,下面我们开始讲解操作实例,博主尽量都在代码中注释,直接看代码就好。
实例代码:
测试结果(博主附近潜在的WiFi热点):
实例代码:
测试结果:
扫描并不是多复杂的功能,分为同步扫描和异步扫描,一般楼主建议用异步扫描方式,不影响代码运行。