如今,一般,为了让手机连上一个WiFi热点,基本上都是打开手机设置里面的WiFi设置功能,而后会看到里面有个WiFi热点列表,而后选择你要的链接上。 基本上你只要打开手机链接WiFi功能,都会发现附近有超级多的各类来路不明的WiFi热点(链接有风险需谨慎),那么手机是怎么知道附近的WiFi的呢?
一般,无线网络提供的WiFi热点,大部分都开放了SSID广播(记得以前博主讲过WiFi热点也能够隐藏的),Scan WiFi的功能就是扫描出全部附近的WiFi热点的SSID信息,这样一来,客户端就能够根据须要选择不一样的SSID连入对应的无线网络中。缓存
通常扫描网络须要几百毫秒才能完成。
而扫描WiFi过程包括:网络
那么Scan WiFi库提供了两种方式实现上面的扫描过程:多线程
通常来讲,学过多线程的读者应该都知道同步和异步的区别,这里就不细说,非本篇的重点内容。异步
有了前面的理论基础,那么咱们开始详解一下ESP8266 scan wifi功能专用库——ESP8266WiFiScan库,你们使用的时候不须要async
#include <ESP8266WiFiSTA.h>
只须要引入ide
#include<ESP8266WiFi.h>
至于缘由,敬请回顾 ESP8266开发之旅 网络篇② ESP8266 工做模式与ESP8266WiFi库。 首先,对于Scan类库的描述,能够拆分为两个部分:函数
讲解以前,先浏览一下博主整理的百度脑图,以便有个总体认识:
oop
函数说明:测试
/** * 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);
应用实例:ui
//实例代码 这只是部分代码 不能直接使用 //同步扫描 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(); }
函数说明:
/** * Starts scanning WiFi networks available in async mode * @param onComplete the event handler executed when the scan is done * @param show_hidden show hidden networks */ void scanNetworksAsync(std::function<void(int)> onComplete, bool show_hidden = false);
应用实例:
//实例代码 #include "ESP8266WiFi.h" void prinScanResult(int networksFound) { Serial.printf("%d network(s) found\n", networksFound); for (int i = 0; i < networksFound; 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" : ""); } } void setup() { Serial.begin(115200); Serial.println(); WiFi.mode(WIFI_STA); WiFi.disconnect(); delay(100); WiFi.scanNetworksAsync(prinScanResult); } void loop() {} //应该会打印以下相似的显示 //5 network(s) found //1: Tech_D005107, Ch:6 (-72dBm) //2: HP-Print-A2-Photosmart 7520, Ch:6 (-79dBm) //3: ESP_0B09E3, Ch:9 (-89dBm) open //4: Hack-4-fun-net, Ch:9 (-91dBm) //5: UPC Wi-Free, Ch:11 (-79dBm)
函数说明:
/** * 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();
函数说明:
/** * delete last scan result from RAM(从内存中删除最近的扫描结果) */ void scanDelete();
注意点:
函数说明:
/** * 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);
注意点:
函数说明:
/** * return channel of scanned wifi(通道号) */ int32_t channel(uint8_t networkItem);
函数说明:
/** * return if the scanned wifi is Hidden (no SSID)(判断扫描到的wifi是不是隐藏wifi) * @param networkItem specify from which network item want to get the information * @return bool (true == hidden) */ bool isHidden(uint8_t networkItem);
上面博主讲了一堆方法理论的知识,下面咱们开始讲解操做实例,博主尽可能都在代码中注释,直接看代码就好。
实例代码:
/** * Demo: * STA模式下,演示同步扫描Scan wifi功能 * @author 单片机菜鸟 * @date 2019/09/03 */ #include <ESP8266WiFi.h> //如下三个定义为调试定义 #define DebugBegin(baud_rate) Serial.begin(baud_rate) #define DebugPrintln(message) Serial.println(message) #define DebugPrint(message) Serial.print(message) void setup() { //设置串口波特率,以便打印信息 DebugBegin(115200); //延时5s 为了演示效果 delay(5000); // 我不想别人链接我,只想作个站点 WiFi.mode(WIFI_STA); //断开链接 WiFi.disconnect(); delay(100); DebugPrintln("Setup done"); } void loop() { DebugPrintln("scan start"); // 同步扫描,等待返回结果 int n = WiFi.scanNetworks(); DebugPrintln("scan done"); if (n == 0){ DebugPrintln("no networks found"); }else{ DebugPrint(n); DebugPrintln(" networks found"); for (int i = 0; i < n; ++i){ DebugPrint(i + 1); DebugPrint(": "); //打印wifi帐号 DebugPrint(WiFi.SSID(i)); DebugPrint(","); DebugPrint(String("Ch:")+WiFi.channel(i)); DebugPrint(","); DebugPrint(WiFi.isHidden(i)?"hide":"show"); DebugPrint(" ("); //打印wifi信号强度 DebugPrint(WiFi.RSSI(i)); DebugPrint("dBm"); DebugPrint(")"); //打印wifi加密方式 DebugPrintln((WiFi.encryptionType(i) == ENC_TYPE_NONE)?"open":"*"); delay(10); } } DebugPrintln(""); // 延时5s以后再次扫描 delay(5000); }
测试结果(博主附近潜在的WiFi热点):
实例代码:
/** * Demo: * STA模式下,演示异步扫描Scan wifi功能 * @author 单片机菜鸟 * @date 2019/09/03 */ #include <ESP8266WiFi.h> //如下三个定义为调试定义 #define DebugBegin(baud_rate) Serial.begin(baud_rate) #define DebugPrintln(message) Serial.println(message) #define DebugPrint(message) Serial.print(message) //定义一个扫描时间间隔 #define SCAN_PERIOD 5000 long lastScanMillis; void setup() { //设置串口波特率,以便打印信息 DebugBegin(115200); //延时5s 为了演示效果 delay(5000); // 我不想别人链接我,只想作个站点 WiFi.mode(WIFI_STA); //断开链接 WiFi.disconnect(); delay(100); DebugPrintln("Setup done"); } void loop() { long currentMillis = millis(); //触发扫描 if (currentMillis - lastScanMillis > SCAN_PERIOD){ WiFi.scanNetworks(true); Serial.print("\nScan start ... "); lastScanMillis = currentMillis; } // 判断是否有扫描结果 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(); } }
测试结果:
实例代码:
/** * Demo: * STA模式下,演示异步扫描Scan wifi功能 * @author 单片机菜鸟 * @date 2019/09/03 */ #include <ESP8266WiFi.h> //如下三个定义为调试定义 #define DebugBegin(baud_rate) Serial.begin(baud_rate) #define DebugPrintln(message) Serial.println(message) #define DebugPrint(message) Serial.print(message) /** * 打印扫描结果 * @param networksFound 结果个数 */ void prinScanResult(int networksFound){ Serial.printf("%d network(s) found\n", networksFound); for (int i = 0; i < networksFound; 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" : ""); } } void setup() { //设置串口波特率,以便打印信息 DebugBegin(115200); //延时5s 为了演示效果 delay(5000); // 我不想别人链接我,只想作个站点 WiFi.mode(WIFI_STA); //断开链接 WiFi.disconnect(); delay(100); DebugPrintln("Setup done"); Serial.print("\nScan start ... "); WiFi.scanNetworksAsync(prinScanResult); } void loop() { }
测试结果:
扫描并非多复杂的功能,分为同步扫描和异步扫描,通常楼主建议用异步扫描方式,不影响代码运行。