1. 程式人生 > >【IoT】物聯網之 WIFI 一鍵配網 smartConfig 淺析(ESP32)

【IoT】物聯網之 WIFI 一鍵配網 smartConfig 淺析(ESP32)

一、背景

物聯網時代技術開始規模化服務於民眾,方便快捷顯得尤為重要,WIFI 直連便是一個典型案例。

目前主流的 WIFI 配置模式有以下 2 種:

1、智慧硬體處於 AP 模式(類似路由器,組成區域網),手機用於 STA 模式

手機連線到處於 AP 模式的智慧硬體後組成區域網,手機發送需要連線路由的 SSID 及密碼至智慧硬體,智慧硬體主動去連線指定路由後,完成配網

2、一鍵配網(smartConfig)模式

智慧硬體處於混雜模式下,監聽網路中的所有報文;手機 APP 將 SSID 和密碼編碼到 UDP 報文中,通過廣播包或組播報傳送,智慧硬體接收到 UDP 報文後解碼,得到正確的 SSID 和密碼,然後主動連線指定 SSID 的路由完成連線。

AP 模式:

AP 是 (Wireless) Access Point 的縮寫,即 (無線) 訪問接入點。簡單來講就像是無線路由器一樣,裝置開啟後進入 AP 模式,在手機的網路列表裡面,可以搜尋到類似 TPLINK_XXX 的名字(SSID)。

連線步驟:

1、智慧硬體裝置初始化並進入 AP 模式
2、手機掃描 WIFI 列表:掃描到智慧硬體裝置後(SSID)連線該智慧硬體裝置,通過 UDP 傳送 經過 AES 加密過的 ssid/password/token
3、智慧硬體裝置通過 UDP 包獲取配置資訊,切換網路模式連線 WIFI 後配網完成

smartConfig 模式:

這種快速連線方式,相對於 AP 模式連線簡化操作,更加貼近於市場

1、手機連上 WiFi,開啟智慧硬體指定 APP 軟體,進入配置介面,輸入手機所在 WiFi 密碼,請求配網 TOKEN
2、智慧硬體開啟混雜模式監聽所有網路資料包
3、手機通過廣播、組播迴圈傳送 ssid/password/token
4、硬體裝置通過 UDP 包(長度)獲取配置資訊捕捉到 ssid/password/token,連線路由器(廣播根據 UDP 包長度,組播根據 IP 地址資訊)


從原理上講只要晶片驅動支援開啟混雜模式(WiFi Promiscuous),就可以支援一鍵配網功能

手機編碼傳送採用有 UDP 組播或廣播,不同的傳送方式和編碼,對應的解碼過程也不一樣

1、廣播:

傳送方可通過改變其所需要傳送資料包的長度進行控制,因此只要指定出一套利用長度編碼的通訊協議,就可利用資料包的 Length 欄位進行資料傳遞

2、 組播:

組播地址是保留的 D 類地址從224.0.0.0-239.255.255.255

IP 地址與 MAC 地址對映關係為:將 MAC 地址的前 25 位設定為 01.00.5e,而 MAC 地址的後 23 位對應 IP 地址位

故傳送端可以將資料編碼在組播 IP 的後 23bit 中,通過組播包傳送接收端進行解碼即可

二、smartConfig 原理淺析

在沒有和其他裝置(支援 smartConfig 技術)建立任何性質的通訊鏈路的情況下, 配置該裝置接入 WIFI 網路 

普通許可權的應用程式是沒有能力完全控制和定義傳輸層及下層所有協議資料的, 唯一可以完全控制的就是應用層資料

本質上就是將 UDP 包頭的資料長度作為 smartConfig 的資料,APP 端和裝置端共用一套編碼表即可解析資料 

TCP/IP 協議棧中的網路層和傳輸層的資料結構 

常用的網路層協議是 IPv4, IPv4 的頭部絕大多數情況下都是定長的20位元組

傳輸層協議是 UDP, 因為 UDP 協議頭部為定長的 8 位元組

明文長度 = 20 + 8 + dataLen

