Files
vd_960/docs/DLD960_BLE协议.md
T
wangfq ef3316f2b3 docs(vd960DBN): BLE 日志查询交互过程文档 + 协议 V1.01 动态分包 + 周期心跳
- 新增 docs/DLD960_BLE日志查询交互.md: 0x25/0x26/0x27 完整交互示例
  (真实日志逐字节解析, 分包规则, 第二分包未发问题记录)
- DLD960_BLE协议.md V1.01: 分包上限改为随协商 MTU 动态 (min(MTU-9,94))
- peripheral.c: performPeriodicTask 加 500ms 心跳打印 (确认 TMOS 周期存活
  + resp 队列状态, 定位第二分包为何不续传)
2026-08-12 13:51:32 +08:00

6.9 KiB
Raw Blame History

DLD960 BLE 通信协议(脱机事件日志)

版本: V1.012026-08-12,分包上限改为随协商 MTU 动态) 适用: vd960DBNCH32V208WCH BLE 协议栈) 用途: 小程序/APP 经蓝牙读取设备本地 W25Q32 环形事件日志(离线取证:区分设备真复位 vs MQTT 断连重连)


1 帧格式

与既有 BLE 配置命令一致:

Magic  |     Header       |  Data  |   CheckByte
       | Addr/Sub Len CMD |        |    Xor  Sum
1 Byte |  1B    1B    1B  |   xx   |   1B   1B
  • Len = len(CMD) + len(Data)(即 pkg[2] = 1 + data_len
  • 校验:Xor = XOR(pkg[1..Len+2])Sum = SUM(pkg[1..Len+2]),覆盖 header + cmd + data(不含 magic
  • 本命令族 Magic = 0x8FMAGIC_BYTE_DBN_DEFAULT

分包(长响应)

响应单包数据上限随协商 MTU 动态变化V1.01,修复"Too large noti 丢包"):chunk = min(peripheralMTU - 9, 94)(整包 = 帧头4 + dat + ckb2,须 ≤ MTU-3 且 ≤ 本地缓冲 100B)。分包时 header 字节 = (pkg_amount << 4) | pkg_seqpkg_seq 从 1 递增;收端按 pkg_amount/pkg_seq 重组,最后一片 pkg_amount == pkg_seq

协商 MTU 单包最大 dat 整包最大长度
23(未协商) 14 20
96(常见 Android 87 93
185iOS 常见) 94 100

脱机日志 QUERY 响应最大 130BMTU=96 时 2 包(87+43 dat);MTU≥103 时 2 包(94+36 dat)。

分包发送由 performPeriodicTask(50ms TMOS 周期)主动续传,两包间隔 ≤50ms,不依赖收包事件(2026-08-12 修复)。


2 命令码

命令码 名称 方向 说明
0x25 OFFLOG_STAT APP→设备 查询脱机事件日志统计(分页定位)
0x26 OFFLOG_QUERY APP→设备 按全局序号分页拉取日志记录
0x27 OFFLOG_CLEAR APP→设备 清除日志(审计留痕)

与 MQTT V1.06 / TCP JSON V1.02 的 log_stat / log_query / log_clear 语义一致,通道不同。


3 查询日志统计 OFFLOG_STAT (0x25)

请求 data 无(Len=1,仅 cmd 字节)。

响应 data19B,全小端):

偏移 长度 字段 说明
0 1 status 0x00=OK0x01=日志未启用(Flash 初始化失败)
1 2 boot_seq 当前启动序号(每次上电 +1,区分复位段)
3 4 count 有效记录条数(0~8064,环形覆盖后 < capacity
7 4 capacity 容量上限(8064
11 4 seq_first 逻辑首条记录全局序号(seq_last - count + 1count=0 时为 0
15 4 seq_last 最新一条记录全局序号(跨 boot 单调递增)

示例(boot_seq=2, count=1234, capacity=8064, seq_first=100, seq_last=1333):

8F 00 14 25 00 02 00 D2 04 00 00 00 80 1F 00 00 00 64 00 00 00 35 05 00 00 00 XX XX
   -- -- -- -- -------------------- -------------------- -------------------- -----
   |  |  |  |  status           count=1234        capacity=8064      seq_first=100
   |  |  |  cmd=0x25            boot_seq=2                                              seq_last=1333

4 分页拉取日志 OFFLOG_QUERY (0x26)

请求 data5B):

偏移 长度 字段 说明
0 4 start_seq 起始全局序号(小端,含);越界(< seq_first 或 > seq_last)返回 0 条
4 1 count 拉取条数,上限 4,超限按 40 按 4 处理

响应 data

偏移 长度 字段 说明
0 1 status 0x00=OK0x01=日志未启用;0x02=请求帧过短
1 1 count 本次实际返回记录条数(0~4
2 N×32 记录 count 条 OfflogEvt 原始结构(小端,见 §6)

记录顺序 = 逻辑序号升序(与 start_seq 一致)。越界/空日志:count=0

请求示例(start_seq=1330, count=4):

8F 00 06 26 32 05 00 00 04 XX XX
   -- -- -- -- -- -- -- -- ---
   |  |  |  |  |  |  |  |  count=4
   |  |  |  |  +--+--+--+ start_seq=1330 (LE)
   |  |  |  cmd=0x26
   |  |  Len=5+1=6

5 清除日志 OFFLOG_CLEAR (0x27)

请求 data 无。

响应 data1B): status0x00=OK。

高风险操作:清除动作本身写入事件流(log_clear 审计——留痕不可清除)。设备侧应做权限控制(与 MQTT log_clear 同语义)。

阻塞 ~2.8s:63 个数据扇区 SPI 擦除(~45ms/扇区),期间主循环阻塞。若设备 IoT MQTT 在线,此期间 WCHNET 无法轮询,可能导致断连重连(60s keepalive 内可恢复)。请勿高频调用。

成功后 OFFLOG_STATcount 归 1(仅剩审计记录),seq_last 继续递增(序号不复位)。


6 记录格式(OfflogEvt32B 定长,小端)

偏移 长度 字段 说明
0 1 magic 0xA5
1 1 type 事件类型(下表)
2 1 len payload 有效字节数(0~12
3 1 flags bit0=1 → unix_ts 有效
4 4 seq 全局序号(跨 boot 递增)
8 4 ts_ms boot 内相对时间(ms,断电归零)
12 4 unix_ts 已同步 Unix 秒;flags.bit0=0 → 0/无效(未同步段仅相对时间)
16 2 boot_seq 所属启动段
18 2 rsvd 保留(0
20 12 payload 事件参数(下表)

事件类型与 payload

type 事件 payload 说明
0x01 boot [4] 复位原因寄存器原始值(大端),位解析:bit31=IWDG(看门狗) bit30=WWDG bit29=LPWR bit26=NRST引脚 bit25=POR(真断电) bit24=软件复位 上电/复位
0x10 iot_connect MQTT TCP 连接成功
0x11 iot_ready MQTT 订阅完成 → 发 initialize(重复上线直接证据)
0x12 iot_disconnect [1] reason1=断开 2=超时 3=CONNACK拒绝 4=连接超时 MQTT 断连
0x13 iot_reconn [4] 重连退避 ms(大端) 重连退避
0x30 evt_retry [5] msg_id(大端4) + retry(1) event_report ACK 超时重发
0x31 evt_giveup [4] msg_id(大端) event_report 重试耗尽挂起
0x40 coil [6] sub(1) + ch(1) + value(大端4, 50ms 单位) 线圈事件;sub1=car_enter 2=car_leave 3=loop_cut 4=loop_restore
0x50 time_anchor —(unix_ts 即平台下发值,严格一致) 时钟同步锚点
0x70 log_clear 日志清除(审计,不可清除)

payload 内多字节为大端(与 offlog 写入侧一致),OfflogEvt 其余字段为小端(CPU 原生序,直接 memcpy)。


7 版本历史

版本 日期 说明
V1.00 2026-08-10 脱机事件日志 3 命令:OFFLOG_STAT / OFFLOG_QUERY / OFFLOG_CLEAR