一、BLE 蓝牙地址的两种基本类型

在蓝牙低功耗(Bluetooth Low Energy, BLE)中,设备地址(Bluetooth Device Address, BD_ADDR)分为两大类别:

1. 公共地址(Public Device Address)

  • 定义:由 IEEE 分配给制造商的全球唯一地址,类似于以太网的 MAC 地址。
  • 特点
    • 48 位(6 字节)长度
    • 前 24 位为 Company ID(OUI, Organizationally Unique Identifier),由 IEEE 分配
    • 后 24 位由厂商自行分配,确保全球唯一性
    • 永不改变,烧录在硬件中
  • 标识特征:地址的最高两位(bit 47-46)为 00

2. 随机地址(Random Device Address)

  • 定义:设备动态生成的地址,非全球唯一,用于隐私保护。
  • 特点
    • 同样为 48 位长度
    • 最高两位(bit 47-46)为 0110 或 11,用于区分子类型
    • 可以周期性更换,防止被追踪
  • 子类型
    • 静态随机地址(Static Random Address)
    • 私有随机地址(Private Random Address)
      • 不可解析私有地址(Non-resolvable Private Address)
      • 可解析私有地址(Resolvable Private Address)

二、地址类型的详细标识规则

BLE 地址的 最高两位(bit 47-46) 是区分地址类型的关键标志位:

地址类型Bit 47Bit 46二进制前缀说明
公共地址0000...IEEE 分配的全球唯一地址
静态随机地址1111...上电时生成,生命周期内不变
不可解析私有地址0101...周期性更换,不可被解析
可解析私有地址1010...周期性更换,可被配对设备解析

注意:随机地址的其余 46 位不能全为 0 或全为 1,这是 BLE 规范的要求。


三、各地址类型详解

1. 公共地址(Public Device Address)

格式: [OUI (3 bytes)][Company Assigned (3 bytes)]
示例: 00:1A:7D:DA:71:13
      └──┬──┘ └────┬────┘
      Company ID   厂商分配
  • 优点:全球唯一,稳定可靠
  • 缺点:永久暴露设备身份,存在隐私风险
  • 应用场景:不需要隐私保护的场景,如固定 Beacon、公开设备

2. 静态随机地址(Static Random Address)

  • 生成时机:设备每次上电时生成,或首次使用时生成并存储在 Flash 中
  • 生命周期:直到设备重新上电或恢复出厂设置前保持不变
  • 用途:设备没有公共地址时的替代方案
  • 隐私性:中等,地址不随时间变化,但仍非全球唯一
格式: 11xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
      ↑↑
      固定前缀 11

3. 不可解析私有地址(Non-resolvable Private Address)

  • 生成方式:完全随机生成(除标志位外)
  • 更换周期:建议每 15 分钟更换一次
  • 特点
    • 连配对设备也无法识别其身份
    • 提供最高级别的隐私保护
  • 缺点:配对设备无法自动重连,需要用户手动选择
  • 应用场景:对隐私要求极高且不需要自动重连的场景
格式: 01xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
      ↑↑
      固定前缀 01

4. 可解析私有地址(Resolvable Private Address)

  • 生成方式:基于 Identity Resolving Key (IRK) 和随机数生成
  • 更换周期:建议每 15 分钟更换一次
  • 特点
    • 只有持有相同 IRK 的配对设备才能解析出真实身份
    • 兼顾隐私保护和自动重连能力
  • 解析原理
    • 地址包含 24 位哈希值和 24 位随机数
    • 配对设备使用 IRK 和随机数计算哈希,匹配则识别成功
  • 应用场景:大多数 BLE 设备(如手环、耳机)的默认选择
格式: 10xx xxxx xxxx xxxx xxxx xxxx | xxxx xxxx xxxx xxxx xxxx xxxx
      ↑↑                              └────┬────┘ └────┬────┘
      固定前缀 10                          哈希值(24b)  随机数(24b)

四、地址类型对连接的影响

1. 扫描与广播阶段

场景影响说明
广播地址类型决定扫描响应的处理方式扫描方需要根据地址类型决定是否尝试连接
可解析私有地址广播只有配对设备能识别未配对设备看到的是不断变化的随机地址
公共地址广播所有设备可见设备身份公开,容易被追踪

2. 连接建立阶段

地址类型组合连接可行性注意事项
公共 ↔ 公共✅ 完全支持最稳定的连接方式
公共 ↔ 随机✅ 完全支持需正确识别对方地址类型
随机 ↔ 随机✅ 完全支持静态随机地址需注意地址冲突(概率极低)
可解析私有 ↔ 可解析私有✅ 支持双方需已配对并交换 IRK
不可解析私有 ↔ 任意⚠️ 受限配对设备无法自动识别,需用户干预

3. 连接后的影响

特性公共地址静态随机可解析私有不可解析私有
自动重连✅ 支持✅ 支持✅ 支持(需 IRK)❌ 不支持
隐私保护❌ 无⚠️ 弱✅ 强✅ 最强
地址变化❌ 不变❌ 不变✅ 周期性变化✅ 周期性变化
配对要求需要配对需要配对
追踪难度极易较难困难极难

4. 实际开发中的注意事项

  1. 地址类型声明

    • 广播数据包中必须正确声明地址类型(TxAdd 字段)
    • 连接请求中必须正确指定目标地址类型
  2. 白名单(White List)过滤

    • 使用可解析私有地址时,控制器需要 IRK 才能正确过滤白名单
    • 白名单可以配置为只接受特定地址类型的设备
  3. 绑定(Bonding)与 IRK

    • 配对过程中交换 IRK 是支持可解析私有地址自动重连的前提
    • 如果 IRK 丢失,已配对设备将无法识别地址变化后的设备
  4. Android/iOS 差异

    • iOS:强制使用随机地址(通常是可解析私有地址),公共地址很少暴露
    • Android:较为灵活,但新版本也倾向于使用随机地址保护隐私
    • 这导致在开发跨平台应用时,必须正确处理地址类型
  5. 连接失败排查

    • 如果设备使用随机地址但连接请求中指定为公共地址,连接会失败
    • 如果 IRK 不匹配,可解析私有地址设备将无法被白名单接受

五、Python 示例:解析 BLE 地址类型

def parse_ble_address(address: str) -> dict:
    """
    解析 BLE 蓝牙地址类型

    Args:
        address: 蓝牙地址字符串,如 "A4:CF:12:34:56:78"

    Returns:
        包含地址类型信息的字典
    """
    # 清理地址字符串
    addr_clean = address.replace(':', '').replace('-', '').replace(' ', '')
    if len(addr_clean) != 12:
        raise ValueError("无效的蓝牙地址长度")

    # 获取第一个字节
    first_byte = int(addr_clean[:2], 16)

    # 提取最高两位
    bit47 = (first_byte >> 7) & 0x01
    bit46 = (first_byte >> 6) & 0x01

    # 判断地址类型
    if bit47 == 0 and bit46 == 0:
        addr_type = "公共地址 (Public Device Address)"
        subtype = "IEEE 全球唯一地址"
    elif bit47 == 1 and bit46 == 1:
        addr_type = "随机地址 (Random Device Address)"
        subtype = "静态随机地址 (Static Random Address)"
    elif bit47 == 0 and bit46 == 1:
        addr_type = "随机地址 (Random Device Address)"
        subtype = "不可解析私有地址 (Non-resolvable Private Address)"
    elif bit47 == 1 and bit46 == 0:
        addr_type = "随机地址 (Random Device Address)"
        subtype = "可解析私有地址 (Resolvable Private Address)"
    else:
        addr_type = "未知"
        subtype = "未知"

    return {
        "address": address,
        "first_byte": f"0x{addr_clean[:2].upper()}",
        "bit47": bit47,
        "bit46": bit46,
        "address_type": addr_type,
        "subtype": subtype,
        "oui": addr_clean[:6].upper() if bit47 == 0 and bit46 == 0 else None,
        "is_random": not (bit47 == 0 and bit46 == 0)
    }


# 示例测试
if __name__ == "__main__":
    test_addresses = [
        "00:1A:7D:DA:71:13",  # 公共地址 (00)
        "F4:CF:A2:34:56:78",  # 静态随机地址 (11)
        "5E:CF:A2:34:56:78",  # 不可解析私有地址 (01)
        "A4:CF:A2:34:56:78",  # 可解析私有地址 (10)
    ]

    for addr in test_addresses:
        result = parse_ble_address(addr)
        print(f"\n地址: {result['address']}")
        print(f"  首字节: {result['first_byte']} (Bit47={result['bit47']}, Bit46={result['bit46']})")
        print(f"  类型: {result['address_type']}")
        print(f"  子类型: {result['subtype']}")
        if result['oui']:
            print(f"  OUI: {result['oui']}")

六、总结

核心要点说明
地址长度所有 BLE 地址均为 48 位(6 字节)
类型标识最高两位(bit 47-46)决定地址类型
隐私优先级不可解析私有 > 可解析私有 > 静态随机 > 公共
自动重连只有公共、静态随机、可解析私有地址支持
开发注意必须正确声明和识别地址类型,否则连接失败

BLE 的地址类型设计在 设备识别隐私保护 之间取得了平衡。理解这些地址类型及其标识规则,对于开发稳定的 BLE 应用和排查连接问题至关重要。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