Baji_Rtc_Toy/BLE_JSON_通讯模块开发计划.md

14 KiB
Raw Permalink Blame History

BLE JSON 通讯模块开发计划

新增功能,保留原有 BluFi 配网等全部功能不变。


一、功能定位

在现有 BluFi 蓝牙配网基础上,新增一个自定义 BLE GATT Service使用 JSON 格式进行设备与 App 之间的双向通讯。

  • BluFi 配网模块(bluetooth_provisioning.*完全保留,不做任何修改
  • 新 BLE JSON 通讯模块(ble_service.*):独立注册 GATTS App与 BluFi 共存

共存原理

Bluedroid GATTS 栈(已配置 max_profiles=8
  ├── App 0: BluFi Service (UUID: 0xFFFF)    ← 已有,不动
  └── App 1: JSON Service  (UUID: 0xAB00)    ← 新增

两个 App 独立回调、独立 handle共享同一个 Bluedroid 栈和 BLE 连接。


二、底层传输参数约束

参数 说明
默认 MTU 23 bytes BLE 标准默认值
协商目标 MTU 512 bytes esp_ble_gatt_set_local_mtu(512)
ATT 协议头开销 3 bytes 固定开销
单包最大有效载荷 509 bytes 512 - 3
广播包最大长度 31 + 31 bytes ADV + SCAN RSP
BLE 协议版本 4.2 BLE 5.0 已关闭BluFi 兼容)
最大连接数 4 (CONFIG_BT_ACL_CONNECTIONS) 当前 BluFi 占 1

三、GATT Service 设计

Custom JSON Communication Service
│
├── Service UUID: 0xAB00 (Primary Service)
│
├── Characteristic 1: JSON_WRITE (App → 设备)
│   ├── UUID:        0xAB01
│   ├── Properties:  WRITE
│   ├── Permissions: ESP_GATT_PERM_WRITE
│   └── Max Value:   512 bytes
│
├── Characteristic 2: JSON_NOTIFY (设备 → App)
│   ├── UUID:        0xAB02
│   ├── Properties:  NOTIFY | READ
│   ├── Permissions: ESP_GATT_PERM_READ
│   ├── Max Value:   512 bytes
│   └── Descriptor:  CCCD (0x2902, 2 bytes, 用于开启/关闭 NOTIFY)
│
└── Characteristic 3: JSON_STATUS (设备状态被动读取,可选)
    ├── UUID:        0xAB03
    ├── Properties:  READ
    ├── Permissions: ESP_GATT_PERM_READ
    └── Max Value:   512 bytes

四、JSON 消息格式

4.1 公共格式

请求App → 设备):

{"cmd":"xxx","id":1,"data":{...}}

