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 0000000000..6d6114fcf1 --- /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 0000000000..41dd19a00f --- /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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 ({?WWvibFv=c(o8 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%0D;GFkWWxBTrb$^s)2C+?UUjzx}$@e07=V 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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 cc2ffbbd4d..7f56023b3b 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 7f56023b3b..429c5d9e64 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 74f0689617..1f9ec8905f 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

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%0D;GFkWWxBTrb$^s)2C+?UUjzx}$@e07=V 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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 41dd19a00f..9b518cd296 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 6d6114fcf1..1542c5cd99 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 3e8b2ece51..648a9d1dbb 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 1542c5cd99..027d40e00a 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 a6a7d85661..a9a150cd86 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 9b518cd296..0da1c38384 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 0da1c38384..1aeace66d7 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 1aeace66d7..9c70a08e7b 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 9c70a08e7b..2aab6db8d5 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 2aab6db8d5..95a2dfad06 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 027d40e00a..50b8d41f31 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 95a2dfad06..9e2554dfa5 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 9e2554dfa5..cc2ffbbd4d 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 50b8d41f31..74f0689617 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 648a9d1dbb..3f1fafc252 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 a9a150cd86..661be7ee83 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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 ({?WWvibFv=c(o8 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