美文网首页ESP8266 Arduino物联网开发之旅
ESP8266开发之旅 网络篇⑤ Scan WiFi——ESP8

ESP8266开发之旅 网络篇⑤ Scan WiFi——ESP8

作者: 单片机菜鸟博哥 | 来源:发表于2019-02-13 15:09 被阅读60次

    1.1 前言

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

    1.2 scan WiFi功能

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

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

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

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

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

    1.3 ESP8266WiFiScan库

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

    #include <ESP8266WiFiSTA.h>
    

    只需要引入

    #include<ESP8266WiFi.h>
    

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

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

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


    image

    1.3.1 扫描操作方法

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

    函数说明:

    /**
     * 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);
    

    应用实例:

    //实例代码 这只是部分代码 不能直接使用
    //同步扫描
    int n = WiFi.scanNetworks();//不需要填任何参数
    Serial.println("scan done");
    if (n == 0) {
        Serial.println("no networks found");
    } else {
        Serial.println(" networks found");
    }
    
    1.3.1.2 scanNetworks(async ) —— 异步扫描周边有效wifi网络

    函数说明:

    /**
     * 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();
    }
    
    1.3.1.3 scanNetworksAsync —— 异步扫描周边wifi网络,并回调结果

    函数说明:

    /**
     * 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)
    
    1.3.1.4 scanComplete —— 检测异步扫描的结果

    函数说明:

    /**
     * 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();
    
    1.3.1.5 scanDelete —— 从内存中删掉最近扫描结果

    函数说明:

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

    注意点:

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

    1.3.2 扫描结果方法

    1.3.2.1 SSID —— 获取wifi网络名字

    函数说明:

    /**
     * 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);
    
    1.3.2.2 RSSI —— 获取wifi网络信号强度

    函数说明:

    /**
     * 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);
    
    1.3.2.3 encryptionType —— 获取wifi网络加密方式

    函数说明:

    /**
     * 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);
    
    1.3.2.4 BSSID —— 获取wifi网络mac地址

    函数说明:

    /**
     * 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);
    
    1.3.2.5 getNetworkInfo —— 获取整体网络信息,名字,信号强度等

    函数说明:

    /**
     * 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);
    

    注意点:

    • 入参前面多数加了&,意味着调完函数后外面获取到详细信息;
    1.3.2.6 channel —— 获取wifi网络通道号

    函数说明:

    /**
     * return channel of scanned wifi(通道号)
     */
    int32_t channel(uint8_t networkItem);
    
    1.3.2.7 isHidden —— 判断wifi网络是否是隐藏网络

    函数说明:

    /**
     * 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);
    

    1.4 实例操作

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

    1.4.1 操作实例1:同步扫描

    实例代码:

    /**
     * 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热点):


    image

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

    实例代码:

    /**
     * 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();
      }
    }
    

    测试结果:


    image

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

    实例代码:

    /**
     * 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() {
    }
    

    测试结果:


    image

    1.5 总结

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

    博哥ESP8266 qq交流群:869920142

    image

    相关文章

      网友评论

        本文标题:ESP8266开发之旅 网络篇⑤ Scan WiFi——ESP8

        本文链接:https://www.haomeiwen.com/subject/veldeqtx.html