一. 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模式
1 | WiFi.mode(WIFI_MODE_AP); |
模式定义如下:
1 2 3 4 5 6 7 | 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工作模式
1 | WiFi.getMode(); |
3. 使能/使能STA模式
1 | WiFi.enableSTA(true); |
4. 使能/使能AP模式
1 | WiFi.enableAP(true); |
5. 使能/使能Wifi休眠
1 | WiFi.setSleep(true); |
仅限STA模式, 默认开启休眠, 如果对实时性要求高,应关闭休眠
三. AP热点
1. WIFI AP热点建立 WiFisoftAP()
1 2 3 4 5 6 7 8 9 | 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();
1 2 3 4 5 6 7 8 | 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();
1 2 3 4 5 6 7 8 9 10 | bool WiFiSTAClass::disconnect(bool wifioff = false, bool eraseap = false) 功能: 断开AP热点 参数: wifioff : 为true则还将关闭网络功能, 默认false eraseap : 为true则清空AP热点配置信息, 默认false 返回: 返回wlan状态码 |
4. 一些获取AP热点信息的API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #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");
1 2 3 4 5 6 7 8 | 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()
1 2 3 4 5 6 7 8 9 10 11 | 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 |
1 2 3 4 5 6 7 | WiFi.begin("anny", "20141208"); while (!WiFi.isConnected()) { delay(500); Serial.print("."); } Serial.println("WIFI连接成功!"); |
2. wifi配置
1 2 3 4 5 6 7 8 9 | 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一样
1 2 3 4 5 6 7 8 | bool WiFiSTAClass::disconnect(bool wifioff = false, bool eraseap = false) Disconnect from the network 参数: wifioff 返回: one value of wl_status_t enum |
4. 其他一些获取WIFI信息的API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #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. 设置自动连接
1 2 3 4 5 6 7 8 | 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断开后是否自动尝试重连
1 | bool WiFiSTAClass::setAutoReconnect(bool autoReconnect) |
五. 扫描WIFI
1. 扫描WIFI,返回扫描数量
这个功能默认在阻塞模式下运行,程序会扫描WIFI,期间什么事情都做不了, 可以通过参数设置改为异步模式.
1 2 3 4 5 6 7 8 9 | 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(同步方式)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #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();
1 2 3 4 5 | 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. 清除现有的扫描结果
1 | WiFi.scanDelete(); |
5. 扫描连接WIFI(异步)
采用异步扫描方式, 每隔0.5秒询问一下WiFi.scanComplete();判断是否扫描完毕.
如果扫描完毕,置标志位,停定时器.
触发连接程序, 连接完成后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | #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秒, 如果失败了进入智能配网阶段, 智能配网过程如上??
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #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); } } |
第一次连接时:
手机端也会同步显示:
第二次连接时: