Skip to content

蓝牙配置协议

帧格式

数据八位一个字节。下面的数字表示一个字节char.

完整帧的格式 [header(3)][type(1)][ctrl(1)][seq(1)][len(1)][data(len)][crc(2)]

分片帧的格式 [header(3)][type(1)][ctrl(1)][seq(1)][len(1)][data_total(2)][data(len)][crc(2)]

帧固定头 [0xBC, 0x59, 0x51];

type

帧类型定义 (低2位表示类型,高6位表示子类型) 所以一个帧类型是

Main Type

类型名称类型值类型说明
控制帧0x00用于发送控制指令
数据帧0x01用于发送数据指令
应答帧0x02用于应答指令

Sub Type

控制帧的Sub Type
类型名称类型值类型说明回复帧类型
设置 Wi‑Fi0x05用于设置WI-FI指令应答帧 0x02
设置 MQTT0x06用于设置MQTT指令应答帧 0x02
获取版本信息0x07用于获取设备版本信息指令数据帧 0x03
重启设备0x08用于重启设备指令应答帧 0x02
获取设备状态0x09用于获取设备状态指令
设置串口参数0x0A用于设置串口指令应答帧 0x02
设置低功耗模式参数0x0E用于设置低功耗参数指令应答帧 0x02
获取低功耗模式参数0x0F用于设置获取低功耗参数指令数据帧 0x03
清除WI-FI与MQTT配置0x10用于清除WI-FI与MQTT配置指令应答帧 0x02
获取WI-FI参数和状态0x11获取WI-FI状态数据帧 0x03
获取MQTT参数和状态0x12用于清除WI-FI与MQTT配置指令数据帧 0x03
获取UART参数0x13用于清除WI-FI与MQTT配置指令数据帧 0x03
数据帧的Sub Type
类型名称类型值类型说明
设备版本信息0x10版本信息
低功耗设置0x13低功耗设置的数据
WI-FI状态数据0x14WI-FI状态数据
MQTT状态数据0x15MQTT状态数据
UART设置数据0x16UART设置数据
应答帧 Sub Type

与控制帧一致。

Payload 只带有一个值 0/1

分别表示 失败 / 成功

ctrl

帧控制字段定义

是否还有数据分片是否为 ACK 帧数据方向是否包含校验位是否加密
0x100x080x040x020x01
0x01 是否加密 (0: 不加密;1: 加密)

0x02:是否包含校验位(CRC等)

0x04:数据方向(0: 手机->设备;1: 设备->手机)

0x08:是否为 ACK 帧 (废除)

0x10:是否还有后续数据分片(1 表示还有分片)

使用的时候进行或运算即可

seq

分片序号

len

当前帧传输数据的长度

data_total

分片的时候有效,当表示数据总的长度

data

传输的数据内容

crc

CRC16 校验 校验为止从帧头开始一直到data。

Data格式 (TLV)

TLV(Type-Length-Value)是一种高效的数据编码格式,通过“类型-长度-值”三元组实现灵活的数据传输,特别适合物联网、网络协议等场景。

‌核心结构‌
‌Type(类型)‌:固定长度字段(1字节),标识数据类型。
‌Length(长度)‌:动态变长编码(1字节),声明Value的字节数。
‌Value(值)‌:实际数据内容,长度由Length指定。

WIFI设置

0x01: SSID (str), //SSID
0x02: Password (str) //密码

MQTT设置:

0x00 is_ssl               //是否开启SSL (预留,默认为不开启)
0x01 server               //服务器地址
0x02 port                 //服务器端口号
0x03 username             //用户名
0x04 password             //密码
0x05 topic                //自定义topic
0x06 server_ca_pem        //证书(预留)
0x07 client_cert_pem      //证书(预留)
0x08 client_key_pem       //证书(预留)
0x09 mqtt_proto            //MQTT 协议版本 默认 311 ,值 311,31,5  

NOTE

SSL 当前版本未实现。啥时候实现待定。主要没有合适的测试环境

串口设置命令

0x01 baud,                  //波特率
0x02 data_bits,             //数据位
0x03 stop_bits,             //停止位 
0x04 parity,                //奇偶校验
0x05 flow_control           //流量控制

状态采集指令

// Wi‑Fi 相关字段

const int TLV_WIFI_STATE = 0x01; // u8
const int TLV_WIFI_SSID = 0x02; // str
const int TLV_WIFI_IP = 0x03; // str
const int TLV_TYPE_WIFI_DISCONNECT_REASON = 0x0E //u8


// MQTT 相关字段
const int TLV_MQTT_STATE = 0x04; // u8
const int TLV_MQTT_URI = 0x05; // str (server address or URI)
const int TLV_MQTT_SUB_TOPIC = 0x06; // str
const int TLV_MQTT_PUB_TOPIC = 0x07; // str

