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 都指向对方时,才算配对成功。

参数: