Skip to content

引入

ts
import {
  BluetoothBumpDeps,
  BluetoothDeviceInfo,
  BluetoothBumpError,
  BluetoothBumpPayload,
  BluetoothBumpOptions,
  ShouldTriggerBumpParams,
  PeerRecord,
  WxBluetoothAdapter,
  DEFAULT_SERVICE_UUID,
  DEFAULT_CHARACTERISTIC_UUID,
  DEFAULT_RSSI_THRESHOLD,
  DEFAULT_COOLDOWN_MS,
  DEFAULT_LINGER_BEFORE_STOP_MS,
  DEFAULT_POLL_INTERVAL_MS,
  DEFAULT_PRIVACY_CONTENT,
  DEFAULT_PEER_TTL_MS,
  DEFAULT_ADVERTISE_UPDATE_THROTTLE_MS,
  EMPTY_PEER_ID,
  PAYLOAD_SEPARATOR,
  TEMP_ID_LENGTH,
  BUMP_NAME_PREFIX,
  genTempId,
  str2ArrayBuffer,
  arrayBuffer2Hex,
  reverseHexBytes,
  matchesService,
  shouldTriggerBump,
  encodePayload,
  encodeBumpName,
  parseBumpName,
  parsePayloadString,
  parsePayload,
  pickBestPeer,
  pruneExpiredPeers,
  arrayBufferToUtf8,
  padOrTrim,
  BluetoothBumpMode
} from 't-comm';

// 不支持 tree-shaking 的项目
import {
  BluetoothBumpDeps,
  BluetoothDeviceInfo,
  BluetoothBumpError,
  BluetoothBumpPayload,
  BluetoothBumpOptions,
  ShouldTriggerBumpParams,
  PeerRecord,
  WxBluetoothAdapter,
  DEFAULT_SERVICE_UUID,
  DEFAULT_CHARACTERISTIC_UUID,
  DEFAULT_RSSI_THRESHOLD,
  DEFAULT_COOLDOWN_MS,
  DEFAULT_LINGER_BEFORE_STOP_MS,
  DEFAULT_POLL_INTERVAL_MS,
  DEFAULT_PRIVACY_CONTENT,
  DEFAULT_PEER_TTL_MS,
  DEFAULT_ADVERTISE_UPDATE_THROTTLE_MS,
  EMPTY_PEER_ID,
  PAYLOAD_SEPARATOR,
  TEMP_ID_LENGTH,
  BUMP_NAME_PREFIX,
  genTempId,
  str2ArrayBuffer,
  arrayBuffer2Hex,
  reverseHexBytes,
  matchesService,
  shouldTriggerBump,
  encodePayload,
  encodeBumpName,
  parseBumpName,
  parsePayloadString,
  parsePayload,
  pickBestPeer,
  pruneExpiredPeers,
  arrayBufferToUtf8,
  padOrTrim,
  BluetoothBumpMode
} from 't-comm/lib/bluetooth-bump/index';

// 只支持 ESM 的项目
import {
  BluetoothBumpDeps,
  BluetoothDeviceInfo,
  BluetoothBumpError,
  BluetoothBumpPayload,
  BluetoothBumpOptions,
  ShouldTriggerBumpParams,
  PeerRecord,
  WxBluetoothAdapter,
  DEFAULT_SERVICE_UUID,
  DEFAULT_CHARACTERISTIC_UUID,
  DEFAULT_RSSI_THRESHOLD,
  DEFAULT_COOLDOWN_MS,
  DEFAULT_LINGER_BEFORE_STOP_MS,
  DEFAULT_POLL_INTERVAL_MS,
  DEFAULT_PRIVACY_CONTENT,
  DEFAULT_PEER_TTL_MS,
  DEFAULT_ADVERTISE_UPDATE_THROTTLE_MS,
  EMPTY_PEER_ID,
  PAYLOAD_SEPARATOR,
  TEMP_ID_LENGTH,
  BUMP_NAME_PREFIX,
  genTempId,
  str2ArrayBuffer,
  arrayBuffer2Hex,
  reverseHexBytes,
  matchesService,
  shouldTriggerBump,
  encodePayload,
  encodeBumpName,
  parseBumpName,
  parsePayloadString,
  parsePayload,
  pickBestPeer,
  pruneExpiredPeers,
  arrayBufferToUtf8,
  padOrTrim,
  BluetoothBumpMode
} from 't-comm/es/bluetooth-bump/index';