// 串口(UART)相关字段
const int TLV_UART_BAUD = 0x08; // u32 BE
const int TLV_UART_DATA_BITS = 0x09; // u8
const int TLV_UART_STOP_BITS = 0x0A; // u8 (encoded: 0,1,1.5,2 as 0..3)
const int TLV_UART_PARITY = 0x0B; // u8 (0 none,1 odd,2 even)
const int TLV_UART_FLOW = 0x0C; // u8 (0 none,1 hw,2 sw)

OTA_URL 设置命令 (预留)

0x01: OTA URL (string). len==0 表示清除 OTA_URL。

低功耗设置命令

0x01: deep_sleep_enable (u8) 0/1
0x02: deep_sleep_wake_sec (u32 BE)
0x03: awake_keep_sec (u32 BE)

WIFI 断网原因对照表

 const Map<int, String> m = <int, String>{
    1: 'UNSPECIFIED',
    2: 'AUTH_EXPIRE',
    3: 'AUTH_LEAVE',
    4: 'DISASSOC_DUE_TO_INACTIVITY',
    5: 'ASSOC_TOOMANY',
    6: 'CLASS2_FRAME_FROM_NONAUTH_STA',
    7: 'CLASS3_FRAME_FROM_NONASSOC_STA',
    8: 'ASSOC_LEAVE',
    9: 'ASSOC_NOT_AUTHED',
    10: 'DISASSOC_PWRCAP_BAD',
    11: 'DISASSOC_SUPCHAN_BAD',
    12: 'BSS_TRANSITION_DISASSOC',
    13: 'IE_INVALID',
    14: 'MIC_FAILURE',
    15: '4WAY_HANDSHAKE_TIMEOUT',
    16: 'GROUP_KEY_UPDATE_TIMEOUT',
    17: 'IE_IN_4WAY_DIFFERS',
    18: 'GROUP_CIPHER_INVALID',
    19: 'PAIRWISE_CIPHER_INVALID',
    20: 'AKMP_INVALID',
    21: 'UNSUPP_RSN_IE_VERSION',
    22: 'INVALID_RSN_IE_CAP',
    23: '802_1X_AUTH_FAILED',
    24: 'CIPHER_SUITE_REJECTED',
    25: 'TDLS_PEER_UNREACHABLE',
    26: 'TDLS_UNSPECIFIED',
    27: 'SSP_REQUESTED_DISASSOC',
    28: 'NO_SSP_ROAMING_AGREEMENT',
    29: 'BAD_CIPHER_OR_AKM',
    30: 'NOT_AUTHORIZED_THIS_LOCATION',
    31: 'SERVICE_CHANGE_PERCLUDES_TS',
    32: 'UNSPECIFIED_QOS',
    33: 'NOT_ENOUGH_BANDWIDTH',
    34: 'MISSING_ACKS',
    35: 'EXCEEDED_TXOP',
    36: 'STA_LEAVING',
    37: 'END_BA',
    38: 'UNKNOWN_BA',
    39: 'TIMEOUT',
    46: 'PEER_INITIATED',
    47: 'AP_INITIATED',
    48: 'INVALID_FT_ACTION_FRAME_COUNT',
    49: 'INVALID_PMKID',
    50: 'INVALID_MDE',
    51: 'INVALID_FTE',
    67: 'TRANSMISSION_LINK_ESTABLISH_FAILED',
    68: 'ALTERATIVE_CHANNEL_OCCUPIED',
    200: 'BEACON_TIMEOUT',
    201: 'NO_AP_FOUND',
    202: 'AUTH_FAIL',
    203: 'ASSOC_FAIL',
    204: 'HANDSHAKE_TIMEOUT',
    205: 'CONNECTION_FAIL',
    206: 'AP_TSF_RESET',
    207: 'ROAMING',
    208: 'ASSOC_COMEBACK_TIME_TOO_LONG',
    209: 'SA_QUERY_TIMEOUT',
    210: 'NO_AP_FOUND_W_COMPATIBLE_SECURITY',
    211: 'NO_AP_FOUND_IN_AUTHMODE_THRESHOLD',
    212: 'NO_AP_FOUND_IN_RSSI_THRESHOLD',
  };

长度限制

参数

参数最大长度(char)
WI-FI SSID32
WI-FI Password64
MQTT 自定义topic16
MQTT sub/pub 订阅和发布的主题128

透传

透传为最大 1024 char.

分帧说明

由于蓝牙MTU设置为23,所以Data过长的时候是需要分帧的。解析前需要把分帧合并成单帧再进行解析

指令例子

WI-FI状态查询

发送:[0xBC, 0x59, 0x51, 0x44, 0x02, 0x00, 0x00, 0x1C, 0xC9]