响应(设备 → App

{"cmd":"xxx","id":1,"code":0,"data":{...}}

主动推送(设备 → App无 id

{"cmd":"event","data":{"type":"xxx",...}}

4.2 固定开销

字段 占用 说明
{"cmd":""} 10 bytes 命令名空壳
,"id":1 7 bytes 消息 ID1~999
,"data":{} 10 bytes 数据域空壳
,"code":0 9 bytes 响应码(仅响应)
请求固定开销 ~27 bytes 留给 data 约 482 bytes
响应固定开销 ~36 bytes 留给 data 约 473 bytes

五、逐条命令参数与大小计算

5.1 set_wifi — WiFi 配置

方向: App → 设备

请求:

{"cmd":"set_wifi","id":1,"data":{"ssid":"MyHomeWiFi_5G","pass":"myP@ssw0rd123"}}
字段 类型 最大长度 来源
ssid string 32 bytes IEEE 802.11 标准
pass string 64 bytes WPA2 标准

最大请求大小: 55(框架) + 32(ssid) + 64(pass) = 151 bytes → 单包

响应:

{"cmd":"set_wifi","id":1,"code":0,"data":{"status":"connecting"}}

大小: ~60 bytes → 单包


5.2 wifi_list — 获取 WiFi 列表

方向: App → 设备

请求:

{"cmd":"wifi_list","id":2}

大小: 24 bytes → 单包

响应:

{"cmd":"wifi_list","id":2,"code":0,"data":{"list":[{"s":"MyWiFi","r":-40},{"s":"Office","r":-55}]}}
字段 类型 最大长度 说明
s string 32 bytes SSID 名称
r number 4 bytes RSSI 值 (-100~0)

单条记录最大: ~46 bytesSSID 32字符时

容量计算(可用空间 = 509 - 58 = 451 bytes

场景 每条大小 单包可容纳
典型SSID ~10字符 ~25 bytes ~17 条
最坏SSID 32字符 ~46 bytes ~9 条
设计限制 最多返回 8 条

最大响应大小: 58(框架) + 8 × 46 = 426 bytes → 单包


5.3 dev_info — 获取设备信息

方向: App → 设备

请求:

{"cmd":"dev_info","id":3}

大小: 23 bytes → 单包

响应:

{"cmd":"dev_info","id":3,"code":0,"data":{"model":"Kapi_Rtc","fw":"1.0.0","mac":"AA:BB:CC:DD:EE:FF","board":"movecall-moji-esp32s3","uuid":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}}
字段 类型 最大长度 说明
model string 20 bytes 产品型号
fw string 12 bytes 固件版本 x.x.x
mac string 17 bytes MAC 地址 AA:BB:CC:DD:EE:FF
board string 30 bytes 板型名称
uuid string 36 bytes 设备 UUID

最大响应大小: ~180 bytes → 单包


5.4 status — 获取设备运行状态

方向: App → 设备

请求:

{"cmd":"status","id":4}

大小: 21 bytes → 单包

响应:

{"cmd":"status","id":4,"code":0,"data":{"state":"idle","bat":85,"chg":false,"rssi":-45,"vol":70}}
字段 类型 最大长度 说明
state string 11 bytes 设备状态(见状态枚举表)
bat number 3 bytes 电池电量 0~100
chg boolean 5 bytes 是否充电中
rssi number 4 bytes WiFi 信号 -100~0
vol number 3 bytes 音量 0~100

设备状态枚举对照:

DeviceState 枚举 JSON 值 字节数
kDeviceStateUnknown "unknown" 7
kDeviceStateStarting "starting" 8
kDeviceStateWifiConfiguring "wifi_config" 11
kDeviceStateIdle "idle" 4
kDeviceStateConnecting "connecting" 10
kDeviceStateListening "listening" 9
kDeviceStateSpeaking "speaking" 8
kDeviceStateDialog "dialog" 6
kDeviceStateUpgrading "upgrading" 9
kDeviceStateActivating "activating" 10
kDeviceStateFatalError "error" 5

最大响应大小: ~105 bytes → 单包


5.5 set_vol — 设置音量

方向: App → 设备

请求:

{"cmd":"set_vol","id":5,"data":{"vol":80}}
字段 类型 范围 说明
vol number 0~100 音量百分比

最大请求大小: 37 bytes → 单包

响应:

{"cmd":"set_vol","id":5,"code":0}

大小: 30 bytes → 单包


5.6 iot — 控制 IoT 设备属性

方向: App → 设备

请求:

{"cmd":"iot","id":6,"data":{"thing":"lamp","prop":"brightness","val":50}}
字段 类型 最大长度 说明
thing string 20 bytes IoT 设备名 (speaker/lamp/screen 等)
prop string 20 bytes 属性名
val number/string/bool 20 bytes 属性值

最大请求大小: ~95 bytes → 单包

响应:

{"cmd":"iot","id":6,"code":0}

大小: 27 bytes → 单包


5.7 reboot — 重启设备

方向: App → 设备

请求:

{"cmd":"reboot","id":7}

大小: 22 bytes → 单包

响应:

{"cmd":"reboot","id":7,"code":0}

大小: 29 bytes → 单包


5.8 ota — 检查固件更新

方向: App → 设备

请求:

{"cmd":"ota","id":8}

大小: 19 bytes → 单包

响应:

{"cmd":"ota","id":8,"code":0,"data":{"cur":"1.0.0","new":"1.1.0","has_update":true}}
字段 类型 最大长度 说明
cur string 12 bytes 当前版本
new string 12 bytes 最新版本
has_update boolean 5 bytes 是否有更新

最大响应大小: ~78 bytes → 单包


5.9 ping — 心跳保活

方向: 双向

请求:

{"cmd":"ping","id":9}

大小: 20 bytes → 单包

响应:

{"cmd":"ping","id":9,"code":0}

大小: 28 bytes → 单包


5.10 event — 设备主动推送

方向: 设备 → App通过 NOTIFY无 id

WiFi 连接成功:

{"cmd":"event","data":{"type":"wifi_connected","ssid":"Home","ip":"192.168.1.100","rssi":-40}}

最大大小: ~125 bytes → 单包

WiFi 断开:

{"cmd":"event","data":{"type":"wifi_disconnected","reason":201}}

大小: ~58 bytes → 单包

电池低电量:

{"cmd":"event","data":{"type":"low_battery","bat":10}}

大小: ~51 bytes → 单包

设备状态变化:

{"cmd":"event","data":{"type":"state_changed","state":"listening"}}

大小: ~62 bytes → 单包


六、总览表

# 命令 方向 请求最大 响应最大 单包?
1 set_wifi App→设备 151 B 60 B
2 wifi_list App→设备 24 B 426 B (限8条)
3 dev_info App→设备 23 B 180 B
4 status App→设备 21 B 105 B
5 set_vol App→设备 37 B 30 B
6 iot App→设备 95 B 27 B
7 reboot App→设备 22 B 29 B
8 ota App→设备 19 B 78 B
9 ping 双向 20 B 28 B
10 event 设备→App ≤125 B

结论MTU=512 时,所有命令均可单包传输,不需要分包机制。


七、错误码定义

code 含义 示例场景
0 成功 所有正常响应
1 参数错误 JSON 格式错误 / 缺少必要字段
2 命令不支持 未知的 cmd
3 设备忙 正在 OTA / 正在配网
4 WiFi 连接失败 SSID 不存在 / 密码错误
5 超时 操作超时
6 内部错误 设备内部异常

错误响应示例:

{"cmd":"set_wifi","id":1,"code":4,"msg":"wrong password"}

八、通讯时序示例

场景App 配置 WiFi

App                                          设备
 │                                            │
 │──── BLE Connect ──────────────────────────>│
 │<─── MTU Exchange (512) ───────────────────>│
 │──── Enable NOTIFY (write CCCD=0x0001) ───>│
 │                                            │
 │──── WRITE: {"cmd":"status","id":1}        │
 │<─── NOTIFY: {"cmd":"status","id":1,       │
 │       "code":0,"data":{"state":"idle",    │
 │       "bat":85,"chg":false,"rssi":0,      │
 │       "vol":70}}                           │
 │                                            │
 │──── WRITE: {"cmd":"wifi_list","id":2}     │
 │                                   [设备扫描WiFi]
 │<─── NOTIFY: {"cmd":"wifi_list","id":2,    │
 │       "code":0,"data":{"list":[           │
 │       {"s":"Home","r":-40},               │
 │       {"s":"Office","r":-55}]}}           │
 │                                            │
 │──── WRITE: {"cmd":"set_wifi","id":3,      │
 │       "data":{"ssid":"Home",              │
 │       "pass":"123456"}}                   │
 │<─── NOTIFY: {"cmd":"set_wifi","id":3,     │
 │       "code":0,"data":{                   │
 │       "status":"connecting"}}             │
 │                                   [设备连接WiFi]
 │<─── NOTIFY: {"cmd":"event","data":        │
 │       {"type":"wifi_connected",           │
 │       "ssid":"Home",                      │
 │       "ip":"192.168.1.100","rssi":-40}}   │
 │                                            │

九、实现文件清单

文件 动作 说明
main/ble_service.h 新增 BleJsonService 类定义
main/ble_service.cc 新增 GATT Server 实现 + JSON 收发
main/ble_service_config.h 新增 UUID / MTU / 超时等配置宏
main/application.cc 修改 集成 BleJsonService注册命令处理回调
main/application.h 修改 添加 BleJsonService 成员指针
main/CMakeLists.txt 修改 添加 ble_service.cc 到编译列表
sdkconfig.defaults 可能修改 若需调整 GATT profile 数量
bluetooth_provisioning.* 不动 BluFi 配网保持原样
bluetooth_provisioning_config.h 不动 BluFi 配置保持原样

十、备用分包协议(当前不需要实现)

若未来某条消息超过 509 字节,可启用以下分包协议:

分包头 (2 bytes):
  Byte 0: [7:4] 总包数(1~15), [3:0] 当前包号(0~14)
  Byte 1: 0x00=中间包, 0x01=最后一包
  Byte 2~N: JSON 片段

单包判断: 首字节为 '{' (0x7B) → 完整 JSON无分包头
          首字节非 '{' → 分包数据,需重组

当前设计下 WiFi 列表限制 8 条,所有消息均 ≤509 字节,无需实现分包


十一、依赖与约束

  • JSON 库: cJSON项目已有无需引入新依赖
  • BLE 栈: Bluedroid已启用与 BluFi 共用)
  • GATT 资源: max_profiles=8BluFi 占 1新模块占 1富余 6 个)
  • 内存: 8MB PSRAM + 320KB DRAMJSON 解析开销可忽略)
  • 输出格式: 使用 cJSON_PrintUnformatted() 紧凑输出,无空格无换行
  • BLE 回调线程安全: GATTS 回调中不直接解析 JSON通过 FreeRTOS 队列转发到应用任务处理