玩轉 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閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380