1. 前言

    现在,通常,为了让手机连上一个WiFi热点,基本上都是打开手机设置里面的WiFi设置功能,然后会看到里面有个WiFi热点列表,然后选择你要的连接上。 基本上你只要打开手机连接WiFi功能,都会发现附近有超级多的各种来路不明的WiFi热点(连接有风险需谨慎),那么手机是怎么知道附近的WiFi的呢?
    通常,无线网络提供的WiFi热点,大部分都开放了SSID广播(记得之前博主讲过WiFi热点也可以隐藏的),Scan WiFi的功能就是扫描出所有附近的WiFi热点的SSID信息,这样一来,客户端就可以根据需要选择不同的SSID连入对应的无线网络中。

2. scan WiFi功能

    一般扫描网络需要几百毫秒才能完成。
    而扫描WiFi过程包括:

  • 触发扫描过程
  • 等待完成
  • 提供结果

    那么Scan WiFi库提供了两种方式实现上面的扫描过程:

  1. 同步扫描:通过单个函数在一次运行中完成,需要等待完成所有操作才能继续运行下面的操作。
  2. 异步扫描:把上面的过程分成几个步骤,每个步骤由一个单独函数完成,我们可以在扫描过程中执行其他任务。

    一般来说,学过多线程的读者应该都知道同步和异步的区别,这里就不细说,非本篇的重点内容。

3. ESP8266WiFiScan库

    有了前面的理论基础,那么我们开始详解一下ESP8266 scan wifi功能专用库——ESP8266WiFiScan库,大家使用的时候不需要

  1. #include <ESP8266WiFiSTA.h>

只需要引入

  1. #include<ESP8266WiFi.h>

    至于原因,敬请回顾 ESP8266开发之旅 网络篇② ESP8266 工作模式与ESP8266WiFi库。 首先,对于Scan类库的描述,可以拆分为两个部分:

  1. 第一部分方法,扫描操作;
  2. 第二部分方法,获取扫描结果;

    讲解之前,先浏览一下博主整理的百度脑图,以便有个整体认识:

3.1 扫描操作方法

3.1.1 scanNetworks —— 同步扫描周边有效wifi网络

函数说明:

  1. /**
  2. * Start scan WiFi networks available
  3. * @param async run in async mode(是否启动异步扫描)
  4. * @param show_hidden show hidden networks(是否扫描隐藏网络)
  5. * @param channel scan only this channel (0 for all channels)(是否扫描特定通道)
  6. * @param ssid* scan for only this ssid (NULL for all ssid's)(是否扫描特定的SSID)
  7. * @return Number of discovered networks
  8. */
  9. int8_t scanNetworks(bool async = false, bool show_hidden = false, uint8 channel = 0, uint8* ssid = NULL);

应用实例:

  1. //实例代码 这只是部分代码 不能直接使用
  2. //同步扫描
  3. int n = WiFi.scanNetworks();//不需要填任何参数
  4. Serial.println("scan done");
  5. if (n == 0) {
  6. Serial.println("no networks found");
  7. } else {
  8. Serial.println(" networks found");
  9. }

3.1.2 scanNetworks(async ) —— 异步扫描周边有效wifi网络

函数说明:

  1. /**
  2. * Start scan WiFi networks available
  3. * @param async run in async mode(是否启动异步扫描)
  4. * @param show_hidden show hidden networks(是否扫描隐藏网络)
  5. * @param channel scan only this channel (0 for all channels)(是否扫描特定通道)
  6. * @param ssid* scan for only this ssid (NULL for all ssid's)(是否扫描特定的SSID)
  7. * @return Number of discovered networks
  8. */
  9. int8_t scanNetworks(bool async = false, bool show_hidden = false, uint8 channel = 0, uint8* ssid = NULL);