BluetoothBumpDeps

描述:主类的额外依赖(用于测试时注入假时钟、假 timer、假 adapter)

参数

BluetoothDeviceInfo

描述:蓝牙"碰一碰"对外类型定义

参数

BluetoothBumpError

描述:启动失败时通过 onError 抛出的错误信息

参数

BluetoothBumpPayload

描述:广播载荷(mutual 模式):固定长度 13 字节,myTempId|seenPeerId

参数

bluetoothBumpPayload.myTempId : string

发送端自己的临时 ID(6 位大写)

Kind: instance property of BluetoothBumpPayload

bluetoothBumpPayload.seenPeerId : string

发送端当前"看到的对方 ID",未看到时为 '------'

Kind: instance property of BluetoothBumpPayload

BluetoothBumpOptions

描述:BluetoothBump 构造选项

参数

bluetoothBumpOptions.serviceUuid : string

服务 UUID,两端必须一致

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.characteristicUuid : string

特征 UUID(仅外围模式使用)

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.rssiThreshold : number

RSSI 阈值,超过此值视为"碰到了"

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.cooldownMs : number

同一设备的去重冷却时间

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.lingerBeforeStopMs : number

成功触发后保持广播的时长(让对方也能扫到自己)

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.pollIntervalMs : number

iOS 兜底轮询间隔

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.privacyContent : string

隐私协议弹窗内容(不传用默认文案)

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.mode : BluetoothBumpMode

匹配模式,默认 'simple'(保持向后兼容)。 选 'mutual' 开启前端自撮合(双向互认后才触发 onBump)。

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.peerTtlMs : number

mutual 模式:候选 peer 信息的有效期(毫秒),过期则从候选池移除

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.advertiseUpdateThrottleMs : number

mutual 模式:更新自己广播里 seenPeerId 的最小间隔(毫秒),防抖

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.onBump : function

业务回调:碰到对方时触发

  • peerDeviceId:扫描层的设备地址(iOS 是本机视角的 UUID,Android 是 MAC)。 ⚠️ 这个值是"扫描者本地"视角的,A 拿到的对方 deviceId 与 B 自己的 deviceId 不一定相同, 不能用它跟对方的 myTempId 直接对比。
  • peerTempId:对方写在广播 payload 里的 myTempId(6 位字符串)。 这个值是"对方应用层产生的",A 看到的 peerTempId 与 B 的 myTempId 一定一致, 适合两台手机做配对核对("我方 ID" vs "对方 ID")。 若对方广播解析失败则为空字符串。

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.onError : function

业务回调:启动失败时触发

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.onLog : function

业务回调:日志/状态变化(用于打日志或 UI 更新)

Kind: instance property of BluetoothBumpOptions
Optional:

bluetoothBumpOptions.onDeviceFound : function

业务回调:每次扫到设备(不论是否碰到)时触发,用于调试/UI 展示

Kind: instance property of BluetoothBumpOptions
Optional:

ShouldTriggerBumpParams

描述:触发碰一碰的判定参数(纯函数 shouldTriggerBump 使用)

参数

PeerRecord

描述:候选 peer 的内存记录

参数

peerRecord.seenPeerId : string

对方广播里携带的"它看到的对方 ID"(用于判断是否是双向互认)

Kind: instance property of PeerRecord

peerRecord.lastSeen : number

最近一次见到的时间戳

Kind: instance property of PeerRecord

peerRecord.dev : BluetoothDeviceInfo

对应的原始设备,便于回传给业务方

