From 799771b3fa802fad2cd0d99fdd5f3497e795a2a4 Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Thu, 10 May 2018 10:54:56 +0800 Subject: [PATCH 01/23] Upload blufi.rst --- docs/zh_CN/api-guides/blufi.rst | 303 ++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 docs/zh_CN/api-guides/blufi.rst diff --git a/docs/zh_CN/api-guides/blufi.rst b/docs/zh_CN/api-guides/blufi.rst new file mode 100644 index 000000000..6d6114fcf --- /dev/null +++ b/docs/zh_CN/api-guides/blufi.rst @@ -0,0 +1,303 @@ +BluFi +***** + +概览 +==== +ESP32 的蓝牙配网功能称为 BluFi。 + +ESP32 BluFi 功能基于 GATT 协议构建,定义了 ESP32 作为 GATT Server 接收 GATT Client(手机等设备)的 Wi-Fi 连接信息,实现 ESP32 通过 Wi-Fi 连接 AP 或配置使用 SoftAP Profile 的过程。必要功能包含 BluFi 层上的分片、数据加密、校验和确认等。 + +你可以自定义 BluFi 配网过程中使用的对称加密、非对称加密以及校验算法。 BluFi 提供的示例程序默认将使用 DH 算法进行密钥协商,使用 128-AES 算法进行数据加密,使用 CRC16 进行进行数据校验。 + +流程: +---- +BluFi 配网功能包含配置 SoftAP 和 Station 两部分。 + +下面以配置 Station 为例说明配置步骤。 +BluFi 配网的配置 Station 包含广播、连接、服务发现、协商共享密钥、传输数据、回传连接状态等步骤。 + +完整的配网过程如下: +---------------- + +1. ESP32 开启 GATT Server 功能,发送带有特定 *adv data* 的广播。你可以自定义该广播,该广播不属于 BluFi Profile。 + +2. 使用手机 APP 搜索到该特定广播,手机作为 GATT Client 连接 ESP32。你可以决定使用哪款手机 APP。 + +3. GATT 连接建立成功后,手机向 ESP32 发送『协商过程』数据帧(详情见 BluFi 传输格式)。 + +4. ESP32 收到『协商过程』数据帧后,会按照使用者自定义的协商过程来解析。 + +5. 手机与 ESP32 进行密钥协商。协商过程可使用 DH/RSA/ECC 等加密算法进行。 + +6. 协商结束后,手机端向 ESP32 发送『设置安全模式』控制帧。 + +7. ESP32 收到『设置安全模式』控制帧后,使用经过协商的共享密钥以及配置的安全策略对通信数据进行加密和解密。 + +8. 手机向 ESP32 发送『BluFi 传输格式』定义的 SSID、Password 等用于 Wi-Fi 连接的必要信息。 + +9. 手机向 ESP32 发送『Wi-Fi 连接请求』控制帧,ESP32 收到之后,识别为手机已将必要的信息传输完毕,准备连接 Wi-Fi。 + +10. ESP32 连接到 Wi-Fi 后,发送『Wi-Fi 连接状态报告』控制帧到手机,以报告连接状态。至此配网结束。 + +.. note:: + + 1. 安全模式设置可在任何时候进行,ESP32 收到安全模式的配置后,会根据安全模式指定的模式进行安全相关的操作。 + + 2. 进行对称加密和解密时,加密和解密前后的数据长度必须一致,支持原地加密和解密。 + +配网流程图请参考下图: + +.. figure:: https://github.com/Freddy-Jin/ESP32_BLUFI_-Design_Guidelines/blob/master/Docs/Figure1.png + :align: center + :figclass: align-center + +BLUFI 传输格式 +************* + +手机 APP 与 ESP32 之间的 BluFi 通信格式定义如下: + +帧不分片情况下的标准格式 (8 bit): + ++------------+---------------+-----------------+-------------+----------------+----------------+ +| LSB - Type | Frame Control | Sequence Number | Data Length | Data | MSB - CheckSum | ++------------+---------------+-----------------+-------------+----------------+----------------+ +| 1 | 1 | 1 | 1 | ${Data Length} | 2 | ++------------+---------------+-----------------+-------------+----------------+----------------+ + +如果 **Frame Control** 帧中的 **More Frag** 使能,则 **Total Content Length** 为数据帧中剩余部分的总长度,用于报告终端需要分配多少内存。 + +帧分片格式(8 bit): + ++------------+--------------------+----------------+------------+-------------------------------------------+----------------+ +| LSB - Type | FrameControl(Frag) | SequenceNumber | DataLength | Data | MSB - CheckSum | ++ + + + +-------------------------------------------+ + +| | | | | Total Content Length | Content | | ++------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ +| 1 | 1 | 1 | 1 | 2 | ${Data Length} - 2 | 2 | ++------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ + +通常情况下,控制帧不包含数据位,Ack 帧类型除外。 + +Ack 帧格式(8 bit): + ++------------------+---------------+-----------------+-------------+-----------------------+----------------+ +| LSB - Type (Ack) | Frame Control | SequenceNumber | Data Length | Data | MSB - CheckSum | ++ + + + +-----------------------+ + +| | | | | Acked Sequence Number | | ++------------------+---------------+-----------------+-------------+-----------------------+----------------+ +| 1 | 1 | 1 | 1 | 1 | 2 | ++------------------+---------------+-----------------+-------------+-----------------------+----------------+ + +1. Type + +   类型域,占 1 Byte。分为 Type 和 Subtype(子类型域)两部分, Type 占低 2 bit,Subtype 占高 6 bit。 + +   * 控制帧,暂不进行加密,可校验; + +   * 数据帧,可加密,可校验。 ++---------+------------------------+--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Type | 帧类型 | Subtype | 含义 | 解释 | 备注 | ++---------+------------------------+--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x0b’00 | 控制帧 (Control Frame) | 0x0b’000000 | Ack | 用来回复对方发的帧,Ack 帧的 Data 域使用回复对象帧的 Sequence 值。 | Data 域使用1 Byte Sequence 值,与恢复对象帧的Sequence 值相同。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x1b’000001 | Set ESP32 to the security mode. | 通知 ESP32 发送数据时使用的安全模式,在该过程中可设置多次,每次设置后影响后续安全模式。在不设置的情况下,ESP32 默认控制帧和数据帧均为无校验、无加密。手机到 ESP32 方向依赖于帧 Control 域。 | Data 域占用 1 Byte,高 4 bit 为控制帧的安全模式,低 4bit 为数据帧的安全模式。 | +| | | | | | b’0000:无校验、无加密; | +| | | | | | b’0001:有校验、无加密; | +| | | | | | b’0010:无校验、有加密; | +| | | | | | b’0011:有校验、有加密。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x2b’000010 | Set the Wi-Fi opmode of ESP32. | 设置 ESP32 的 Wi-Fi 模式,帧包含 opmode 信息。 | data[0] 用于表示 opmode 类型,包括: | +| | | | | | 0x00: NULL; | +| | | | | | 0x01: STA; | +| | | | | | 0x02: SoftAP; | +| | | | | | 0x03: SoftAP&STA. | +| | | | | | 如果设置有包含 AP,请尽量优先设置 AP 模式的 SSID/Password/Max Conn Number 等。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x3b’000011 | Connect ESP32 to the AP. | 通知 ESP32,必要的信息已经发送完毕,可以连接 AP。 | 不包含 Data 域。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x4b’000100 | Disconnect ESP32 from the AP. | 通知 ESP32 断开与 AP 的连接 | 不包含 Data 域。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x5b’000101 | Get the status of Wi-Fi. | 获取 ESP32 的 Wi-Fi 模式和状态等信息。 | 不包含 Data 域。 | +| | | | | | ESP32 收到此控制帧后,后续会通过 Wi-Fi 连接状态报告 (Wi-Fi Connection State Report) 数据帧来回复手机端当前所处的 opmode、连接状态、SSID 等信息。提供给手机端的信息由应用决定。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x6b’000110 | Disconnect the STA device from the SoftAP in SoftAP mode. | 处于 SoftAP 模式时,踢掉某个 STA 设备。 | data[0~5] 为 STA 设备的 MAC 地址,如有多个 STA,则 [6-11] 为第二个,依次类推。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x7b'000111 | Get the version. | | | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x8b’001000 | Tell ESP32 to disconnect the BLE GATT link. | 通知 ESP32 断开蓝牙连接。 | ESP32 收到该指令后主动断开蓝牙连接。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x9b’001001 | Tell ESP32 to get the Wi-Fi list. | 通知 ESP32 扫描周围的 Wi-Fi 热点 | 不包含 Data 域。ESP32 收到此控制帧后,会发送包含 Wi-Fi 热点报告 (Wi-Fi List Report) 的数据帧回复手机端 ESP32 周围的 Wi-Fi 热点。 | ++---------+------------------------+--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x1b’01 | 数据帧 (Data Frame) | 0x0b’000000 | Negotiation data. | 用来发送协商数据,传输到应用层注册的回调函数。 | 数据长度与 Length 域有关。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x1b’000001 | BSSID for STA mode. | STA 将要连接的 AP 的 BSSID(用于隐藏SSID)。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x2b’000010 | SSID for STA mode. | STA 将要连接的 AP 的 SSID。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x3b’000011 | Password for STA mode. | STA 将要连接的 AP 的密码。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x4b’000100 | SSID for SoftAP mode. | SoftAP 模式使用的 SSID。 | 数据长度与 Length 域有关。当传输方向为ESP32 到手机时,表示向手机端提供信息。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x5b’000101 | Password for SoftAPmode. | SoftAP 模式使用的密码。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x6b’000110 | Max connection number for SoftAP mode. | AP 模式的最大连接数。 | data[0] 表示连接数的值,范围 1~4。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x7b’000111 | Authentication mode for SoftAP mode. | AP 模式的认证模式。 | data[0]: | +| | | | | | 0x00: OPEN; | +| | | | | | 0x01: WEP; | +| | | | | | 0x02: WPA_PSK; | +| | | | | | 0x03: WPA2_PSK; | +| | | | | | 0x04: WPA_WPA2_PSK. | +| | | | | | 当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x8b’001000 | Channel for SoftAP mode. | SoftAP 模式的通道数量。 | data[0] 表示通道的数量,范围 1~14。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x9b’001001 | Username. | 使用企业级加密时,Client 端的用户名。 | 数据长度与 Length 域有关。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0xab’001010 | CA certification. | 进行企业级加密时使用的 CA 证书。 | 数据长度与 Length 域有关,长度不够,可用分片。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0xbb’001011 | Client certification. | 进行企业级加密时,Client 端的证书。可包含或不包含私钥,由证书内容决定。 | 数据长度与 Length 域有关,长度不够,可用分片。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0xcb’001100 | Server certification. | 进行企业级加密时,Server 端的证书。可包含或不包含私钥,由证书内容决定。 | 数据长度与 Length 域有关,长度不够,可用分片。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0xdb’001101 | Client private key. | 进行企业级加密时,Client 端的私钥。 | 数据长度与 Length 域有关,长度不够,可用分片。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0xeb’001110 | Server private key. | 进行企业级加密时,Server 端的私钥。 | 数据长度与 Length 域有关,长度不够,可用分片。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0xfb’001111 | Wi-Fi connection state report. | 通知手机 ESP32 的 Wi-Fi 状态,包括 STA状态和 SoftAP 状态,用于手机配置 STA 连接时的通知,或有 STA 连接上 SoftAP 时的通知。但收到手机询问 Wi-Fi 状态时,除了回复此帧外,还可回复其他数据帧。 | data[0] 表示 opmode,包括: | +| | | | | | 0x00: NULL; | +| | | | | | 0x01: STA; | +| | | | | | 0x02: SoftAP; | +| | | | | | 0x03: SoftAP&STA | +| | | | | | data[1]:STA 的连接状态,0x0 表示处于连接状态, 其他表示处于非连接状态; | +| | | | | | data[2]:SoftAP 的连接状态,即表示有多少 STA 已经连接。 | +| | | | | | data[3] 及以后:为按照本协议格式 SSID\BSSID 等信息。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x10b’010000 | Version. | | data[0]= great version | +| | | | | | data[1]= sub version | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x11B’010001 | Wi-Fi list. | 通知手机 ESP32 周围的 Wi-Fi 热点列表。 | 数据帧数据格式为 Length + RSSI + SSID, 数据较长时可分片发送。 | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x12B’010010 | Report error. | 通知手机 BluFi 过程出现异常错误。 | 0x00: sequence error; | +| | | | | | 0x01: checksum error; | +| | | | | | 0x02: decrypt error; | +| | | | | | 0x03: encrypt error; | +| | | | | | 0x04: init security error; | +| | | | | | 0x05: dh malloc error; | +| | | | | | 0x06: dh param error; | +| | | | | | 0x07: read param error; | +| | | | | | 0x08: make public error. | ++ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x13B’010011 | Custom data. | 用户发送或者接收自定义数据。 | 数据较长时可分片发送。 | ++---------+------------------------+--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +2. Frame Control + + 帧控制域,占 1 Byte,每个 bit 表示不同含义。 + ++----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| bit | 含义 | ++----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x01 | 表示帧是否加密。1 表示加密,0 表示未加密。加密部分帧括完整的 Data 域加密之前的明文(不帧含末尾的校验)。控制帧暂不加密,故控制帧此位为 0。 | ++----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x02 | 表示帧 Data 域结尾是否帧含校验(例如 SHA1、MD5、CRC等)需要校验的数据域包括『序列 + 数据长度 + 明文数据』。控制帧和数据帧都可以包含校验位或不包含。 | ++----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x04 | 表示数据方向。0 表示手机发向 ESP32;1 表示 ESP32 发向手机。 | ++----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x08 | 表示是否要求对方回复 Ack。0 表示不要求;1 表示要求回复 Ack。 | ++----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x10 | 表示是否有后续的数据分片。0 表示此帧没有后续数据分片;1 表示还有后续数据分片。用来传输较长的数据。如果是 Frag 帧,则告知当前『内容部分+后续内容部分』的总长度,位于 Data 域的前 2 Byte (即最大支持 64K 的内容数据)。 | ++----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x10~0x80 保留 | | ++----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +3. Sequence Control + +   序列控制域。帧发送时,无论帧的类型是什么,序列 (Sequence) 都会自动加 1,用来防止重放攻击 (Replay Attack)。每次重现连接后,序列清零。 + +4. Length + +   Data 域的长度,不包含 CheckSum。 + +5. Data + +   不同的 Type 或 Subtype,Data 域的含义均不同。请参考上方表格。 + +6. CheckSum + +   此域为 2 Byte 的校验,用来校验『序列 + 数据长度 + 明文数据』。 + +ESP32端的安全实现 +**************** + +1. 保证数据安全 + + 为了保证 Wi-Fi SSID 和密码的传输过程是安全的,需要使用对称加密算法(例如 AES、DES等)对报文进行加密。在使用对称加密算法之前,需要使用非对称加密算法(DH、RSA、ECC 等)协商出(或生成出)一个共享密钥。 + +2. 保证数据完整性 + + 保证数据完整性,需要加入校验算法(例如 SHA1、MD5、CRC 等)。 + +3. 身份安全(签名) + + 某些算法如 RSA 可以保证身份安全。有些算法如 DH,本身不能保证身份安全,需要添加其他算法来签名。 + +4. 防止重放攻击 (Replay Attack) + +   加入帧发送序列(Sequence),并且序列参与数据校验。 + +   在 ESP32 端的代码中,你可以决定和开发密钥协商等安全处理的流程参考上述流程图)。手机应用向 ESP32 发送协商数据,将传送给应用层处理。如果应用层不处理,可使用 BluFi 提供的 DH 加密算法来磋商密钥。应用层需向 BluFi 注册以下几个与安全相关的函数: + +.. highlight:: none + +:: + + typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free); + +   该函数用来接收协商期间的正常数据 (normal data),处理完成后,需要将待发送的数据使用 output_data 和 output_len 传出。 + + BluFi 会在调用完 negotiate_data_handler 后,发送 negotiate_data_handler 传出的 output_data。 + +   这里的两个『*』,因为需要发出去的数据长度未知,所以需要函数自行分配 (malloc) 或者指向全局变量,通过 need_free 通知是否需要释放内存。 + +.. highlight:: none + +:: + + typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len); +   + 加密和解密的数据长度必须一致。其中 iv8 为帧的 8 bit 序列 (sequence),可作为 iv 的某 8 bit 来使用。 + +.. highlight:: none + +:: + + typedef int (* esp_blufi_decrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len); + + 加密和解密的数据长度必须一致。其中 iv8 为帧的 8 bit 序列 (sequence),可作为 iv 的某 8 bit 来使用。 + +.. highlight:: none + +:: + + typedef uint16_t (*esp_blufi_checksum_func_t)(uint8_t iv8, uint8_t *data, int len); + +   该函数用来计算 CheckSum,返回值为 CheckSum 的值。BluFi 会使用该函数返回值与包末尾的 CheckSum 做比较。 + +GATT 相关说明 +************* + +UUID 相关: +========== + +BluFi Service UUID: 0xFFFF,16 bit + +BluFi(手机 -> ESP32)特性:0xFF01,主要权限:可写 + +BluFi(ESP32 -> 手机)特性:0xFF02,主要权限:可读可通知 + +.. note:: + + 1. 目前 Ack 机制已经在该 Profile 协议中定义,但是还没有代码实现。 + + 2. 其他部分均已实现。 From dd0bbebd4ad22fa16627269f437c135f7fa101a1 Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Thu, 10 May 2018 10:55:47 +0800 Subject: [PATCH 02/23] Upload blufi.rst --- docs/en/api-guides/blufi.rst | 256 +++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 docs/en/api-guides/blufi.rst diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst new file mode 100644 index 000000000..41dd19a00 --- /dev/null +++ b/docs/en/api-guides/blufi.rst @@ -0,0 +1,256 @@ +BluFi +***** + +Overview +======== +BluFi for ESP32 is a network-configuration funcion via Bluetooth channel. + +It is built on the GATT protocol, which defines the procedure of ESP32 working as the GATT Server to connect the GATT Client (e.g. an SoftAP created by a mobile phone) through Wi-Fi or configuring for the SoftAP Profile. Sharding, data encryption, checksum verification in the BluFi layer are the key parts that need your attention. + +The algorithms of symmetric encryption, asymmetric encryption and checksum support custmization on your demand in practical use. Here we use the DH algorithm for key negotiation, 128-AES algorithm for data encryption, and CRC16 algorithm for checksum verification. + +The BluFi Flow: +--------------- +The BluFi networking flow includes the configuration of the SoftAP and Station. + +Take the configuration of the Station as an example to illustrate the core parts of the procedure, including broadcast, connection, service discovery, negotiation of the shared key, data transmission, connection status backhaul. + +The procedure is as follows: +------------------------------ + +1. Set the ESP32 into GATT Server mode and then it will send broadcasts with specific *adv data*. You can customize this broadcast as needed, which is not a part of the BluFi Profile. + +2. Use the APP installed on the mobile phone to search for this particular broadcast. The mobile phone will connect to ESP32 as the GATT Client once the broadcast is confirmed. The APP used during this part is up to you. + +3. After the GATT connection is successfully established, the mobile phone will send a data frame for key negotiation to ESP32 (see the section of "The Formats of Data Frames" for details). + +4. After ESP32 receives the data frame of key negotiation, it will parse the content according to the user-defined negotiation method. + +5. The mobile phone works with ESP32 for key negotiation using the encryption algorithms such as DH, RSA or ECC. + +6. After the negotiation process is completed, the mobile phone will send a control frame for security-mode setup to ESP32. + +7. When receiving this control frame, ESP32 will be able to encrypt and decrypt the communication data using the shared key and the security configuration. + +8. The mobile phone sends the data frame defined in the section of "The Formats of Data Frames",with the Wi-Fi configuration information to ESP32, including SSID, password, etc. + +9. The mobile phone sends a control frame of Wi-Fi connection request to ESP32. When receiving this control frame, ESP32 will regard the communication of essential information as done and get ready to connect to the Wi-Fi. + +10. After connecting to the Wi-Fi, ESP32 will send a control frame of Wi-Fi connection status report to the mobile phone,to report the connection status. At this point the networking procedure is completed. + +.. note:: + + 1. After ESP32 receives the control frame of security-mode configuration, it will execute the operations in accordance with the defined security mode. + + 2. The data lengths before and after symmetric encryption/decryption must stay the same. It also supports in-place encryption and decryption. + +The flow chat of BluFi: + +.. figure:: https://github.com/Freddy-Jin/ESP32_BLUFI_-Design_Guidelines/blob/master/Docs/Figure1.png + :align: center + :figclass: align-center + +The Frame Formats Defined in BluFi +*************************************** + +The frame formats for the communication between the mobile phone APP and ESP32 is defined as follows: + +The frame format with no fragment (8 bit): + ++------------+---------------+-----------------+-------------+----------------+----------------+ +| LSB - Type | Frame Control | Sequence Number | Data Length | Data | MSB - CheckSum | ++------------+---------------+-----------------+-------------+----------------+----------------+ +| 1 | 1 | 1 | 1 | ${Data Length} | 2 | ++------------+---------------+-----------------+-------------+----------------+----------------+ + +If the **Frame Ctrl** bit is enabled, the **Total length** bit indicates the length of data frame's rest part. It can tell the remote how much memory needs to be alloced. + +The frame format with fragments(8 bit): + ++------------+--------------------+----------------+------------+-------------------------------------------+----------------+ +| LSB - Type | FrameControl(Frag) | SequenceNumber | DataLength | Data | MSB - CheckSum | ++ + + + +-------------------------------------------+ + +| | | | | Total Content Length | Content | | ++------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ +| 1 | 1 | 1 | 1 | 2 | ${Data Length} - 2 | 2 | ++------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ + +Normally, the control frame does not contain data bits, except for Ack frame. + +The format of Ack Frame(8 bit): + ++------------------+----------------+------------------+--------------+-----------------------+----------------+ +| LSB - Type (Ack) | Frame Control | SequenceNumber | Data Length | Data | MSB - CheckSum | ++ + + + +-----------------------+ + +| | | | | Acked Sequence Number | | ++------------------+----------------+------------------+--------------+-----------------------+----------------+ +| 1 | 1 | 1 | 1 | 1 | 2 | ++------------------+----------------+------------------+--------------+-----------------------+----------------+ + +1. Type + +   Type field, taking 1 Byte, is divided into Type and Subtype that Type uses the lower 2 bit and Subtype uses the upper 6 bit. + +   * The control frame is not encrypted for the time being and supports to be verified; + +   * The data frame supports to be encrypted and verified. + ++---------+---------------+--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Type | Frame Type | Subtype | Implication | Explanation | Note | ++---------+---------------+--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x0b’00 | Control Frame | 0x0b’000000 | Ack | The data field of the Ack frame uses the same sequence value of the frame to reply to. | The data field consumes a byte and its value is the same as the sequence field of the frame to reply to. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x1b’000001 | Set ESP32 to the security mode. | To inform ESP32 of the security mode to use when sending data, which is allowed to be reset multiple times during the process.Each setting affects the subsequent security mode used.If it is not set, ESP32 will send the control frame and data frame with no checksum and encryption by default.The data transmission from the mobile phone to ESP32 is controlled by this control frame. | The data field consumes a byte.The higher 4 bits are for the security mode setting of the control frame, and the lower 4 bits are for the security mode setting of the data frame.b’0000: no checksum and no encryption;b’0001: with checksum but no encryption;b’0010: no checksum but with encryption;b’0011: with both checksum and encryption. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x2b’000010 | Set the opmode of Wi-Fi. | The frame contains opmode settings for configuring for the Wi-Fi mode of ESP32. | data[0] is for opmode settings, including:0x00: NULL;0x01: STA;0x02: SoftAP;0x03: SoftAP&STA.Please set the SSID/Password/Max Connection Number of the AP mode in the first place if an AP gets involved . | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x3b’000011 | Connect ESP32 to the AP. | To notify ESP32 that the essential information has been sent and it is allowed to connect to the AP. | No data field is contained. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x4b’000100 | Disconnect ESP32 from the AP. | | No data field is contained. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x5b’000101 | To get the information of ESP32’s Wi-Fi mode and its status. | | No data field is contained.When receiving this control frame, ESP32 will send back a follow-up frame of Wi-Fi connection state report to the mobile phone with the information of the current opmode, connection status, SSID and so on. The types of information sent to the mobile phone is defined by the application installed on the phone. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x6b’000110 | Disconnect the STA device from the SoftAP (in SoftAP mode). | | Date[0~5] is taken as the MAC address for the STA device. If there is a second STA device, then it uses data[6-11] and the rest can be done in the same manner. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x7b'000111 | Get the version information. | | | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x8b’001000 | Disconnect the BLE GATT link. | | ESP32 will disconnect the BLE GATT link after receives this command. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x9b’001001 | Get the Wi-Fi list. | To get ESP32 to scan the Wi-Fi access points around. | No data field is contained.When receiving this control frame, ESP32 will send back a follow-up frame of Wi-Fi list report to the mobile phone. | ++---------+---------------+--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x1b’01 | Data Frame | 0x0b’000000 | Send the negotiation data. | The negotiation data will be sent to the callback function registered in the application layer. | The length of the data depends on the length field. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x1b’000001 | Send the BSSID for STA mode. | To send the BSSID of the AP for the STA device to connect under the condition that the SSID is hidden. | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x2b’000010 | Send the SSID for STA mode. | To send the SSID of the AP for the STA device to connect. | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x3b’000011 | Send the password for STA mode. | To send the password of the AP for the STA device to connect. | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x4b’000100 | Send the SSID for SoftAP mode. | | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x5b’000101 | Send the password for SoftAPmode. | | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x6b’000110 | Set the maximum connection number for SoftAP mode. | | data[0] represents the value of the connection number, ranging from 1 to 4.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x7b’000111 | Set the authentication mode for the SoftAP. | | data[0]:0x00: OPEN0x01: WEP0x02: WPA_PSK0x03: WPA2_PSK0x04:WPA_WPA2_PSK。When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x8b’001000 | Set the channel amount for SoftAP mode. | | data[0] represents the quantity of the supported channels, ranging from 1 to 14.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x9b’001001 | Username | It provides the username of the GATT client when using encryption of enterprise level. | The length of the data depends on the length field. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0xab’001010 | CA Certification | It provides the CA Certification when using encryption of enterprise level. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0xbb’001011 | Client Certification | It provides the client certification when using encryption of enterprise level. Whether the private key is contained or not depends on the content of the certification. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0xcb’001100 | Server Certification | It provides the sever certification when using encryption of enterprise level. Whether the private key is contained or not depends on the content of the certification. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0xdb’001101 | ClientPrivate Key | It provides the private key of the client when using encryption of enterprise level. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0xeb’001110 | ServerPrivate Key | It provides the private key of the sever when using encryption of enterprise level. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0xfb’001111 | Wi-Fi Connection State Report | To notify the phone of the ESP32's Wi-Fi status, including STA status and SoftAP status. It is for the STA device to connect to the mobile phone or the SoftAP.However, when the mobile phone receives the Wi-Fi status, it can reply to other frames in addition to this frame. | data[0] represents opmode, including:0x00: NULL;0x01: STA;0x02: SoftAP;0x03: SoftAP&STAdata[1]:the connection state of the STA device, 0x0 indicates a connection state, and others represent a disconnected state;data[2]:the connection state of the SoftAP , that is, how many STA devices have been connected.data[3] and the subsequent is in accordance with the format of SSID/BSSID information. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x10b’010000 | Version | | data[0]= great versiondata[1]= sub version | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x11B’010001 | Wi-Fi List | To send the Wi-Fi list to ESP32. | The format of the data frame is length + RSSI + SSID and it supports to be sent into fragments if the data length is too long. | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x12B’010010 | Report Error | To notify the mobile phone that there is an error with BluFi. | 0x00: sequence error0x01: checksum error0x02: decrypt error0x03: encrypt error0x04: init security error0x05: dh malloc error0x06: dh param error0x07: read param error0x08: make public error | ++ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | 0x13B’010011 | Custom Data | To send or receive custom data. | The data frame supports to be sent into fragments if the data length is too long. | ++---------+---------------+--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +2. Frame Control + + Control field, takes 1 Byte and each bit has a different meaning. + +3. Sequence Control + + Sequence control field. When a frame is sent,the value of sequence fied is automatically added by 1 regardless of the type of frame, which prevents Replay Attack. The sequence is cleared after each reconnection. + +4. Length + +   The length of the data field that does not include CheckSum. + +5. Data + +   The instruction of the data field is different according to various value s of Type or Subtype. Please refer to the table above. + +6. CheckSum + +   This field takes 2 bytes that is used to check "sequence + data length + clear text data". + +The Security Implementation of ESP32 +************************************* + +1. To secure data + + To ensure that the transmission of the Wi-Fi SSID and password is secure, the message needs to be encrypted using symmetric encryption algorithms, such as AES, DES and so on. Before using symmetric encryption algorithms, the devices are required to negotiate (or generate) a shared key using an asymmetric encryption algorithm (DH, RSA, ECC, etc). + +2. To ensure data integrity + + To ensure data integrity, you need to add a checksum algorithm, such as SHA1, MD5, CRC, etc. + +3. Identity security (signature) + + Algorithm like RSA can used to secure identity. But for DH, it needs other algorithms as an companion for signature. + +4. To prevent replay attack + +   It is added to the Sequence field and used during the checksum verification. + +   For the coding of ESP32, you can determine and develop the security processing, such as key negotiation. The mobile application sends the negotiation data to ESP32 and then the data will be sent to the application layer for processing. If the application layer does not process it, you can use the DH encryption algorithm provided by BluFi to negotiate the key. The application layer needs to register several security-related functions to BluFi: + +.. highlight:: none + +:: + + typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free); + +   This function is for ESP32 to receive normal data during negotiation, and after processing is completed, the data will be transmitted using Output_data and Output_len. + + BluFi will send output_data from Negotiate_data_handler after Negotiate_data_handler is called. + +   Here are two "*", because the length of the data to be emitted is unknown that requires the function to allocate itself (malloc) or point to the global variable, and to infrom whether the memory needs to be freed by NEED_FREE. + + +.. highlight:: none + +:: + + typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len); +   + The data to be encrypted and decrypted must use the same length. The IV8 is a 8 bit sequence value of frames, which can be used as a 8 bit of IV. + +.. highlight:: none + +:: + + typedef int (* esp_blufi_decrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len); + + The data to be encrypted and decrypted must use the same length. The IV8 is a 8 bit sequence value of frames, which can be used as a 8 bit of IV. + +.. highlight:: none + +:: + + typedef uint16_t (*esp_blufi_checksum_func_t)(uint8_t iv8, uint8_t *data, int len); + + This function is used to compute CheckSum and return a value of CheckSum. Blufi uses the returned value to compare the CheckSum of the frame. + +GATT Related Instructions +************************* + +UUID: +========== + +BluFi Service UUID: 0xFFFF,16 bit + +BluFi(the mobile -> ESP32): 0xFF01, writable + +Blufi(ESP32 -> the mobile phone): 0xFF02, readable and callable + +.. note:: + + 1. The Ack mechanism is already defined in the profile, but there is no implementation based on the code for the time being. + + 2. Other parts have been implemented. From 75021e376a8cd852164f8e9b7f85e52bfbeb007d Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Thu, 10 May 2018 10:58:28 +0800 Subject: [PATCH 03/23] Upload api-guides_blufi.png --- docs/_static/api-guides_blufi.png | Bin 0 -> 215887 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/_static/api-guides_blufi.png diff --git a/docs/_static/api-guides_blufi.png b/docs/_static/api-guides_blufi.png new file mode 100644 index 0000000000000000000000000000000000000000..b010db4cee5213e869a02d2037b2cea194c81d7f GIT binary patch literal 215887 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%0Deq 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 literal 0 HcmV?d00001 From 241048c9f9b0e1999820d0c4432fa45aaaf2868b Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Thu, 10 May 2018 11:01:32 +0800 Subject: [PATCH 04/23] Update blufi.rst --- docs/en/api-guides/blufi.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst index 41dd19a00..9b518cd29 100644 --- a/docs/en/api-guides/blufi.rst +++ b/docs/en/api-guides/blufi.rst @@ -46,7 +46,7 @@ The procedure is as follows: The flow chat of BluFi: -.. figure:: https://github.com/Freddy-Jin/ESP32_BLUFI_-Design_Guidelines/blob/master/Docs/Figure1.png +.. figure:: ../../_static/api-guides_blufi.png :align: center :figclass: align-center From 7db69b4da34b6cf9a24c0dc7bfae36a40f0954ff Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Thu, 10 May 2018 11:03:19 +0800 Subject: [PATCH 05/23] Update blufi.rst --- docs/zh_CN/api-guides/blufi.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh_CN/api-guides/blufi.rst b/docs/zh_CN/api-guides/blufi.rst index 6d6114fcf..1542c5cd9 100644 --- a/docs/zh_CN/api-guides/blufi.rst +++ b/docs/zh_CN/api-guides/blufi.rst @@ -47,7 +47,7 @@ BluFi 配网的配置 Station 包含广播、连接、服务发现、协商共 配网流程图请参考下图: -.. figure:: https://github.com/Freddy-Jin/ESP32_BLUFI_-Design_Guidelines/blob/master/Docs/Figure1.png +.. figure:: ../../_static/api-guides_blufi.png :align: center :figclass: align-center From b44307513370b409e8e91347384ca7107bc9cca9 Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Thu, 10 May 2018 11:07:20 +0800 Subject: [PATCH 06/23] Update index.rst --- docs/en/api-guides/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/api-guides/index.rst b/docs/en/api-guides/index.rst index 3e8b2ece5..648a9d1db 100644 --- a/docs/en/api-guides/index.rst +++ b/docs/en/api-guides/index.rst @@ -23,4 +23,5 @@ API Guides ROM debug console WiFi Driver Mesh Stack + Blu-Fi External SPI-connected RAM From 0ea39a72b090fd9578009c1eb6e6e2f1125ee2e6 Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Thu, 17 May 2018 16:39:33 +0800 Subject: [PATCH 07/23] Update blufi.rst --- docs/zh_CN/api-guides/blufi.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/zh_CN/api-guides/blufi.rst b/docs/zh_CN/api-guides/blufi.rst index 1542c5cd9..027d40e00 100644 --- a/docs/zh_CN/api-guides/blufi.rst +++ b/docs/zh_CN/api-guides/blufi.rst @@ -10,14 +10,14 @@ ESP32 BluFi 功能基于 GATT 协议构建,定义了 ESP32 作为 GATT Server 你可以自定义 BluFi 配网过程中使用的对称加密、非对称加密以及校验算法。 BluFi 提供的示例程序默认将使用 DH 算法进行密钥协商,使用 128-AES 算法进行数据加密,使用 CRC16 进行进行数据校验。 流程: ----- +----- BluFi 配网功能包含配置 SoftAP 和 Station 两部分。 下面以配置 Station 为例说明配置步骤。 BluFi 配网的配置 Station 包含广播、连接、服务发现、协商共享密钥、传输数据、回传连接状态等步骤。 完整的配网过程如下: ----------------- +------------------- 1. ESP32 开启 GATT Server 功能,发送带有特定 *adv data* 的广播。你可以自定义该广播,该广播不属于 BluFi Profile。 @@ -52,7 +52,7 @@ BluFi 配网的配置 Station 包含广播、连接、服务发现、协商共 :figclass: align-center BLUFI 传输格式 -************* +************** 手机 APP 与 ESP32 之间的 BluFi 通信格式定义如下: @@ -95,6 +95,7 @@ Ack 帧格式(8 bit):   * 控制帧,暂不进行加密,可校验;   * 数据帧,可加密,可校验。 + +---------+------------------------+--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Type | 帧类型 | Subtype | 含义 | 解释 | 备注 | +---------+------------------------+--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -228,7 +229,7 @@ Ack 帧格式(8 bit):   此域为 2 Byte 的校验,用来校验『序列 + 数据长度 + 明文数据』。 ESP32端的安全实现 -**************** +***************** 1. 保证数据安全 From 27d22a75749d72fe6b9f241e439d58bae6867fad Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Thu, 17 May 2018 16:42:17 +0800 Subject: [PATCH 08/23] Update index.rst --- docs/zh_CN/api-guides/index.rst | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/zh_CN/api-guides/index.rst b/docs/zh_CN/api-guides/index.rst index a6a7d8566..a9a150cd8 100644 --- a/docs/zh_CN/api-guides/index.rst +++ b/docs/zh_CN/api-guides/index.rst @@ -1 +1,27 @@ -.. include:: ../../en/api-guides/index.rst \ No newline at end of file +API Guides +********** + +.. toctree:: + :maxdepth: 1 + + General Notes + Build System + Deep Sleep Wake Stubs + ESP32 Core Dump + Flash Encryption <../security/flash-encryption> + FreeRTOS SMP Changes + Thread Local Storage + High Level Interrupts + JTAG Debugging + Bootloader + Partition Tables + Secure Boot <../security/secure-boot> + ULP Coprocessor + Unit Testing + Application Level Tracing + Console Component + ROM debug console + WiFi Driver + Mesh Stack + Blu-Fi + External SPI-connected RAM \ No newline at end of file From 5a3f351207e7f538513ce82dad7f9285ae0e1b8e Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Thu, 17 May 2018 17:15:56 +0800 Subject: [PATCH 09/23] Update blufi.rst --- docs/en/api-guides/blufi.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst index 9b518cd29..0da1c3838 100644 --- a/docs/en/api-guides/blufi.rst +++ b/docs/en/api-guides/blufi.rst @@ -3,22 +3,22 @@ BluFi Overview ======== -BluFi for ESP32 is a network-configuration funcion via Bluetooth channel. +The BluFi for ESP32 is a Wi-Fi network configuration function via Bluetooth channel. It provides a secure protocol to pass Wi-Fi configuration and credentials to the ESP32. Using this information ESP32 can then e.g. connect to an AP or establish a SoftAP. -It is built on the GATT protocol, which defines the procedure of ESP32 working as the GATT Server to connect the GATT Client (e.g. an SoftAP created by a mobile phone) through Wi-Fi or configuring for the SoftAP Profile. Sharding, data encryption, checksum verification in the BluFi layer are the key parts that need your attention. +Fragmenting, data encryption, checksum verification in the BluFi layer are the key elements of this process.. -The algorithms of symmetric encryption, asymmetric encryption and checksum support custmization on your demand in practical use. Here we use the DH algorithm for key negotiation, 128-AES algorithm for data encryption, and CRC16 algorithm for checksum verification. +You can customize symmetric encryption, asymmetric encryption and checksum support custmization on your demand in practical use. Here we use the DH algorithm for key negotiation, 128-AES algorithm for data encryption, and CRC16 algorithm for checksum verification. The BluFi Flow: --------------- The BluFi networking flow includes the configuration of the SoftAP and Station. -Take the configuration of the Station as an example to illustrate the core parts of the procedure, including broadcast, connection, service discovery, negotiation of the shared key, data transmission, connection status backhaul. +The following uses Station as an example to illustrate the core parts of the procedure, including broadcast, connection, service discovery, negotiation of the shared key, data transmission, connection status backhaul. -The procedure is as follows: ------------------------------- +The procedure is as follows +--------------------------- -1. Set the ESP32 into GATT Server mode and then it will send broadcasts with specific *adv data*. You can customize this broadcast as needed, which is not a part of the BluFi Profile. +1. Set the ESP32 into GATT Server mode and then it will send broadcasts with specific *advertising data*. You can customize this broadcast as needed, which is not a part of the BluFi Profile. 2. Use the APP installed on the mobile phone to search for this particular broadcast. The mobile phone will connect to ESP32 as the GATT Client once the broadcast is confirmed. The APP used during this part is up to you. From d0bf4a0e230ae90fdca2b1042742024315b6ee16 Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Wed, 23 May 2018 13:56:34 +0800 Subject: [PATCH 10/23] Update blufi.rst --- docs/en/api-guides/blufi.rst | 258 +++++++++++++++++++---------------- 1 file changed, 140 insertions(+), 118 deletions(-) diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst index 0da1c3838..1aeace66d 100644 --- a/docs/en/api-guides/blufi.rst +++ b/docs/en/api-guides/blufi.rst @@ -1,28 +1,26 @@ +***** BluFi ***** Overview -======== +========== The BluFi for ESP32 is a Wi-Fi network configuration function via Bluetooth channel. It provides a secure protocol to pass Wi-Fi configuration and credentials to the ESP32. Using this information ESP32 can then e.g. connect to an AP or establish a SoftAP. -Fragmenting, data encryption, checksum verification in the BluFi layer are the key elements of this process.. +Fragmenting, data encryption, checksum verification in the BluFi layer are the key elements of this process. You can customize symmetric encryption, asymmetric encryption and checksum support custmization on your demand in practical use. Here we use the DH algorithm for key negotiation, 128-AES algorithm for data encryption, and CRC16 algorithm for checksum verification. -The BluFi Flow: ---------------- +The BluFi Flow +-------------- The BluFi networking flow includes the configuration of the SoftAP and Station. The following uses Station as an example to illustrate the core parts of the procedure, including broadcast, connection, service discovery, negotiation of the shared key, data transmission, connection status backhaul. -The procedure is as follows ---------------------------- - 1. Set the ESP32 into GATT Server mode and then it will send broadcasts with specific *advertising data*. You can customize this broadcast as needed, which is not a part of the BluFi Profile. 2. Use the APP installed on the mobile phone to search for this particular broadcast. The mobile phone will connect to ESP32 as the GATT Client once the broadcast is confirmed. The APP used during this part is up to you. -3. After the GATT connection is successfully established, the mobile phone will send a data frame for key negotiation to ESP32 (see the section of "The Formats of Data Frames" for details). +3. After the GATT connection is successfully established, the mobile phone will send a data frame for key negotiation to ESP32 (see the section :ref:`frame_formats` for details). 4. After ESP32 receives the data frame of key negotiation, it will parse the content according to the user-defined negotiation method. @@ -32,7 +30,7 @@ The procedure is as follows 7. When receiving this control frame, ESP32 will be able to encrypt and decrypt the communication data using the shared key and the security configuration. -8. The mobile phone sends the data frame defined in the section of "The Formats of Data Frames",with the Wi-Fi configuration information to ESP32, including SSID, password, etc. +8. The mobile phone sends the data frame defined in the section of :ref:`frame_formats`,with the Wi-Fi configuration information to ESP32, including SSID, password, etc. 9. The mobile phone sends a control frame of Wi-Fi connection request to ESP32. When receiving this control frame, ESP32 will regard the communication of essential information as done and get ready to connect to the Wi-Fi. @@ -44,16 +42,39 @@ The procedure is as follows 2. The data lengths before and after symmetric encryption/decryption must stay the same. It also supports in-place encryption and decryption. -The flow chat of BluFi: +The flow chat of BluFi +----------------------- -.. figure:: ../../_static/api-guides_blufi.png +.. seqdiag:: + :caption: BluFi Flow Chart :align: center - :figclass: align-center + + seqdiag blufi { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 380; + span_height = 10; + default_fontsize = 12; + + Phone <- ESP32 [label="Advertising"]; + Phone -> ESP32 [label="Create GATT connection"]; + Phone <- ESP32 [label="Negotiate key procedure"]; + Phone -> ESP32 [label="Negotiate key procedure"]; + Phone -> ESP32 [label="CTRL: Set ESP32 to Phone Security mode"]; + Phone -> ESP32 [label="DATA: SSID"]; + Phone -> ESP32 [label="DATA: Password"]; + Phone -> ESP32 [label="DATA: Other information, such as CA certification"]; + Phone -> ESP32 [label="CTRL: Connect to AP"]; + Phone <- ESP32 [label="DATA: Connection State Report"]; + } + +.. _frame_formats: The Frame Formats Defined in BluFi -*************************************** +=================================== -The frame formats for the communication between the mobile phone APP and ESP32 is defined as follows: +The frame formats for the communication between the mobile phone APP and ESP32 are defined as follows: The frame format with no fragment (8 bit): @@ -63,19 +84,19 @@ The frame format with no fragment (8 bit): | 1 | 1 | 1 | 1 | ${Data Length} | 2 | +------------+---------------+-----------------+-------------+----------------+----------------+ -If the **Frame Ctrl** bit is enabled, the **Total length** bit indicates the length of data frame's rest part. It can tell the remote how much memory needs to be alloced. +If the **Frame Ctrl** bit is enabled, the **Total length** bit indicates the length of remaining part of the frame. It can tell the remote how much memory needs to be alloced. The frame format with fragments(8 bit): +------------+--------------------+----------------+------------+-------------------------------------------+----------------+ -| LSB - Type | FrameControl(Frag) | SequenceNumber | DataLength | Data | MSB - CheckSum | -+ + + + +-------------------------------------------+ + -| | | | | Total Content Length | Content | | +| LSB - Type | FrameControl(Frag) | SequenceNumber | DataLength | Data | MSB - CheckSum | ++ + + + +----------------------+--------------------+ + +| | | | | Total Content Length | Content | | +------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ -| 1 | 1 | 1 | 1 | 2 | ${Data Length} - 2 | 2 | +| 1 | 1 | 1 | 1 | 2 | ${Data Length} - 2 | 2 | +------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ -Normally, the control frame does not contain data bits, except for Ack frame. +Normally, the control frame does not contain data bits, except for Ack Frame. The format of Ack Frame(8 bit): @@ -89,75 +110,83 @@ The format of Ack Frame(8 bit): 1. Type -   Type field, taking 1 Byte, is divided into Type and Subtype that Type uses the lower 2 bit and Subtype uses the upper 6 bit. +   The **Type** field, taking 1 Byte, is divided into **Type** and **Subtype**, that Type uses the lower 2 bit and **Subtype** uses the upper 6 bit.   * The control frame is not encrypted for the time being and supports to be verified;   * The data frame supports to be encrypted and verified. -+---------+---------------+--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Type | Frame Type | Subtype | Implication | Explanation | Note | -+---------+---------------+--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x0b’00 | Control Frame | 0x0b’000000 | Ack | The data field of the Ack frame uses the same sequence value of the frame to reply to. | The data field consumes a byte and its value is the same as the sequence field of the frame to reply to. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x1b’000001 | Set ESP32 to the security mode. | To inform ESP32 of the security mode to use when sending data, which is allowed to be reset multiple times during the process.Each setting affects the subsequent security mode used.If it is not set, ESP32 will send the control frame and data frame with no checksum and encryption by default.The data transmission from the mobile phone to ESP32 is controlled by this control frame. | The data field consumes a byte.The higher 4 bits are for the security mode setting of the control frame, and the lower 4 bits are for the security mode setting of the data frame.b’0000: no checksum and no encryption;b’0001: with checksum but no encryption;b’0010: no checksum but with encryption;b’0011: with both checksum and encryption. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x2b’000010 | Set the opmode of Wi-Fi. | The frame contains opmode settings for configuring for the Wi-Fi mode of ESP32. | data[0] is for opmode settings, including:0x00: NULL;0x01: STA;0x02: SoftAP;0x03: SoftAP&STA.Please set the SSID/Password/Max Connection Number of the AP mode in the first place if an AP gets involved . | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x3b’000011 | Connect ESP32 to the AP. | To notify ESP32 that the essential information has been sent and it is allowed to connect to the AP. | No data field is contained. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x4b’000100 | Disconnect ESP32 from the AP. | | No data field is contained. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x5b’000101 | To get the information of ESP32’s Wi-Fi mode and its status. | | No data field is contained.When receiving this control frame, ESP32 will send back a follow-up frame of Wi-Fi connection state report to the mobile phone with the information of the current opmode, connection status, SSID and so on. The types of information sent to the mobile phone is defined by the application installed on the phone. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x6b’000110 | Disconnect the STA device from the SoftAP (in SoftAP mode). | | Date[0~5] is taken as the MAC address for the STA device. If there is a second STA device, then it uses data[6-11] and the rest can be done in the same manner. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x7b'000111 | Get the version information. | | | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x8b’001000 | Disconnect the BLE GATT link. | | ESP32 will disconnect the BLE GATT link after receives this command. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x9b’001001 | Get the Wi-Fi list. | To get ESP32 to scan the Wi-Fi access points around. | No data field is contained.When receiving this control frame, ESP32 will send back a follow-up frame of Wi-Fi list report to the mobile phone. | -+---------+---------------+--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x1b’01 | Data Frame | 0x0b’000000 | Send the negotiation data. | The negotiation data will be sent to the callback function registered in the application layer. | The length of the data depends on the length field. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x1b’000001 | Send the BSSID for STA mode. | To send the BSSID of the AP for the STA device to connect under the condition that the SSID is hidden. | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x2b’000010 | Send the SSID for STA mode. | To send the SSID of the AP for the STA device to connect. | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x3b’000011 | Send the password for STA mode. | To send the password of the AP for the STA device to connect. | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x4b’000100 | Send the SSID for SoftAP mode. | | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x5b’000101 | Send the password for SoftAPmode. | | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x6b’000110 | Set the maximum connection number for SoftAP mode. | | data[0] represents the value of the connection number, ranging from 1 to 4.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x7b’000111 | Set the authentication mode for the SoftAP. | | data[0]:0x00: OPEN0x01: WEP0x02: WPA_PSK0x03: WPA2_PSK0x04:WPA_WPA2_PSK。When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x8b’001000 | Set the channel amount for SoftAP mode. | | data[0] represents the quantity of the supported channels, ranging from 1 to 14.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x9b’001001 | Username | It provides the username of the GATT client when using encryption of enterprise level. | The length of the data depends on the length field. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0xab’001010 | CA Certification | It provides the CA Certification when using encryption of enterprise level. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0xbb’001011 | Client Certification | It provides the client certification when using encryption of enterprise level. Whether the private key is contained or not depends on the content of the certification. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0xcb’001100 | Server Certification | It provides the sever certification when using encryption of enterprise level. Whether the private key is contained or not depends on the content of the certification. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0xdb’001101 | ClientPrivate Key | It provides the private key of the client when using encryption of enterprise level. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0xeb’001110 | ServerPrivate Key | It provides the private key of the sever when using encryption of enterprise level. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0xfb’001111 | Wi-Fi Connection State Report | To notify the phone of the ESP32's Wi-Fi status, including STA status and SoftAP status. It is for the STA device to connect to the mobile phone or the SoftAP.However, when the mobile phone receives the Wi-Fi status, it can reply to other frames in addition to this frame. | data[0] represents opmode, including:0x00: NULL;0x01: STA;0x02: SoftAP;0x03: SoftAP&STAdata[1]:the connection state of the STA device, 0x0 indicates a connection state, and others represent a disconnected state;data[2]:the connection state of the SoftAP , that is, how many STA devices have been connected.data[3] and the subsequent is in accordance with the format of SSID/BSSID information. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x10b’010000 | Version | | data[0]= great versiondata[1]= sub version | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x11B’010001 | Wi-Fi List | To send the Wi-Fi list to ESP32. | The format of the data frame is length + RSSI + SSID and it supports to be sent into fragments if the data length is too long. | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x12B’010010 | Report Error | To notify the mobile phone that there is an error with BluFi. | 0x00: sequence error0x01: checksum error0x02: decrypt error0x03: encrypt error0x04: init security error0x05: dh malloc error0x06: dh param error0x07: read param error0x08: make public error | -+ + +--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x13B’010011 | Custom Data | To send or receive custom data. | The data frame supports to be sent into fragments if the data length is too long. | -+---------+---------------+--------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + **1.1 Control Frame (0x0b’00)** + ++---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Control Frame | Implication | Explanation | Note | ++---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x0b’000000 | Ack | The data field of the Ack frame uses the same sequence value of the frame to reply to. | The data field consumes a byte and its value is the same as the sequence field of the frame to reply to. | ++---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x1b’000001 | Set ESP32 to the security mode. | To inform ESP32 of the security mode to use when sending data, which is allowed to be reset multiple times during the process.Each setting affects the subsequent security mode used.If it is not set, ESP32 will send the control frame and data frame with no checksum and encryption by default.The data transmission from the mobile phone to ESP32 is controlled by this control frame. | The data field consumes a byte.The higher 4 bits are for the security mode setting of the control frame, and the lower 4 bits are for the security mode setting of the data frame.b’0000: no checksum and no encryption;b’0001: with checksum but no encryption;b’0010: no checksum but with encryption;b’0011: with both checksum and encryption. | ++---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x2b’000010 | Set the opmode of Wi-Fi. | The frame contains opmode settings for configuring for the Wi-Fi mode of ESP32. | data[0] is for opmode settings, including:0x00: NULL;0x01: STA;0x02: SoftAP;0x03: SoftAP&STA.Please set the SSID/Password/Max Connection Number of the AP mode in the first place if an AP gets involved . | ++---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x3b’000011 | Connect ESP32 to the AP. | To notify ESP32 that the essential information has been sent and it is allowed to connect to the AP. | No data field is contained. | ++---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x4b’000100 | Disconnect ESP32 from the AP. | | No data field is contained. | ++---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x5b’000101 | To get the information of ESP32’s Wi-Fi mode and its status. | | No data field is contained.When receiving this control frame, ESP32 will send back a follow-up frame of Wi-Fi connection state report to the mobile phone with the information of the current opmode, connection status, SSID and so on. The types of information sent to the mobile phone is defined by the application installed on the phone. | ++---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x6b’000110 | Disconnect the STA device from the SoftAP (in SoftAP mode). | | Date[0~5] is taken as the MAC address for the STA device. If there is a second STA device, then it uses data[6-11] and the rest can be done in the same manner. | ++---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x7b'000111 | Get the version information. | | | ++---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x8b’001000 | Disconnect the BLE GATT link. | | ESP32 will disconnect the BLE GATT link after receives this command. | ++---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x9b’001001 | Get the Wi-Fi list. | To get ESP32 to scan the Wi-Fi access points around. | No data field is contained.When receiving this control frame, ESP32 will send back a follow-up frame of Wi-Fi list report to the mobile phone. | ++---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + **1.2 Data Frame (0x1b’01)** + ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Data Frame | Implication | Explanation | Note | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x0b’000000 | Send the negotiation data. | The negotiation data will be sent to the callback function registered in the application layer. | The length of the data depends on the length field. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x1b’000001 | Send the BSSID for STA mode. | To send the BSSID of the AP for the STA device to connect under the condition that the SSID is hidden. | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x2b’000010 | Send the SSID for STA mode. | To send the SSID of the AP for the STA device to connect. | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x3b’000011 | Send the password for STA mode. | To send the password of the AP for the STA device to connect. | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x4b’000100 | Send the SSID for SoftAP mode. | | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x5b’000101 | Send the password for SoftAPmode. | | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x6b’000110 | Set the maximum connection number for SoftAP mode. | | data[0] represents the value of the connection number, ranging from 1 to 4.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x7b’000111 | Set the authentication mode for the SoftAP. | | data[0]:0x00: OPEN0x01: WEP0x02: WPA_PSK0x03: WPA2_PSK0x04:WPA_WPA2_PSK。When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x8b’001000 | Set the channel amount for SoftAP mode. | | data[0] represents the quantity of the supported channels, ranging from 1 to 14.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x9b’001001 | Username | It provides the username of the GATT client when using encryption of enterprise level. | The length of the data depends on the length field. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0xab’001010 | CA Certification | It provides the CA Certification when using encryption of enterprise level. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0xbb’001011 | Client Certification | It provides the client certification when using encryption of enterprise level. Whether the private key is contained or not depends on the content of the certification. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0xcb’001100 | Server Certification | It provides the sever certification when using encryption of enterprise level. Whether the private key is contained or not depends on the content of the certification. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0xdb’001101 | ClientPrivate Key | It provides the private key of the client when using encryption of enterprise level. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0xeb’001110 | ServerPrivate Key | It provides the private key of the sever when using encryption of enterprise level. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0xfb’001111 | Wi-Fi Connection State Report | To notify the phone of the ESP32's Wi-Fi status, including STA status and SoftAP status. It is for the STA device to connect to the mobile phone or the SoftAP.However, when the mobile phone receives the Wi-Fi status, it can reply to other frames in addition to this frame. | data[0] represents opmode, including:0x00: NULL;0x01: STA;0x02: SoftAP;0x03: SoftAP&STAdata[1]:the connection state of the STA device, 0x0 indicates a connection state, and others represent a disconnected state;data[2]:the connection state of the SoftAP , that is, how many STA devices have been connected.data[3] and the subsequent is in accordance with the format of SSID/BSSID information. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x10b’010000 | Version | | data[0]= great versiondata[1]= sub version | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x11B’010001 | Wi-Fi List | To send the Wi-Fi list to ESP32. | The format of the data frame is length + RSSI + SSID and it supports to be sent into fragments if the data length is too long. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x12B’010010 | Report Error | To notify the mobile phone that there is an error with BluFi. | 0x00: sequence error0x01: checksum error0x02: decrypt error0x03: encrypt error0x04: init security error0x05: dh malloc error0x06: dh param error0x07: read param error0x08: make public error | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x13B’010011 | Custom Data | To send or receive custom data. | The data frame supports to be sent into fragments if the data length is too long. | ++--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 2. Frame Control @@ -165,7 +194,7 @@ The format of Ack Frame(8 bit): 3. Sequence Control - Sequence control field. When a frame is sent,the value of sequence fied is automatically added by 1 regardless of the type of frame, which prevents Replay Attack. The sequence is cleared after each reconnection. + Sequence control field. When a frame is sent,the value of sequence fied is automatically incremented by 1 regardless of the type of frame, which prevents Replay Attack. The sequence is cleared after each reconnection. 4. Length @@ -173,7 +202,7 @@ The format of Ack Frame(8 bit): 5. Data -   The instruction of the data field is different according to various value s of Type or Subtype. Please refer to the table above. +   The instruction of the data field is different according to various values of Type or Subtype. Please refer to the table above. 6. CheckSum @@ -182,66 +211,59 @@ The format of Ack Frame(8 bit): The Security Implementation of ESP32 ************************************* -1. To secure data +1. Securing data To ensure that the transmission of the Wi-Fi SSID and password is secure, the message needs to be encrypted using symmetric encryption algorithms, such as AES, DES and so on. Before using symmetric encryption algorithms, the devices are required to negotiate (or generate) a shared key using an asymmetric encryption algorithm (DH, RSA, ECC, etc). -2. To ensure data integrity +2. Ensuring data integrity To ensure data integrity, you need to add a checksum algorithm, such as SHA1, MD5, CRC, etc. -3. Identity security (signature) +3. Securing identity (signature) - Algorithm like RSA can used to secure identity. But for DH, it needs other algorithms as an companion for signature. + Algorithm like RSA can be used to secure identity. But for DH, it needs other algorithms as an companion for signature. -4. To prevent replay attack +4. Replay attack prevention   It is added to the Sequence field and used during the checksum verification. -   For the coding of ESP32, you can determine and develop the security processing, such as key negotiation. The mobile application sends the negotiation data to ESP32 and then the data will be sent to the application layer for processing. If the application layer does not process it, you can use the DH encryption algorithm provided by BluFi to negotiate the key. The application layer needs to register several security-related functions to BluFi: +   For the coding of ESP32, you can determine and develop the security processing, such as key negotiation. The mobile application sends the negotiation data to ESP32 and then the data will be sent to the application layer for processing. If the application layer does not process it, you can use the DH encryption algorithm provided by BluFi to negotiate the key. + + The application layer needs to register several security-related functions to BluFi: -.. highlight:: none +.. code-block:: c -:: + typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free) - typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free); +This function is for ESP32 to receive normal data during negotiation, and after processing is completed, the data will be transmitted using Output_data and Output_len. -   This function is for ESP32 to receive normal data during negotiation, and after processing is completed, the data will be transmitted using Output_data and Output_len. +BluFi will send output_data from Negotiate_data_handler after Negotiate_data_handler is called. - BluFi will send output_data from Negotiate_data_handler after Negotiate_data_handler is called. +Here are two "*", because the length of the data to be emitted is unknown that requires the function to allocate itself (malloc) or point to the global variable, and to inform whether the memory needs to be freed by NEED_FREE. -   Here are two "*", because the length of the data to be emitted is unknown that requires the function to allocate itself (malloc) or point to the global variable, and to infrom whether the memory needs to be freed by NEED_FREE. +.. code-block:: c + typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len)  -.. highlight:: none +The data to be encrypted and decrypted must use the same length. The IV8 is a 8 bit sequence value of frames, which can be used as a 8 bit of IV. -:: +.. code-block:: c - typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len); -   - The data to be encrypted and decrypted must use the same length. The IV8 is a 8 bit sequence value of frames, which can be used as a 8 bit of IV. + typedef int (* esp_blufi_decrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len) -.. highlight:: none +The data to be encrypted and decrypted must use the same length. The IV8 is a 8 bit sequence value of frames, which can be used as a 8 bit of IV. -:: +.. code-block:: c - typedef int (* esp_blufi_decrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len); + typedef uint16_t (*esp_blufi_checksum_func_t)(uint8_t iv8, uint8_t *data, int len) - The data to be encrypted and decrypted must use the same length. The IV8 is a 8 bit sequence value of frames, which can be used as a 8 bit of IV. - -.. highlight:: none - -:: - - typedef uint16_t (*esp_blufi_checksum_func_t)(uint8_t iv8, uint8_t *data, int len); - - This function is used to compute CheckSum and return a value of CheckSum. Blufi uses the returned value to compare the CheckSum of the frame. +This function is used to compute CheckSum and return a value of CheckSum. BluFi uses the returned value to compare the CheckSum of the frame. GATT Related Instructions -************************* +************************** -UUID: -========== +UUID +==== BluFi Service UUID: 0xFFFF,16 bit From 27e4bea69986d20c2db95f23611aaaa04affaa7a Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Wed, 23 May 2018 14:02:09 +0800 Subject: [PATCH 11/23] Update blufi.rst --- docs/en/api-guides/blufi.rst | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst index 1aeace66d..9c70a08e7 100644 --- a/docs/en/api-guides/blufi.rst +++ b/docs/en/api-guides/blufi.rst @@ -110,11 +110,11 @@ The format of Ack Frame(8 bit): 1. Type -   The **Type** field, taking 1 Byte, is divided into **Type** and **Subtype**, that Type uses the lower 2 bit and **Subtype** uses the upper 6 bit. + The **Type** field, taking 1 Byte, is divided into **Type** and **Subtype**, that Type uses the lower 2 bit and **Subtype** uses the upper 6 bit. -   * The control frame is not encrypted for the time being and supports to be verified; + * The control frame is not encrypted for the time being and supports to be verified; -   * The data frame supports to be encrypted and verified. + * The data frame supports to be encrypted and verified. **1.1 Control Frame (0x0b’00)** @@ -198,15 +198,15 @@ The format of Ack Frame(8 bit): 4. Length -   The length of the data field that does not include CheckSum. + The length of the data field that does not include CheckSum. 5. Data -   The instruction of the data field is different according to various values of Type or Subtype. Please refer to the table above. + The instruction of the data field is different according to various values of Type or Subtype. Please refer to the table above. 6. CheckSum -   This field takes 2 bytes that is used to check "sequence + data length + clear text data". + This field takes 2 bytes that is used to check "sequence + data length + clear text data". The Security Implementation of ESP32 ************************************* @@ -225,9 +225,9 @@ The Security Implementation of ESP32 4. Replay attack prevention -   It is added to the Sequence field and used during the checksum verification. + It is added to the Sequence field and used during the checksum verification. -   For the coding of ESP32, you can determine and develop the security processing, such as key negotiation. The mobile application sends the negotiation data to ESP32 and then the data will be sent to the application layer for processing. If the application layer does not process it, you can use the DH encryption algorithm provided by BluFi to negotiate the key. + For the coding of ESP32, you can determine and develop the security processing, such as key negotiation. The mobile application sends the negotiation data to ESP32 and then the data will be sent to the application layer for processing. If the application layer does not process it, you can use the DH encryption algorithm provided by BluFi to negotiate the key. The application layer needs to register several security-related functions to BluFi: @@ -265,11 +265,11 @@ GATT Related Instructions UUID ==== -BluFi Service UUID: 0xFFFF,16 bit +BluFi Service UUID: 0xFFFF,16 bit -BluFi(the mobile -> ESP32): 0xFF01, writable +BluFi (the mobile -> ESP32): 0xFF01, writable -Blufi(ESP32 -> the mobile phone): 0xFF02, readable and callable +Blufi (ESP32 -> the mobile phone): 0xFF02, readable and callable .. note:: From 02d4168d68aff5c6f323476b8cebdedf39af8715 Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Wed, 23 May 2018 14:02:30 +0800 Subject: [PATCH 12/23] Update blufi.rst --- docs/en/api-guides/blufi.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst index 9c70a08e7..2aab6db8d 100644 --- a/docs/en/api-guides/blufi.rst +++ b/docs/en/api-guides/blufi.rst @@ -11,7 +11,7 @@ Fragmenting, data encryption, checksum verification in the BluFi layer are the k You can customize symmetric encryption, asymmetric encryption and checksum support custmization on your demand in practical use. Here we use the DH algorithm for key negotiation, 128-AES algorithm for data encryption, and CRC16 algorithm for checksum verification. The BluFi Flow --------------- +---------------- The BluFi networking flow includes the configuration of the SoftAP and Station. The following uses Station as an example to illustrate the core parts of the procedure, including broadcast, connection, service discovery, negotiation of the shared key, data transmission, connection status backhaul. From ad3af2cfc19ae2c5ca04da1fe65a1d00700d3d7d Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Wed, 23 May 2018 17:15:24 +0800 Subject: [PATCH 13/23] Update blufi.rst --- docs/en/api-guides/blufi.rst | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst index 2aab6db8d..95a2dfad0 100644 --- a/docs/en/api-guides/blufi.rst +++ b/docs/en/api-guides/blufi.rst @@ -1,9 +1,8 @@ -***** BluFi -***** +^^^^^ Overview -========== +-------- The BluFi for ESP32 is a Wi-Fi network configuration function via Bluetooth channel. It provides a secure protocol to pass Wi-Fi configuration and credentials to the ESP32. Using this information ESP32 can then e.g. connect to an AP or establish a SoftAP. Fragmenting, data encryption, checksum verification in the BluFi layer are the key elements of this process. @@ -11,7 +10,7 @@ Fragmenting, data encryption, checksum verification in the BluFi layer are the k You can customize symmetric encryption, asymmetric encryption and checksum support custmization on your demand in practical use. Here we use the DH algorithm for key negotiation, 128-AES algorithm for data encryption, and CRC16 algorithm for checksum verification. The BluFi Flow ----------------- +-------------- The BluFi networking flow includes the configuration of the SoftAP and Station. The following uses Station as an example to illustrate the core parts of the procedure, including broadcast, connection, service discovery, negotiation of the shared key, data transmission, connection status backhaul. @@ -72,7 +71,7 @@ The flow chat of BluFi .. _frame_formats: The Frame Formats Defined in BluFi -=================================== +---------------------------------- The frame formats for the communication between the mobile phone APP and ESP32 are defined as follows: @@ -209,7 +208,7 @@ The format of Ack Frame(8 bit): This field takes 2 bytes that is used to check "sequence + data length + clear text data". The Security Implementation of ESP32 -************************************* +------------------------------------ 1. Securing data @@ -243,7 +242,7 @@ Here are two "*", because the length of the data to be emitted is unknown that r .. code-block:: c - typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len)  + typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len) The data to be encrypted and decrypted must use the same length. The IV8 is a 8 bit sequence value of frames, which can be used as a 8 bit of IV. @@ -260,10 +259,10 @@ The data to be encrypted and decrypted must use the same length. The IV8 is a 8 This function is used to compute CheckSum and return a value of CheckSum. BluFi uses the returned value to compare the CheckSum of the frame. GATT Related Instructions -************************** +------------------------- UUID -==== +>>>>> BluFi Service UUID: 0xFFFF,16 bit @@ -275,4 +274,4 @@ Blufi (ESP32 -> the mobile phone): 0xFF02, readable and callable 1. The Ack mechanism is already defined in the profile, but there is no implementation based on the code for the time being. - 2. Other parts have been implemented. + 2. Other parts have been implemented. \ No newline at end of file From 1001083b1bb52743341a29df0ba8a2fc9f3b3ea2 Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Thu, 24 May 2018 14:33:14 +0800 Subject: [PATCH 14/23] Update blufi.rst --- docs/zh_CN/api-guides/blufi.rst | 299 ++++++++++++++++---------------- 1 file changed, 145 insertions(+), 154 deletions(-) diff --git a/docs/zh_CN/api-guides/blufi.rst b/docs/zh_CN/api-guides/blufi.rst index 027d40e00..50b8d41f3 100644 --- a/docs/zh_CN/api-guides/blufi.rst +++ b/docs/zh_CN/api-guides/blufi.rst @@ -1,43 +1,43 @@ BluFi -***** +^^^^^ 概览 -==== -ESP32 的蓝牙配网功能称为 BluFi。 - -ESP32 BluFi 功能基于 GATT 协议构建,定义了 ESP32 作为 GATT Server 接收 GATT Client(手机等设备)的 Wi-Fi 连接信息,实现 ESP32 通过 Wi-Fi 连接 AP 或配置使用 SoftAP Profile 的过程。必要功能包含 BluFi 层上的分片、数据加密、校验和确认等。 - -你可以自定义 BluFi 配网过程中使用的对称加密、非对称加密以及校验算法。 BluFi 提供的示例程序默认将使用 DH 算法进行密钥协商,使用 128-AES 算法进行数据加密,使用 CRC16 进行进行数据校验。 - -流程: ----- +BluFi 是一款基于蓝牙通道的 Wi-Fi 网络配置功能,适用于 ESP32。它通过安全协议将 Wi-Fi 配置和证书传输到 ESP32,然后 ESP32 可基于这些信息连接到 AP 或建立 SoftAP。 + +BluFi 流程的关键部分包括数据的分片、加密、校验和验证。 + +用户可按需自定义用于对称加密、非对称加密和校验的算法。这里我们采用 DH 算法进行密钥协商、128-AES 算法用于数据加密、CRC16 算法用于校验和验证。 + +BluFi 流程 +---------- BluFi 配网功能包含配置 SoftAP 和 Station 两部分。 下面以配置 Station 为例说明配置步骤。 BluFi 配网的配置 Station 包含广播、连接、服务发现、协商共享密钥、传输数据、回传连接状态等步骤。 -完整的配网过程如下: -------------------- +ESP32 配网流程 +-------------- 1. ESP32 开启 GATT Server 功能,发送带有特定 *adv data* 的广播。你可以自定义该广播,该广播不属于 BluFi Profile。 2. 使用手机 APP 搜索到该特定广播,手机作为 GATT Client 连接 ESP32。你可以决定使用哪款手机 APP。 -3. GATT 连接建立成功后,手机向 ESP32 发送『协商过程』数据帧(详情见 BluFi 传输格式)。 +3. GATT 连接建立成功后,手机向 ESP32 发送“协商过程”数据帧(详情见 :ref:`frame_formats` )。 -4. ESP32 收到『协商过程』数据帧后,会按照使用者自定义的协商过程来解析。 +4. ESP32 收到“协商过程”数据帧后,会按照使用者自定义的协商过程来解析。 5. 手机与 ESP32 进行密钥协商。协商过程可使用 DH/RSA/ECC 等加密算法进行。 -6. 协商结束后,手机端向 ESP32 发送『设置安全模式』控制帧。 +6. 协商结束后,手机端向 ESP32 发送“设置安全模式”控制帧。 -7. ESP32 收到『设置安全模式』控制帧后,使用经过协商的共享密钥以及配置的安全策略对通信数据进行加密和解密。 +7. ESP32 收到“设置安全模式”控制帧后,使用经过协商的共享密钥以及配置的安全策略对通信数据进行加密和解密。 -8. 手机向 ESP32 发送『BluFi 传输格式』定义的 SSID、Password 等用于 Wi-Fi 连接的必要信息。 +8. 手机向 ESP32 发送“BluFi 传输格式”定义的 SSID、Password 等用于 Wi-Fi 连接的必要信息。 -9. 手机向 ESP32 发送『Wi-Fi 连接请求』控制帧,ESP32 收到之后,识别为手机已将必要的信息传输完毕,准备连接 Wi-Fi。 +9. 手机向 ESP32 发送“Wi-Fi 连接请求”控制帧,ESP32 收到之后,识别为手机已将必要的信息传输完毕,准备连接 Wi-Fi。 -10. ESP32 连接到 Wi-Fi 后,发送『Wi-Fi 连接状态报告』控制帧到手机,以报告连接状态。至此配网结束。 +10. ESP32 连接到 Wi-Fi 后,发送“Wi-Fi 连接状态报告”控制帧到手机,以报告连接状态。至此配网结束。 .. note:: @@ -45,14 +45,37 @@ BluFi 配网的配置 Station 包含广播、连接、服务发现、协商共 2. 进行对称加密和解密时,加密和解密前后的数据长度必须一致,支持原地加密和解密。 -配网流程图请参考下图: +配网流程图 +----------- -.. figure:: ../../_static/api-guides_blufi.png +.. seqdiag:: + :caption: BluFi Flow Chart :align: center - :figclass: align-center -BLUFI 传输格式 -************** + seqdiag blufi { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 380; + span_height = 10; + default_fontsize = 12; + + Phone <- ESP32 [label="广播"]; + Phone -> ESP32 [label="建立 GATT 链接"]; + Phone <- ESP32 [label="协商密钥"]; + Phone -> ESP32 [label="协商密钥"]; + Phone -> ESP32 [label="CTRL: 设置 ESP32 手机安全模式"]; + Phone -> ESP32 [label="DATA: SSID"]; + Phone -> ESP32 [label="DATA: Password"]; + Phone -> ESP32 [label="DATA: 其他信息,如 CA 认证"]; + Phone -> ESP32 [label="CTRL: 连接到 AP"]; + Phone <- ESP32 [label="DATA: 连接状态报告"]; + } + +.. _frame_formats: + +BluFi 传输格式 +-------------- 手机 APP 与 ESP32 之间的 BluFi 通信格式定义如下: @@ -70,7 +93,7 @@ BLUFI 传输格式 +------------+--------------------+----------------+------------+-------------------------------------------+----------------+ | LSB - Type | FrameControl(Frag) | SequenceNumber | DataLength | Data | MSB - CheckSum | -+ + + + +-------------------------------------------+ + ++ + + + +----------------------+--------------------+ + | | | | | Total Content Length | Content | | +------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ | 1 | 1 | 1 | 1 | 2 | ${Data Length} - 2 | 2 | @@ -90,107 +113,83 @@ Ack 帧格式(8 bit): 1. Type -   类型域,占 1 Byte。分为 Type 和 Subtype(子类型域)两部分, Type 占低 2 bit,Subtype 占高 6 bit。 + 类型域,占 1 Byte。分为 Type 和 Subtype(子类型域)两部分, Type 占低 2 bit,Subtype 占高 6 bit。 -   * 控制帧,暂不进行加密,可校验; + * 控制帧,暂不进行加密,可校验; -   * 数据帧,可加密,可校验。 + * 数据帧,可加密,可校验。 -+---------+------------------------+--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Type | 帧类型 | Subtype | 含义 | 解释 | 备注 | -+---------+------------------------+--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x0b’00 | 控制帧 (Control Frame) | 0x0b’000000 | Ack | 用来回复对方发的帧,Ack 帧的 Data 域使用回复对象帧的 Sequence 值。 | Data 域使用1 Byte Sequence 值,与恢复对象帧的Sequence 值相同。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x1b’000001 | Set ESP32 to the security mode. | 通知 ESP32 发送数据时使用的安全模式,在该过程中可设置多次,每次设置后影响后续安全模式。在不设置的情况下,ESP32 默认控制帧和数据帧均为无校验、无加密。手机到 ESP32 方向依赖于帧 Control 域。 | Data 域占用 1 Byte,高 4 bit 为控制帧的安全模式,低 4bit 为数据帧的安全模式。 | -| | | | | | b’0000:无校验、无加密; | -| | | | | | b’0001:有校验、无加密; | -| | | | | | b’0010:无校验、有加密; | -| | | | | | b’0011:有校验、有加密。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x2b’000010 | Set the Wi-Fi opmode of ESP32. | 设置 ESP32 的 Wi-Fi 模式,帧包含 opmode 信息。 | data[0] 用于表示 opmode 类型,包括: | -| | | | | | 0x00: NULL; | -| | | | | | 0x01: STA; | -| | | | | | 0x02: SoftAP; | -| | | | | | 0x03: SoftAP&STA. | -| | | | | | 如果设置有包含 AP,请尽量优先设置 AP 模式的 SSID/Password/Max Conn Number 等。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x3b’000011 | Connect ESP32 to the AP. | 通知 ESP32,必要的信息已经发送完毕,可以连接 AP。 | 不包含 Data 域。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x4b’000100 | Disconnect ESP32 from the AP. | 通知 ESP32 断开与 AP 的连接 | 不包含 Data 域。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x5b’000101 | Get the status of Wi-Fi. | 获取 ESP32 的 Wi-Fi 模式和状态等信息。 | 不包含 Data 域。 | -| | | | | | ESP32 收到此控制帧后,后续会通过 Wi-Fi 连接状态报告 (Wi-Fi Connection State Report) 数据帧来回复手机端当前所处的 opmode、连接状态、SSID 等信息。提供给手机端的信息由应用决定。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x6b’000110 | Disconnect the STA device from the SoftAP in SoftAP mode. | 处于 SoftAP 模式时,踢掉某个 STA 设备。 | data[0~5] 为 STA 设备的 MAC 地址,如有多个 STA,则 [6-11] 为第二个,依次类推。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x7b'000111 | Get the version. | | | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x8b’001000 | Tell ESP32 to disconnect the BLE GATT link. | 通知 ESP32 断开蓝牙连接。 | ESP32 收到该指令后主动断开蓝牙连接。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x9b’001001 | Tell ESP32 to get the Wi-Fi list. | 通知 ESP32 扫描周围的 Wi-Fi 热点 | 不包含 Data 域。ESP32 收到此控制帧后,会发送包含 Wi-Fi 热点报告 (Wi-Fi List Report) 的数据帧回复手机端 ESP32 周围的 Wi-Fi 热点。 | -+---------+------------------------+--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x1b’01 | 数据帧 (Data Frame) | 0x0b’000000 | Negotiation data. | 用来发送协商数据,传输到应用层注册的回调函数。 | 数据长度与 Length 域有关。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x1b’000001 | BSSID for STA mode. | STA 将要连接的 AP 的 BSSID(用于隐藏SSID)。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x2b’000010 | SSID for STA mode. | STA 将要连接的 AP 的 SSID。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x3b’000011 | Password for STA mode. | STA 将要连接的 AP 的密码。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x4b’000100 | SSID for SoftAP mode. | SoftAP 模式使用的 SSID。 | 数据长度与 Length 域有关。当传输方向为ESP32 到手机时,表示向手机端提供信息。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x5b’000101 | Password for SoftAPmode. | SoftAP 模式使用的密码。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x6b’000110 | Max connection number for SoftAP mode. | AP 模式的最大连接数。 | data[0] 表示连接数的值,范围 1~4。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x7b’000111 | Authentication mode for SoftAP mode. | AP 模式的认证模式。 | data[0]: | -| | | | | | 0x00: OPEN; | -| | | | | | 0x01: WEP; | -| | | | | | 0x02: WPA_PSK; | -| | | | | | 0x03: WPA2_PSK; | -| | | | | | 0x04: WPA_WPA2_PSK. | -| | | | | | 当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x8b’001000 | Channel for SoftAP mode. | SoftAP 模式的通道数量。 | data[0] 表示通道的数量,范围 1~14。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x9b’001001 | Username. | 使用企业级加密时,Client 端的用户名。 | 数据长度与 Length 域有关。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0xab’001010 | CA certification. | 进行企业级加密时使用的 CA 证书。 | 数据长度与 Length 域有关,长度不够,可用分片。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0xbb’001011 | Client certification. | 进行企业级加密时,Client 端的证书。可包含或不包含私钥,由证书内容决定。 | 数据长度与 Length 域有关,长度不够,可用分片。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0xcb’001100 | Server certification. | 进行企业级加密时,Server 端的证书。可包含或不包含私钥,由证书内容决定。 | 数据长度与 Length 域有关,长度不够,可用分片。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0xdb’001101 | Client private key. | 进行企业级加密时,Client 端的私钥。 | 数据长度与 Length 域有关,长度不够,可用分片。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0xeb’001110 | Server private key. | 进行企业级加密时,Server 端的私钥。 | 数据长度与 Length 域有关,长度不够,可用分片。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0xfb’001111 | Wi-Fi connection state report. | 通知手机 ESP32 的 Wi-Fi 状态,包括 STA状态和 SoftAP 状态,用于手机配置 STA 连接时的通知,或有 STA 连接上 SoftAP 时的通知。但收到手机询问 Wi-Fi 状态时,除了回复此帧外,还可回复其他数据帧。 | data[0] 表示 opmode,包括: | -| | | | | | 0x00: NULL; | -| | | | | | 0x01: STA; | -| | | | | | 0x02: SoftAP; | -| | | | | | 0x03: SoftAP&STA | -| | | | | | data[1]:STA 的连接状态,0x0 表示处于连接状态, 其他表示处于非连接状态; | -| | | | | | data[2]:SoftAP 的连接状态,即表示有多少 STA 已经连接。 | -| | | | | | data[3] 及以后:为按照本协议格式 SSID\BSSID 等信息。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x10b’010000 | Version. | | data[0]= great version | -| | | | | | data[1]= sub version | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x11B’010001 | Wi-Fi list. | 通知手机 ESP32 周围的 Wi-Fi 热点列表。 | 数据帧数据格式为 Length + RSSI + SSID, 数据较长时可分片发送。 | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x12B’010010 | Report error. | 通知手机 BluFi 过程出现异常错误。 | 0x00: sequence error; | -| | | | | | 0x01: checksum error; | -| | | | | | 0x02: decrypt error; | -| | | | | | 0x03: encrypt error; | -| | | | | | 0x04: init security error; | -| | | | | | 0x05: dh malloc error; | -| | | | | | 0x06: dh param error; | -| | | | | | 0x07: read param error; | -| | | | | | 0x08: make public error. | -+ + +--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | | 0x13B’010011 | Custom data. | 用户发送或者接收自定义数据。 | 数据较长时可分片发送。 | -+---------+------------------------+--------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + **1.1 控制帧 (0x0b’00)** + ++-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 控制帧 | 含义 | 解释 | 备注 | ++-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x0b’000000 | Ack | 用来回复对方发的帧,Ack 帧的 Data 域使用回复对象帧的 Sequence 值。 | Data 域使用1 Byte Sequence 值,与恢复对象帧的Sequence 值相同。 | ++-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x1b’000001 | Set ESP32 to the security mode. | 通知 ESP32 发送数据时使用的安全模式,在该过程中可设置多次,每次设置后影响后续安全模式。在不设置的情况下,ESP32 默认控制帧和数据帧均为无校验、无加密。手机到 ESP32 方向依赖于帧 Control 域。 | Data 域占用 1 Byte。高 4 bit 为控制帧的安全模式,低 4bit 为数据帧的安全模式。b’0000:无校验、无加密;b’0001:有校验、无加密;b’0010:无校验、有加密;b’0011:有校验、有加密。 | ++-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x2b’000010 | Set the Wi-Fi opmode of ESP32. | 设置 ESP32 的 Wi-Fi 模式,帧包含 opmode 信息。 | data[0] 用于表示 opmode 类型,包括:0x00: NULL;0x01: STA;0x02: SoftAP;0x03: SoftAP&STA.如果设置有包含 AP,请尽量优先设置 AP 模式的SSID/Password/Max Conn Number 等。 | ++-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x3b’000011 | Connect ESP32 to the AP. | 通知 ESP32,必要的信息已经发送完毕,可以连接 AP。 | 不包含 Data 域。 | ++-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x4b’000100 | Disconnect ESP32 from the AP. | 通知 ESP32 断开与 AP 的连接 | 不包含 Data 域。 | ++-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x5b’000101 | Get the status of Wi-Fi. | 获取 ESP32 的 Wi-Fi 模式和状态等信息。 | 不包含 Data 域。ESP32 收到此控制帧后,后续会通过 Wi-Fi 连接状态报告 (Wi-Fi Connection State Report) 数据帧来回复手机端当前所处的 opmode、连接状态、SSID 等信息。提供给手机端的信息由应用决定。 | ++-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x6b’000110 | Disconnect the STA device from the SoftAP in SoftAP mode. | 处于 SoftAP 模式时,踢掉某个 STA 设备。 | data[0~5] 为 STA 设备的 MAC 地址,如有多个 STA,则 [6-11] 为第二个,依次类推。 | ++-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x7b'000111 | Get the version. | | | ++-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x8b’001000 | Tell ESP32 to disconnect the BLE GATT link. | 通知 ESP32 断开蓝牙连接。 | ESP32 收到该指令后主动断开蓝牙连接。 | ++-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x9b’001001 | Tell ESP32 to get the Wi-Fi list. | 通知 ESP32 扫描周围的 Wi-Fi 热点 | 不包含 Data 域。ESP32 收到此控制帧后,会发送包含 Wi-Fi 热点报告 (Wi-Fi List Report) 的数据帧回复手机端 ESP32 周围的 Wi-Fi 热点。 | ++-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + **1.2 数据帧 (0x1b’01)** + ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 数据帧 | 含义 | 解释 | 备注 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x0b’000000 | Negotiation data. | 用来发送协商数据,传输到应用层注册的回调函数。 | 数据长度与 Length 域有关。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x1b’000001 | BSSID for STA mode. | STA 将要连接的 AP 的 BSSID(用于隐藏SSID)。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x2b’000010 | SSID for STA mode. | STA 将要连接的 AP 的 SSID。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x3b’000011 | Password for STA mode. | STA 将要连接的 AP 的密码。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x4b’000100 | SSID for SoftAP mode. | SoftAP 模式使用的 SSID。 | 数据长度与 Length 域有关。当传输方向为ESP32 到手机时,表示向手机端提供信息。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x5b’000101 | Password for SoftAPmode. | SoftAP 模式使用的密码。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x6b’000110 | Max connection number for SoftAP mode. | AP 模式的最大连接数。 | data[0] 表示连接数的值,范围 1~4。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x7b’000111 | Authentication mode for SoftAP mode. | AP 模式的认证模式。 | data[0]:0x00: OPEN;0x01: WEP;0x02: WPA_PSK;0x03: WPA2_PSK;0x04: WPA_WPA2_PSK.当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x8b’001000 | Channel for SoftAP mode. | SoftAP 模式的通道数量。 | data[0] 表示通道的数量,范围 1~14。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x9b’001001 | Username. | 使用企业级加密时,Client 端的用户名。 | 数据长度与 Length 域有关。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0xab’001010 | CA certification. | 进行企业级加密时使用的 CA 证书。 | 数据长度与 Length 域有关,长度不够,可用分片。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0xbb’001011 | Client certification. | 进行企业级加密时,Client 端的证书。可包含或不包含私钥,由证书内容决定。 | 数据长度与 Length 域有关,长度不够,可用分片。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0xcb’001100 | Server certification. | 进行企业级加密时,Server 端的证书。可包含或不包含私钥,由证书内容决定。 | 数据长度与 Length 域有关,长度不够,可用分片。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0xdb’001101 | Client private key. | 进行企业级加密时,Client 端的私钥。 | 数据长度与 Length 域有关,长度不够,可用分片。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0xeb’001110 | Server private key. | 进行企业级加密时,Server 端的私钥。 | 数据长度与 Length 域有关,长度不够,可用分片。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0xfb’001111 | Wi-Fi connection state report. | 通知手机 ESP32 的 Wi-Fi 状态,包括 STA状态和 SoftAP 状态,用于手机配置 STA 连接时的通知,或有 STA 连接上 SoftAP 时的通知。但收到手机询问 Wi-Fi 状态时,除了回复此帧外,还可回复其他数据帧。 | data[0] 表示 opmode,包括:0x00: NULL;0x01: STA;0x02: SoftAP;0x03: SoftAP&STAdata[1]:STA 的连接状态,0x0 表示处于连接状态, 其他表示处于非连接状态;data[2]:SoftAP 的连接状态,即表示有多少 STA 已经连接。data[3] 及以后:为按照本协议格式 SSID\BSSID 等信息。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x10b’010000 | Version. | | data[0]= great versiondata[1]=sub version | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x11B’010001 | Wi-Fi list. | 通知手机 ESP32 周围的 Wi-Fi 热点列表。 | 数据帧数据格式为 Length + RSSI + SSID, 数据较长时可分片发送。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x12B’010010 | Report error. | 通知手机 BluFi 过程出现异常错误。 | 0x00: sequence error;0x01: checksum error;0x02: decrypt error;0x03: encrypt error;0x04: init security error;0x05: dh malloc error;0x06: dh param error;0x07: read param error;0x08: make public error. | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 0x13B’010011 | Custom data. | 用户发送或者接收自定义数据。 | 数据较长时可分片发送。 | ++--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 2. Frame Control @@ -214,22 +213,22 @@ Ack 帧格式(8 bit): 3. Sequence Control -   序列控制域。帧发送时,无论帧的类型是什么,序列 (Sequence) 都会自动加 1,用来防止重放攻击 (Replay Attack)。每次重现连接后,序列清零。 + 序列控制域。帧发送时,无论帧的类型是什么,序列 (Sequence) 都会自动加 1,用来防止重放攻击 (Replay Attack)。每次重现连接后,序列清零。 4. Length -   Data 域的长度,不包含 CheckSum。 + Data 域的长度,不包含 CheckSum。 5. Data -   不同的 Type 或 Subtype,Data 域的含义均不同。请参考上方表格。 + 不同的 Type 或 Subtype,Data 域的含义均不同。请参考上方表格。 6. CheckSum -   此域为 2 Byte 的校验,用来校验『序列 + 数据长度 + 明文数据』。 + 此域为 2 Byte 的校验,用来校验『序列 + 数据长度 + 明文数据』。 -ESP32端的安全实现 -***************** +ESP32 端的安全实现 +------------------ 1. 保证数据安全 @@ -245,57 +244,49 @@ ESP32端的安全实现 4. 防止重放攻击 (Replay Attack) -   加入帧发送序列(Sequence),并且序列参与数据校验。 + 加入帧发送序列(Sequence),并且序列参与数据校验。 -   在 ESP32 端的代码中,你可以决定和开发密钥协商等安全处理的流程参考上述流程图)。手机应用向 ESP32 发送协商数据,将传送给应用层处理。如果应用层不处理,可使用 BluFi 提供的 DH 加密算法来磋商密钥。应用层需向 BluFi 注册以下几个与安全相关的函数: + 在 ESP32 端的代码中,你可以决定和开发密钥协商等安全处理的流程参考上述流程图)。手机应用向 ESP32 发送协商数据,将传送给应用层处理。如果应用层不处理,可使用 BluFi 提供的 DH 加密算法来磋商密钥。应用层需向 BluFi 注册以下几个与安全相关的函数: -.. highlight:: none - -:: +.. code-block:: c typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free); -   该函数用来接收协商期间的正常数据 (normal data),处理完成后,需要将待发送的数据使用 output_data 和 output_len 传出。 +该函数用来接收协商期间的正常数据 (normal data),处理完成后,需要将待发送的数据使用 output_data 和 output_len 传出。 - BluFi 会在调用完 negotiate_data_handler 后,发送 negotiate_data_handler 传出的 output_data。 +BluFi 会在调用完 negotiate_data_handler 后,发送 negotiate_data_handler 传出的 output_data。 -   这里的两个『*』,因为需要发出去的数据长度未知,所以需要函数自行分配 (malloc) 或者指向全局变量,通过 need_free 通知是否需要释放内存。 +这里的两个『*』,因为需要发出去的数据长度未知,所以需要函数自行分配 (malloc) 或者指向全局变量,通过 need_free 通知是否需要释放内存。 -.. highlight:: none - -:: +.. code-block:: c typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len); -   - 加密和解密的数据长度必须一致。其中 iv8 为帧的 8 bit 序列 (sequence),可作为 iv 的某 8 bit 来使用。 -.. highlight:: none - -:: +加密和解密的数据长度必须一致。其中 iv8 为帧的 8 bit 序列 (sequence),可作为 iv 的某 8 bit 来使用。 + +.. code-block:: c typedef int (* esp_blufi_decrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len); - 加密和解密的数据长度必须一致。其中 iv8 为帧的 8 bit 序列 (sequence),可作为 iv 的某 8 bit 来使用。 +加密和解密的数据长度必须一致。其中 iv8 为帧的 8 bit 序列 (sequence),可作为 iv 的某 8 bit 来使用。 -.. highlight:: none - -:: +.. code-block:: c typedef uint16_t (*esp_blufi_checksum_func_t)(uint8_t iv8, uint8_t *data, int len); -   该函数用来计算 CheckSum,返回值为 CheckSum 的值。BluFi 会使用该函数返回值与包末尾的 CheckSum 做比较。 +该函数用来计算 CheckSum,返回值为 CheckSum 的值。BluFi 会使用该函数返回值与包末尾的 CheckSum 做比较。 GATT 相关说明 -************* +------------- -UUID 相关: -========== +UUID +>>>>> BluFi Service UUID: 0xFFFF,16 bit -BluFi(手机 -> ESP32)特性:0xFF01,主要权限:可写 +BluFi (手机 -> ESP32) 特性:0xFF01,主要权限:可写 -BluFi(ESP32 -> 手机)特性:0xFF02,主要权限:可读可通知 +BluFi (ESP32 -> 手机) 特性:0xFF02,主要权限:可读可通知 .. note:: From 8b884c4debb4c059b2e8dc3d6e2ca63e0893e90f Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Thu, 24 May 2018 14:33:58 +0800 Subject: [PATCH 15/23] Update blufi.rst --- docs/en/api-guides/blufi.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst index 95a2dfad0..9e2554dfa 100644 --- a/docs/en/api-guides/blufi.rst +++ b/docs/en/api-guides/blufi.rst @@ -10,7 +10,7 @@ Fragmenting, data encryption, checksum verification in the BluFi layer are the k You can customize symmetric encryption, asymmetric encryption and checksum support custmization on your demand in practical use. Here we use the DH algorithm for key negotiation, 128-AES algorithm for data encryption, and CRC16 algorithm for checksum verification. The BluFi Flow --------------- +--------------- The BluFi networking flow includes the configuration of the SoftAP and Station. The following uses Station as an example to illustrate the core parts of the procedure, including broadcast, connection, service discovery, negotiation of the shared key, data transmission, connection status backhaul. @@ -71,7 +71,7 @@ The flow chat of BluFi .. _frame_formats: The Frame Formats Defined in BluFi ----------------------------------- +----------------------------------- The frame formats for the communication between the mobile phone APP and ESP32 are defined as follows: @@ -208,7 +208,7 @@ The format of Ack Frame(8 bit): This field takes 2 bytes that is used to check "sequence + data length + clear text data". The Security Implementation of ESP32 ------------------------------------- +------------------------------------- 1. Securing data From aff4696cc43c59432c0bfa66ca8f87a700037a1b Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Mon, 4 Jun 2018 14:21:12 +0800 Subject: [PATCH 16/23] Update blufi.rst --- docs/en/api-guides/blufi.rst | 302 ++++++++++++++++++++++++++--------- 1 file changed, 228 insertions(+), 74 deletions(-) diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst index 9e2554dfa..cc2ffbbd4 100644 --- a/docs/en/api-guides/blufi.rst +++ b/docs/en/api-guides/blufi.rst @@ -7,7 +7,7 @@ The BluFi for ESP32 is a Wi-Fi network configuration function via Bluetooth chan Fragmenting, data encryption, checksum verification in the BluFi layer are the key elements of this process. -You can customize symmetric encryption, asymmetric encryption and checksum support custmization on your demand in practical use. Here we use the DH algorithm for key negotiation, 128-AES algorithm for data encryption, and CRC16 algorithm for checksum verification. +You can customize symmetric encryption, asymmetric encryption and checksum support customization. Here we use the DH algorithm for key negotiation, 128-AES algorithm for data encryption, and CRC16 algorithm for checksum verification. The BluFi Flow --------------- @@ -17,7 +17,7 @@ The following uses Station as an example to illustrate the core parts of the pro 1. Set the ESP32 into GATT Server mode and then it will send broadcasts with specific *advertising data*. You can customize this broadcast as needed, which is not a part of the BluFi Profile. -2. Use the APP installed on the mobile phone to search for this particular broadcast. The mobile phone will connect to ESP32 as the GATT Client once the broadcast is confirmed. The APP used during this part is up to you. +2. Use the App installed on the mobile phone to search for this particular broadcast. The mobile phone will connect to ESP32 as the GATT Client once the broadcast is confirmed. The App used during this part is up to you. 3. After the GATT connection is successfully established, the mobile phone will send a data frame for key negotiation to ESP32 (see the section :ref:`frame_formats` for details). @@ -73,13 +73,13 @@ The flow chat of BluFi The Frame Formats Defined in BluFi ----------------------------------- -The frame formats for the communication between the mobile phone APP and ESP32 are defined as follows: +The frame formats for the communication between the mobile phone App and ESP32 are defined as follows: The frame format with no fragment (8 bit): +------------+---------------+-----------------+-------------+----------------+----------------+ | LSB - Type | Frame Control | Sequence Number | Data Length | Data | MSB - CheckSum | -+------------+---------------+-----------------+-------------+----------------+----------------+ ++============+===============+=================+=============+================+================+ | 1 | 1 | 1 | 1 | ${Data Length} | 2 | +------------+---------------+-----------------+-------------+----------------+----------------+ @@ -91,7 +91,7 @@ The frame format with fragments(8 bit): | LSB - Type | FrameControl(Frag) | SequenceNumber | DataLength | Data | MSB - CheckSum | + + + + +----------------------+--------------------+ + | | | | | Total Content Length | Content | | -+------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ ++============+====================+================+============+======================+====================+================+ | 1 | 1 | 1 | 1 | 2 | ${Data Length} - 2 | 2 | +------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ @@ -103,13 +103,13 @@ The format of Ack Frame(8 bit): | LSB - Type (Ack) | Frame Control | SequenceNumber | Data Length | Data | MSB - CheckSum | + + + + +-----------------------+ + | | | | | Acked Sequence Number | | -+------------------+----------------+------------------+--------------+-----------------------+----------------+ ++==================+================+==================+==============+=======================+================+ | 1 | 1 | 1 | 1 | 1 | 2 | +------------------+----------------+------------------+--------------+-----------------------+----------------+ 1. Type - The **Type** field, taking 1 Byte, is divided into **Type** and **Subtype**, that Type uses the lower 2 bit and **Subtype** uses the upper 6 bit. + The **Type** field, taking 1 byte, is divided into **Type** and **Subtype**, that Type uses the lower 2 bits and **Subtype** uses the upper 6 bits. * The control frame is not encrypted for the time being and supports to be verified; @@ -117,79 +117,233 @@ The format of Ack Frame(8 bit): **1.1 Control Frame (0x0b’00)** -+---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Control Frame | Implication | Explanation | Note | -+---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x0b’000000 | Ack | The data field of the Ack frame uses the same sequence value of the frame to reply to. | The data field consumes a byte and its value is the same as the sequence field of the frame to reply to. | -+---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x1b’000001 | Set ESP32 to the security mode. | To inform ESP32 of the security mode to use when sending data, which is allowed to be reset multiple times during the process.Each setting affects the subsequent security mode used.If it is not set, ESP32 will send the control frame and data frame with no checksum and encryption by default.The data transmission from the mobile phone to ESP32 is controlled by this control frame. | The data field consumes a byte.The higher 4 bits are for the security mode setting of the control frame, and the lower 4 bits are for the security mode setting of the data frame.b’0000: no checksum and no encryption;b’0001: with checksum but no encryption;b’0010: no checksum but with encryption;b’0011: with both checksum and encryption. | -+---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x2b’000010 | Set the opmode of Wi-Fi. | The frame contains opmode settings for configuring for the Wi-Fi mode of ESP32. | data[0] is for opmode settings, including:0x00: NULL;0x01: STA;0x02: SoftAP;0x03: SoftAP&STA.Please set the SSID/Password/Max Connection Number of the AP mode in the first place if an AP gets involved . | -+---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x3b’000011 | Connect ESP32 to the AP. | To notify ESP32 that the essential information has been sent and it is allowed to connect to the AP. | No data field is contained. | -+---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x4b’000100 | Disconnect ESP32 from the AP. | | No data field is contained. | -+---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x5b’000101 | To get the information of ESP32’s Wi-Fi mode and its status. | | No data field is contained.When receiving this control frame, ESP32 will send back a follow-up frame of Wi-Fi connection state report to the mobile phone with the information of the current opmode, connection status, SSID and so on. The types of information sent to the mobile phone is defined by the application installed on the phone. | -+---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x6b’000110 | Disconnect the STA device from the SoftAP (in SoftAP mode). | | Date[0~5] is taken as the MAC address for the STA device. If there is a second STA device, then it uses data[6-11] and the rest can be done in the same manner. | -+---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x7b'000111 | Get the version information. | | | -+---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x8b’001000 | Disconnect the BLE GATT link. | | ESP32 will disconnect the BLE GATT link after receives this command. | -+---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x9b’001001 | Get the Wi-Fi list. | To get ESP32 to scan the Wi-Fi access points around. | No data field is contained.When receiving this control frame, ESP32 will send back a follow-up frame of Wi-Fi list report to the mobile phone. | -+---------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ +| Control Frame / 0x0b’00 | Implication | Explanation | Note | ++=========================+==============================================================+===============================================================+===============================================================+ +| 0x0b’000000 | Ack | The data field of the Ack frame uses the same | The data field consumes a byte and its value is | +| | | sequence value of the frame to reply to. | the same as the sequence field of the frame to reply to. | ++-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ +| 0x1b’000001 | Set ESP32 to the security mode. | To inform ESP32 of the security mode to use | The data field consumes a byte. | +| | | when sending data, which is allowed to be reset | The higher 4 bits are for the security mode setting | +| | | multiple times during the process. | of the control frame, and the lower 4 bits are for | +| | | Each setting affects the subsequent security mode used. | the security mode setting of the data frame. | ++ + + If it is not set, ESP32 will send the control frame +---------------------------------------------------------------+ +| | | and data frame with no checksum and encryption by default. | b’0000: no checksum and no encryption; | ++ + + The data transmission from the mobile phone to ESP32 is +---------------------------------------------------------------+ +| | | controlled by this control frame. | b’0001: with checksum but no encryption; | ++ + + +---------------------------------------------------------------+ +| | | | b’0010: no checksum but with encryption; | ++ + + +---------------------------------------------------------------+ +| | | | b’0011: with both checksum and encryption. | ++-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ +| 0x2b’000010 | Set the opmode of Wi-Fi. | The frame contains opmode settings for | data[0] is for opmode settings, including: | ++ + + configuring for the Wi-Fi mode of ESP32. +---------------------------------------------------------------+ +| | | | 0x00: NULL; | ++ + + +---------------------------------------------------------------+ +| | | | 0x01: STA; | ++ + + +---------------------------------------------------------------+ +| | | | 0x02: SoftAP; | ++ + + +---------------------------------------------------------------+ +| | | | 0x03: SoftAP&STA. | ++ + + +---------------------------------------------------------------+ +| | | | Please set the SSID/Password/Max Connection Number of | +| | | | the AP mode in the first place if an AP gets involved. | ++-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ +| 0x3b’000011 | Connect ESP32 to the AP. | To notify ESP32 that the essential information has been sent | No data field is contained. | +| | | and it is allowed to connect to the AP. | | ++-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ +| 0x4b’000100 | Disconnect ESP32 from the AP. | | No data field is contained. | ++-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ +| 0x5b’000101 | To get the information of ESP32’s Wi-Fi mode and its status. | | No data field is contained. | +| | | | When receiving this control frame, ESP32 will send back | +| | | | a follow-up frame of Wi-Fi connection state report to | +| | | | the mobile phone with the information of the current opmode, | +| | | | connection status, SSID and so on. | +| | | | The types of information sent to the mobile phone is | +| | | | defined by the application installed on the phone. | ++-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ +| 0x6b’000110 | Disconnect the STA device from the SoftAP (in SoftAP mode). | | Date[0~5] is taken as the MAC address for the STA device. | +| | | | If there is a second STA device, then it uses data[6-11] | +| | | | and the rest can be done in the same manner. | ++-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ +| 0x7b'000111 | Get the version information. | | | ++-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ +| 0x8b’001000 | Disconnect the BLE GATT link. | | ESP32 will disconnect the BLE GATT link | +| | | | after receives this command. | ++-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ +| 0x9b’001001 | Get the Wi-Fi list. | To get ESP32 to scan the Wi-Fi access points around. | No data field is contained. | +| | | | When receiving this control frame, | +| | | | ESP32 will send back a follow-up frame of Wi-Fi list | +| | | | report to the mobile phone. | ++-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ **1.2 Data Frame (0x1b’01)** -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Data Frame | Implication | Explanation | Note | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x0b’000000 | Send the negotiation data. | The negotiation data will be sent to the callback function registered in the application layer. | The length of the data depends on the length field. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x1b’000001 | Send the BSSID for STA mode. | To send the BSSID of the AP for the STA device to connect under the condition that the SSID is hidden. | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x2b’000010 | Send the SSID for STA mode. | To send the SSID of the AP for the STA device to connect. | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x3b’000011 | Send the password for STA mode. | To send the password of the AP for the STA device to connect. | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x4b’000100 | Send the SSID for SoftAP mode. | | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x5b’000101 | Send the password for SoftAPmode. | | The length of the data depends on the length field.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x6b’000110 | Set the maximum connection number for SoftAP mode. | | data[0] represents the value of the connection number, ranging from 1 to 4.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x7b’000111 | Set the authentication mode for the SoftAP. | | data[0]:0x00: OPEN0x01: WEP0x02: WPA_PSK0x03: WPA2_PSK0x04:WPA_WPA2_PSK。When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x8b’001000 | Set the channel amount for SoftAP mode. | | data[0] represents the quantity of the supported channels, ranging from 1 to 14.When the transmission direction is ESP32 to the mobile phone, it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x9b’001001 | Username | It provides the username of the GATT client when using encryption of enterprise level. | The length of the data depends on the length field. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0xab’001010 | CA Certification | It provides the CA Certification when using encryption of enterprise level. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0xbb’001011 | Client Certification | It provides the client certification when using encryption of enterprise level. Whether the private key is contained or not depends on the content of the certification. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0xcb’001100 | Server Certification | It provides the sever certification when using encryption of enterprise level. Whether the private key is contained or not depends on the content of the certification. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0xdb’001101 | ClientPrivate Key | It provides the private key of the client when using encryption of enterprise level. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0xeb’001110 | ServerPrivate Key | It provides the private key of the sever when using encryption of enterprise level. | The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0xfb’001111 | Wi-Fi Connection State Report | To notify the phone of the ESP32's Wi-Fi status, including STA status and SoftAP status. It is for the STA device to connect to the mobile phone or the SoftAP.However, when the mobile phone receives the Wi-Fi status, it can reply to other frames in addition to this frame. | data[0] represents opmode, including:0x00: NULL;0x01: STA;0x02: SoftAP;0x03: SoftAP&STAdata[1]:the connection state of the STA device, 0x0 indicates a connection state, and others represent a disconnected state;data[2]:the connection state of the SoftAP , that is, how many STA devices have been connected.data[3] and the subsequent is in accordance with the format of SSID/BSSID information. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x10b’010000 | Version | | data[0]= great versiondata[1]= sub version | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x11B’010001 | Wi-Fi List | To send the Wi-Fi list to ESP32. | The format of the data frame is length + RSSI + SSID and it supports to be sent into fragments if the data length is too long. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x12B’010010 | Report Error | To notify the mobile phone that there is an error with BluFi. | 0x00: sequence error0x01: checksum error0x02: decrypt error0x03: encrypt error0x04: init security error0x05: dh malloc error0x06: dh param error0x07: read param error0x08: make public error | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x13B’010011 | Custom Data | To send or receive custom data. | The data frame supports to be sent into fragments if the data length is too long. | -+--------------+----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| Data Frame | Implication | Explanation | Note | ++==============+====================================================+===============================================================+=======================================================================+ +| 0x0b’000000 | Send the negotiation data. | The negotiation data will be sent to the callback | The length of the data depends on the length field. | +| | | function registered in the application layer. | | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x1b’000001 | Send the BSSID for STA mode. | To send the BSSID of the AP for the STA device to | The length of the data depends on the length field. | +| | | connect under the condition that the SSID is hidden. | When the transmission direction is ESP32 to the mobile phone, | +| | | | it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x2b’000010 | Send the SSID for STA mode. | To send the SSID of the AP for the STA device to connect. | The length of the data depends on the length field. | +| | | | When the transmission direction is ESP32 to the mobile phone, | +| | | | it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x3b’000011 | Send the password for STA mode. | To send the password of the AP for the STA device to connect. | The length of the data depends on the length field. | +| | | | When the transmission direction is ESP32 to the mobile phone, | +| | | | it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x4b’000100 | Send the SSID for SoftAP mode. | | The length of the data depends on the length field. | +| | | | When the transmission direction is ESP32 to the mobile phone, | +| | | | it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x5b’000101 | Send the password for SoftAPmode. | | The length of the data depends on the length field. | +| | | | When the transmission direction is ESP32 to the mobile phone, | +| | | | it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x6b’000110 | Set the maximum connection number for SoftAP mode. | | data[0] represents the value of the connection number, | +| | | | ranging from 1 to 4. When the transmission direction is ESP32 | +| | | | to the mobile phone, it means to provide the mobile phone with | +| | | | the needed information. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x7b’000111 | Set the authentication mode for the SoftAP. | | data[0]: | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x00: OPEN | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x01: WEP | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x02: WPA_PSK | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x03: WPA2_PSK | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x04: WPA_WPA2_PSK | ++ + + +-----------------------------------------------------------------------+ +| | | | When the transmission direction is ESP32 to the mobile phone, | +| | | | it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x8b’001000 | Set the channel amount for SoftAP mode. | | data[0] represents the quantity of the supported channels, | +| | | | ranging from 1 to 14. | +| | | | When the transmission direction is ESP32 to the mobile phone, | +| | | | it means to provide the mobile phone with the needed information. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x9b’001001 | Username | It provides the username of the GATT client when using | The length of the data depends on the length field. | +| | | encryption of enterprise level. | | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0xab’001010 | CA Certification | It provides the CA Certification when using encryption | The length of the data depends on the length field. | +| | | of enterprise level. | The frame supports to be fragmented if the data length is not enough. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0xbb’001011 | Client Certification | It provides the client certification when | The length of the data depends on the length field. | +| | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | +| | | Whether the private key is contained or not | | +| | | depends on the content of the certification. | | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0xcb’001100 | Server Certification | It provides the sever certification when using | The length of the data depends on the length field. | +| | | encryption of enterprise level. Whether the private key is | The frame supports to be fragmented if the data length is not enough. | +| | | contained or not depends on the content of the certification. | | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0xdb’001101 | ClientPrivate Key | It provides the private key of the client when | The length of the data depends on the length field. | +| | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0xeb’001110 | ServerPrivate Key | It provides the private key of the sever when | The length of the data depends on the length field. | +| | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0xfb’001111 | Wi-Fi Connection State Report | To notify the phone of the ESP32's Wi-Fi status, | data[0] represents opmode, including: | ++ + + including STA status and SoftAP status. +-----------------------------------------------------------------------+ +| | | It is for the STA device to connect to the | 0x00: NULL | ++ + + mobile phone or the SoftAP. +-----------------------------------------------------------------------+ +| | | However, when the mobile phone receives the Wi-Fi status, | 0x01: STA | ++ + + it can reply to other frames in addition to this frame. +-----------------------------------------------------------------------+ +| | | | 0x02: SoftAP | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x03: SoftAP&STA | ++ + + +-----------------------------------------------------------------------+ +| | | | data[1]:the connection state of the STA device, | +| | | | 0x0 indicates a connection state, | +| | | | and others represent a disconnected state; | ++ + + +-----------------------------------------------------------------------+ +| | | | data[2]:the connection state of the SoftAP, | +| | | | that is, how many STA devices have been connected. | ++ + + +-----------------------------------------------------------------------+ +| | | | data[3] and the subsequent is in accordance with the | +| | | | format of SSID/BSSID information. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x10b’010000 | Version | | data[0]= great versiondata[1]= sub version | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x11B’010001 | Wi-Fi List | To send the Wi-Fi list to ESP32. | The format of the data frame is length + RSSI + SSID | +| | | | and it supports to be sent into fragments | +| | | | if the data length is too long. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x12B’010010 | Report Error | To notify the mobile phone that there is an error with BluFi. | 0x00: sequence error | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x01: checksum error | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x02: decrypt error | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x03: encrypt error | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x04: init security error | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x05: dh malloc error | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x06: dh param error | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x07: read param error | ++ + + +-----------------------------------------------------------------------+ +| | | | 0x08: make public error | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ +| 0x13B’010011 | Custom Data | To send or receive custom data. | The data frame supports to be sent into | +| | | | fragments if the data length is too long. | ++--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ 2. Frame Control - Control field, takes 1 Byte and each bit has a different meaning. + Control field, takes 1 byte and each bit has a different meaning. + ++--------------------+------------------------------------------------------------------------------------------------+ +| Bit | Meaning | ++====================+================================================================================================+ +| 0x01 | Indicates whether the frame is encrypted. | ++ +------------------------------------------------------------------------------------------------+ +| | 1 means encryption, and 0 means unencrypted. | ++ +------------------------------------------------------------------------------------------------+ +| | The encrypted part of the frame includes | +| | the full clear data before the DATA field is encrypted (no checksum). | ++ +------------------------------------------------------------------------------------------------+ +| | Control frame is not encrypted, so this bit is 0. | ++--------------------+------------------------------------------------------------------------------------------------+ +| 0x02 | The data field that indicates whether a frame contains | +| | a checksum (such as SHA1,MD5,CRC, etc.) for the end of | +| | the frame data field includes SEQUCNE + data length + clear text. | +| | Both the control frame and the data frame can contain a check bit or not. | ++--------------------+------------------------------------------------------------------------------------------------+ +| 0x04 | Represents the data direction. | ++--------------------+------------------------------------------------------------------------------------------------+ +| | 0 means the mobile phone to ESP32; | ++--------------------+------------------------------------------------------------------------------------------------+ +| | 1 means ESP32 to the mobile phone. | ++--------------------+------------------------------------------------------------------------------------------------+ +| 0x08 | Indicates whether the other person is required to reply to an ACK. | ++--------------------+------------------------------------------------------------------------------------------------+ +| | 0 indicates no requirement; | ++--------------------+------------------------------------------------------------------------------------------------+ +| | 1 indicates to reply Ack. | ++--------------------+------------------------------------------------------------------------------------------------+ +| 0x10 | Indicates whether there are subsequent data fragments. | ++--------------------+------------------------------------------------------------------------------------------------+ +| | 0 indicates that there are no subsequent data fragments for this frame; | ++--------------------+------------------------------------------------------------------------------------------------+ +| | 1 indicates that there are subsequent data fragments and used to transmit longer data. | ++--------------------+------------------------------------------------------------------------------------------------+ +| | In the case of a frag frame, | +| | the total length of the current content section + subsequent content section is given, | +| | in the first 2 bytes of the data field (that is, the content data of the maximum support 64K). | ++--------------------+------------------------------------------------------------------------------------------------+ +| 0x10~0x80 reserved | | ++--------------------+------------------------------------------------------------------------------------------------+ 3. Sequence Control From 4232f69f98283663dc6a868cbd92beed5e7052bd Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Mon, 4 Jun 2018 14:22:04 +0800 Subject: [PATCH 17/23] Update blufi.rst --- docs/zh_CN/api-guides/blufi.rst | 307 +++++++++++++++++++++++--------- 1 file changed, 220 insertions(+), 87 deletions(-) diff --git a/docs/zh_CN/api-guides/blufi.rst b/docs/zh_CN/api-guides/blufi.rst index 50b8d41f3..74f068961 100644 --- a/docs/zh_CN/api-guides/blufi.rst +++ b/docs/zh_CN/api-guides/blufi.rst @@ -83,7 +83,7 @@ BluFi 传输格式 +------------+---------------+-----------------+-------------+----------------+----------------+ | LSB - Type | Frame Control | Sequence Number | Data Length | Data | MSB - CheckSum | -+------------+---------------+-----------------+-------------+----------------+----------------+ ++============+===============+=================+=============+================+================+ | 1 | 1 | 1 | 1 | ${Data Length} | 2 | +------------+---------------+-----------------+-------------+----------------+----------------+ @@ -95,7 +95,7 @@ BluFi 传输格式 | LSB - Type | FrameControl(Frag) | SequenceNumber | DataLength | Data | MSB - CheckSum | + + + + +----------------------+--------------------+ + | | | | | Total Content Length | Content | | -+------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ ++============+====================+================+============+======================+====================+================+ | 1 | 1 | 1 | 1 | 2 | ${Data Length} - 2 | 2 | +------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ @@ -107,13 +107,13 @@ Ack 帧格式(8 bit): | LSB - Type (Ack) | Frame Control | SequenceNumber | Data Length | Data | MSB - CheckSum | + + + + +-----------------------+ + | | | | | Acked Sequence Number | | -+------------------+---------------+-----------------+-------------+-----------------------+----------------+ ++==================+===============+=================+=============+=======================+================+ | 1 | 1 | 1 | 1 | 1 | 2 | +------------------+---------------+-----------------+-------------+-----------------------+----------------+ 1. Type - 类型域,占 1 Byte。分为 Type 和 Subtype(子类型域)两部分, Type 占低 2 bit,Subtype 占高 6 bit。 + 类型域,占 1 byte。分为 Type 和 Subtype(子类型域)两部分, Type 占低 2 bit,Subtype 占高 6 bit。 * 控制帧,暂不进行加密,可校验; @@ -121,95 +121,228 @@ Ack 帧格式(8 bit): **1.1 控制帧 (0x0b’00)** -+-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 控制帧 | 含义 | 解释 | 备注 | -+-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x0b’000000 | Ack | 用来回复对方发的帧,Ack 帧的 Data 域使用回复对象帧的 Sequence 值。 | Data 域使用1 Byte Sequence 值,与恢复对象帧的Sequence 值相同。 | -+-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x1b’000001 | Set ESP32 to the security mode. | 通知 ESP32 发送数据时使用的安全模式,在该过程中可设置多次,每次设置后影响后续安全模式。在不设置的情况下,ESP32 默认控制帧和数据帧均为无校验、无加密。手机到 ESP32 方向依赖于帧 Control 域。 | Data 域占用 1 Byte。高 4 bit 为控制帧的安全模式,低 4bit 为数据帧的安全模式。b’0000:无校验、无加密;b’0001:有校验、无加密;b’0010:无校验、有加密;b’0011:有校验、有加密。 | -+-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x2b’000010 | Set the Wi-Fi opmode of ESP32. | 设置 ESP32 的 Wi-Fi 模式,帧包含 opmode 信息。 | data[0] 用于表示 opmode 类型,包括:0x00: NULL;0x01: STA;0x02: SoftAP;0x03: SoftAP&STA.如果设置有包含 AP,请尽量优先设置 AP 模式的SSID/Password/Max Conn Number 等。 | -+-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x3b’000011 | Connect ESP32 to the AP. | 通知 ESP32,必要的信息已经发送完毕,可以连接 AP。 | 不包含 Data 域。 | -+-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x4b’000100 | Disconnect ESP32 from the AP. | 通知 ESP32 断开与 AP 的连接 | 不包含 Data 域。 | -+-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x5b’000101 | Get the status of Wi-Fi. | 获取 ESP32 的 Wi-Fi 模式和状态等信息。 | 不包含 Data 域。ESP32 收到此控制帧后,后续会通过 Wi-Fi 连接状态报告 (Wi-Fi Connection State Report) 数据帧来回复手机端当前所处的 opmode、连接状态、SSID 等信息。提供给手机端的信息由应用决定。 | -+-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x6b’000110 | Disconnect the STA device from the SoftAP in SoftAP mode. | 处于 SoftAP 模式时,踢掉某个 STA 设备。 | data[0~5] 为 STA 设备的 MAC 地址,如有多个 STA,则 [6-11] 为第二个,依次类推。 | -+-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x7b'000111 | Get the version. | | | -+-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x8b’001000 | Tell ESP32 to disconnect the BLE GATT link. | 通知 ESP32 断开蓝牙连接。 | ESP32 收到该指令后主动断开蓝牙连接。 | -+-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x9b’001001 | Tell ESP32 to get the Wi-Fi list. | 通知 ESP32 扫描周围的 Wi-Fi 热点 | 不包含 Data 域。ESP32 收到此控制帧后,会发送包含 Wi-Fi 热点报告 (Wi-Fi List Report) 的数据帧回复手机端 ESP32 周围的 Wi-Fi 热点。 | -+-------------+-----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ +| 控制帧 / 0x0b’00 | 含义 | 解释 | 备注 | ++==================+===================================+================================================================+======================================================================+ +| 0x0b’000000 | Ack | 用来回复对方发的帧, | Data 域使用1 byte Sequence 值, | +| | | Ack 帧的 Data 域使用回复对象帧的 Sequence 值。 | 与恢复对象帧的Sequence 值相同。 | ++------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ +| 0x1b’000001 | Set ESP32 to the security mode. | 通知 ESP32 发送数据时使用的安全模式, | Data 域占用 1 byte。 | +| | | 在该过程中可设置多次,每次设置后影响后续安全模式。 | 高 4 bit 为控制帧的安全模式,低 4bit 为数据帧的安全模式。 | ++ + + 在不设置的情况下,ESP32 默认控制帧和数据帧均为无校验、无加密。 +----------------------------------------------------------------------+ +| | | 手机到 ESP32 方向依赖于帧 Control 域。 | b’0000:无校验、无加密; | ++ + + +----------------------------------------------------------------------+ +| | | | b’0001:有校验、无加密; | ++ + + +----------------------------------------------------------------------+ +| | | | b’0010:无校验、有加密; | ++ + + +----------------------------------------------------------------------+ +| | | | b’0011:有校验、有加密。 | ++------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ +| 0x2b’000010 | Set the Wi-Fi opmode of ESP32. | 设置 ESP32 的 Wi-Fi 模式,帧包含 opmode 信息。 | data[0] 用于表示 opmode 类型,包括: | ++ + + +----------------------------------------------------------------------+ +| | | | 0x00: NULL; | ++ + + +----------------------------------------------------------------------+ +| | | | 0x01: STA; | ++ + + +----------------------------------------------------------------------+ +| | | | 0x02: SoftAP; | ++ + + +----------------------------------------------------------------------+ +| | | | 0x03: SoftAP&STA. | ++ + + +----------------------------------------------------------------------+ +| | | | 如果设置有包含 AP,请尽量优先 | +| | | | 设置 AP 模式的SSID/Password/Max Conn Number 等。 | ++------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ +| 0x3b’000011 | Connect ESP32 to the AP. | 通知 ESP32,必要的信息已经发送完毕,可以连接 AP。 | 不包含 Data 域。 | ++------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ +| 0x4b’000100 | Disconnect ESP32 from the AP. | 通知 ESP32 断开与 AP 的连接 | 不包含 Data 域。 | ++------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ +| 0x5b’000101 | Get the status of Wi-Fi. | 获取 ESP32 的 Wi-Fi 模式和状态等信息。 | 不包含 Data 域。 | +| | | | ESP32 收到此控制帧后,后续会通过 Wi-Fi 连接状态 | +| | | | 报告 (Wi-Fi Connection State Report) 数据帧来回复手机端当前 | +| | | | 所处的 opmode、连接状态、SSID 等信息。提供给手机端的信息由应用决定。 | ++------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ +| 0x6b’000110 | Disconnect the STA device | 处于 SoftAP 模式时,踢掉某个 STA 设备。 | data[0~5] 为 STA 设备的 MAC 地址, | +| | from the SoftAP in SoftAP mode. | | 如有多个 STA,则 [6-11] 为第二个,依次类推。 | ++------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ +| 0x7b'000111 | Get the version. | | | ++------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ +| 0x8b’001000 | Tell ESP32 to disconnect | 通知 ESP32 断开蓝牙连接。 | ESP32 收到该指令后主动断开蓝牙连接。 | +| | the BLE GATT link. | | | ++------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ +| 0x9b’001001 | Tell ESP32 to get the Wi-Fi list. | 通知 ESP32 扫描周围的 Wi-Fi 热点 | 不包含 Data 域。 | +| | | | ESP32 收到此控制帧后,会发送包含 Wi-Fi 热点 | +| | | | 报告 (Wi-Fi List Report) 的数据帧回复 | +| | | | 手机端 ESP32 周围的 Wi-Fi 热点。 | ++------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ **1.2 数据帧 (0x1b’01)** -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 数据帧 | 含义 | 解释 | 备注 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x0b’000000 | Negotiation data. | 用来发送协商数据,传输到应用层注册的回调函数。 | 数据长度与 Length 域有关。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x1b’000001 | BSSID for STA mode. | STA 将要连接的 AP 的 BSSID(用于隐藏SSID)。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x2b’000010 | SSID for STA mode. | STA 将要连接的 AP 的 SSID。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x3b’000011 | Password for STA mode. | STA 将要连接的 AP 的密码。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x4b’000100 | SSID for SoftAP mode. | SoftAP 模式使用的 SSID。 | 数据长度与 Length 域有关。当传输方向为ESP32 到手机时,表示向手机端提供信息。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x5b’000101 | Password for SoftAPmode. | SoftAP 模式使用的密码。 | 数据长度与 Length 域有关。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x6b’000110 | Max connection number for SoftAP mode. | AP 模式的最大连接数。 | data[0] 表示连接数的值,范围 1~4。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x7b’000111 | Authentication mode for SoftAP mode. | AP 模式的认证模式。 | data[0]:0x00: OPEN;0x01: WEP;0x02: WPA_PSK;0x03: WPA2_PSK;0x04: WPA_WPA2_PSK.当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x8b’001000 | Channel for SoftAP mode. | SoftAP 模式的通道数量。 | data[0] 表示通道的数量,范围 1~14。当传输方向为 ESP32 到手机时,表示向手机端提供信息。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x9b’001001 | Username. | 使用企业级加密时,Client 端的用户名。 | 数据长度与 Length 域有关。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0xab’001010 | CA certification. | 进行企业级加密时使用的 CA 证书。 | 数据长度与 Length 域有关,长度不够,可用分片。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0xbb’001011 | Client certification. | 进行企业级加密时,Client 端的证书。可包含或不包含私钥,由证书内容决定。 | 数据长度与 Length 域有关,长度不够,可用分片。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0xcb’001100 | Server certification. | 进行企业级加密时,Server 端的证书。可包含或不包含私钥,由证书内容决定。 | 数据长度与 Length 域有关,长度不够,可用分片。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0xdb’001101 | Client private key. | 进行企业级加密时,Client 端的私钥。 | 数据长度与 Length 域有关,长度不够,可用分片。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0xeb’001110 | Server private key. | 进行企业级加密时,Server 端的私钥。 | 数据长度与 Length 域有关,长度不够,可用分片。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0xfb’001111 | Wi-Fi connection state report. | 通知手机 ESP32 的 Wi-Fi 状态,包括 STA状态和 SoftAP 状态,用于手机配置 STA 连接时的通知,或有 STA 连接上 SoftAP 时的通知。但收到手机询问 Wi-Fi 状态时,除了回复此帧外,还可回复其他数据帧。 | data[0] 表示 opmode,包括:0x00: NULL;0x01: STA;0x02: SoftAP;0x03: SoftAP&STAdata[1]:STA 的连接状态,0x0 表示处于连接状态, 其他表示处于非连接状态;data[2]:SoftAP 的连接状态,即表示有多少 STA 已经连接。data[3] 及以后:为按照本协议格式 SSID\BSSID 等信息。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x10b’010000 | Version. | | data[0]= great versiondata[1]=sub version | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x11B’010001 | Wi-Fi list. | 通知手机 ESP32 周围的 Wi-Fi 热点列表。 | 数据帧数据格式为 Length + RSSI + SSID, 数据较长时可分片发送。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x12B’010010 | Report error. | 通知手机 BluFi 过程出现异常错误。 | 0x00: sequence error;0x01: checksum error;0x02: decrypt error;0x03: encrypt error;0x04: init security error;0x05: dh malloc error;0x06: dh param error;0x07: read param error;0x08: make public error. | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x13B’010011 | Custom data. | 用户发送或者接收自定义数据。 | 数据较长时可分片发送。 | -+--------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 数据帧 | 含义 | 解释 | 备注 | ++===============+========================================+================================================+======================================================+ +| 0x0 b’000000 | Negotiation data. | 用来发送协商数据,传输到应用层注册的回调函数。 | 数据长度与 Length 域有关。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x1 b’000001 | BSSID for STA mode. | STA 将要连接的 AP 的 BSSID(用于隐藏SSID)。 | 数据长度与 Length 域有关。 | ++ + + +------------------------------------------------------+ +| | | | 当传输方向为 ESP32 到手机时, | +| | | | 表示向手机端提供信息。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x2 b’000010 | SSID for STA mode. | STA 将要连接的 AP 的 SSID。 | 数据长度与 Length 域有关。 | ++ + + +------------------------------------------------------+ +| | | | 当传输方向为 ESP32 到手机时, | +| | | | 表示向手机端提供信息。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x3 b’000011 | Password for STA mode. | STA 将要连接的 AP 的密码。 | 数据长度与 Length 域有关。 | ++ + + +------------------------------------------------------+ +| | | | 当传输方向为 ESP32 到手机时, | +| | | | 表示向手机端提供信息。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x4 b’000100 | SSID for SoftAP mode. | SoftAP 模式使用的 SSID。 | 数据长度与 Length 域有关。 | ++ + + +------------------------------------------------------+ +| | | | 当传输方向为 ESP32 到手机时, | +| | | | 表示向手机端提供信息。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x5 b’000101 | Password for SoftAPmode. | SoftAP 模式使用的密码。 | 数据长度与 Length 域有关。 | ++ + + +------------------------------------------------------+ +| | | | 当传输方向为 ESP32 到手机时, | +| | | | 表示向手机端提供信息。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x6 b’000110 | Max connection number for SoftAP mode. | AP 模式的最大连接数。 | data[0] 表示连接数的值,范围 1~4。 | ++ + + +------------------------------------------------------+ +| | | | 当传输方向为 ESP32 到手机时, | +| | | | 表示向手机端提供信息。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x7b’000111 | Authentication mode for SoftAP mode. | AP 模式的认证模式。 | data[0]: | ++ + + +------------------------------------------------------+ +| | | | 0x00: OPEN; | ++ + + +------------------------------------------------------+ +| | | | 0x01: WEP; | ++ + + +------------------------------------------------------+ +| | | | 0x02: WPA_PSK; | ++ + + +------------------------------------------------------+ +| | | | 0x03: WPA2_PSK; | ++ + + +------------------------------------------------------+ +| | | | 0x04: WPA_WPA2_PSK. | ++ + + +------------------------------------------------------+ +| | | | 当传输方向为 ESP32 到手机时, | +| | | | 表示向手机端提供信息。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x8b’001000 | Channel for SoftAP mode. | SoftAP 模式的通道数量。 | data[0] 表示通道的数量,范围 1~14。 | ++ + + +------------------------------------------------------+ +| | | | 当传输方向为 ESP32 到手机时, | +| | | | 表示向手机端提供信息。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x9b’001001 | Username. | 使用企业级加密时,Client 端的用户名。 | 数据长度与 Length 域有关。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0xab’001010 | CA certification. | 进行企业级加密时使用的 CA 证书。 | 数据长度与 Length 域有关, | +| | | | 长度不够,可用分片。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0xbb’001011 | Client certification. | 进行企业级加密时,Client 端的证书。 | 数据长度与 Length 域有关, | ++ + +------------------------------------------------+ 长度不够,可用分片。 + +| | | 可包含或不包含私钥,由证书内容决定。 | | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0xcb’001100 | Server certification. | 进行企业级加密时,Server 端的证书。 | 数据长度与 Length 域有关, | ++ + +------------------------------------------------+ 长度不够,可用分片。 + +| | | 可包含或不包含私钥,由证书内容决定。 | | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0xdb’001101 | Client private key. | 进行企业级加密时,Client 端的私钥。 | 数据长度与 Length 域有关, | +| | | | 长度不够,可用分片。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0xeb’001110 | Server private key. | 进行企业级加密时,Server 端的私钥。 | 数据长度与 Length 域有关, | +| | | | 长度不够,可用分片。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0xf b’001111 | Wi-Fi connection state report. | 通知手机 ESP32 的 Wi-Fi 状态, | data[0] 表示 opmode,包括: | +| | | 包括 STA状态和 SoftAP 状态, | | +| | | 用于手机配置 STA 连接时的通知, | | +| | | 或有 STA 连接上 SoftAP 时的通知。 | | ++ + +------------------------------------------------+------------------------------------------------------+ +| | | 但收到手机询问 Wi-Fi 状态时, | 0x00: NULL; | ++ + + 除了回复此帧外,还可回复其他数据帧。 +------------------------------------------------------+ +| | | | 0x01: STA; | ++ + + +------------------------------------------------------+ +| | | | 0x02: SoftAP; | ++ + + +------------------------------------------------------+ +| | | | 0x03: SoftAP&STA | ++ + + +------------------------------------------------------+ +| | | | data[1]:STA 的连接状态, | +| | | | 0x0 表示处于连接状态, | +| | | | 其他表示处于非连接状态; | ++ + + +------------------------------------------------------+ +| | | | data[2]:SoftAP 的连接状态, | +| | | | 即表示有多少 STA 已经连接。 | ++ + + +------------------------------------------------------+ +| | | | data[3] 及以后:为按照本协议格式 SSID\BSSID 等信息。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x10 b’010000 | Version. | | data[0]= great version | ++ + + +------------------------------------------------------+ +| | | | data[1]=sub version | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x11 B’010001 | Wi-Fi list. | 通知手机 ESP32 周围的 Wi-Fi 热点列表。 | 数据帧数据格式为 Length + RSSI + SSID, | +| | | | 数据较长时可分片发送。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x12 B’010010 | Report error. | 通知手机 BluFi 过程出现异常错误。 | 0x00: sequence error; | ++ + + +------------------------------------------------------+ +| | | | 0x01: checksum error; | ++ + + +------------------------------------------------------+ +| | | | 0x02: decrypt error; | ++ + + +------------------------------------------------------+ +| | | | 0x03: encrypt error; | ++ + + +------------------------------------------------------+ +| | | | 0x04: init security error; | ++ + + +------------------------------------------------------+ +| | | | 0x05: dh malloc error; | ++ + + +------------------------------------------------------+ +| | | | 0x06: dh param error; | ++ + + +------------------------------------------------------+ +| | | | 0x07: read param error; | ++ + + +------------------------------------------------------+ +| | | | 0x08: make public error. | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ +| 0x13 B’010011 | Custom data. | 用户发送或者接收自定义数据。 | 数据较长时可分片发送。 | ++---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ 2. Frame Control - 帧控制域,占 1 Byte,每个 bit 表示不同含义。 + 帧控制域,占 1 byte,每个 bit 表示不同含义。 -+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| bit | 含义 | -+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x01 | 表示帧是否加密。1 表示加密,0 表示未加密。加密部分帧括完整的 Data 域加密之前的明文(不帧含末尾的校验)。控制帧暂不加密,故控制帧此位为 0。 | -+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x02 | 表示帧 Data 域结尾是否帧含校验(例如 SHA1、MD5、CRC等)需要校验的数据域包括『序列 + 数据长度 + 明文数据』。控制帧和数据帧都可以包含校验位或不包含。 | -+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x04 | 表示数据方向。0 表示手机发向 ESP32;1 表示 ESP32 发向手机。 | -+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x08 | 表示是否要求对方回复 Ack。0 表示不要求;1 表示要求回复 Ack。 | -+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x10 | 表示是否有后续的数据分片。0 表示此帧没有后续数据分片;1 表示还有后续数据分片。用来传输较长的数据。如果是 Frag 帧,则告知当前『内容部分+后续内容部分』的总长度,位于 Data 域的前 2 Byte (即最大支持 64K 的内容数据)。 | -+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 0x10~0x80 保留 | | -+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++----------------+-------------------------------------------------------------------------+ +| 位 | 含义 | ++================+=========================================================================+ +| 0x01 | 表示帧是否加密。 | ++ +-------------------------------------------------------------------------+ +| | 1 表示加密,0 表示未加密。 | ++ +-------------------------------------------------------------------------+ +| | 加密部分帧括完整的 DATA 域加密之前的明文(不帧含末尾的校验)。 | ++ +-------------------------------------------------------------------------+ +| | 控制帧暂不加密,故控制帧此位为 0。 | ++----------------+-------------------------------------------------------------------------+ +| 0x02 | 表示帧 Data 域结尾是否帧含校验(例如 SHA1,MD5,CRC等)需要校验的数据域, | +| | 包括 sequcne + data length + 明文 data。 | ++ +-------------------------------------------------------------------------+ +| | 控制帧和数据帧都可以包含校验位或不包含。 | ++----------------+-------------------------------------------------------------------------+ +| 0x04 | 表示数据方向。 | ++ +-------------------------------------------------------------------------+ +| | 0 表示手机发向 ESP32; | ++ +-------------------------------------------------------------------------+ +| | 1 表示 ESP32 发向手机。 | ++----------------+-------------------------------------------------------------------------+ +| 0x08 | 表示是否要求对方回复 ack。 | ++ +-------------------------------------------------------------------------+ +| | 0 表示不要求; | ++ +-------------------------------------------------------------------------+ +| | 1 表示要求回复 ack。 | ++----------------+-------------------------------------------------------------------------+ +| 0x10 | 表示是否有后续的数据分片。 | ++ +-------------------------------------------------------------------------+ +| | 0 表示此帧没有后续数据分片; | ++ +-------------------------------------------------------------------------+ +| | 1 表示还有后续数据分片,用来传输较长的数据。 | ++ +-------------------------------------------------------------------------+ +| | 如果是 Frag 帧,则告知当前 content 部分+后续 content 部分的总长度, | +| | 位于 Data 域的前 2 字节(即最大支持 64K 的 content 数据)。 | ++----------------+-------------------------------------------------------------------------+ +| 0x10~0x80 保留 | | ++----------------+-------------------------------------------------------------------------+ 3. Sequence Control @@ -225,7 +358,7 @@ Ack 帧格式(8 bit): 6. CheckSum - 此域为 2 Byte 的校验,用来校验『序列 + 数据长度 + 明文数据』。 + 此域为 2 byte 的校验,用来校验『序列 + 数据长度 + 明文数据』。 ESP32 端的安全实现 ------------------ From bf29c7ca57c846aaa398b8f1198bed197b13e27f Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Mon, 4 Jun 2018 14:24:10 +0800 Subject: [PATCH 18/23] Update index.rst --- docs/en/api-guides/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/api-guides/index.rst b/docs/en/api-guides/index.rst index 648a9d1db..3f1fafc25 100644 --- a/docs/en/api-guides/index.rst +++ b/docs/en/api-guides/index.rst @@ -23,5 +23,5 @@ API Guides ROM debug console WiFi Driver Mesh Stack - Blu-Fi + BluFi External SPI-connected RAM From 27d1a5d51e658cdec96c80a29103a66c079877a4 Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Mon, 4 Jun 2018 14:24:40 +0800 Subject: [PATCH 19/23] Update index.rst --- docs/zh_CN/api-guides/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh_CN/api-guides/index.rst b/docs/zh_CN/api-guides/index.rst index a9a150cd8..661be7ee8 100644 --- a/docs/zh_CN/api-guides/index.rst +++ b/docs/zh_CN/api-guides/index.rst @@ -23,5 +23,5 @@ API Guides ROM debug console WiFi Driver Mesh Stack - Blu-Fi + BluFi External SPI-connected RAM \ No newline at end of file From 3a15efd3c37fceb63a5964d2cbb6c06266509a81 Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Wed, 6 Jun 2018 11:46:13 +0800 Subject: [PATCH 20/23] Delete api-guides_blufi.png --- docs/_static/api-guides_blufi.png | Bin 215887 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/_static/api-guides_blufi.png diff --git a/docs/_static/api-guides_blufi.png b/docs/_static/api-guides_blufi.png deleted file mode 100644 index b010db4cee5213e869a02d2037b2cea194c81d7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 215887 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%0Deq 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 From ad48c2689fa1d0f1fc685c5692c0f08f1714c885 Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Wed, 6 Jun 2018 11:58:46 +0800 Subject: [PATCH 21/23] Update blufi.rst --- docs/en/api-guides/blufi.rst | 438 +++++++++++++++++------------------ 1 file changed, 219 insertions(+), 219 deletions(-) diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst index cc2ffbbd4..7f56023b3 100644 --- a/docs/en/api-guides/blufi.rst +++ b/docs/en/api-guides/blufi.rst @@ -117,233 +117,233 @@ The format of Ack Frame(8 bit): **1.1 Control Frame (0x0b’00)** -+-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ -| Control Frame / 0x0b’00 | Implication | Explanation | Note | -+=========================+==============================================================+===============================================================+===============================================================+ -| 0x0b’000000 | Ack | The data field of the Ack frame uses the same | The data field consumes a byte and its value is | -| | | sequence value of the frame to reply to. | the same as the sequence field of the frame to reply to. | -+-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ -| 0x1b’000001 | Set ESP32 to the security mode. | To inform ESP32 of the security mode to use | The data field consumes a byte. | -| | | when sending data, which is allowed to be reset | The higher 4 bits are for the security mode setting | -| | | multiple times during the process. | of the control frame, and the lower 4 bits are for | -| | | Each setting affects the subsequent security mode used. | the security mode setting of the data frame. | -+ + + If it is not set, ESP32 will send the control frame +---------------------------------------------------------------+ -| | | and data frame with no checksum and encryption by default. | b’0000: no checksum and no encryption; | -+ + + The data transmission from the mobile phone to ESP32 is +---------------------------------------------------------------+ -| | | controlled by this control frame. | b’0001: with checksum but no encryption; | -+ + + +---------------------------------------------------------------+ -| | | | b’0010: no checksum but with encryption; | -+ + + +---------------------------------------------------------------+ -| | | | b’0011: with both checksum and encryption. | -+-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ -| 0x2b’000010 | Set the opmode of Wi-Fi. | The frame contains opmode settings for | data[0] is for opmode settings, including: | -+ + + configuring for the Wi-Fi mode of ESP32. +---------------------------------------------------------------+ -| | | | 0x00: NULL; | -+ + + +---------------------------------------------------------------+ -| | | | 0x01: STA; | -+ + + +---------------------------------------------------------------+ -| | | | 0x02: SoftAP; | -+ + + +---------------------------------------------------------------+ -| | | | 0x03: SoftAP&STA. | -+ + + +---------------------------------------------------------------+ -| | | | Please set the SSID/Password/Max Connection Number of | -| | | | the AP mode in the first place if an AP gets involved. | -+-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ -| 0x3b’000011 | Connect ESP32 to the AP. | To notify ESP32 that the essential information has been sent | No data field is contained. | -| | | and it is allowed to connect to the AP. | | -+-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ -| 0x4b’000100 | Disconnect ESP32 from the AP. | | No data field is contained. | -+-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ -| 0x5b’000101 | To get the information of ESP32’s Wi-Fi mode and its status. | | No data field is contained. | -| | | | When receiving this control frame, ESP32 will send back | -| | | | a follow-up frame of Wi-Fi connection state report to | -| | | | the mobile phone with the information of the current opmode, | -| | | | connection status, SSID and so on. | -| | | | The types of information sent to the mobile phone is | -| | | | defined by the application installed on the phone. | -+-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ -| 0x6b’000110 | Disconnect the STA device from the SoftAP (in SoftAP mode). | | Date[0~5] is taken as the MAC address for the STA device. | -| | | | If there is a second STA device, then it uses data[6-11] | -| | | | and the rest can be done in the same manner. | -+-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ -| 0x7b'000111 | Get the version information. | | | -+-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ -| 0x8b’001000 | Disconnect the BLE GATT link. | | ESP32 will disconnect the BLE GATT link | -| | | | after receives this command. | -+-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ -| 0x9b’001001 | Get the Wi-Fi list. | To get ESP32 to scan the Wi-Fi access points around. | No data field is contained. | -| | | | When receiving this control frame, | -| | | | ESP32 will send back a follow-up frame of Wi-Fi list | -| | | | report to the mobile phone. | -+-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | Control Frame / 0x0b’00 | Implication | Explanation | Note | + +=========================+==============================================================+===============================================================+===============================================================+ + | 0x0b’000000 | Ack | The data field of the Ack frame uses the same | The data field consumes a byte and its value is | + | | | sequence value of the frame to reply to. | the same as the sequence field of the frame to reply to. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x1b’000001 | Set ESP32 to the security mode. | To inform ESP32 of the security mode to use | The data field consumes a byte. | + | | | when sending data, which is allowed to be reset | The higher 4 bits are for the security mode setting | + | | | multiple times during the process. | of the control frame, and the lower 4 bits are for | + | | | Each setting affects the subsequent security mode used. | the security mode setting of the data frame. | + + + + If it is not set, ESP32 will send the control frame +---------------------------------------------------------------+ + | | | and data frame with no checksum and encryption by default. | b’0000: no checksum and no encryption; | + + + + The data transmission from the mobile phone to ESP32 is +---------------------------------------------------------------+ + | | | controlled by this control frame. | b’0001: with checksum but no encryption; | + + + + +---------------------------------------------------------------+ + | | | | b’0010: no checksum but with encryption; | + + + + +---------------------------------------------------------------+ + | | | | b’0011: with both checksum and encryption. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x2b’000010 | Set the opmode of Wi-Fi. | The frame contains opmode settings for | data[0] is for opmode settings, including: | + + + + configuring for the Wi-Fi mode of ESP32. +---------------------------------------------------------------+ + | | | | 0x00: NULL; | + + + + +---------------------------------------------------------------+ + | | | | 0x01: STA; | + + + + +---------------------------------------------------------------+ + | | | | 0x02: SoftAP; | + + + + +---------------------------------------------------------------+ + | | | | 0x03: SoftAP&STA. | + + + + +---------------------------------------------------------------+ + | | | | Please set the SSID/Password/Max Connection Number of | + | | | | the AP mode in the first place if an AP gets involved. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x3b’000011 | Connect ESP32 to the AP. | To notify ESP32 that the essential information has been sent | No data field is contained. | + | | | and it is allowed to connect to the AP. | | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x4b’000100 | Disconnect ESP32 from the AP. | | No data field is contained. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x5b’000101 | To get the information of ESP32’s Wi-Fi mode and its status. | | No data field is contained. | + | | | | When receiving this control frame, ESP32 will send back | + | | | | a follow-up frame of Wi-Fi connection state report to | + | | | | the mobile phone with the information of the current opmode, | + | | | | connection status, SSID and so on. | + | | | | The types of information sent to the mobile phone is | + | | | | defined by the application installed on the phone. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x6b’000110 | Disconnect the STA device from the SoftAP (in SoftAP mode). | | Date[0~5] is taken as the MAC address for the STA device. | + | | | | If there is a second STA device, then it uses data[6-11] | + | | | | and the rest can be done in the same manner. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x7b'000111 | Get the version information. | | | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x8b’001000 | Disconnect the BLE GATT link. | | ESP32 will disconnect the BLE GATT link | + | | | | after receives this command. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x9b’001001 | Get the Wi-Fi list. | To get ESP32 to scan the Wi-Fi access points around. | No data field is contained. | + | | | | When receiving this control frame, | + | | | | ESP32 will send back a follow-up frame of Wi-Fi list | + | | | | report to the mobile phone. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ **1.2 Data Frame (0x1b’01)** -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| Data Frame | Implication | Explanation | Note | -+==============+====================================================+===============================================================+=======================================================================+ -| 0x0b’000000 | Send the negotiation data. | The negotiation data will be sent to the callback | The length of the data depends on the length field. | -| | | function registered in the application layer. | | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x1b’000001 | Send the BSSID for STA mode. | To send the BSSID of the AP for the STA device to | The length of the data depends on the length field. | -| | | connect under the condition that the SSID is hidden. | When the transmission direction is ESP32 to the mobile phone, | -| | | | it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x2b’000010 | Send the SSID for STA mode. | To send the SSID of the AP for the STA device to connect. | The length of the data depends on the length field. | -| | | | When the transmission direction is ESP32 to the mobile phone, | -| | | | it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x3b’000011 | Send the password for STA mode. | To send the password of the AP for the STA device to connect. | The length of the data depends on the length field. | -| | | | When the transmission direction is ESP32 to the mobile phone, | -| | | | it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x4b’000100 | Send the SSID for SoftAP mode. | | The length of the data depends on the length field. | -| | | | When the transmission direction is ESP32 to the mobile phone, | -| | | | it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x5b’000101 | Send the password for SoftAPmode. | | The length of the data depends on the length field. | -| | | | When the transmission direction is ESP32 to the mobile phone, | -| | | | it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x6b’000110 | Set the maximum connection number for SoftAP mode. | | data[0] represents the value of the connection number, | -| | | | ranging from 1 to 4. When the transmission direction is ESP32 | -| | | | to the mobile phone, it means to provide the mobile phone with | -| | | | the needed information. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x7b’000111 | Set the authentication mode for the SoftAP. | | data[0]: | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x00: OPEN | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x01: WEP | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x02: WPA_PSK | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x03: WPA2_PSK | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x04: WPA_WPA2_PSK | -+ + + +-----------------------------------------------------------------------+ -| | | | When the transmission direction is ESP32 to the mobile phone, | -| | | | it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x8b’001000 | Set the channel amount for SoftAP mode. | | data[0] represents the quantity of the supported channels, | -| | | | ranging from 1 to 14. | -| | | | When the transmission direction is ESP32 to the mobile phone, | -| | | | it means to provide the mobile phone with the needed information. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x9b’001001 | Username | It provides the username of the GATT client when using | The length of the data depends on the length field. | -| | | encryption of enterprise level. | | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0xab’001010 | CA Certification | It provides the CA Certification when using encryption | The length of the data depends on the length field. | -| | | of enterprise level. | The frame supports to be fragmented if the data length is not enough. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0xbb’001011 | Client Certification | It provides the client certification when | The length of the data depends on the length field. | -| | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | -| | | Whether the private key is contained or not | | -| | | depends on the content of the certification. | | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0xcb’001100 | Server Certification | It provides the sever certification when using | The length of the data depends on the length field. | -| | | encryption of enterprise level. Whether the private key is | The frame supports to be fragmented if the data length is not enough. | -| | | contained or not depends on the content of the certification. | | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0xdb’001101 | ClientPrivate Key | It provides the private key of the client when | The length of the data depends on the length field. | -| | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0xeb’001110 | ServerPrivate Key | It provides the private key of the sever when | The length of the data depends on the length field. | -| | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0xfb’001111 | Wi-Fi Connection State Report | To notify the phone of the ESP32's Wi-Fi status, | data[0] represents opmode, including: | -+ + + including STA status and SoftAP status. +-----------------------------------------------------------------------+ -| | | It is for the STA device to connect to the | 0x00: NULL | -+ + + mobile phone or the SoftAP. +-----------------------------------------------------------------------+ -| | | However, when the mobile phone receives the Wi-Fi status, | 0x01: STA | -+ + + it can reply to other frames in addition to this frame. +-----------------------------------------------------------------------+ -| | | | 0x02: SoftAP | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x03: SoftAP&STA | -+ + + +-----------------------------------------------------------------------+ -| | | | data[1]:the connection state of the STA device, | -| | | | 0x0 indicates a connection state, | -| | | | and others represent a disconnected state; | -+ + + +-----------------------------------------------------------------------+ -| | | | data[2]:the connection state of the SoftAP, | -| | | | that is, how many STA devices have been connected. | -+ + + +-----------------------------------------------------------------------+ -| | | | data[3] and the subsequent is in accordance with the | -| | | | format of SSID/BSSID information. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x10b’010000 | Version | | data[0]= great versiondata[1]= sub version | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x11B’010001 | Wi-Fi List | To send the Wi-Fi list to ESP32. | The format of the data frame is length + RSSI + SSID | -| | | | and it supports to be sent into fragments | -| | | | if the data length is too long. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x12B’010010 | Report Error | To notify the mobile phone that there is an error with BluFi. | 0x00: sequence error | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x01: checksum error | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x02: decrypt error | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x03: encrypt error | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x04: init security error | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x05: dh malloc error | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x06: dh param error | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x07: read param error | -+ + + +-----------------------------------------------------------------------+ -| | | | 0x08: make public error | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ -| 0x13B’010011 | Custom Data | To send or receive custom data. | The data frame supports to be sent into | -| | | | fragments if the data length is too long. | -+--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | Data Frame | Implication | Explanation | Note | + +==============+====================================================+===============================================================+=======================================================================+ + | 0x0b’000000 | Send the negotiation data. | The negotiation data will be sent to the callback | The length of the data depends on the length field. | + | | | function registered in the application layer. | | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x1b’000001 | Send the BSSID for STA mode. | To send the BSSID of the AP for the STA device to | The length of the data depends on the length field. | + | | | connect under the condition that the SSID is hidden. | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x2b’000010 | Send the SSID for STA mode. | To send the SSID of the AP for the STA device to connect. | The length of the data depends on the length field. | + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x3b’000011 | Send the password for STA mode. | To send the password of the AP for the STA device to connect. | The length of the data depends on the length field. | + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x4b’000100 | Send the SSID for SoftAP mode. | | The length of the data depends on the length field. | + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x5b’000101 | Send the password for SoftAPmode. | | The length of the data depends on the length field. | + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x6b’000110 | Set the maximum connection number for SoftAP mode. | | data[0] represents the value of the connection number, | + | | | | ranging from 1 to 4. When the transmission direction is ESP32 | + | | | | to the mobile phone, it means to provide the mobile phone with | + | | | | the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x7b’000111 | Set the authentication mode for the SoftAP. | | data[0]: | + + + + +-----------------------------------------------------------------------+ + | | | | 0x00: OPEN | + + + + +-----------------------------------------------------------------------+ + | | | | 0x01: WEP | + + + + +-----------------------------------------------------------------------+ + | | | | 0x02: WPA_PSK | + + + + +-----------------------------------------------------------------------+ + | | | | 0x03: WPA2_PSK | + + + + +-----------------------------------------------------------------------+ + | | | | 0x04: WPA_WPA2_PSK | + + + + +-----------------------------------------------------------------------+ + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x8b’001000 | Set the channel amount for SoftAP mode. | | data[0] represents the quantity of the supported channels, | + | | | | ranging from 1 to 14. | + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x9b’001001 | Username | It provides the username of the GATT client when using | The length of the data depends on the length field. | + | | | encryption of enterprise level. | | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xab’001010 | CA Certification | It provides the CA Certification when using encryption | The length of the data depends on the length field. | + | | | of enterprise level. | The frame supports to be fragmented if the data length is not enough. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xbb’001011 | Client Certification | It provides the client certification when | The length of the data depends on the length field. | + | | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | + | | | Whether the private key is contained or not | | + | | | depends on the content of the certification. | | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xcb’001100 | Server Certification | It provides the sever certification when using | The length of the data depends on the length field. | + | | | encryption of enterprise level. Whether the private key is | The frame supports to be fragmented if the data length is not enough. | + | | | contained or not depends on the content of the certification. | | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xdb’001101 | ClientPrivate Key | It provides the private key of the client when | The length of the data depends on the length field. | + | | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xeb’001110 | ServerPrivate Key | It provides the private key of the sever when | The length of the data depends on the length field. | + | | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xfb’001111 | Wi-Fi Connection State Report | To notify the phone of the ESP32's Wi-Fi status, | data[0] represents opmode, including: | + + + + including STA status and SoftAP status. +-----------------------------------------------------------------------+ + | | | It is for the STA device to connect to the | 0x00: NULL | + + + + mobile phone or the SoftAP. +-----------------------------------------------------------------------+ + | | | However, when the mobile phone receives the Wi-Fi status, | 0x01: STA | + + + + it can reply to other frames in addition to this frame. +-----------------------------------------------------------------------+ + | | | | 0x02: SoftAP | + + + + +-----------------------------------------------------------------------+ + | | | | 0x03: SoftAP&STA | + + + + +-----------------------------------------------------------------------+ + | | | | data[1]:the connection state of the STA device, | + | | | | 0x0 indicates a connection state, | + | | | | and others represent a disconnected state; | + + + + +-----------------------------------------------------------------------+ + | | | | data[2]:the connection state of the SoftAP, | + | | | | that is, how many STA devices have been connected. | + + + + +-----------------------------------------------------------------------+ + | | | | data[3] and the subsequent is in accordance with the | + | | | | format of SSID/BSSID information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x10b’010000 | Version | | data[0]= great versiondata[1]= sub version | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x11B’010001 | Wi-Fi List | To send the Wi-Fi list to ESP32. | The format of the data frame is length + RSSI + SSID | + | | | | and it supports to be sent into fragments | + | | | | if the data length is too long. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x12B’010010 | Report Error | To notify the mobile phone that there is an error with BluFi. | 0x00: sequence error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x01: checksum error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x02: decrypt error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x03: encrypt error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x04: init security error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x05: dh malloc error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x06: dh param error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x07: read param error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x08: make public error | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x13B’010011 | Custom Data | To send or receive custom data. | The data frame supports to be sent into | + | | | | fragments if the data length is too long. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ 2. Frame Control Control field, takes 1 byte and each bit has a different meaning. -+--------------------+------------------------------------------------------------------------------------------------+ -| Bit | Meaning | -+====================+================================================================================================+ -| 0x01 | Indicates whether the frame is encrypted. | -+ +------------------------------------------------------------------------------------------------+ -| | 1 means encryption, and 0 means unencrypted. | -+ +------------------------------------------------------------------------------------------------+ -| | The encrypted part of the frame includes | -| | the full clear data before the DATA field is encrypted (no checksum). | -+ +------------------------------------------------------------------------------------------------+ -| | Control frame is not encrypted, so this bit is 0. | -+--------------------+------------------------------------------------------------------------------------------------+ -| 0x02 | The data field that indicates whether a frame contains | -| | a checksum (such as SHA1,MD5,CRC, etc.) for the end of | -| | the frame data field includes SEQUCNE + data length + clear text. | -| | Both the control frame and the data frame can contain a check bit or not. | -+--------------------+------------------------------------------------------------------------------------------------+ -| 0x04 | Represents the data direction. | -+--------------------+------------------------------------------------------------------------------------------------+ -| | 0 means the mobile phone to ESP32; | -+--------------------+------------------------------------------------------------------------------------------------+ -| | 1 means ESP32 to the mobile phone. | -+--------------------+------------------------------------------------------------------------------------------------+ -| 0x08 | Indicates whether the other person is required to reply to an ACK. | -+--------------------+------------------------------------------------------------------------------------------------+ -| | 0 indicates no requirement; | -+--------------------+------------------------------------------------------------------------------------------------+ -| | 1 indicates to reply Ack. | -+--------------------+------------------------------------------------------------------------------------------------+ -| 0x10 | Indicates whether there are subsequent data fragments. | -+--------------------+------------------------------------------------------------------------------------------------+ -| | 0 indicates that there are no subsequent data fragments for this frame; | -+--------------------+------------------------------------------------------------------------------------------------+ -| | 1 indicates that there are subsequent data fragments and used to transmit longer data. | -+--------------------+------------------------------------------------------------------------------------------------+ -| | In the case of a frag frame, | -| | the total length of the current content section + subsequent content section is given, | -| | in the first 2 bytes of the data field (that is, the content data of the maximum support 64K). | -+--------------------+------------------------------------------------------------------------------------------------+ -| 0x10~0x80 reserved | | -+--------------------+------------------------------------------------------------------------------------------------+ + +--------------------+------------------------------------------------------------------------------------------------+ + | Bit | Meaning | + +====================+================================================================================================+ + | 0x01 | Indicates whether the frame is encrypted. | + + +------------------------------------------------------------------------------------------------+ + | | 1 means encryption, and 0 means unencrypted. | + + +------------------------------------------------------------------------------------------------+ + | | The encrypted part of the frame includes | + | | the full clear data before the DATA field is encrypted (no checksum). | + + +------------------------------------------------------------------------------------------------+ + | | Control frame is not encrypted, so this bit is 0. | + +--------------------+------------------------------------------------------------------------------------------------+ + | 0x02 | The data field that indicates whether a frame contains | + | | a checksum (such as SHA1,MD5,CRC, etc.) for the end of | + | | the frame data field includes SEQUCNE + data length + clear text. | + | | Both the control frame and the data frame can contain a check bit or not. | + +--------------------+------------------------------------------------------------------------------------------------+ + | 0x04 | Represents the data direction. | + +--------------------+------------------------------------------------------------------------------------------------+ + | | 0 means the mobile phone to ESP32; | + +--------------------+------------------------------------------------------------------------------------------------+ + | | 1 means ESP32 to the mobile phone. | + +--------------------+------------------------------------------------------------------------------------------------+ + | 0x08 | Indicates whether the other person is required to reply to an ACK. | + +--------------------+------------------------------------------------------------------------------------------------+ + | | 0 indicates no requirement; | + +--------------------+------------------------------------------------------------------------------------------------+ + | | 1 indicates to reply Ack. | + +--------------------+------------------------------------------------------------------------------------------------+ + | 0x10 | Indicates whether there are subsequent data fragments. | + +--------------------+------------------------------------------------------------------------------------------------+ + | | 0 indicates that there are no subsequent data fragments for this frame; | + +--------------------+------------------------------------------------------------------------------------------------+ + | | 1 indicates that there are subsequent data fragments and used to transmit longer data. | + +--------------------+------------------------------------------------------------------------------------------------+ + | | In the case of a frag frame, | + | | the total length of the current content section + subsequent content section is given, | + | | in the first 2 bytes of the data field (that is, the content data of the maximum support 64K). | + +--------------------+------------------------------------------------------------------------------------------------+ + | 0x10~0x80 reserved | | + +--------------------+------------------------------------------------------------------------------------------------+ 3. Sequence Control From 4a25f18f2184606399a36f56d75489221c416843 Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Wed, 6 Jun 2018 12:05:27 +0800 Subject: [PATCH 22/23] Update blufi.rst --- docs/en/api-guides/blufi.rst | 356 +++++++++++++++++------------------ 1 file changed, 178 insertions(+), 178 deletions(-) diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst index 7f56023b3..429c5d9e6 100644 --- a/docs/en/api-guides/blufi.rst +++ b/docs/en/api-guides/blufi.rst @@ -117,187 +117,187 @@ The format of Ack Frame(8 bit): **1.1 Control Frame (0x0b’00)** - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | Control Frame / 0x0b’00 | Implication | Explanation | Note | - +=========================+==============================================================+===============================================================+===============================================================+ - | 0x0b’000000 | Ack | The data field of the Ack frame uses the same | The data field consumes a byte and its value is | - | | | sequence value of the frame to reply to. | the same as the sequence field of the frame to reply to. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x1b’000001 | Set ESP32 to the security mode. | To inform ESP32 of the security mode to use | The data field consumes a byte. | - | | | when sending data, which is allowed to be reset | The higher 4 bits are for the security mode setting | - | | | multiple times during the process. | of the control frame, and the lower 4 bits are for | - | | | Each setting affects the subsequent security mode used. | the security mode setting of the data frame. | - + + + If it is not set, ESP32 will send the control frame +---------------------------------------------------------------+ - | | | and data frame with no checksum and encryption by default. | b’0000: no checksum and no encryption; | - + + + The data transmission from the mobile phone to ESP32 is +---------------------------------------------------------------+ - | | | controlled by this control frame. | b’0001: with checksum but no encryption; | - + + + +---------------------------------------------------------------+ - | | | | b’0010: no checksum but with encryption; | - + + + +---------------------------------------------------------------+ - | | | | b’0011: with both checksum and encryption. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x2b’000010 | Set the opmode of Wi-Fi. | The frame contains opmode settings for | data[0] is for opmode settings, including: | - + + + configuring for the Wi-Fi mode of ESP32. +---------------------------------------------------------------+ - | | | | 0x00: NULL; | - + + + +---------------------------------------------------------------+ - | | | | 0x01: STA; | - + + + +---------------------------------------------------------------+ - | | | | 0x02: SoftAP; | - + + + +---------------------------------------------------------------+ - | | | | 0x03: SoftAP&STA. | - + + + +---------------------------------------------------------------+ - | | | | Please set the SSID/Password/Max Connection Number of | - | | | | the AP mode in the first place if an AP gets involved. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x3b’000011 | Connect ESP32 to the AP. | To notify ESP32 that the essential information has been sent | No data field is contained. | - | | | and it is allowed to connect to the AP. | | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x4b’000100 | Disconnect ESP32 from the AP. | | No data field is contained. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x5b’000101 | To get the information of ESP32’s Wi-Fi mode and its status. | | No data field is contained. | - | | | | When receiving this control frame, ESP32 will send back | - | | | | a follow-up frame of Wi-Fi connection state report to | - | | | | the mobile phone with the information of the current opmode, | - | | | | connection status, SSID and so on. | - | | | | The types of information sent to the mobile phone is | - | | | | defined by the application installed on the phone. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x6b’000110 | Disconnect the STA device from the SoftAP (in SoftAP mode). | | Date[0~5] is taken as the MAC address for the STA device. | - | | | | If there is a second STA device, then it uses data[6-11] | - | | | | and the rest can be done in the same manner. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x7b'000111 | Get the version information. | | | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x8b’001000 | Disconnect the BLE GATT link. | | ESP32 will disconnect the BLE GATT link | - | | | | after receives this command. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x9b’001001 | Get the Wi-Fi list. | To get ESP32 to scan the Wi-Fi access points around. | No data field is contained. | - | | | | When receiving this control frame, | - | | | | ESP32 will send back a follow-up frame of Wi-Fi list | - | | | | report to the mobile phone. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | Control Frame / 0x0b’00 | Implication | Explanation | Note | + +=========================+==============================================================+===============================================================+===============================================================+ + | 0x0b’000000 | Ack | The data field of the Ack frame uses the same | The data field consumes a byte and its value is | + | | | sequence value of the frame to reply to. | the same as the sequence field of the frame to reply to. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x1b’000001 | Set ESP32 to the security mode. | To inform ESP32 of the security mode to use | The data field consumes a byte. | + | | | when sending data, which is allowed to be reset | The higher 4 bits are for the security mode setting | + | | | multiple times during the process. | of the control frame, and the lower 4 bits are for | + | | | Each setting affects the subsequent security mode used. | the security mode setting of the data frame. | + + + + If it is not set, ESP32 will send the control frame +---------------------------------------------------------------+ + | | | and data frame with no checksum and encryption by default. | b’0000: no checksum and no encryption; | + + + + The data transmission from the mobile phone to ESP32 is +---------------------------------------------------------------+ + | | | controlled by this control frame. | b’0001: with checksum but no encryption; | + + + + +---------------------------------------------------------------+ + | | | | b’0010: no checksum but with encryption; | + + + + +---------------------------------------------------------------+ + | | | | b’0011: with both checksum and encryption. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x2b’000010 | Set the opmode of Wi-Fi. | The frame contains opmode settings for | data[0] is for opmode settings, including: | + + + + configuring for the Wi-Fi mode of ESP32. +---------------------------------------------------------------+ + | | | | 0x00: NULL; | + + + + +---------------------------------------------------------------+ + | | | | 0x01: STA; | + + + + +---------------------------------------------------------------+ + | | | | 0x02: SoftAP; | + + + + +---------------------------------------------------------------+ + | | | | 0x03: SoftAP&STA. | + + + + +---------------------------------------------------------------+ + | | | | Please set the SSID/Password/Max Connection Number of | + | | | | the AP mode in the first place if an AP gets involved. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x3b’000011 | Connect ESP32 to the AP. | To notify ESP32 that the essential information has been sent | No data field is contained. | + | | | and it is allowed to connect to the AP. | | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x4b’000100 | Disconnect ESP32 from the AP. | | No data field is contained. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x5b’000101 | To get the information of ESP32’s Wi-Fi mode and its status. | | No data field is contained. | + | | | | When receiving this control frame, ESP32 will send back | + | | | | a follow-up frame of Wi-Fi connection state report to | + | | | | the mobile phone with the information of the current opmode, | + | | | | connection status, SSID and so on. | + | | | | The types of information sent to the mobile phone is | + | | | | defined by the application installed on the phone. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x6b’000110 | Disconnect the STA device from the SoftAP (in SoftAP mode). | | Date[0~5] is taken as the MAC address for the STA device. | + | | | | If there is a second STA device, then it uses data[6-11] | + | | | | and the rest can be done in the same manner. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x7b'000111 | Get the version information. | | | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x8b’001000 | Disconnect the BLE GATT link. | | ESP32 will disconnect the BLE GATT link | + | | | | after receives this command. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x9b’001001 | Get the Wi-Fi list. | To get ESP32 to scan the Wi-Fi access points around. | No data field is contained. | + | | | | When receiving this control frame, | + | | | | ESP32 will send back a follow-up frame of Wi-Fi list | + | | | | report to the mobile phone. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ **1.2 Data Frame (0x1b’01)** - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | Data Frame | Implication | Explanation | Note | - +==============+====================================================+===============================================================+=======================================================================+ - | 0x0b’000000 | Send the negotiation data. | The negotiation data will be sent to the callback | The length of the data depends on the length field. | - | | | function registered in the application layer. | | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x1b’000001 | Send the BSSID for STA mode. | To send the BSSID of the AP for the STA device to | The length of the data depends on the length field. | - | | | connect under the condition that the SSID is hidden. | When the transmission direction is ESP32 to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x2b’000010 | Send the SSID for STA mode. | To send the SSID of the AP for the STA device to connect. | The length of the data depends on the length field. | - | | | | When the transmission direction is ESP32 to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x3b’000011 | Send the password for STA mode. | To send the password of the AP for the STA device to connect. | The length of the data depends on the length field. | - | | | | When the transmission direction is ESP32 to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x4b’000100 | Send the SSID for SoftAP mode. | | The length of the data depends on the length field. | - | | | | When the transmission direction is ESP32 to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x5b’000101 | Send the password for SoftAPmode. | | The length of the data depends on the length field. | - | | | | When the transmission direction is ESP32 to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x6b’000110 | Set the maximum connection number for SoftAP mode. | | data[0] represents the value of the connection number, | - | | | | ranging from 1 to 4. When the transmission direction is ESP32 | - | | | | to the mobile phone, it means to provide the mobile phone with | - | | | | the needed information. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x7b’000111 | Set the authentication mode for the SoftAP. | | data[0]: | - + + + +-----------------------------------------------------------------------+ - | | | | 0x00: OPEN | - + + + +-----------------------------------------------------------------------+ - | | | | 0x01: WEP | - + + + +-----------------------------------------------------------------------+ - | | | | 0x02: WPA_PSK | - + + + +-----------------------------------------------------------------------+ - | | | | 0x03: WPA2_PSK | - + + + +-----------------------------------------------------------------------+ - | | | | 0x04: WPA_WPA2_PSK | - + + + +-----------------------------------------------------------------------+ - | | | | When the transmission direction is ESP32 to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x8b’001000 | Set the channel amount for SoftAP mode. | | data[0] represents the quantity of the supported channels, | - | | | | ranging from 1 to 14. | - | | | | When the transmission direction is ESP32 to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x9b’001001 | Username | It provides the username of the GATT client when using | The length of the data depends on the length field. | - | | | encryption of enterprise level. | | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0xab’001010 | CA Certification | It provides the CA Certification when using encryption | The length of the data depends on the length field. | - | | | of enterprise level. | The frame supports to be fragmented if the data length is not enough. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0xbb’001011 | Client Certification | It provides the client certification when | The length of the data depends on the length field. | - | | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | - | | | Whether the private key is contained or not | | - | | | depends on the content of the certification. | | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0xcb’001100 | Server Certification | It provides the sever certification when using | The length of the data depends on the length field. | - | | | encryption of enterprise level. Whether the private key is | The frame supports to be fragmented if the data length is not enough. | - | | | contained or not depends on the content of the certification. | | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0xdb’001101 | ClientPrivate Key | It provides the private key of the client when | The length of the data depends on the length field. | - | | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0xeb’001110 | ServerPrivate Key | It provides the private key of the sever when | The length of the data depends on the length field. | - | | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0xfb’001111 | Wi-Fi Connection State Report | To notify the phone of the ESP32's Wi-Fi status, | data[0] represents opmode, including: | - + + + including STA status and SoftAP status. +-----------------------------------------------------------------------+ - | | | It is for the STA device to connect to the | 0x00: NULL | - + + + mobile phone or the SoftAP. +-----------------------------------------------------------------------+ - | | | However, when the mobile phone receives the Wi-Fi status, | 0x01: STA | - + + + it can reply to other frames in addition to this frame. +-----------------------------------------------------------------------+ - | | | | 0x02: SoftAP | - + + + +-----------------------------------------------------------------------+ - | | | | 0x03: SoftAP&STA | - + + + +-----------------------------------------------------------------------+ - | | | | data[1]:the connection state of the STA device, | - | | | | 0x0 indicates a connection state, | - | | | | and others represent a disconnected state; | - + + + +-----------------------------------------------------------------------+ - | | | | data[2]:the connection state of the SoftAP, | - | | | | that is, how many STA devices have been connected. | - + + + +-----------------------------------------------------------------------+ - | | | | data[3] and the subsequent is in accordance with the | - | | | | format of SSID/BSSID information. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x10b’010000 | Version | | data[0]= great versiondata[1]= sub version | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x11B’010001 | Wi-Fi List | To send the Wi-Fi list to ESP32. | The format of the data frame is length + RSSI + SSID | - | | | | and it supports to be sent into fragments | - | | | | if the data length is too long. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x12B’010010 | Report Error | To notify the mobile phone that there is an error with BluFi. | 0x00: sequence error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x01: checksum error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x02: decrypt error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x03: encrypt error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x04: init security error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x05: dh malloc error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x06: dh param error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x07: read param error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x08: make public error | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x13B’010011 | Custom Data | To send or receive custom data. | The data frame supports to be sent into | - | | | | fragments if the data length is too long. | - +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | Data Frame | Implication | Explanation | Note | + +==============+====================================================+===============================================================+=======================================================================+ + | 0x0b’000000 | Send the negotiation data. | The negotiation data will be sent to the callback | The length of the data depends on the length field. | + | | | function registered in the application layer. | | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x1b’000001 | Send the BSSID for STA mode. | To send the BSSID of the AP for the STA device to | The length of the data depends on the length field. | + | | | connect under the condition that the SSID is hidden. | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x2b’000010 | Send the SSID for STA mode. | To send the SSID of the AP for the STA device to connect. | The length of the data depends on the length field. | + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x3b’000011 | Send the password for STA mode. | To send the password of the AP for the STA device to connect. | The length of the data depends on the length field. | + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x4b’000100 | Send the SSID for SoftAP mode. | | The length of the data depends on the length field. | + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x5b’000101 | Send the password for SoftAPmode. | | The length of the data depends on the length field. | + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x6b’000110 | Set the maximum connection number for SoftAP mode. | | data[0] represents the value of the connection number, | + | | | | ranging from 1 to 4. When the transmission direction is ESP32 | + | | | | to the mobile phone, it means to provide the mobile phone with | + | | | | the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x7b’000111 | Set the authentication mode for the SoftAP. | | data[0]: | + + + + +-----------------------------------------------------------------------+ + | | | | 0x00: OPEN | + + + + +-----------------------------------------------------------------------+ + | | | | 0x01: WEP | + + + + +-----------------------------------------------------------------------+ + | | | | 0x02: WPA_PSK | + + + + +-----------------------------------------------------------------------+ + | | | | 0x03: WPA2_PSK | + + + + +-----------------------------------------------------------------------+ + | | | | 0x04: WPA_WPA2_PSK | + + + + +-----------------------------------------------------------------------+ + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x8b’001000 | Set the channel amount for SoftAP mode. | | data[0] represents the quantity of the supported channels, | + | | | | ranging from 1 to 14. | + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x9b’001001 | Username | It provides the username of the GATT client when using | The length of the data depends on the length field. | + | | | encryption of enterprise level. | | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xab’001010 | CA Certification | It provides the CA Certification when using encryption | The length of the data depends on the length field. | + | | | of enterprise level. | The frame supports to be fragmented if the data length is not enough. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xbb’001011 | Client Certification | It provides the client certification when | The length of the data depends on the length field. | + | | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | + | | | Whether the private key is contained or not | | + | | | depends on the content of the certification. | | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xcb’001100 | Server Certification | It provides the sever certification when using | The length of the data depends on the length field. | + | | | encryption of enterprise level. Whether the private key is | The frame supports to be fragmented if the data length is not enough. | + | | | contained or not depends on the content of the certification. | | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xdb’001101 | ClientPrivate Key | It provides the private key of the client when | The length of the data depends on the length field. | + | | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xeb’001110 | ServerPrivate Key | It provides the private key of the sever when | The length of the data depends on the length field. | + | | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xfb’001111 | Wi-Fi Connection State Report | To notify the phone of the ESP32's Wi-Fi status, | data[0] represents opmode, including: | + + + + including STA status and SoftAP status. +-----------------------------------------------------------------------+ + | | | It is for the STA device to connect to the | 0x00: NULL | + + + + mobile phone or the SoftAP. +-----------------------------------------------------------------------+ + | | | However, when the mobile phone receives the Wi-Fi status, | 0x01: STA | + + + + it can reply to other frames in addition to this frame. +-----------------------------------------------------------------------+ + | | | | 0x02: SoftAP | + + + + +-----------------------------------------------------------------------+ + | | | | 0x03: SoftAP&STA | + + + + +-----------------------------------------------------------------------+ + | | | | data[1]:the connection state of the STA device, | + | | | | 0x0 indicates a connection state, | + | | | | and others represent a disconnected state; | + + + + +-----------------------------------------------------------------------+ + | | | | data[2]:the connection state of the SoftAP, | + | | | | that is, how many STA devices have been connected. | + + + + +-----------------------------------------------------------------------+ + | | | | data[3] and the subsequent is in accordance with the | + | | | | format of SSID/BSSID information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x10b’010000 | Version | | data[0]= great versiondata[1]= sub version | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x11B’010001 | Wi-Fi List | To send the Wi-Fi list to ESP32. | The format of the data frame is length + RSSI + SSID | + | | | | and it supports to be sent into fragments | + | | | | if the data length is too long. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x12B’010010 | Report Error | To notify the mobile phone that there is an error with BluFi. | 0x00: sequence error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x01: checksum error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x02: decrypt error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x03: encrypt error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x04: init security error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x05: dh malloc error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x06: dh param error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x07: read param error | + + + + +-----------------------------------------------------------------------+ + | | | | 0x08: make public error | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x13B’010011 | Custom Data | To send or receive custom data. | The data frame supports to be sent into | + | | | | fragments if the data length is too long. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ 2. Frame Control From b889305c1b07c97dc108147c3386207ed1298840 Mon Sep 17 00:00:00 2001 From: Jin Fang Cheng Cheng Date: Wed, 6 Jun 2018 12:11:57 +0800 Subject: [PATCH 23/23] Update blufi.rst --- docs/zh_CN/api-guides/blufi.rst | 427 ++++++++++++++++---------------- 1 file changed, 213 insertions(+), 214 deletions(-) diff --git a/docs/zh_CN/api-guides/blufi.rst b/docs/zh_CN/api-guides/blufi.rst index 74f068961..1f9ec8905 100644 --- a/docs/zh_CN/api-guides/blufi.rst +++ b/docs/zh_CN/api-guides/blufi.rst @@ -121,228 +121,227 @@ Ack 帧格式(8 bit): **1.1 控制帧 (0x0b’00)** -+------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ -| 控制帧 / 0x0b’00 | 含义 | 解释 | 备注 | -+==================+===================================+================================================================+======================================================================+ -| 0x0b’000000 | Ack | 用来回复对方发的帧, | Data 域使用1 byte Sequence 值, | -| | | Ack 帧的 Data 域使用回复对象帧的 Sequence 值。 | 与恢复对象帧的Sequence 值相同。 | -+------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ -| 0x1b’000001 | Set ESP32 to the security mode. | 通知 ESP32 发送数据时使用的安全模式, | Data 域占用 1 byte。 | -| | | 在该过程中可设置多次,每次设置后影响后续安全模式。 | 高 4 bit 为控制帧的安全模式,低 4bit 为数据帧的安全模式。 | -+ + + 在不设置的情况下,ESP32 默认控制帧和数据帧均为无校验、无加密。 +----------------------------------------------------------------------+ -| | | 手机到 ESP32 方向依赖于帧 Control 域。 | b’0000:无校验、无加密; | -+ + + +----------------------------------------------------------------------+ -| | | | b’0001:有校验、无加密; | -+ + + +----------------------------------------------------------------------+ -| | | | b’0010:无校验、有加密; | -+ + + +----------------------------------------------------------------------+ -| | | | b’0011:有校验、有加密。 | -+------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ -| 0x2b’000010 | Set the Wi-Fi opmode of ESP32. | 设置 ESP32 的 Wi-Fi 模式,帧包含 opmode 信息。 | data[0] 用于表示 opmode 类型,包括: | -+ + + +----------------------------------------------------------------------+ -| | | | 0x00: NULL; | -+ + + +----------------------------------------------------------------------+ -| | | | 0x01: STA; | -+ + + +----------------------------------------------------------------------+ -| | | | 0x02: SoftAP; | -+ + + +----------------------------------------------------------------------+ -| | | | 0x03: SoftAP&STA. | -+ + + +----------------------------------------------------------------------+ -| | | | 如果设置有包含 AP,请尽量优先 | -| | | | 设置 AP 模式的SSID/Password/Max Conn Number 等。 | -+------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ -| 0x3b’000011 | Connect ESP32 to the AP. | 通知 ESP32,必要的信息已经发送完毕,可以连接 AP。 | 不包含 Data 域。 | -+------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ -| 0x4b’000100 | Disconnect ESP32 from the AP. | 通知 ESP32 断开与 AP 的连接 | 不包含 Data 域。 | -+------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ -| 0x5b’000101 | Get the status of Wi-Fi. | 获取 ESP32 的 Wi-Fi 模式和状态等信息。 | 不包含 Data 域。 | -| | | | ESP32 收到此控制帧后,后续会通过 Wi-Fi 连接状态 | -| | | | 报告 (Wi-Fi Connection State Report) 数据帧来回复手机端当前 | -| | | | 所处的 opmode、连接状态、SSID 等信息。提供给手机端的信息由应用决定。 | -+------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ -| 0x6b’000110 | Disconnect the STA device | 处于 SoftAP 模式时,踢掉某个 STA 设备。 | data[0~5] 为 STA 设备的 MAC 地址, | -| | from the SoftAP in SoftAP mode. | | 如有多个 STA,则 [6-11] 为第二个,依次类推。 | -+------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ -| 0x7b'000111 | Get the version. | | | -+------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ -| 0x8b’001000 | Tell ESP32 to disconnect | 通知 ESP32 断开蓝牙连接。 | ESP32 收到该指令后主动断开蓝牙连接。 | -| | the BLE GATT link. | | | -+------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ -| 0x9b’001001 | Tell ESP32 to get the Wi-Fi list. | 通知 ESP32 扫描周围的 Wi-Fi 热点 | 不包含 Data 域。 | -| | | | ESP32 收到此控制帧后,会发送包含 Wi-Fi 热点 | -| | | | 报告 (Wi-Fi List Report) 的数据帧回复 | -| | | | 手机端 ESP32 周围的 Wi-Fi 热点。 | -+------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 控制帧 / 0x0b’00 | 含义 | 解释 | 备注 | + +==================+===================================+================================================================+======================================================================+ + | 0x0b’000000 | Ack | 用来回复对方发的帧, | Data 域使用1 byte Sequence 值, | + | | | Ack 帧的 Data 域使用回复对象帧的 Sequence 值。 | 与恢复对象帧的Sequence 值相同。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x1b’000001 | Set ESP32 to the security mode. | 通知 ESP32 发送数据时使用的安全模式, | Data 域占用 1 byte。 | + | | | 在该过程中可设置多次,每次设置后影响后续安全模式。 | 高 4 bit 为控制帧的安全模式,低 4bit 为数据帧的安全模式。 | + + + + 在不设置的情况下,ESP32 默认控制帧和数据帧均为无校验、无加密。 +----------------------------------------------------------------------+ + | | | 手机到 ESP32 方向依赖于帧 Control 域。 | b’0000:无校验、无加密; | + + + + +----------------------------------------------------------------------+ + | | | | b’0001:有校验、无加密; | + + + + +----------------------------------------------------------------------+ + | | | | b’0010:无校验、有加密; | + + + + +----------------------------------------------------------------------+ + | | | | b’0011:有校验、有加密。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x2b’000010 | Set the Wi-Fi opmode of ESP32. | 设置 ESP32 的 Wi-Fi 模式,帧包含 opmode 信息。 | data[0] 用于表示 opmode 类型,包括: | + + + + +----------------------------------------------------------------------+ + | | | | 0x00: NULL; | + + + + +----------------------------------------------------------------------+ + | | | | 0x01: STA; | + + + + +----------------------------------------------------------------------+ + | | | | 0x02: SoftAP; | + + + + +----------------------------------------------------------------------+ + | | | | 0x03: SoftAP&STA. | + + + + +----------------------------------------------------------------------+ + | | | | 如果设置有包含 AP,请尽量优先 | + | | | | 设置 AP 模式的SSID/Password/Max Conn Number 等。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x3b’000011 | Connect ESP32 to the AP. | 通知 ESP32,必要的信息已经发送完毕,可以连接 AP。 | 不包含 Data 域。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x4b’000100 | Disconnect ESP32 from the AP. | 通知 ESP32 断开与 AP 的连接 | 不包含 Data 域。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x5b’000101 | Get the status of Wi-Fi. | 获取 ESP32 的 Wi-Fi 模式和状态等信息。 | 不包含 Data 域。 | + | | | | ESP32 收到此控制帧后,后续会通过 Wi-Fi 连接状态 | + | | | | 报告 (Wi-Fi Connection State Report) 数据帧来回复手机端当前 | + | | | | 所处的 opmode、连接状态、SSID 等信息。提供给手机端的信息由应用决定。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x6b’000110 | Disconnect the STA device | 处于 SoftAP 模式时,踢掉某个 STA 设备。 | data[0~5] 为 STA 设备的 MAC 地址, | + | | from the SoftAP in SoftAP mode. | | 如有多个 STA,则 [6-11] 为第二个,依次类推。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x7b'000111 | Get the version. | | | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x8b’001000 | Tell ESP32 to disconnect | 通知 ESP32 断开蓝牙连接。 | ESP32 收到该指令后主动断开蓝牙连接。 | + | | the BLE GATT link. | | | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x9b’001001 | Tell ESP32 to get the Wi-Fi list. | 通知 ESP32 扫描周围的 Wi-Fi 热点 | 不包含 Data 域。 | + | | | | ESP32 收到此控制帧后,会发送包含 Wi-Fi 热点 | + | | | | 报告 (Wi-Fi List Report) 的数据帧回复 | + | | | | 手机端 ESP32 周围的 Wi-Fi 热点。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ **1.2 数据帧 (0x1b’01)** -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 数据帧 | 含义 | 解释 | 备注 | -+===============+========================================+================================================+======================================================+ -| 0x0 b’000000 | Negotiation data. | 用来发送协商数据,传输到应用层注册的回调函数。 | 数据长度与 Length 域有关。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x1 b’000001 | BSSID for STA mode. | STA 将要连接的 AP 的 BSSID(用于隐藏SSID)。 | 数据长度与 Length 域有关。 | -+ + + +------------------------------------------------------+ -| | | | 当传输方向为 ESP32 到手机时, | -| | | | 表示向手机端提供信息。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x2 b’000010 | SSID for STA mode. | STA 将要连接的 AP 的 SSID。 | 数据长度与 Length 域有关。 | -+ + + +------------------------------------------------------+ -| | | | 当传输方向为 ESP32 到手机时, | -| | | | 表示向手机端提供信息。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x3 b’000011 | Password for STA mode. | STA 将要连接的 AP 的密码。 | 数据长度与 Length 域有关。 | -+ + + +------------------------------------------------------+ -| | | | 当传输方向为 ESP32 到手机时, | -| | | | 表示向手机端提供信息。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x4 b’000100 | SSID for SoftAP mode. | SoftAP 模式使用的 SSID。 | 数据长度与 Length 域有关。 | -+ + + +------------------------------------------------------+ -| | | | 当传输方向为 ESP32 到手机时, | -| | | | 表示向手机端提供信息。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x5 b’000101 | Password for SoftAPmode. | SoftAP 模式使用的密码。 | 数据长度与 Length 域有关。 | -+ + + +------------------------------------------------------+ -| | | | 当传输方向为 ESP32 到手机时, | -| | | | 表示向手机端提供信息。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x6 b’000110 | Max connection number for SoftAP mode. | AP 模式的最大连接数。 | data[0] 表示连接数的值,范围 1~4。 | -+ + + +------------------------------------------------------+ -| | | | 当传输方向为 ESP32 到手机时, | -| | | | 表示向手机端提供信息。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x7b’000111 | Authentication mode for SoftAP mode. | AP 模式的认证模式。 | data[0]: | -+ + + +------------------------------------------------------+ -| | | | 0x00: OPEN; | -+ + + +------------------------------------------------------+ -| | | | 0x01: WEP; | -+ + + +------------------------------------------------------+ -| | | | 0x02: WPA_PSK; | -+ + + +------------------------------------------------------+ -| | | | 0x03: WPA2_PSK; | -+ + + +------------------------------------------------------+ -| | | | 0x04: WPA_WPA2_PSK. | -+ + + +------------------------------------------------------+ -| | | | 当传输方向为 ESP32 到手机时, | -| | | | 表示向手机端提供信息。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x8b’001000 | Channel for SoftAP mode. | SoftAP 模式的通道数量。 | data[0] 表示通道的数量,范围 1~14。 | -+ + + +------------------------------------------------------+ -| | | | 当传输方向为 ESP32 到手机时, | -| | | | 表示向手机端提供信息。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x9b’001001 | Username. | 使用企业级加密时,Client 端的用户名。 | 数据长度与 Length 域有关。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0xab’001010 | CA certification. | 进行企业级加密时使用的 CA 证书。 | 数据长度与 Length 域有关, | -| | | | 长度不够,可用分片。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0xbb’001011 | Client certification. | 进行企业级加密时,Client 端的证书。 | 数据长度与 Length 域有关, | -+ + +------------------------------------------------+ 长度不够,可用分片。 + -| | | 可包含或不包含私钥,由证书内容决定。 | | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0xcb’001100 | Server certification. | 进行企业级加密时,Server 端的证书。 | 数据长度与 Length 域有关, | -+ + +------------------------------------------------+ 长度不够,可用分片。 + -| | | 可包含或不包含私钥,由证书内容决定。 | | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0xdb’001101 | Client private key. | 进行企业级加密时,Client 端的私钥。 | 数据长度与 Length 域有关, | -| | | | 长度不够,可用分片。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0xeb’001110 | Server private key. | 进行企业级加密时,Server 端的私钥。 | 数据长度与 Length 域有关, | -| | | | 长度不够,可用分片。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0xf b’001111 | Wi-Fi connection state report. | 通知手机 ESP32 的 Wi-Fi 状态, | data[0] 表示 opmode,包括: | -| | | 包括 STA状态和 SoftAP 状态, | | -| | | 用于手机配置 STA 连接时的通知, | | -| | | 或有 STA 连接上 SoftAP 时的通知。 | | -+ + +------------------------------------------------+------------------------------------------------------+ -| | | 但收到手机询问 Wi-Fi 状态时, | 0x00: NULL; | -+ + + 除了回复此帧外,还可回复其他数据帧。 +------------------------------------------------------+ -| | | | 0x01: STA; | -+ + + +------------------------------------------------------+ -| | | | 0x02: SoftAP; | -+ + + +------------------------------------------------------+ -| | | | 0x03: SoftAP&STA | -+ + + +------------------------------------------------------+ -| | | | data[1]:STA 的连接状态, | -| | | | 0x0 表示处于连接状态, | -| | | | 其他表示处于非连接状态; | -+ + + +------------------------------------------------------+ -| | | | data[2]:SoftAP 的连接状态, | -| | | | 即表示有多少 STA 已经连接。 | -+ + + +------------------------------------------------------+ -| | | | data[3] 及以后:为按照本协议格式 SSID\BSSID 等信息。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x10 b’010000 | Version. | | data[0]= great version | -+ + + +------------------------------------------------------+ -| | | | data[1]=sub version | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x11 B’010001 | Wi-Fi list. | 通知手机 ESP32 周围的 Wi-Fi 热点列表。 | 数据帧数据格式为 Length + RSSI + SSID, | -| | | | 数据较长时可分片发送。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x12 B’010010 | Report error. | 通知手机 BluFi 过程出现异常错误。 | 0x00: sequence error; | -+ + + +------------------------------------------------------+ -| | | | 0x01: checksum error; | -+ + + +------------------------------------------------------+ -| | | | 0x02: decrypt error; | -+ + + +------------------------------------------------------+ -| | | | 0x03: encrypt error; | -+ + + +------------------------------------------------------+ -| | | | 0x04: init security error; | -+ + + +------------------------------------------------------+ -| | | | 0x05: dh malloc error; | -+ + + +------------------------------------------------------+ -| | | | 0x06: dh param error; | -+ + + +------------------------------------------------------+ -| | | | 0x07: read param error; | -+ + + +------------------------------------------------------+ -| | | | 0x08: make public error. | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ -| 0x13 B’010011 | Custom data. | 用户发送或者接收自定义数据。 | 数据较长时可分片发送。 | -+---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 数据帧 | 含义 | 解释 | 备注 | + +===============+========================================+================================================+======================================================+ + | 0x0 b’000000 | Negotiation data. | 用来发送协商数据,传输到应用层注册的回调函数。 | 数据长度与 Length 域有关。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x1 b’000001 | BSSID for STA mode. | STA 将要连接的 AP 的 BSSID(用于隐藏SSID)。 | 数据长度与 Length 域有关。 | + + + + +------------------------------------------------------+ + | | | | 当传输方向为 ESP32 到手机时, | + | | | | 表示向手机端提供信息。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x2 b’000010 | SSID for STA mode. | STA 将要连接的 AP 的 SSID。 | 数据长度与 Length 域有关。 | + + + + +------------------------------------------------------+ + | | | | 当传输方向为 ESP32 到手机时, | + | | | | 表示向手机端提供信息。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x3 b’000011 | Password for STA mode. | STA 将要连接的 AP 的密码。 | 数据长度与 Length 域有关。 | + + + + +------------------------------------------------------+ + | | | | 当传输方向为 ESP32 到手机时, | + | | | | 表示向手机端提供信息。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x4 b’000100 | SSID for SoftAP mode. | SoftAP 模式使用的 SSID。 | 数据长度与 Length 域有关。 | + + + + +------------------------------------------------------+ + | | | | 当传输方向为 ESP32 到手机时, | + | | | | 表示向手机端提供信息。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x5 b’000101 | Password for SoftAPmode. | SoftAP 模式使用的密码。 | 数据长度与 Length 域有关。 | + + + + +------------------------------------------------------+ + | | | | 当传输方向为 ESP32 到手机时, | + | | | | 表示向手机端提供信息。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x6 b’000110 | Max connection number for SoftAP mode. | AP 模式的最大连接数。 | data[0] 表示连接数的值,范围 1~4。 | + + + + +------------------------------------------------------+ + | | | | 当传输方向为 ESP32 到手机时, | + | | | | 表示向手机端提供信息。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x7b’000111 | Authentication mode for SoftAP mode. | AP 模式的认证模式。 | data[0]: | + + + + +------------------------------------------------------+ + | | | | 0x00: OPEN; | + + + + +------------------------------------------------------+ + | | | | 0x01: WEP; | + + + + +------------------------------------------------------+ + | | | | 0x02: WPA_PSK; | + + + + +------------------------------------------------------+ + | | | | 0x03: WPA2_PSK; | + + + + +------------------------------------------------------+ + | | | | 0x04: WPA_WPA2_PSK. | + + + + +------------------------------------------------------+ + | | | | 当传输方向为 ESP32 到手机时, | + | | | | 表示向手机端提供信息。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x8b’001000 | Channel for SoftAP mode. | SoftAP 模式的通道数量。 | data[0] 表示通道的数量,范围 1~14。 | + + + + +------------------------------------------------------+ + | | | | 当传输方向为 ESP32 到手机时, | + | | | | 表示向手机端提供信息。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x9b’001001 | Username. | 使用企业级加密时,Client 端的用户名。 | 数据长度与 Length 域有关。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0xab’001010 | CA certification. | 进行企业级加密时使用的 CA 证书。 | 数据长度与 Length 域有关, | + | | | | 长度不够,可用分片。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0xbb’001011 | Client certification. | 进行企业级加密时,Client 端的证书。 | 数据长度与 Length 域有关, | + + + +------------------------------------------------+ 长度不够,可用分片。 + + | | | 可包含或不包含私钥,由证书内容决定。 | | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0xcb’001100 | Server certification. | 进行企业级加密时,Server 端的证书。 | 数据长度与 Length 域有关, | + + + +------------------------------------------------+ 长度不够,可用分片。 + + | | | 可包含或不包含私钥,由证书内容决定。 | | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0xdb’001101 | Client private key. | 进行企业级加密时,Client 端的私钥。 | 数据长度与 Length 域有关, | + | | | | 长度不够,可用分片。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0xeb’001110 | Server private key. | 进行企业级加密时,Server 端的私钥。 | 数据长度与 Length 域有关, | + | | | | 长度不够,可用分片。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0xf b’001111 | Wi-Fi connection state report. | 通知手机 ESP32 的 Wi-Fi 状态, | data[0] 表示 opmode,包括: | + | | | 包括 STA状态和 SoftAP 状态, | | + | | | 用于手机配置 STA 连接时的通知, | | + | | | 或有 STA 连接上 SoftAP 时的通知。 | | + + + +------------------------------------------------+------------------------------------------------------+ + | | | 但收到手机询问 Wi-Fi 状态时, | 0x00: NULL; | + + + + 除了回复此帧外,还可回复其他数据帧。 +------------------------------------------------------+ + | | | | 0x01: STA; | + + + + +------------------------------------------------------+ + | | | | 0x02: SoftAP; | + + + + +------------------------------------------------------+ + | | | | 0x03: SoftAP&STA | + + + + +------------------------------------------------------+ + | | | | data[1]:STA 的连接状态, | + | | | | 0x0 表示处于连接状态, | + | | | | 其他表示处于非连接状态; | + + + + +------------------------------------------------------+ + | | | | data[2]:SoftAP 的连接状态, | + | | | | 即表示有多少 STA 已经连接。 | + + + + +------------------------------------------------------+ + | | | | data[3] 及以后:为按照本协议格式 SSID\BSSID 等信息。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x10 b’010000 | Version. | | data[0]= great version | + + + + +------------------------------------------------------+ + | | | | data[1]=sub version | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x11 B’010001 | Wi-Fi list. | 通知手机 ESP32 周围的 Wi-Fi 热点列表。 | 数据帧数据格式为 Length + RSSI + SSID, | + | | | | 数据较长时可分片发送。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x12 B’010010 | Report error. | 通知手机 BluFi 过程出现异常错误。 | 0x00: sequence error; | + + + + +------------------------------------------------------+ + | | | | 0x01: checksum error; | + + + + +------------------------------------------------------+ + | | | | 0x02: decrypt error; | + + + + +------------------------------------------------------+ + | | | | 0x03: encrypt error; | + + + + +------------------------------------------------------+ + | | | | 0x04: init security error; | + + + + +------------------------------------------------------+ + | | | | 0x05: dh malloc error; | + + + + +------------------------------------------------------+ + | | | | 0x06: dh param error; | + + + + +------------------------------------------------------+ + | | | | 0x07: read param error; | + + + + +------------------------------------------------------+ + | | | | 0x08: make public error. | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x13 B’010011 | Custom data. | 用户发送或者接收自定义数据。 | 数据较长时可分片发送。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ 2. Frame Control 帧控制域,占 1 byte,每个 bit 表示不同含义。 -+----------------+-------------------------------------------------------------------------+ -| 位 | 含义 | -+================+=========================================================================+ -| 0x01 | 表示帧是否加密。 | -+ +-------------------------------------------------------------------------+ -| | 1 表示加密,0 表示未加密。 | -+ +-------------------------------------------------------------------------+ -| | 加密部分帧括完整的 DATA 域加密之前的明文(不帧含末尾的校验)。 | -+ +-------------------------------------------------------------------------+ -| | 控制帧暂不加密,故控制帧此位为 0。 | -+----------------+-------------------------------------------------------------------------+ -| 0x02 | 表示帧 Data 域结尾是否帧含校验(例如 SHA1,MD5,CRC等)需要校验的数据域, | -| | 包括 sequcne + data length + 明文 data。 | -+ +-------------------------------------------------------------------------+ -| | 控制帧和数据帧都可以包含校验位或不包含。 | -+----------------+-------------------------------------------------------------------------+ -| 0x04 | 表示数据方向。 | -+ +-------------------------------------------------------------------------+ -| | 0 表示手机发向 ESP32; | -+ +-------------------------------------------------------------------------+ -| | 1 表示 ESP32 发向手机。 | -+----------------+-------------------------------------------------------------------------+ -| 0x08 | 表示是否要求对方回复 ack。 | -+ +-------------------------------------------------------------------------+ -| | 0 表示不要求; | -+ +-------------------------------------------------------------------------+ -| | 1 表示要求回复 ack。 | -+----------------+-------------------------------------------------------------------------+ -| 0x10 | 表示是否有后续的数据分片。 | -+ +-------------------------------------------------------------------------+ -| | 0 表示此帧没有后续数据分片; | -+ +-------------------------------------------------------------------------+ -| | 1 表示还有后续数据分片,用来传输较长的数据。 | -+ +-------------------------------------------------------------------------+ -| | 如果是 Frag 帧,则告知当前 content 部分+后续 content 部分的总长度, | -| | 位于 Data 域的前 2 字节(即最大支持 64K 的 content 数据)。 | -+----------------+-------------------------------------------------------------------------+ -| 0x10~0x80 保留 | | -+----------------+-------------------------------------------------------------------------+ + +----------------+-------------------------------------------------------------------------------------------------------------------------------+ + | 位 | 含义 | + +================+===============================================================================================================================+ + | 0x01 | 表示帧是否加密。 | + + +-------------------------------------------------------------------------------------------------------------------------------+ + | | 1 表示加密,0 表示未加密。 | + + +-------------------------------------------------------------------------------------------------------------------------------+ + | | 加密部分帧括完整的 DATA 域加密之前的明文(不帧含末尾的校验)。 | + + +-------------------------------------------------------------------------------------------------------------------------------+ + | | 控制帧暂不加密,故控制帧此位为 0。 | + +----------------+-------------------------------------------------------------------------------------------------------------------------------+ + | 0x02 | 表示帧 Data 域结尾是否帧含校验(例如 SHA1,MD5,CRC等)需要校验的数据域包括 sequcne + data length + 明文 data。 | + + +-------------------------------------------------------------------------------------------------------------------------------+ + | | 控制帧和数据帧都可以包含校验位或不包含。 | + +----------------+-------------------------------------------------------------------------------------------------------------------------------+ + | 0x04 | 表示数据方向。 | + + +-------------------------------------------------------------------------------------------------------------------------------+ + | | 0 表示手机发向 ESP32; | + + +-------------------------------------------------------------------------------------------------------------------------------+ + | | 1 表示 ESP32 发向手机。 | + +----------------+-------------------------------------------------------------------------------------------------------------------------------+ + | 0x08 | 表示是否要求对方回复 ack。 | + + +-------------------------------------------------------------------------------------------------------------------------------+ + | | 0 表示不要求; | + + +-------------------------------------------------------------------------------------------------------------------------------+ + | | 1 表示要求回复 ack。 | + +----------------+-------------------------------------------------------------------------------------------------------------------------------+ + | 0x10 | 表示是否有后续的数据分片。 | + + +-------------------------------------------------------------------------------------------------------------------------------+ + | | 0 表示此帧没有后续数据分片; | + + +-------------------------------------------------------------------------------------------------------------------------------+ + | | 1 表示还有后续数据分片,用来传输较长的数据。 | + + +-------------------------------------------------------------------------------------------------------------------------------+ + | | 如果是 Frag 帧,则告知当前 content 部分+后续 content 部分的总长度,位于 Data 域的前 2 字节(即最大支持 64K 的 content 数据)。 | + +----------------+-------------------------------------------------------------------------------------------------------------------------------+ + | 0x10~0x80 保留 | | + +----------------+-------------------------------------------------------------------------------------------------------------------------------+ + 3. Sequence Control