应用实例:

  1. //实例代码 这只是部分代码 不能直接使用
  2. //异步扫描
  3. WiFi.scanNetworks(true);
  4. // print out Wi-Fi network scan result uppon completion
  5. int n = WiFi.scanComplete();
  6. if(n >= 0){
  7. Serial.printf("%d network(s) found\n", n);
  8. for (int i = 0; i < n; i++){
  9. 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" : "");
  10. }
  11. //打印一次结果之后把缓存中的数据清掉
  12. WiFi.scanDelete();
  13. }

3.1.3 scanNetworksAsync —— 异步扫描周边wifi网络,并回调结果

函数说明:

  1. /**
  2. * Starts scanning WiFi networks available in async mode
  3. * @param onComplete the event handler executed when the scan is done
  4. * @param show_hidden show hidden networks
  5. */
  6. void scanNetworksAsync(std::function<void(int)> onComplete, bool show_hidden = false);

应用实例:

  1. //实例代码
  2. #include "ESP8266WiFi.h"
  3. void prinScanResult(int networksFound)
  4. {
  5. Serial.printf("%d network(s) found\n", networksFound);
  6. for (int i = 0; i < networksFound; i++)
  7. {
  8. 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" : "");
  9. }
  10. }
  11. void setup()
  12. {
  13. Serial.begin(115200);
  14. Serial.println();
  15. WiFi.mode(WIFI_STA);
  16. WiFi.disconnect();
  17. delay(100);
  18. WiFi.scanNetworksAsync(prinScanResult);
  19. }
  20. void loop() {}
  21. //应该会打印如下类似的显示
  22. //5 network(s) found
  23. //1: Tech_D005107, Ch:6 (-72dBm)
  24. //2: HP-Print-A2-Photosmart 7520, Ch:6 (-79dBm)
  25. //3: ESP_0B09E3, Ch:9 (-89dBm) open
  26. //4: Hack-4-fun-net, Ch:9 (-91dBm)
  27. //5: UPC Wi-Free, Ch:11 (-79dBm)

3.1.4 scanComplete —— 检测异步扫描的结果

函数说明:

  1. /**
  2. * called to get the scan state in Async mode(异步扫描的结果函数)
  3. * @return scan result or status
  4. * -1 if scan not find
  5. * -2 if scan not triggered
  6. */
  7. int8_t scanComplete();

3.1.5 scanDelete —— 从内存中删掉最近扫描结果

函数说明:

  1. /**
  2. * delete last scan result from RAM(从内存中删除最近的扫描结果)
  3. */
  4. void scanDelete();

注意点:

  • 如果不删除,将会叠加上次扫描的结果;

3.2 扫描结果方法

3.2.1 SSID —— 获取wifi网络名字

函数说明:

  1. /**
  2. * Return the SSID discovered during the network scan.
  3. * @param i specify from which network item want to get the information
  4. * @return ssid string of the specified item on the networks scanned list
  5. */
  6. String SSID(uint8_t networkItem);

3.2.2 RSSI —— 获取wifi网络信号强度

函数说明:

  1. /**
  2. * Return the RSSI of the networks discovered during the scanNetworks(信号强度)
  3. * @param i specify from which network item want to get the information
  4. * @return signed value of RSSI of the specified item on the networks scanned list
  5. */
  6. int32_t RSSI(uint8_t networkItem);

3.2.3 encryptionType —— 获取wifi网络加密方式

函数说明:

  1. /**
  2. * Return the encryption type of the networks discovered during the scanNetworks(加密方式)
  3. * @param i specify from which network item want to get the information
  4. * @return encryption type (enum wl_enc_type) of the specified item on the networks scanned list
  5. * ............ Values map to 802.11 encryption suites.....................
  6. * AUTH_OPEN ----> ENC_TYPE_WEP = 5,
  7. * AUTH_WEP ----> ENC_TYPE_TKIP = 2,
  8. * AUTH_WPA_PSK ----> ENC_TYPE_CCMP = 4,
  9. * ........... except these two, 7 and 8 are reserved in 802.11-2007.......
  10. * AUTH_WPA2_PSK ----> ENC_TYPE_NONE = 7,
  11. * AUTH_WPA_WPA2_PSK ----> ENC_TYPE_AUTO = 8
  12. */
  13. uint8_t encryptionType(uint8_t networkItem);