Kind: instance property of PeerRecord

WxBluetoothAdapter

描述:微信蓝牙能力适配器接口(用于依赖注入,便于测试)

参数

wxBluetoothAdapter.isAvailable : boolean

当前环境是否具备最低限度的蓝牙 API

Kind: instance property of WxBluetoothAdapter

wxBluetoothAdapter.detectPlatform : string

检测平台(ios / android / devtools / unknown ...)

Kind: instance property of WxBluetoothAdapter

wxBluetoothAdapter.ensurePrivacyAuthorized : Promise.<void>

触发隐私授权弹窗并等待用户同意(不支持时直接 resolve)

Kind: instance property of WxBluetoothAdapter

wxBluetoothAdapter.openAdapter : Promise.<OpenAdapterResult>

打开蓝牙适配器;iOS 上分别打开 central + peripheral,并返回是否需跳过广播

Kind: instance property of WxBluetoothAdapter

wxBluetoothAdapter.startAdvertising : Promise.<object>

创建外围设备并开始广播

Kind: instance property of WxBluetoothAdapter

wxBluetoothAdapter.updateAdvertisedValue : Promise.<void>

更新正在广播的 payload(mutual 模式用)。 实现:stopAdvertising → 重新 addService(新 value)→ startAdvertising。 失败时 reject,调用方需要自己决定是否回退。

Kind: instance property of WxBluetoothAdapter

wxBluetoothAdapter.startDiscovery : Promise.<void>

开始扫描:iOS 不传 services(系统重新包装广播包后会扫不到)

Kind: instance property of WxBluetoothAdapter

wxBluetoothAdapter.onDeviceFound : void

注册扫描回调

Kind: instance property of WxBluetoothAdapter

wxBluetoothAdapter.onAdapterStateChange : void

注册适配器状态变化回调

Kind: instance property of WxBluetoothAdapter

wxBluetoothAdapter.getDevices : Promise.<object>

iOS 兜底轮询用

Kind: instance property of WxBluetoothAdapter

wxBluetoothAdapter.stopDiscovery : void

停止扫描 / 停止广播 / 关闭适配器(任一失败都安全吞掉)

Kind: instance property of WxBluetoothAdapter

DEFAULT_SERVICE_UUID

描述:自定义服务 UUID(两端必须一致,作为"同一个小游戏"的识别标记)

参数

DEFAULT_CHARACTERISTIC_UUID

描述:自定义特征 UUID(创建外围设备时需要)

参数

DEFAULT_RSSI_THRESHOLD

描述:触发"碰一碰"的 RSSI 阈值(dBm),越接近 0 表示距离越近

参数

DEFAULT_COOLDOWN_MS

描述:同一台设备多次触发的去重时间(毫秒)

参数

DEFAULT_LINGER_BEFORE_STOP_MS

描述:触发成功后保持广播的时长(毫秒),让对方也能扫到自己

参数

DEFAULT_POLL_INTERVAL_MS

描述:iOS 兜底轮询间隔(毫秒)

参数

DEFAULT_PRIVACY_CONTENT

描述:默认隐私协议弹窗内容

参数

DEFAULT_PEER_TTL_MS

描述:mutual 模式:候选 peer 的 TTL(毫秒),超过未再见即从候选池移除

参数

DEFAULT_ADVERTISE_UPDATE_THROTTLE_MS

描述:mutual 模式:更新自己广播里 seenPeerId 的最小间隔(毫秒)

参数

EMPTY_PEER_ID

描述:mutual 模式:广播 payload 占位符(未看到对方时)

参数

PAYLOAD_SEPARATOR

描述:mutual 模式:广播 payload 分隔符

参数

TEMP_ID_LENGTH

描述:临时 ID 长度(genTempId 生成 6 位)

参数

BUMP_NAME_PREFIX