接收:[0xBC, 0x59, 0x51, 0x51, 0x06, 0x00, 0x1E, 0x01, 0x01, 0x04, 0x0E, 0x01, 0x00, 0x02, 0x07, 0x37, 0x31, 0x32, 0x30, 0x31, 0x2D, 0x32, 0x03, 0x0D, 0x31, 0x39, 0x32, 0x2E, 0x31, 0x36, 0x38, 0x2E, 0x39, 0x2E, 0x31, 0x30, 0x38, 0x35, 0x1B]

请求帧字段解析

请求帧:[0xBC, 0x59, 0x51, 0x44, 0x02, 0x00, 0x00, 0x1C, 0xC9]

字段字节说明
header3BC 59 51固定帧头
type144type & 0x03 = 0 → 控制帧;type >> 2 = 0x11 → SubType=0x11(获取 WI-FI 参数和状态)
ctrl102包含 CRC(0x02
seq100序号(示例为 0)
len100数据长度为 0(本指令无 payload)
crc21C C9CRC16(从 header 到 data 末尾)

响应帧字段解析

响应帧:[0xBC, 0x59, 0x51, 0x51, 0x06, 0x00, 0x1E, ... , 0x35, 0x1B]

字段字节说明
header3BC 59 51固定帧头
type151type & 0x03 = 1 → 数据帧;type >> 2 = 0x14 → SubType=0x14(WI-FI 状态数据)
ctrl1060x04 设备→手机 + 0x02 包含 CRC
seq100序号(示例为 0)
len11E数据长度 0x1E = 30 字节
datalen见下TLV 数据
crc235 1BCRC16(从 header 到 data 末尾)

响应 data(TLV)解析

响应 data 共 30 字节,按 TLV(Type-Length-Value)解析如下:

  1. 01 01 04
  • Type=0x01TLV_WIFI_STATE
  • Length=0x01
  • Value=0x04WIFI_STATE_GOT_IP(已联网并获取 IP)
  1. 0E 01 00
  • Type=0x0ETLV_TYPE_WIFI_DISCONNECT_REASON
  • Length=0x01
  • Value=0x00(示例值为 0;如断网可对照上面的断网原因表)
  1. 02 07 37 31 32 30 31 2D 32
  • Type=0x02TLV_WIFI_SSID
  • Length=0x07
  • Value=37 31 32 30 31 2D 32 → ASCII 字符串 71201-2
  1. 03 0D 31 39 32 2E 31 36 38 2E 39 2E 31 30 38
  • Type=0x03TLV_WIFI_IP
  • Length=0x0D
  • Value=31 39 32 2E 31 36 38 2E 39 2E 31 30 38 → ASCII 字符串 192.168.9.108

MQTT状态查询

发送(十六进制):[0xBC, 0x59, 0x51, 0x48, 0x02, 0x00, 0x00, 0x53, 0xFB]

接收(十六进制):[0xBC, 0x59, 0x51, 0x55, 0x06, 0x00, 0x62, ... , 0x87, 0xD6]

请求帧字段解析

请求帧:[0xBC, 0x59, 0x51, 0x48, 0x02, 0x00, 0x00, 0x53, 0xFB]

字段字节说明
header3BC 59 51固定帧头
type148type & 0x03 = 0 → 控制帧;type >> 2 = 0x12 → SubType=0x12(获取 MQTT 参数和状态)
ctrl102包含 CRC(0x02
seq100序号(示例为 0)
len100数据长度为 0(本指令无 payload)
crc253 FBCRC16(从 header 到 data 末尾)

响应帧字段解析

响应帧(完整十进制数组):

text
[0xBC, 0x59, 0x51, 0x55, 0x06, 0x00, 0x62, 0x04, 0x01, 0x02, 0x05, 0x17, 0x6D, 0x71, 0x74, 0x74, 0x3A, 0x2F, 0x2F, 0x31, 0x30, 0x31, 0x2E, 0x34, 0x32, 0x2E, 0x34, 0x2E, 0x35, 0x31, 0x3A, 0x31, 0x38, 0x38, 0x33, 0x06, 0x21, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x2F, 0x65, 0x73, 0x70, 0x2F, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x2F, 0x73, 0x75, 0x62, 0x2F, 0x36, 0x43, 0x43, 0x38, 0x34, 0x30, 0x42, 0x42, 0x42, 0x38, 0x30, 0x45, 0x07, 0x21, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x2F, 0x65, 0x73, 0x70, 0x2F, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x2F, 0x70, 0x75, 0x62, 0x2F, 0x36, 0x43, 0x43, 0x38, 0x34, 0x30, 0x42, 0x42, 0x42, 0x38, 0x30, 0x45, 0x87, 0xD6]
字段字节说明
header3BC 59 51固定帧头
type155type & 0x03 = 1 → 数据帧;type >> 2 = 0x15 → SubType=0x15(MQTT 状态数据)
ctrl1060x04 设备→手机 + 0x02 包含 CRC
seq100序号(示例为 0)
len162数据长度 0x62 = 98 字节
datalen见下TLV 数据
crc287 D6CRC16(从 header 到 data 末尾)

响应 data(TLV)解析

响应 data 共 98 字节,按 TLV(Type-Length-Value)解析如下:

  1. 04 01 02
  • Type=0x04TLV_MQTT_STATE
  • Length=0x01
  • Value=0x02MQTT_STATE_CONNECTED(已连接)
  1. 05 17 6D 71 74 74 3A 2F 2F 31 30 31 2E 34 32 2E 34 2E 35 31 3A 31 38 38 33
  • Type=0x05TLV_MQTT_URI
  • Length=0x17(23 字节)
  • Value → ASCII 字符串 mqtt://101.42.4.51:1883
  1. 06 21 ...
  • Type=0x06TLV_MQTT_SUB_TOPIC
  • Length=0x21(33 字节)
  • Value → ASCII 字符串 trans/esp/client/sub/6CC840BBB80E
  1. 07 21 ...
  • Type=0x07TLV_MQTT_PUB_TOPIC
  • Length=0x21(33 字节)
  • Value → ASCII 字符串 trans/esp/client/pub/6CC840BBB80E

UART参数查询

发送(十六进制):[0xBC, 0x59, 0x51, 0x4C, 0x02, 0x00, 0x00, 0x99, 0x0A]

接收(十六进制):[0xBC, 0x59, 0x51, 0x59, 0x06, 0x00, 0x12, 0x08, 0x04, 0x00, 0x00, 0x25, 0x80, 0x09, 0x01, 0x08, 0x0A, 0x01, 0x01, 0x0B, 0x01, 0x00, 0x0C, 0x01, 0x00, 0x97, 0x56]

请求帧字段解析

请求帧:[0xBC, 0x59, 0x51, 0x4C, 0x02, 0x00, 0x00, 0x99, 0x0A]

字段字节说明
header3BC 59 51固定帧头
type14Ctype & 0x03 = 0 → 控制帧;type >> 2 = 0x13 → SubType=0x13(获取 UART 参数)
ctrl102包含 CRC(0x02
seq100序号(示例为 0)
len100数据长度为 0(本指令无 payload)
crc299 0ACRC16(从 header 到 data 末尾)

响应帧字段解析

响应帧:[0xBC, 0x59, 0x51, 0x59, 0x06, 0x00, 0x12, ... , 0x97, 0x56]

字段字节说明
header3BC 59 51固定帧头
type159type & 0x03 = 1 → 数据帧;type >> 2 = 0x16 → SubType=0x16(UART 设置数据)
ctrl1060x04 设备→手机 + 0x02 包含 CRC
seq100序号(示例为 0)
len112数据长度 0x12 = 18 字节
datalen见下TLV 数据
crc297 56CRC16(从 header 到 data 末尾)

响应 data(TLV)解析

响应 data 共 18 字节,按 TLV(Type-Length-Value)解析如下:

  1. 08 04 00 00 25 80
  • Type=0x08TLV_UART_BAUD
  • Length=0x04
  • Value=00 00 25 80(u32 BE)→ 9600
  1. 09 01 08
  • Type=0x09TLV_UART_DATA_BITS
  • Length=0x01
  • Value=0x08 → 数据位 8
  1. 0A 01 01
  • Type=0x0ATLV_UART_STOP_BITS
  • Length=0x01
  • Value=0x01 → 停止位编码 1(对应 1 stop bit)
  1. 0B 01 00
  • Type=0x0BTLV_UART_PARITY
  • Length=0x01
  • Value=0x00 → parity none
  1. 0C 01 00
  • Type=0x0CTLV_UART_FLOW
  • Length=0x01
  • Value=0x00 → flow control none

版本信息查询

发送(十六进制):[0xBC, 0x59, 0x51, 0x1C, 0x02, 0x00, 0x00, 0xEC, 0x31]

接收(十六进制):[0xBC, 0x59, 0x51, 0x41, 0x06, 0x00, 0x05, 0x31, 0x2E, 0x35, 0x2E, 0x31, 0xEA, 0x67]

请求帧字段解析

请求帧:[0xBC, 0x59, 0x51, 0x1C, 0x02, 0x00, 0x00, 0xEC, 0x31]

字段字节说明
header3BC 59 51固定帧头
type11Ctype & 0x03 = 0 → 控制帧;type >> 2 = 0x07 → SubType=0x07(获取版本信息)
ctrl102包含 CRC(0x02
seq100序号(示例为 0)
len100数据长度为 0(本指令无 payload)
crc2EC 31CRC16(从 header 到 data 末尾)

响应帧字段解析

响应帧:[0xBC, 0x59, 0x51, 0x41, 0x06, 0x00, 0x05, ... , 0xEA, 0x67]

字段字节说明
header3BC 59 51固定帧头
type141type & 0x03 = 1 → 数据帧;type >> 2 = 0x10 → SubType=0x10(设备版本信息)
ctrl1060x04 设备→手机 + 0x02 包含 CRC
seq100序号(示例为 0)
len105数据长度 5 字节
datalen31 2E 35 2E 31ASCII 字符串 1.5.1
crc2EA 67CRC16(从 header 到 data 末尾)

设置 Wi‑Fi(分帧示例)

提醒:分片帧需要先按 data_total 合并成完整 data,再按 TLV 解析。

发送三个分帧:

  1. [0xBC, 0x59, 0x51, 0x14, 0x12, 0x00, 0x09, 0x00, 0x13, 0x01, 0x07, 0x37, 0x31, 0x32, 0x30, 0x31, 0x2D, 0x32, 0x7C, 0x40]

  2. [0xBC, 0x59, 0x51, 0x14, 0x12, 0x00, 0x09, 0x00, 0x13, 0x02, 0x08, 0x31, 0x71, 0x32, 0x65, 0x33, 0x65, 0x34, 0x00, 0x4E]

  3. [0xBC, 0x59, 0x51, 0x14, 0x02, 0x00, 0x01, 0x00, 0x13, 0x72, 0x0E, 0x18]

接收:[0xBC, 0x59, 0x51, 0x16, 0x06, 0x00, 0x01, 0x00, 0xB2, 0xCC]

分片请求帧字段解析(以第 1 帧为例)

第 1 帧:[0xBC, 0x59, 0x51, 0x14, 0x12, 0x00, 0x09, 0x00, 0x13, ... , 0x7C, 0x40]

字段字节说明
header3BC 59 51固定帧头
type114type & 0x03 = 0 → 控制帧;type >> 2 = 0x05 → SubType=0x05(设置 Wi‑Fi)
ctrl1120x10 表示还有后续分片 + 0x02 表示包含 CRC
seq100分片序号(本示例中均为 0;实现若使用递增序号,应按 seq 排序再合并)
len109当前分片 data 长度(不含 data_total 与 crc)
data_total200 13完整 data 总长度 0x0013 = 19 字节
datalen见下分片数据
crc27C 40CRC16(从 header 到本分片 data 末尾)

合帧(把 3 个分片的 data 拼接)

三个分片的 data(len) 依次为:

  • 分片 1:01 07 37 31 32 30 31 2D 32
  • 分片 2:02 08 31 71 32 65 33 65 34
  • 分片 3:72

合并后的完整 data(19 字节)为:

01 07 37 31 32 30 31 2D 32 02 08 31 71 32 65 33 65 34 72

合并后 data(TLV)解析

按“WIFI设置”TLV 约定:0x01=SSID0x02=Password

  1. 01 07 37 31 32 30 31 2D 32
  • Type=0x01(SSID)
  • Length=0x07
  • Value → ASCII:71201-2
  1. 02 08 31 71 32 65 33 65 34 72
  • Type=0x02(Password)
  • Length=0x08
  • Value → ASCII:1q2e3e4r

响应帧(ACK)解析

理论上:

接收:[0xBC, 0x59, 0x51, 0x16, 0x06, 0x00, 0x01, 0x00, 0xB2, 0xCC]

  • type=0x16type & 0x03 = 2(应答帧),type >> 2 = 0x05(对应设置 Wi‑Fi 的 ACK)
  • len=0x01,payload=0x00
    • 按文档约定:0=失败1=成功 → 本次设置结果为失败 实际上已经重启。没有回复帧。 后期补上吧。

设置 MQTT(分帧示例)

说明:与“设置 Wi‑Fi(分帧示例)”一致,先按 data_total 合并完整 data,再按 MQTT 的 TLV 定义解析。

发送分帧(仅十六进制):

  1. [0xBC, 0x59, 0x51, 0x18, 0x12, 0x00, 0x09, 0x00, 0x3F, 0x00, 0x01, 0x00, 0x01, 0x0B, 0x31, 0x30, 0x31, 0x2E, 0x6A, 0xDC]

  2. [0xBC, 0x59, 0x51, 0x18, 0x12, 0x00, 0x09, 0x00, 0x3F, 0x34, 0x32, 0x2E, 0x34, 0x2E, 0x35, 0x31, 0x02, 0x02, 0xDF, 0x61]

  3. [0xBC, 0x59, 0x51, 0x18, 0x12, 0x00, 0x09, 0x00, 0x3F, 0x07, 0x5B, 0x03, 0x0D, 0x65, 0x73, 0x70, 0x5F, 0x6D, 0x4A, 0xA1]

  4. [0xBC, 0x59, 0x51, 0x18, 0x12, 0x00, 0x09, 0x00, 0x3F, 0x71, 0x74, 0x74, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x04, 0x5E, 0x55]

  5. [0xBC, 0x59, 0x51, 0x18, 0x12, 0x00, 0x09, 0x00, 0x3F, 0x11, 0x65, 0x73, 0x70, 0x5F, 0x6D, 0x71, 0x74, 0x74, 0x89, 0x2D]

  6. [0xBC, 0x59, 0x51, 0x18, 0x12, 0x00, 0x09, 0x00, 0x3F, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x59, 0x97]

  7. [0xBC, 0x59, 0x51, 0x18, 0x02, 0x00, 0x09, 0x00, 0x3F, 0x05, 0x03, 0x65, 0x73, 0x70, 0x09, 0x02, 0x01, 0x37, 0x25, 0x3B]

接收(ACK):[0xBC, 0x59, 0x51, 0x1A, 0x06, 0x00, 0x01, 0x00, 0x39, 0xE7]

分片请求帧字段解析(以第 1 帧为例)

第 1 帧:[0xBC, 0x59, 0x51, 0x18, 0x12, 0x00, 0x09, 0x00, 0x3F, ...]

  • type=0x18 → 控制帧,type >> 2 = 0x06(设置 MQTT)
  • ctrl=0x12 → 有后续分片(0x10)+ 含 CRC(0x02
  • len=0x09
  • data_total=0x003F → 完整 data 总长度 63 字节

合帧(把 7 个分片的 data 拼接)

合并后的完整 data(63 字节)为:

00 01 00 01 0B 31 30 31 2E 34 32 2E 34 2E 35 31 02 02 07 5B 03 0D 65 73 70 5F 6D 71 74 74 5F 75 73 65 72 04 11 65 73 70 5F 6D 71 74 74 5F 70 61 73 73 77 6F 72 64 05 03 65 73 70 09 02 01 37

合并后 data(TLV)解析

按“MQTT设置”TLV 约定:

  • 0x00 is_ssl
  • 0x01 server
  • 0x02 port
  • 0x03 username
  • 0x04 password
  • 0x05 topic
  • 0x09 mqtt_proto
  1. 00 01 00
  • Type=0x00(is_ssl)
  • Length=0x01
  • Value=0x00 → 关闭 SSL
  1. 01 0B 31 30 31 2E 34 32 2E 34 2E 35 31
  • Type=0x01(server)
  • Length=0x0B
  • Value → ASCII:101.42.4.51
  1. 02 02 07 5B
  • Type=0x02(port)
  • Length=0x02
  • Value=07 5B(u16 BE)→ 1883
  1. 03 0D 65 73 70 5F 6D 71 74 74 5F 75 73 65 72
  • Type=0x03(username)
  • Length=0x0D
  • Value → ASCII:esp_mqtt_user
  1. 04 11 65 73 70 5F 6D 71 74 74 5F 70 61 73 73 77 6F 72 64
  • Type=0x04(password)
  • Length=0x11
  • Value → ASCII:esp_mqtt_password
  1. 05 03 65 73 70
  • Type=0x05(topic)
  • Length=0x03
  • Value → ASCII:esp
  1. 09 02 01 37
  • Type=0x09(mqtt_proto)
  • Length=0x02
  • Value=01 37(u16 BE)→ 311(即 MQTT 3.1.1)

响应帧(ACK)解析

接收:[0xBC, 0x59, 0x51, 0x1A, 0x06, 0x00, 0x01, 0x00, 0x39, 0xE7]

  • type=0x1Atype & 0x03 = 2(应答帧),type >> 2 = 0x06(对应设置 MQTT 的 ACK)
  • len=0x01,payload=0x00
    • 按文档约定:0=失败1=成功 → 本次设置结果为失败

设置 UART(分帧示例)

发送分帧(仅十六进制):

  1. [0xBC, 0x59, 0x51, 0x28, 0x12, 0x00, 0x09, 0x00, 0x12, 0x01, 0x04, 0x00, 0x00, 0x25, 0x80, 0x02, 0x01, 0x08, 0x44, 0xC4]

  2. [0xBC, 0x59, 0x51, 0x28, 0x02, 0x00, 0x09, 0x00, 0x12, 0x03, 0x01, 0x01, 0x04, 0x01, 0x00, 0x05, 0x01, 0x00, 0xEA, 0x38]

接收(ACK):[0xBC, 0x59, 0x51, 0x2A, 0x06, 0x00, 0x01, 0x00, 0x35, 0x09]

分片请求帧字段解析(以第 1 帧为例)

第 1 帧:[0xBC, 0x59, 0x51, 0x28, 0x12, 0x00, 0x09, 0x00, 0x12, ...]

  • type=0x28 → 控制帧,type >> 2 = 0x0A(设置串口参数)
  • ctrl=0x12 → 有后续分片(0x10)+ 含 CRC(0x02
  • len=0x09
  • data_total=0x0012 → 完整 data 总长度 18 字节

合帧(把 2 个分片的 data 拼接)

两个分片的 data(len) 依次为:

  • 分片 1:01 04 00 00 25 80 02 01 08
  • 分片 2:03 01 01 04 01 00 05 01 00

合并后的完整 data(18 字节)为:

01 04 00 00 25 80 02 01 08 03 01 01 04 01 00 05 01 00

合并后 data(TLV)解析

按“串口设置命令”TLV 约定:

  • 0x01 baud
  • 0x02 data_bits
  • 0x03 stop_bits
  • 0x04 parity
  • 0x05 flow_control
  1. 01 04 00 00 25 80
  • Type=0x01(baud)
  • Length=0x04
  • Value=00 00 25 80(u32 BE)→ 9600
  1. 02 01 08
  • Type=0x02(data_bits)
  • Length=0x01
  • Value=0x08 → 8
  1. 03 01 01
  • Type=0x03(stop_bits)
  • Length=0x01
  • Value=0x01 → 1 stop bit
  1. 04 01 00
  • Type=0x04(parity)
  • Length=0x01
  • Value=0x00 → none
  1. 05 01 00
  • Type=0x05(flow_control)
  • Length=0x01
  • Value=0x00 → none

响应帧(ACK)解析

接收:[0xBC, 0x59, 0x51, 0x2A, 0x06, 0x00, 0x01, 0x00, 0x35, 0x09]

  • type=0x2Atype & 0x03 = 2(应答帧),type >> 2 = 0x0A(对应设置串口参数的 ACK)
  • len=0x01,payload=0x00
    • 按文档约定:0=失败1=成功 → 本次设置结果为失败

重启设备

发送(十六进制):[0xBC, 0x59, 0x51, 0x20, 0x02, 0x00, 0x00, 0x8F, 0xEA]

请求帧字段解析

请求帧:[0xBC, 0x59, 0x51, 0x20, 0x02, 0x00, 0x00, 0x8F, 0xEA]

字段字节说明
header3BC 59 51固定帧头
type120type & 0x03 = 0 → 控制帧;type >> 2 = 0x08 → SubType=0x08(重启设备)
ctrl102包含 CRC(0x02
seq100序号(示例为 0)
len100数据长度为 0(本指令无 payload)
crc28F EACRC16(从 header 到 data 末尾)

响应帧(ACK)解析(理论)

说明:重启指令可能会在设备重启前来不及返回 ACK;以下为按协议约定的 ACK 帧格式。

理论 ACK:[0xBC, 0x59, 0x51, 0x22, 0x06, 0x00, 0x01, <result>, <crc1>, <crc2>]

  • type=0x22type & 0x03 = 2(应答帧),type >> 2 = 0x08(对应重启设备的 ACK)
  • len=0x01,payload=<result>
    • <result>=0x00:失败
    • <result>=0x01:成功

设置 Low Power(分帧示例)

发送分帧(十六进制):

  1. [0xBC, 0x59, 0x51, 0x38, 0x12, 0x00, 0x09, 0x00, 0x0F, 0x01, 0x01, 0x01, 0x02, 0x04, 0x00, 0x00, 0x17, 0x70, 0x2A, 0x8B]

  2. [0xBC, 0x59, 0x51, 0x38, 0x02, 0x00, 0x06, 0x00, 0x0F, 0x03, 0x04, 0x00, 0x01, 0x5F, 0x90, 0xDE, 0x99]

接收(ACK):[0xBC, 0x59, 0x51, 0x3A, 0x06, 0x00, 0x01, 0x00, 0x31, 0x53]

分片请求帧字段解析(以第 1 帧为例)

第 1 帧:[0xBC, 0x59, 0x51, 0x38, 0x12, 0x00, 0x09, 0x00, 0x0F, ...]

  • type=0x38 → 控制帧,type >> 2 = 0x0E(设置低功耗模式参数)
  • ctrl=0x12 → 有后续分片(0x10)+ 含 CRC(0x02
  • len=0x09
  • data_total=0x000F → 完整 data 总长度 15 字节

合帧(把 2 个分片的 data 拼接)

两个分片的 data(len) 依次为:

  • 分片 1:01 01 01 02 04 00 00 17 70
  • 分片 2:03 04 00 01 5F 90

合并后的完整 data(15 字节)为:

01 01 01 02 04 00 00 17 70 03 04 00 01 5F 90

合并后 data(TLV)解析

按“低功耗设置命令”TLV 约定:

  • 0x01 deep_sleep_enable (u8)
  • 0x02 deep_sleep_wake_sec (u32 BE)
  • 0x03 awake_keep_sec (u32 BE)
  1. 01 01 01
  • deep_sleep_enable=1
  1. 02 04 00 00 17 70
  • deep_sleep_wake_sec=0x00001770 → 6000 秒(约 100 分钟)
  1. 03 04 00 01 5F 90
  • awake_keep_sec=0x00015F90 → 90000 秒(25 小时)

响应帧(ACK)解析

接收:[0xBC, 0x59, 0x51, 0x3A, 0x06, 0x00, 0x01, 0x00, 0x31, 0x53]

  • type=0x3Atype & 0x03 = 2(应答帧),type >> 2 = 0x0E(对应设置低功耗模式参数的 ACK)
  • len=0x01,payload=0x00
    • 按文档约定:0=失败1=成功 → 本次设置结果为失败

查询 Low Power(获取低功耗模式参数)

发送(十六进制):[0xBC, 0x59, 0x51, 0x3C, 0x02, 0x00, 0x00, 0xDB, 0x7F]

接收(十六进制):[0xBC, 0x59, 0x51, 0x4D, 0x06, 0x00, 0x0F, 0x01, 0x01, 0x01, 0x02, 0x04, 0x00, 0x00, 0x17, 0x70, 0x03, 0x04, 0x00, 0x01, 0x5F, 0x90, 0x8D, 0x5A]

请求帧字段解析

请求帧:[0xBC, 0x59, 0x51, 0x3C, 0x02, 0x00, 0x00, 0xDB, 0x7F]

字段字节说明
header3BC 59 51固定帧头
type13Ctype & 0x03 = 0 → 控制帧;type >> 2 = 0x0F → SubType=0x0F(获取低功耗模式参数)
ctrl102包含 CRC(0x02
seq100序号(示例为 0)
len100数据长度为 0(本指令无 payload)
crc2DB 7FCRC16(从 header 到 data 末尾)

响应帧字段解析

响应帧:[0xBC, 0x59, 0x51, 0x4D, 0x06, 0x00, 0x0F, ... , 0x8D, 0x5A]

字段字节说明
header3BC 59 51固定帧头
type14Dtype & 0x03 = 1 → 数据帧;type >> 2 = 0x13 → SubType=0x13(低功耗设置数据)
ctrl1060x04 设备→手机 + 0x02 包含 CRC
seq100序号(示例为 0)
len10F数据长度 0x0F = 15 字节
datalen见下TLV 数据
crc28D 5ACRC16(从 header 到 data 末尾)

响应 data(TLV)解析

响应 data 共 15 字节,按“低功耗设置命令”TLV 约定解析如下:

  1. 01 01 01
  • deep_sleep_enable=1
  1. 02 04 00 00 17 70
  • deep_sleep_wake_sec=0x00001770 → 6000 秒(约 100 分钟)
  1. 03 04 00 01 5F 90
  • awake_keep_sec=0x00015F90 → 90000 秒(25 小时)

清除网络配置(清除WI-FI与MQTT配置)

发送(十六进制):[0xBC, 0x59, 0x51, 0x40, 0x02, 0x00, 0x00, 0xD6, 0x38]

接收(十六进制):[0xBC, 0x59, 0x51, 0x42, 0x06, 0x00, 0x01, 0x00, 0x2E, 0xF8]

请求帧字段解析

请求帧:[0xBC, 0x59, 0x51, 0x40, 0x02, 0x00, 0x00, 0xD6, 0x38]

字段字节说明
header3BC 59 51固定帧头
type140type & 0x03 = 0 → 控制帧;type >> 2 = 0x10 → SubType=0x10(清除WI-FI与MQTT配置)
ctrl102包含 CRC(0x02
seq100序号(示例为 0)
len100数据长度为 0(本指令无 payload)
crc2D6 38CRC16(从 header 到 data 末尾)

响应帧(ACK)解析

响应帧:[0xBC, 0x59, 0x51, 0x42, 0x06, 0x00, 0x01, 0x00, 0x2E, 0xF8]

字段字节说明
header3BC 59 51固定帧头
type142type & 0x03 = 2 → 应答帧;type >> 2 = 0x10 → SubType=0x10(清除WI-FI与MQTT配置的 ACK)
ctrl1060x04 设备→手机 + 0x02 包含 CRC
seq100序号(示例为 0)
len101数据长度 1 字节
payload100结果 0=失败,1=成功(本例为 0,失败)
crc22E F8CRC16(从 header 到 data 末尾)

说明:本例返回 0,表示清除失败。实际使用时 0x01 表示成功。

例子

提供了Flutter 的例子,代码风格人人有别。不喜勿喷。

gitee地址:https://gitee.com/buddycoder/u2mdemo