美文网首页熊爸的学习时间
玩转 ESP32 + Arduino (十) WIFI(AP模式

玩转 ESP32 + Arduino (十) WIFI(AP模式

作者: 熊爸天下_56c7 | 来源:发表于2020-09-08 08:07 被阅读0次

    一. WiFi的STA和AP模式指什么?

    ESP8266有三种工作模式,分别为:AP,STA,AP混合STA

    1. AP

    AP,也就是无线接入点,是一个无线网络的创建者,是网络的中心节点。一般家庭或办公室使用的无线路由器就一个AP。

    2. STA

    STA是Station的简称,类似于无线终端,STA本身并不接受无线的接入,它可以连接到AP,简单来说就是和手机连接WIFI热点的工作状态相同,可以连接其它的热点。

    3. AP混合STA

    了解了前两个概念,AP混合STA模式就不难理解了,就是既可以连接到其它的WIFI热点,也可以让别的无线终端连接,这两个过程能同时进行。

    二. 切换模式相关API

    1. 设置WIFI模式

    WiFi.mode(WIFI_MODE_AP);
    

    模式定义如下:

    typedef enum {
        WIFI_MODE_NULL = 0,  /**< null mode */
        WIFI_MODE_STA,       /**< WiFi station mode */
        WIFI_MODE_AP,        /**< WiFi soft-AP mode */
        WIFI_MODE_APSTA,     /**< WiFi station + soft-AP mode */
        WIFI_MODE_MAX
    } wifi_mode_t;
    

    2. 获取WIFI工作模式

    WiFi.getMode();
    

    3. 使能/使能STA模式

    WiFi.enableSTA(true);
    

    4. 使能/使能AP模式

    WiFi.enableAP(true);
    

    5. 使能/使能Wifi休眠

    WiFi.setSleep(true);
    

    仅限STA模式, 默认开启休眠, 如果对实时性要求高,应关闭休眠

    三. AP热点

    1. WIFI AP热点建立 WiFisoftAP()

    bool WiFiAPClass::softAP(const char *ssid, const char *passphrase = (const char *)__null, int channel = 1, int ssid_hidden = 0, int max_connection = 4)
    
    功能:建立AP热点
    参数:
    ssid – WIFI名称SSID (max 63 char).
    passphrase – WIFI密码(for WPA2 min 8 char, for open use NULL)
    channel – WiFi 信道, 1 - 13.(默认1)
    ssid_hidden – 是否隐藏WIFI名 (0 = broadcast SSID, 1 = hide SSID) 默认0,不隐藏
    max_connection – 最大可连接数, 1 - 4. 默认4
    

    2. 配置AP 热点 WiFi.softAPConfig();

    bool WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet)
    
    功能: 配置AP 热点
    
    参数:
    local_ip – 本地IP 192.168.4.1
    gateway – 网关IP 192.168.4.1
    subnet – 子网掩码 255.255.255.0
    

    3. 断开wifi WiFi.disconnect();

    bool WiFiSTAClass::disconnect(bool wifioff = false, bool eraseap = false)
    
    功能: 断开AP热点
    
    参数:
    wifioff : 为true则还将关闭网络功能, 默认false 
    eraseap : 为true则清空AP热点配置信息, 默认false 
    
    返回:
    返回wlan状态码
    

    4. 一些获取AP热点信息的API

    #include <Arduino.h>
    #include "WiFi.h"
    void setup()
    {
      Serial.begin(115200);
      WiFi.softAP("ESP_AP", "12345678");
    }
    void loop()
    {
      Serial.print("主机名:");
      Serial.println(WiFi.softAPgetHostname());
      Serial.print("主机IP:");
      Serial.println(WiFi.softAPIP());
      Serial.print("主机IPV6:");
      Serial.println(WiFi.softAPIPv6());
      Serial.print("主机SSID:");
      Serial.println(WiFi.SSID());
      Serial.print("主机广播IP:");
      Serial.println(WiFi.softAPBroadcastIP());
      Serial.print("主机mac地址:");
      Serial.println(WiFi.softAPmacAddress());
      Serial.print("主机连接个数:");
      Serial.println(WiFi.softAPgetStationNum());
      Serial.print("主机网络ID:");
      Serial.println(WiFi.softAPNetworkID());
      Serial.print("主机状态:");
      Serial.println(WiFi.status());
      delay(1000);
    }
    

    5. 设置主机名称 WiFi.softAPsetHostname("ESP_xiongba");

    bool WiFiAPClass::softAPsetHostname(const char *hostname)
    Set the softAP interface Host name.
    
    参数:
    hostname – pointer to const string
    
    返回:
    true on success
    

    四. STA模式

    1. 开始wifi连接 WiFi.begin()

    wl_status_t WiFiSTAClass::begin(const char *ssid, const char *passphrase = (const char *)__null, int32_t channel = 0, const uint8_t *bssid = (const uint8_t *)__null, bool connect = true)
    还有 2 个重载
    
    启动Wifi连接如果设置了密码短语,将自动选择最安全的支持模式
    
    参数:
    ssid – WIFI名, const char* Pointer to the SSID string.
    passphrase – 密码, const char * Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal).
    channel – (AP的通道, 可选参数)Optional. Channel of AP
    bssid – BSSID是指站点的MAC地址(可选参数) uint8_t[6] Optional. BSSID / MAC of AP
    connect – (是否连接此WIFI, 可选参数)Optional. call connect
    
      WiFi.begin("anny", "20141208");
      while (!WiFi.isConnected())
      {
        delay(500);
        Serial.print(".");
      }
      Serial.println("WIFI连接成功!");
    

    2. wifi配置

    bool WiFiSTAClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0, IPAddress dns2 = (uint32_t)0)
    Change IP configuration settings disabling the dhcp client
    
    参数:
    local_ip – 当地IP, Static ip configuration
    gateway – 网关, Static gateway configuration
    subnet – 子网掩码, Static Subnet mask
    dns1 – DNS服务器1, Static DNS server 1
    dns2 – DNS服务器2, Static DNS server 2
    

    3. 关闭wifi连接

    用法和AP的disconnect一样

    bool WiFiSTAClass::disconnect(bool wifioff = false, bool eraseap = false)
    Disconnect from the network
    
    参数:
    wifioff
    
    返回:
    one value of wl_status_t enum
    

    4. 其他一些获取WIFI信息的API

    #include <Arduino.h>
    #include "WiFi.h"
    void setup()
    {
      Serial.begin(115200);
      // WiFi.softAP("ESP_AP", "12345678");
      // WiFi.softAPsetHostname("ESP_xiongba");
      WiFi.begin("anny", "20141208");
      WiFi.setAutoReconnect(true);
    }
    void loop()
    {
      Serial.print("是否连接:");
      Serial.println(WiFi.isConnected());
      Serial.print("本地IP:");
      Serial.println(WiFi.localIP());
      Serial.print("本地IPv6:");
      Serial.println(WiFi.localIPv6());
      Serial.print("mac地址:");
      Serial.println(WiFi.macAddress());
      Serial.print("网络ID:");
      Serial.println(WiFi.networkID());
      Serial.print("休息:");
      Serial.println(WiFi.getSleep());
      Serial.print("获取状态吗:");
      Serial.println(WiFi.getStatusBits());
      Serial.print("getTxPower:");
      Serial.println(WiFi.getTxPower());
      Serial.print("是否自动连接:");
      Serial.println(WiFi.getAutoConnect());
      Serial.print("是否自动重连:");
      Serial.println(WiFi.getAutoReconnect());
      Serial.print("获取模式:");
      Serial.println(WiFi.getMode());
      Serial.print("获取主机名:");
      Serial.println(WiFi.getHostname());
      Serial.print("获取网关IP:");
      Serial.println(WiFi.gatewayIP());
      Serial.print("dnsIP:");
      Serial.println(WiFi.dnsIP());
      Serial.print("状态:");
      Serial.println(WiFi.status());
      delay(1000);
    }
    
    连接瞬间的状态变化

    关于状态码, 请看下面解释:

    5. 设置自动连接

    bool WiFiSTAClass::setAutoReCoennect(bool autoConnect)
    Setting the ESP32 station to connect to the AP (which is recorded)automatically or not when powered on. Enable auto-connect by default.
    
    参数:
    autoConnect – bool
    
    返回:
    if saved
    

    6. 设置自动重连

    设置WIFI断开后是否自动尝试重连

    bool WiFiSTAClass::setAutoReconnect(bool autoReconnect)
    

    五. 扫描WIFI

    1. 扫描WIFI,返回扫描数量

    这个功能默认在阻塞模式下运行,程序会扫描WIFI,期间什么事情都做不了, 可以通过参数设置改为异步模式.

    int16_t WiFiScanClass::scanNetworks(bool async = false, bool show_hidden = false, bool passive = false, uint32_t max_ms_per_chan = 300U)
    Start scan WiFi networks available
    
    参数:
    async – run in async mode
    show_hidden – show hidden networks
    
    返回:
    Number of discovered networks
    

    只返回了扫描到的WIFI的数量, 那结果怎么得到? 原来他已经将扫描到的WIFI存入了WIFI单例对应的数组中.
    比如 SSID,都存入了 WiFi.SSID中,可以通过索引值遍历获取. 其他属性亦然.

    2. 扫描连接WIFI(同步方式)

    #include <Arduino.h>
    #include "WiFi.h"
    
    String ssid;
    String password;
    void setup()
    {
      Serial.begin(115200);
      WiFi.mode(WIFI_MODE_STA);
      WiFi.disconnect(); //断开可能的连接
      delay(100);
      Serial.println("开始扫描WIFI:");
      int n = WiFi.scanNetworks();
      if (n)
      {
        Serial.print("扫描到");
        Serial.print(n);
        Serial.println("个WIFI");
        for (size_t i = 0; i < n; i++)
        {
          Serial.print("WiFi的名称(SSID):");
          Serial.println(WiFi.SSID(i));
          Serial.print("WiFi的信号强度(RSSI):");
          Serial.println(WiFi.RSSI(i));
          Serial.print("WiFi加密与否:");
          Serial.println(WiFi.encryptionType(i) == WIFI_AUTH_OPEN ? "未加密" : "加密");
    
          if (WiFi.SSID(i) == "anny")
          {
            ssid = WiFi.SSID(i);
            password = "20141208";
          }
        }
      }
      else
      {
        Serial.println("没扫描到WIFI");
      }
      WiFi.begin(ssid.c_str(), password.c_str());
      while (!WiFi.isConnected())
      {
        Serial.print(".");
      }
      Serial.println("连接成功");
    }
    void loop()
    {
    }
    

    3. 异步模式时,获取扫描完成信息 WiFi.scanComplete();

    int16_t WiFiScanClass::scanComplete()
    called to get the scan state in Async mode
    
    返回:
    scan result or status -1 if scan not fin -2 if scan not triggered
    

    如果没用扫描完成, 则返回-1 , 如果根本没在扫描,返回-2
    如果完成了扫描,返回扫描结果

    4. 清除现有的扫描结果

    WiFi.scanDelete();
    

    5. 扫描连接WIFI(异步)

    采用异步扫描方式, 每隔0.5秒询问一下WiFi.scanComplete();判断是否扫描完毕.
    如果扫描完毕,置标志位,停定时器.
    触发连接程序, 连接完成后

    #include <Arduino.h>
    #include "WiFi.h"
    #include "Ticker.h"
    
    String ssid = "";
    String password = "";
    Ticker t1;
    
    void aysncScanHandler()
    {
      if (!WiFi.isConnected())
      {
        int wifiScanStatus = WiFi.scanComplete();
        switch (wifiScanStatus)
        {
        case -1:
          Serial.println("扫描中...");
          break;
        case -2:
          Serial.println("未进行扫描...");
          break;
        default:
          Serial.println("扫描完成");
          for (size_t i = 0; i < wifiScanStatus; i++)
          {
            Serial.print("WiFi的名称(SSID):");
            Serial.println(WiFi.SSID(i));
            Serial.print("WiFi的信号强度(RSSI):");
            Serial.println(WiFi.RSSI(i));
            Serial.print("WiFi加密与否:");
            Serial.println(WiFi.encryptionType(i) == WIFI_AUTH_OPEN ? "未加密" : "加密");
    
            if (WiFi.SSID(i) == "anny")
            {
              ssid = WiFi.SSID(i);
              password = "20141208";
            };
          }
          WiFi.scanDelete();
          t1.detach();
          break;
        }
      }
    }
    
    void connectAnny()
    {
      WiFi.begin();
      while (!WiFi.isConnected())
      {
        Serial.print(".");
      }
      Serial.println("连接成功");
    }
    
    void setup()
    {
      Serial.begin(115200);
      WiFi.mode(WIFI_MODE_STA);
      WiFi.disconnect(); //断开可能的连接
      delay(100);
      Serial.println("开始扫描WIFI:");
      WiFi.scanNetworks(true);
      t1.attach(0.5, aysncScanHandler);
    }
    void loop()
    {
      if (!WiFi.isConnected())
      {
        if (ssid == "anny")
        {
          Serial.println(ssid);
          connectAnny();
        }
      }
    }
    

    六. 智能配网

    1. 什么是智能配网

    智能配网这种快速连接方式,相对于 AP 模式连接简化操作,更加贴近于市场

    1、手机连上 WiFi,打开智能硬件指定 APP 软件,进入配置界面,输入手机所在 WiFi 密码,请求配网 TOKEN
    2、智能硬件开启混杂模式监听所有网络数据包
    3、手机通过广播、组播循环发送 ssid/password/token
    4、硬件设备通过 UDP 包(长度)获取配置信息捕捉到 ssid/password/token,报文后解码,得到正确的 SSID 和密码,然后主动连接指定 SSID 的路由完成连接。

    2. 智能配网过程

    进入智能配网模式后, 用手机微信扫描安信可官方二维码

    输入WIFI密码

    微信会广播这些信息,

    ESP32获取后得知 WIFI名, 密码. 自动存储好. 自动连接WIFI

    3. 示例, 智能配网过程

    思路: 先自动联网20秒, 如果失败了进入智能配网阶段, 智能配网过程如上👆

    #include <Arduino.h>
    #include "WiFi.h"
    
    void mySmartWifiConfig()
    {
      WiFi.mode(WIFI_MODE_STA);
      Serial.println("开启智能配网:");
      WiFi.beginSmartConfig();
      while (1)
      {
        Serial.print(".");
        delay(500);
        if (WiFi.smartConfigDone())
        {
          Serial.println("配网成功");
          Serial.printf("SSID:%s", WiFi.SSID().c_str());
          Serial.printf("PSW:%s", WiFi.psk().c_str());
          break;
        }
      }
    }
    
    bool autoConfig()
    {
      WiFi.disconnect(true,true);
      WiFi.begin();
      for (size_t i = 0; i < 20; i++)
      {
        int wifiStatus = WiFi.status();
        if (wifiStatus == WL_CONNECTED)
        {
          Serial.println("自动连接成功!");
          return 1;
        }
        else
        {
          delay(1000);
          Serial.println("等待自动配网中...");
        }
      }
      Serial.println("无法自动配网!");
      return 0;
    }
    
    void setup()
    {
      Serial.begin(115200);
      delay(5000);
      if (!autoConfig())
      {
        mySmartWifiConfig();
      }
    }
    void loop()
    {
      if (WiFi.isConnected())
      {
        Serial.println("网络已连接");
        delay(1000);
      }
    }
    

    第一次连接时:

    手机端也会同步显示:

    第二次连接时:

    相关文章

      网友评论

        本文标题:玩转 ESP32 + Arduino (十) WIFI(AP模式

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