Skip to content

设备广播规范

本文档定义FDP配网设备的BLE广播格式规范。

设计约束

BLE广播支持32位和128位两种UUID格式:

  • 32位UUID:共4字节,本规范使用全部4字节
  • 128位UUID:共16字节,本规范使用前4字节(字节[0]~[3])

为同时兼容两种格式,可用于自定义数据的空间限制为4字节

比特结构

4字节共32位,采用小端序

位数取值范围字段名说明取值
[0]10~1configured配网状态0=未配网,1=已配网
[1]10~1sleeping休眠状态0=唤醒,1=休眠
[2]10~1预留保留开关0
[3]10~1预留保留开关0
[4:9]60~63device_type设备类型见设备类型表
[10]10~1预留保留开关0
[11]10~1预留保留开关0
[12:15]40~15vendor厂商标识见厂商标识表
[16:23]8-预留保留位0
[24:31]8-protocol_id协议标识0xFD(253)

设备类型

类型
0x00预留
0x01网关
0x02门锁
0x03~0x3F预留

厂商标识

厂商
0x0公版
0x1芯连
0x2鑫泓佳
0x3~0xF预留

配网状态

APP添加设备页面的设备列表中,只应显示configured=0(未配网)的设备。

休眠状态

部分低功耗设备(如门锁)在待机时单片机处于休眠状态,此时BLE芯片仍在广播但无法响应连接请求。

APP扫描到sleeping=1的设备时,应提示用户唤醒设备(如触摸门锁键盘),待广播中sleeping变为0后再发起连接。

示例解析

公版未配网网关(唤醒):

32位值: 0xFD000010
        ├─ [0]: 0 → 未配网
        ├─ [1]: 0 → 唤醒
        ├─ [2:3]: 0 → 预留
        ├─ [4:9]: 0x01 → 网关
        ├─ [10:11]: 0 → 预留
        ├─ [12:15]: 0x0 → 公版
        ├─ [16:23]: 0 → 预留
        └─ [24:31]: 0xFD → 协议标识

芯连已配网门锁(休眠):

32位值: 0xFD001023
        ├─ [0]: 1 → 已配网
        ├─ [1]: 1 → 休眠
        ├─ [2:3]: 0 → 预留
        ├─ [4:9]: 0x02 → 门锁
        ├─ [10:11]: 0 → 预留
        ├─ [12:15]: 0x1 → 芯连
        ├─ [16:23]: 0 → 预留
        └─ [24:31]: 0xFD → 协议标识

APP扫描过滤

APP扫描到的32位UUID格式为FDxxxxxx-0000-1000-8000-00805F9B34FB,取前8个字符即为广播数据的十六进制表示。

解析与过滤:将前8个字符转为32位整数后按位提取,通过protocolId判断是否为FDP设备。

javascript
function parseAdvertising(uuid) {
  const hex = uuid.substring(0, 8)
  const value = parseInt(hex, 16)

  return {
    configured: (value >> 0) & 0x1,
    sleeping: (value >> 1) & 0x1,
    deviceType: (value >> 4) & 0x3F,
    vendor: (value >> 12) & 0xF,
    protocolId: (value >> 24) & 0xFF
  }
}

function isFDPDevice(uuid) {
  return parseAdvertising(uuid).protocolId === 0xFD
}

设备端实现示例(C语言)

以下是ESP-IDF平台的广播实现示例:

c
#include <stdint.h>
#include <stdbool.h>

// 协议标识
#define FDP_PROTOCOL_ID  0xFD

// 设备类型
#define FDP_DEVICE_TYPE_GATEWAY  0x01
#define FDP_DEVICE_TYPE_LOCK     0x02

// 厂商标识
#define FDP_VENDOR_PUBLIC   0x0
#define FDP_VENDOR_XINLIAN  0x1
#define FDP_VENDOR_XHJ      0x2

// 广播数据结构
typedef struct {
    uint8_t configured : 1;   // [0] 配网状态
    uint8_t sleeping : 1;     // [1] 休眠状态
    uint8_t reserved1 : 2;    // [2:3] 预留
    uint8_t device_type : 6;  // [4:9] 设备类型
    uint8_t reserved2 : 2;    // [10:11] 预留
    uint8_t vendor : 4;       // [12:15] 厂商标识
    uint8_t reserved3;        // [16:23] 预留
    uint8_t protocol_id;      // [24:31] 协议标识
} __attribute__((packed)) fdp_adv_data_t;

// 构建32位广播UUID
uint32_t fdp_build_adv_uuid(uint8_t device_type, uint8_t vendor,
                             bool configured, bool sleeping) {
    fdp_adv_data_t adv = {
        .configured = configured ? 1 : 0,
        .sleeping = sleeping ? 1 : 0,
        .reserved1 = 0,
        .device_type = device_type,
        .reserved2 = 0,
        .vendor = vendor,
        .reserved3 = 0,
        .protocol_id = FDP_PROTOCOL_ID
    };
    return *(uint32_t*)&adv;
}

// 使用示例
void example_start_advertising(void) {
    // 公版未配网网关(唤醒状态)
    uint32_t uuid = fdp_build_adv_uuid(
        FDP_DEVICE_TYPE_GATEWAY,  // 设备类型
        FDP_VENDOR_PUBLIC,        // 厂商
        false,                    // 未配网
        false                     // 唤醒
    );
    // uuid = 0xFD000010

    // 将uuid转换为128位UUID格式用于广播
    // 格式: xxxxxxxx-0000-1000-8000-00805F9B34FB
    uint8_t uuid128[16] = {
        0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
        0x00, 0x10, 0x00, 0x00,
        (uuid >> 0) & 0xFF,   // 字节[12]
        (uuid >> 8) & 0xFF,   // 字节[13]
        (uuid >> 16) & 0xFF,  // 字节[14]
        (uuid >> 24) & 0xFF   // 字节[15]
    };

    // 调用BLE API设置广播数据...
}

物联网设备通信协议文档