密文長度 = 20 + 8 + dataLen + 演算法常量

例子:

如果需要發出一個密文長度為 500 位元組的 802.11 幀,只需要在 UDP 中填充任意(500 – 20 – 8 – 演算法常亮)個位元組資料即可

因此,只需要利用可控的密文長度(dataLen)定義一張編碼表即可將資料告訴任何知道這張編碼表的裝置(IoT硬體裝置)

自定義一張編碼表,流程如下:

dataLen --> 對映
1234    --> 起始符; 連續的3個起始符, 用於表示資料傳輸開始 
1324    --> 結束符; 連續的3個結束符, 用於表示資料傳輸結束 
110     --> 間隔符; 連續的2個間隔符, 用於表示資料符之間的間隔 
1000    --> 資料符; 表示 ASCII 0x00 
1001    --> 資料符; 表示 ASCII 0x01 
… 
1127    --> 資料符; 表示 ASCII 0x7F

假設我們要把字串"Jay"告訴攝像頭, 整個流程大致如下: (假設演算法常亮為 16)

APP 端:
 
開啟手機 APP, 在輸入框中填入要傳送的字串”Jay”, 點擊發送:

1.1、APP 連續傳送 3 個 UDP 廣播包, 填充資料為 1190 個位元組 0x00 資料 ( 1234 – 16 – 20 – 8 = 1190 ), 表示傳輸開始 
1.2、APP 傳送     1 個 UDP 廣播包, 填充資料為 1030 個位元組 0x00 資料 ( 1074 – 16 -20 – 8 = 1030  ), 傳輸字元 J 
1.3、APP 連續傳送 2 個 UDP 廣播包, 填充資料為 66   個位元組 0x00 資料 ( 110 – 16 – 20 – 8 = 66    ), 表示資料間隔 
1.4、APP 傳送     1 個 UDP 廣播包, 填充資料為 1053 個位元組 0x00 資料 ( 1097 – 16 -20 – 8 = 1053  ), 傳輸字元 1097 對應 a 
1.5、APP 連續傳送 2 個 UDP 廣播包, 填充資料為 66   個位元組 0x00 資料 ( 110 – 16 – 20 – 8 = 66    ), 表示資料間隔 
1.6、APP 傳送     1 個 UDP 廣播包, 填充資料為 1077 個位元組 0x00 資料 ( 1121 – 16 -20 – 8 = 1077  ), 傳輸字元 1121 對應 y 
1.7、APP 連續傳送 3 個 UDP 廣播包, 填充資料為 1280 個位元組 0x00 資料 ( 1324- 16 – 20 – 8 = 1280  ), 表示傳輸結束

從步驟 1.1 開始迴圈多次, 直到超時或 IoT 裝置成功接入 WIFI

IoT 裝置端:

裝置上電進入混雜模式,開始監聽訊號覆蓋範圍內的所有 WIFI 資料幀

捕獲資料幀, 如果連續收到 3 個密文,其資料長度 dataLen 為 1234 位元組, 且來自於同一個發射源 channel-A 的資料幀, 則進入下一步, 否則該步驟

捕獲發射源 channel-A 的資料幀, 持續捕獲密文資料長度為 110 或 1000-1127 之間的資料幀, 直到捕獲到連續 3 個密文資料長度為 1324 的資料幀

將上述資料幀按照編碼表進行對映, 由於手機 APP 並非是獨佔網路, 所以捕獲到的資料可能有噪音, 比如解碼出來的結果可能是(/表示分隔符): mnJ/[email protected]/ymmm

如果沒有噪音, 記為候選資料RC, 重複捕獲X, 進行二次驗證, 通過則表示接收完成, 沒通過也重複捕獲 channel-A,

將這次所得結果同上一次做交集, 迴圈如此直到得出唯一結果, 即 RC, 之後再重複 5

由於捕獲的資料幀頭部資訊中已經包含了 WIFI 的 BSSID 資訊, 使用 "Jay" 作為密碼去嘗試連線相應的 WIFI

三、ESP32 配網例項:

手機 APP:

燒寫裝置端:

#include "WiFi.h"

void setup() {
  Serial.begin(115200);

  //Init WiFi as Station, start SmartConfig
  WiFi.mode(WIFI_AP_STA);
  WiFi.beginSmartConfig();

  //Wait for SmartConfig packet from mobile
  Serial.println("Waiting for SmartConfig.");
  while (!WiFi.smartConfigDone()) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("SmartConfig received.");

  //Wait for WiFi to connect to AP
  Serial.println("Waiting for WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("WiFi Connected.");

  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  // put your main code here, to run repeatedly:

}

四、知識擴充套件

在當前網路通訊中有三種通訊模式:

單播、廣播、組播(又叫多播),其中多播出現的時間最晚,但同時具備單播和廣播的優點,最具有發展前景.

通訊方式分類:

    1.單播:單臺主機與單臺主機之間的通訊;

    2.廣播:單臺主機與網路中所有主機的通訊;

    3.組播:單臺主機與選定的一組主機的通訊;

單播:

     單播是網路通訊中最常見的,網路節點之間的通訊 就好像是人們之間的對話一樣,如果一個人對另外一個人說話,那麼用網路技術的術語來描述就是“單播”,此時資訊的接收和傳遞只在兩個節點之間進行。

     1. 單播的優點:

         (1)伺服器以及響應客戶端的請求;

         (2)伺服器能針對每個客戶端的不同請求傳送不同的響應,容易顯示個性化服務;

     2. 單播的缺點:

         伺服器針對每個客戶機發送資料流,伺服器流量=客戶機數量×客戶機流量;在客戶數量大、每個客戶機流量大的流媒體應用中伺服器不堪重負;

     3. 應用場景:

        單播在網路中得到了廣泛的應用,網路上絕大部分的資料都是以單播的形式傳輸的,例如:收發電子郵件、遊覽網頁時,必須與郵件伺服器、伺服器建立連線,此時使用的就是單播通訊方式;

UDP 單播:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
 
// 客戶端
public class ClientTest
{
    private static final int MAXRECEIVED = 255;
 
    public static void main(String[] args) throws IOException
    {
        byte[] msg = new String("connect test successfully!!!").getBytes();
 
        DatagramSocket client = new DatagramSocket();
 
        InetAddress inetAddr = InetAddress.getLocalHost();
        SocketAddress socketAddr = new InetSocketAddress(inetAddr, 8888);
 
        DatagramPacket sendPacket = new DatagramPacket(msg, msg.length,
                socketAddr);
 
        client.send(sendPacket);
 
        client.close();
    }
}
 
 
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Arrays;
 
//服務端
public class ServerTest
{
    private static final int MAXREV = 255;
 
    public static void main(String[] args) throws IOException
    {
        DatagramSocket server = new DatagramSocket(8888);
        DatagramPacket recvPacket = new DatagramPacket(new byte[MAXREV], MAXREV);
 
        while (true)
        {
            server.receive(recvPacket);
 
            byte[] receiveMsg = Arrays.copyOfRange(recvPacket.getData(),
                    recvPacket.getOffset(),
                    recvPacket.getOffset() + recvPacket.getLength());
 
            System.out.println("Handing at client "
                    + recvPacket.getAddress().getHostName() + " ip "
                    + recvPacket.getAddress().getHostAddress());
 
            System.out.println("Server Receive Data:" + new String(receiveMsg));
 
            server.send(recvPacket);
 
        }
 
    }
}

廣播:

    廣播可以比作為一個人通過廣播喇叭對在場的全體說話,換句話說: 廣播是一臺主機對某一個網路上的所有主機發送資料報包。

    這個網路可能是網路,也可能時子網,還有可能是所有子網。

    廣播有兩類:本地廣播和定向廣播:

            定向廣播:將資料報包傳送到本網路之外的特定網路的所有主機,網際網路上的大部分路由器都不轉發定向廣播訊息;

            本地廣播:將資料報包傳送到本地網路的所有主機,IPv4的本地廣播地址為“255.255.255.255”,路由器不會轉發此廣播;

    1.廣播的優點:

       (1)通訊的效率高,資訊一下子就可以傳遞到某一個網路上的所有主機。

       (2)由於伺服器不用向每個客戶端單獨傳送資料,所以伺服器流量比較負載低;

    2.廣播的缺點:

       (1)非常佔用網路的頻寬;

       (2)缺乏針對性,也不管主機是否真的需要接收該資料, 就強制的接收資料;

    3.應用場景:

       有線電視就是典型的廣播型網路

UDP 廣播:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
 
//客戶端
public class BroadcastSender
{
    public static void main(String[] args) throws IOException
    {
        byte[] msg = new String("connection successfully!!!").getBytes();
        /*
         * 在Java UDP中單播與廣播的程式碼是相同的,要實現具有廣播功能的程式只需要使用廣播地址即可, 例如:這裡使用了本地的廣播地址
         */
        InetAddress inetAddr = InetAddress.getByName("255.255.255.255");
        DatagramSocket client = new DatagramSocket();
 
        DatagramPacket sendPack = new DatagramPacket(msg, msg.length, inetAddr,
                8888);
 
        client.send(sendPack);
        System.out.println("Client send msg complete");
        client.close();
    }
}
 
 
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Arrays;
 
//服務端
public class BroadcastReceive
{
    public static void main(String[] args) throws IOException
    {
 
        DatagramPacket receive = new DatagramPacket(new byte[1024], 1024);
        DatagramSocket server = new DatagramSocket(8888);
 
        System.out.println("---------------------------------");
        System.out.println("Server current start......");
        System.out.println("---------------------------------");
 
        while (true)
        {
            server.receive(receive);
 
            byte[] recvByte = Arrays.copyOfRange(receive.getData(), 0,
                    receive.getLength());
 
            System.out.println("Server receive msg:" + new String(recvByte));
        }
 
    }
}

組播:

     組播可以比作為你對著大街喊:女士免費領優惠券,那麼女士就會過來,男士就不會過來(組播:其中所有的女士就是一個組)

     換句話說: 
     
     組播是一臺主機向指定的一組主機發送資料報包,因為如果採用單播方式,逐個節點傳輸,有多少個目標節點就會有多少次傳送過程,這種方式顯然效率極低,是不可取的;
     
     如果採用不區分目標、全部發送的廣播方式,雖然一次可以傳送完資料,但是顯然達不到區分特定資料接收物件的目的,又會佔用網路頻寬。
     
     採用組播方式,既可以實現一次傳送所有目標節點的資料,也可以達到只對特定物件傳送資料的目的;

     IP 網路的組播一般通過組播 IP 地址來實現,組播 IP 地址就是 D 類 IP 地址,即 224.0.0.0 至 239.255.255.255 之間的IP地址。

     1.組播的優點:

        (1)具備廣播所具備的所有優點;

        (2)與單播相比,提供了傳送資料報包的效率,與廣播相比,減少了網路流量;

     2.組播的缺點:

        與單播協議相比沒有糾錯機制,發生丟包錯包後難以彌補,但可以通過一定的容錯機制和QOS加以彌補;

UDP 組播:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
 
//客戶端
public class MulticastSender
{
    public static void main(String[] args) throws IOException
    {
        int port = 8888;
        byte[] msg = "Connection successfully!!!".getBytes();
 
        InetAddress inetRemoteAddr = InetAddress.getByName("224.0.0.5");
 
        /*
         * Java UDP組播應用程式主要通過MulticastSocket例項進行通訊,它是DatagramSocket的是一個子類,
         * 其中包含了一些額外的可以控制多播的屬性.
         * 
         * 注意:
         * 
         * 多播資料報包實際上可以通過DatagramSocket傳送,只需要簡單地指定一個多播地址。
         * 我們這裡使用MulticastSocket,是因為它具有DatagramSocket沒有的能力
         */
        MulticastSocket client = new MulticastSocket();
 
        DatagramPacket sendPack = new DatagramPacket(msg, msg.length,
                inetRemoteAddr, port);
 
        client.send(sendPack);
 
        System.out.println("Client send msg complete");
 
        client.close();
 
    }
}
 
 
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.Arrays;
 
//服務端
public class MulticastReceive
{
    public static void main(String[] args) throws IOException
    {
        InetAddress inetRemoteAddr = InetAddress.getByName("224.0.0.5");
 
        DatagramPacket recvPack = new DatagramPacket(new byte[1024], 1024);
 
        MulticastSocket server = new MulticastSocket(8888);
 
        /*
         * 如果是傳送資料報包,可以不加入多播組; 如果是接收資料報包,必須加入多播組; 這裡是接收資料報包,所以必須加入多播組;
         */
        server.joinGroup(inetRemoteAddr);
 
        System.out.println("---------------------------------");
        System.out.println("Server current start......");
        System.out.println("---------------------------------");
 
        while (true)
        {
            server.receive(recvPack);
 
            byte[] recvByte = Arrays.copyOfRange(recvPack.getData(), 0,
                    recvPack.getLength());
 
            System.out.println("Server receive msg:" + new String(recvByte));
        }
 
    }
}

refer:

https://wenku.baidu.com/view/ab6bc08a9b6648d7c0c746ac.html
https://blog.csdn.net/sadshen/article/details/47049129

https://my.oschina.net/u/2396236/blog/1788674
https://blog.csdn.net/li_yangyang_li/article/details/50989220
https://blog.csdn.net/flyingcys/article/details/49283273

相關推薦

IoT聯網 WIFI smartConfig 淺析ESP32

一、背景 物聯網時代技術開始規模化服務於民眾,方便快捷顯得尤為重要,WIFI 直連便是一個典型案例。 目前主流的 WIFI 配置模式有以下 2 種: 1、智慧硬體處於 AP 模式(類似路由器,組成區域網),手機用於 STA 模式 手機連線到處於 AP 模式的智慧硬體後

wifismartconfig原理及應用

智慧家居/家電現階段還處於普及階段,由於家庭wifi網路的普及,目前普遍採用wifi與路由器完成連線,與手機/雲端進行資料互動. 智慧硬體,如智慧插座,智慧空調,智慧空氣淨化器由於不具備人機互動介面,

ESP32的SDK開發blufi

            ESP32 是整合 2.4 GHz Wi-Fi 和藍芽雙模的單晶片方案,採用臺積電 (TSMC) 超低功耗的 40 納米工藝,擁有最 佳的功耗效能、射頻效能、穩定性、通用性和可靠性,適用於各種應用和不同功耗需

Esp8266進階路17 esp8266自研的快速上電開關五次 (開-關為次) ,無需按鍵觸發則8266進去模式。附帶Demo

本系列部落格學習由非官方人員 半顆心臟 潛心所力所寫,僅僅做個人技術交流分享,不做任何商業用途。如有不對之處,請留言,本人及時更改。 很多人怎麼聯絡我一起學習進步,下面打個小小公告:

連載聯網全棧教程-從雲端到裝置---呼叫阿里雲API,獲取的屬性。

物聯網全棧教程-從雲端到裝置(十一)一千千萬萬的物聯網裝置通過ALink協議接入到了雲端,它們不斷地按照ALink協議的規範向雲端彙報資料,同時也一直在等待伺服器下發一些資料並處理這些資料。關於物聯網裝置端如何搞定這些資料,零妖老哥會在下一篇文章中以一個型號叫做STM32F1

聯網常見通訊協議

轉載地址:https://www.jianshu.com/p/f3f1a35f64cc 1  “通訊”與“通訊”傻傻分得清 傳統意義上的“通訊”主要指電話、電報、電傳。通訊的“訊”指訊息(Message),媒體訊息通過通訊網路從一端傳遞到另外一端。媒體訊息的

Spring核心BeanFactory 張圖看懂getBean全過程

Spring通過資源載入器載入相應的XML檔案,使用讀取器讀取資源載入器中的檔案到讀取器中,在讀取過程中,解析相應的xml檔案元素,轉化為spring定義的資料結BeanDefinition,把相應的BeanDefinition註冊到登錄檔中。登錄檔中包含的BeanDefinition的資料結構,沒有經過加工

IoTISO7816 NFC CPU 卡操作命令淺析

廠家初始設定外部認證金鑰為  FF FF FF FF FF FF FF FF 1、外部認證    1.1、取 4 位元組隨機數 00 84 00 00 04       1.2、程式用外部認證祕鑰 FFFFFFFFFFFFFFFF 和獲取的 4 位元組隨機數加密,生成 8

分類 - 聯網感知技術

專欄達人 授予成功建立個人部落格專欄

FPGA FIR 濾波器Single-rate FIR濾波器的係數資料Filter Coefficient Data

首先要明確什麼是單速率 FIR 濾波器? The basic FIR filter core is a single-rate (input sample rate = output sample rate) finite impulse response filter.

Docker在IDEA中實現部署到伺服器(附ssl連線加密)

近年來微服務可謂是火遍大江南北,隨著業務的拆分和高可用和叢集,服務變得越來越多,不再像原來的單體應用架構那樣,部署只需要執行一條nohup java -jar xx.jar &就可以完成部署,如果在微服務裡還是用這種方式完成部署的話那就太low太耗時間了,Dock

原創源碼角度分析Android的消息機制系列——ThreadLocal的工作過程

機制 simple hand 這就是 數據存儲 read etc lena 並且 ι 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 在上一篇文章中,我們已經提到了ThreadLocal,它並非線程,而是在線程中存儲數據用的。數據存儲以後,只能在指定的線程中獲取到數據

原創源碼角度分析Android的消息機制系列——ThreadLocal的工作原理

沒有 cit gen 管理 pre 靜態 bsp 允許 clas ι 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 先看Android源碼(API24)中對ThreadLocal的定義: public class ThreadLocal<T>

原創源碼角度分析Android的消息機制系列——MessageQueue的工作原理

enc 容易 工作 trie oss 當前 within which ptime ι 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 MessageQueue,主要包含2個操作:插入和讀取。讀取操作會伴隨著刪除操作,插入和讀取對應的方法分別為enqueueMes

原創源碼角度分析Android的消息機制系列——Handler的工作原理

urn long empty isa pat stat 開啟 it is performed ι 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 先看Handler的定義: /** * A Handler allows you to send and proc

思維Codeforces Round #485 (Div. 2) B. High School: Become Human對數

space scanf CA ace ima AC bsp ont http 題目鏈接:http://codeforces.com/contest/987/problem/B 在運算的時候取對數就好了 1 #include <bits/stdc++

轉載掌握 HTTP 快取——從請求到響應過程的一切

作者:Ulrich Kautz  編譯:鬍子大哈 翻譯原文:http://huziketang.com/blog/posts/detail?postId=58b77935204d50674934c3ad  英文原文:Mastering HTTP Caching - from

原始碼MATLAB的BMS工具箱:貝葉斯模型平均BMA

Zellner g先驗條件下線性模型的貝葉斯模型平均 Bayesian Model Averaging for linear modelsunder Zellner’s g prior. 可選項包括:固定的(BRIC,UIP, …)和可調的g先驗(經驗貝葉斯,hyper-g)、

MPC5744PS32DS中Processor Expert自動生成程式碼工具使用教程 FreeMaster除錯

對於使用除錯口,下位機不需要做任何特別的設定,直接按照連結中設定方法來設定上位機即可,注意FreeMaster只能監測下位機中的全域性變數。連結地址:https://blog.csdn.net/u010875635/article/details/84789579   若是使用

更新Essential Studio for ASP.NET MVC更新至2018 v4

下載Essential Studio for ASP.NET MVC最新版本 Essential Studio for ASP.NET MVC控制元件包是一款MVC介面開發包,它包含了幾乎所有企業級Web應用程式開發所需要的控制元件,如Grids、 Charts、Gauges、Menus、Cal