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

一. 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);
  }
}

第一次连接时:

手机端也会同步显示:

第二次连接时:

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,376评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,126评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,966评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,432评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,519评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,792评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,933评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,701评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,143评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,488评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,626评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,292评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,896评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,494评论 2 348