描述:广播设备名前缀(iOS Peripheral 唯一能下发的自定义字段就是 localName) 完整格式: BUMP_<myTempId>BUMP_<myTempId>_<seenPeerId> 原理:iOS CoreBluetooth 不允许 Peripheral 在广播包里塞 ServiceData, 只允许 localName + serviceUUIDs。所以 iOS↔iOS 必须靠 localName 传 myTempId。 Android 同样支持 localName,所以这套方案跨平台一致。

参数

genTempId()

描述:生成 6 位随机大写临时 ID(写到广播特征值里)

参数

str2ArrayBuffer()

描述:把字符串编码为 ArrayBuffer,用于写入特征值

参数

arrayBuffer2Hex()

描述:ArrayBuffer 转十六进制大写字符串

参数

reverseHexBytes()

描述:反转十六进制字符串的字节序(小端 ↔ 大端)

参数

matchesService()

描述:判断扫到的设备是否携带我们的 service iOS 上 startBluetoothDevicesDiscovery 不传 services 时收到的设备都需要手动过滤。 依次检查:advertisServiceUUIDs / serviceData / advertisData / 设备名前缀(BUMP_)。 ⚠️ iOS↔iOS 时前 3 项几乎都拿不到,必须靠设备名前缀做最终兜底。

参数

shouldTriggerBump()

描述:判断这次扫描结果是否应该触发"碰一碰" 条件:

    - RSSI 不低于阈值(够近) - 距离上次同设备触发已超过冷却时间(避免重复)
抽成纯函数后,边界条件可以一行测一个。

参数

encodePayload()

描述:把 myTempId / seenPeerId 组装为广播 payload 字符串。 固定长度,便于解析:${myTempId}|${seenPeerId} → 13 字节。

  • myTempId 如果不足 TEMP_ID_LENGTH 位会自动补 '-'(防御性处理)
  • seenPeerId 为空时填占位符 '------'

参数

encodeBumpName()

描述:把 payload 编码进设备名(iOS Peripheral 唯一可控的广播字段)。 BUMP_<myTempId>_<seenPeerId> → 例 BUMP_ABC123_------(19 字符) 不少机型对 localName 长度有限制(iOS Peripheral 推荐 ≤ 28 字节),这里 19 字符够用。

参数

parseBumpName()

描述:解析设备名形如 BUMP_ABC123_XYZ789 → { myTempId, seenPeerId }。 仅需 myTempId 时(旧格式 BUMP_ABC123)也兼容,seenPeerId 返回空串。

参数

parsePayloadString()

描述:解析广播 payload 字符串 → { myTempId, seenPeerId } 解析失败返回 null(payload 不是本协议)。 seenPeerId 为占位符 '------' 时返回空字符串,方便上层 if (seenPeerId) 判断。

参数

parsePayload()

描述:从扫描到的设备里提取 mutual 协议 payload。 解析顺序(按"iOS 上能拿到的可能性"由高到低):

    - 设备名 / localName 前缀 `BUMP_` —— iOS↔iOS 唯一可靠通道 - serviceData[serviceUuid] —— Android 标准方案 - advertisData 整段 —— 部分机型把 payload 塞这里 - 设备名按旧格式 `myTempId|seenPeerId` 解析(向后兼容)

参数

pickBestPeer()

描述:从候选池里挑选"信号最强且在 TTL 内"的 peer(用于决定广播里要"点名"谁)

参数

pruneExpiredPeers()

描述:清理候选池里过期的 peer(就地修改)

参数

arrayBufferToUtf8()

描述:ArrayBuffer 转 UTF-8 字符串(失败返回空字符串)

参数

padOrTrim()

描述:定长裁剪/补齐(补 '-')

参数

BluetoothBumpMode

描述:匹配模式:

  • 'simple' :默认行为。扫到对方且 RSSI 达标即触发(单向发现,简单快速)。
  • 'mutual' :前端自撮合。双向互认后才触发: 我广播里带"我看到的对方 ID",对方广播里也带"它看到的对方 ID"; 当双方广播里携带的 peerId 都指向对方时,才算配对成功。

参数