3.2.4 BSSID —— 获取wifi网络mac地址

函数说明:

  1. /**
  2. * return MAC / BSSID of scanned wifi (物理地址)
  3. * @param i specify from which network item want to get the information
  4. * @return uint8_t * MAC / BSSID of scanned wifi
  5. */
  6. uint8_t * BSSID(uint8_t networkItem);
  7. /**
  8. * return MAC / BSSID of scanned wifi (物理地址)
  9. * @param i specify from which network item want to get the information
  10. * @return uint8_t * MAC / BSSID of scanned wifi
  11. */
  12. String BSSIDstr(uint8_t networkItem);

3.2.5 getNetworkInfo —— 获取整体网络信息,名字,信号强度等

函数说明:

  1. /**
  2. * loads all infos from a scanned wifi in to the ptr parameters
  3. * @param networkItem uint8_t
  4. * @param ssid const char**
  5. * @param encryptionType uint8_t *
  6. * @param RSSI int32_t *
  7. * @param BSSID uint8_t **
  8. * @param channel int32_t *
  9. * @param isHidden bool *
  10. * @return (true if ok)
  11. */
  12. bool getNetworkInfo(uint8_t networkItem, String &ssid, uint8_t &encryptionType, int32_t &RSSI, uint8_t* &BSSID, int32_t &channel, bool &isHidden);

注意点:

  • 入参前面多数加了&,意味着调完函数后外面获取到详细信息;

3.2.6 channel —— 获取wifi网络通道号

函数说明:

  1. /**
  2. * return channel of scanned wifi(通道号)
  3. */
  4. int32_t channel(uint8_t networkItem);

3.2.7 isHidden —— 判断wifi网络是否是隐藏网络

函数说明:

  1. /**
  2. * return if the scanned wifi is Hidden (no SSID)(判断扫描到的wifi是否是隐藏wifi)
  3. * @param networkItem specify from which network item want to get the information
  4. * @return bool (true == hidden)
  5. */
  6. bool isHidden(uint8_t networkItem);

4. 实例操作

    上面博主讲了一堆方法理论的知识,下面我们开始讲解操作实例,博主尽量都在代码中注释,直接看代码就好。

4.1 操作实例1:同步扫描

实例代码:

  1. /**
  2. * Demo:
  3. * STA模式下,演示同步扫描Scan wifi功能
  4. * @author 单片机菜鸟
  5. * @date 2019/09/03
  6. */
  7. #include <ESP8266WiFi.h>
  8. //以下三个定义为调试定义
  9. #define DebugBegin(baud_rate) Serial.begin(baud_rate)
  10. #define DebugPrintln(message) Serial.println(message)
  11. #define DebugPrint(message) Serial.print(message)
  12. void setup() {
  13. //设置串口波特率,以便打印信息
  14. DebugBegin(115200);
  15. //延时5s 为了演示效果
  16. delay(5000);
  17. // 我不想别人连接我,只想做个站点
  18. WiFi.mode(WIFI_STA);
  19. //断开连接
  20. WiFi.disconnect();
  21. delay(100);
  22. DebugPrintln("Setup done");
  23. }
  24. void loop() {
  25. DebugPrintln("scan start");
  26. // 同步扫描,等待返回结果
  27. int n = WiFi.scanNetworks();
  28. DebugPrintln("scan done");
  29. if (n == 0){
  30. DebugPrintln("no networks found");
  31. }else{
  32. DebugPrint(n);
  33. DebugPrintln(" networks found");
  34. for (int i = 0; i < n; ++i){
  35. DebugPrint(i + 1);
  36. DebugPrint(": ");
  37. //打印wifi账号
  38. DebugPrint(WiFi.SSID(i));
  39. DebugPrint(",");
  40. DebugPrint(String("Ch:")+WiFi.channel(i));
  41. DebugPrint(",");
  42. DebugPrint(WiFi.isHidden(i)?"hide":"show");
  43. DebugPrint(" (");
  44. //打印wifi信号强度
  45. DebugPrint(WiFi.RSSI(i));
  46. DebugPrint("dBm");
  47. DebugPrint(")");
  48. //打印wifi加密方式
  49. DebugPrintln((WiFi.encryptionType(i) == ENC_TYPE_NONE)?"open":"*");
  50. delay(10);
  51. }
  52. }
  53. DebugPrintln("");
  54. // 延时5s之后再次扫描
  55. delay(5000);
  56. }

测试结果(博主附近潜在的WiFi热点):

4.2 操作实例2: 异步扫描方式1

实例代码:

  1. /**
  2. * Demo:
  3. * STA模式下,演示异步扫描Scan wifi功能
  4. * @author 单片机菜鸟
  5. * @date 2019/09/03
  6. */
  7. #include <ESP8266WiFi.h>
  8. //以下三个定义为调试定义
  9. #define DebugBegin(baud_rate) Serial.begin(baud_rate)
  10. #define DebugPrintln(message) Serial.println(message)
  11. #define DebugPrint(message) Serial.print(message)
  12. //定义一个扫描时间间隔
  13. #define SCAN_PERIOD 5000
  14. long lastScanMillis;
  15. void setup() {
  16. //设置串口波特率,以便打印信息
  17. DebugBegin(115200);
  18. //延时5s 为了演示效果
  19. delay(5000);
  20. // 我不想别人连接我,只想做个站点
  21. WiFi.mode(WIFI_STA);
  22. //断开连接
  23. WiFi.disconnect();
  24. delay(100);
  25. DebugPrintln("Setup done");
  26. }
  27. void loop() {
  28. long currentMillis = millis();
  29. //触发扫描
  30. if (currentMillis - lastScanMillis > SCAN_PERIOD){
  31. WiFi.scanNetworks(true);
  32. Serial.print("\nScan start ... ");
  33. lastScanMillis = currentMillis;
  34. }
  35. // 判断是否有扫描结果
  36. int n = WiFi.scanComplete();
  37. if(n >= 0){
  38. Serial.printf("%d network(s) found\n", n);
  39. for (int i = 0; i < n; i++){
  40. 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" : "");
  41. }
  42. //打印完一次扫描结果之后 删除内存保存结果
  43. WiFi.scanDelete();
  44. }
  45. }

测试结果:

4.3 操作实例3:异步扫描方式2

实例代码:

  1. /**
  2. * Demo:
  3. * STA模式下,演示异步扫描Scan wifi功能
  4. * @author 单片机菜鸟
  5. * @date 2019/09/03
  6. */
  7. #include <ESP8266WiFi.h>
  8. //以下三个定义为调试定义
  9. #define DebugBegin(baud_rate) Serial.begin(baud_rate)
  10. #define DebugPrintln(message) Serial.println(message)
  11. #define DebugPrint(message) Serial.print(message)
  12. /**
  13. * 打印扫描结果
  14. * @param networksFound 结果个数
  15. */
  16. void prinScanResult(int networksFound){
  17. Serial.printf("%d network(s) found\n", networksFound);
  18. for (int i = 0; i < networksFound; i++)
  19. {
  20. 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" : "");
  21. }
  22. }
  23. void setup() {
  24. //设置串口波特率,以便打印信息
  25. DebugBegin(115200);
  26. //延时5s 为了演示效果
  27. delay(5000);
  28. // 我不想别人连接我,只想做个站点
  29. WiFi.mode(WIFI_STA);
  30. //断开连接
  31. WiFi.disconnect();
  32. delay(100);
  33. DebugPrintln("Setup done");
  34. Serial.print("\nScan start ... ");
  35. WiFi.scanNetworksAsync(prinScanResult);
  36. }
  37. void loop() {
  38. }

测试结果:

5. 总结

    扫描并不是多复杂的功能,分为同步扫描和异步扫描,一般楼主建议用异步扫描方式,不影响代码运行。

ESP8266开发之旅 网络篇⑤ Scan WiFi——ESP8266WiFiScan库的使用的更多相关文章

  1. ESP8266开发之旅 网络篇⑯ 无线更新——OTA固件更新

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  2. ESP8266开发之旅 网络篇⑦ TCP Server & TCP Client

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  3. ESP8266开发之旅 网络篇⑧ SmartConfig——一键配网

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  4. ESP8266开发之旅 网络篇⑨ HttpClient——ESP8266HTTPClient库的使用

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  5. ESP8266开发之旅 网络篇⑩ UDP服务

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  6. ESP8266开发之旅 网络篇⑪ WebServer——ESP8266WebServer库的使用

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  7. ESP8266开发之旅 网络篇⑬ SPIFFS——ESP8266 SPIFFS文件系统

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  8. ESP8266开发之旅 网络篇④ Station——ESP8266WiFiSTA库的使用

    1. 前言     在前面的篇章中,博主给大家讲解了ESP8266的软硬件配置以及基本功能使用,目的就是想让大家有个初步认识.并且,博主一直重点强调 ESP8266 WiFi模块有三种工作模式: St ...

  9. ESP8266开发之旅 网络篇③ Soft-AP——ESP8266WiFiAP库的使用

    1. 前言     在前面的篇章中,博主给大家讲解了ESP8266的软硬件配置以及基本功能使用,目的就是想让大家有个初步认识.并且,博主一直重点强调 ESP8266 WiFi模块有三种工作模式: St ...

随机推荐

  1. Linux 文件/目录操作详解

    目录 Linux 文件/目录操作详解 初识Linux 一.文件/目录显示命令 ls 二.目录创建命令 mkdir 三.目录转移命令 cd 四.当前目录显示命令 pwd 五.文件处理命令 rmdir 六 ...

  2. 接口测试返回数据为JSONP格式时如何处理

    #需要被处理的jsonp数据 JSONP = "jsonpreturn({'c': 1, 'd': 2});" #处理方法 def jsonp_to_json(JSONP): JS ...

  3. SpringSecurity原理剖析与权限系统设计

    Spring Secutity和Apache Shiro是Java领域的两大主流开源安全框架,也是权限系统设计的主要技术选型.本文主要介绍Spring Secutity的实现原理,并基于Spring ...

  4. 从SpringMVC获取用户信息谈起

    Github地址:https://github.com/andyslin/spring-ext 编译.运行环境:JDK 8 + Maven 3 + IDEA + Lombok spring-boot: ...

  5. uptimerobot 监控

    前言 由于搞了多个公共服务于多台vps,需要监控项目稳定性与服务器稳定性,考察了阿里云云监控与uptimerobot,最后选择了uptimerobot 教程 访问官网,注册账号 : https://u ...

  6. Ajax async属性

    async: 默认是true:异步,false:同步. 其他属性扩展: 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为String类型的参数, ...

  7. 设计模式——统一建模语言UML

    目录 一.UML的结构 1.1视图 1.2图 1.3模型元素 二.类图 2.1类与类图 2.2类之间的关系 三.序列图 3.1序列图定义 3.2序列图组成元素与绘制 四.状态图 4.1状态图定义 4. ...

  8. SpringBootSecurity学习(16)前后端分离版之 OAuth2.0 加密配置

    示例代码的改进 前面使用spring cloud security和spring cloud oauth2写了一个第三方授权的例子,例子非常的简单,主要目的是用来熟悉OAuth2.0 申请授权的整个流 ...

  9. CentOS7 Redis5.0.5环境搭建

    CentOS7 Redis5.0.5环境搭建 1基本环境配置 CentOS Linux release 7.6.1810 (Core) redis 5.0.5 1.下载解压redis.通过wget在官 ...

  10. Nebula 架构剖析系列(零)图数据库的整体架构设计

    Nebula Graph 是一个高性能的分布式开源图数据库,本文为大家介绍 Nebula Graph 的整体架构. 一个完整的 Nebula 部署集群包含三个服务,即  Query Service,S ...