t-comm
Version:
专业、稳定、纯粹的工具库
87 lines (86 loc) • 4.35 kB
TypeScript
/**
* 蓝牙"碰一碰"纯函数工具集
*
* 这里的所有函数都是 *无副作用* 的纯函数,不依赖 wx / 全局状态,
* 因此可以脱离微信小程序环境直接 jest 单测。
*/
import type { BluetoothBumpPayload, BluetoothDeviceInfo, ShouldTriggerBumpParams } from './types';
/** 生成 6 位随机大写临时 ID(写到广播特征值里) */
export declare function genTempId(): string;
/** 把字符串编码为 ArrayBuffer,用于写入特征值 */
export declare function str2ArrayBuffer(str: string): ArrayBuffer;
/** ArrayBuffer 转十六进制大写字符串 */
export declare function arrayBuffer2Hex(buf: ArrayBuffer | undefined | null): string;
/** 反转十六进制字符串的字节序(小端 ↔ 大端) */
export declare function reverseHexBytes(hex: string): string;
/**
* 判断扫到的设备是否携带我们的 service
*
* iOS 上 startBluetoothDevicesDiscovery 不传 services 时收到的设备都需要手动过滤。
* 依次检查:advertisServiceUUIDs / serviceData / advertisData / 设备名前缀(BUMP_)。
*
* ⚠️ iOS↔iOS 时前 3 项几乎都拿不到,必须靠设备名前缀做最终兜底。
*/
export declare function matchesService(dev: BluetoothDeviceInfo, serviceUuid: string): boolean;
/**
* 判断这次扫描结果是否应该触发"碰一碰"
*
* 条件:
* 1. RSSI 不低于阈值(够近)
* 2. 距离上次同设备触发已超过冷却时间(避免重复)
*
* 抽成纯函数后,边界条件可以一行测一个。
*/
export declare function shouldTriggerBump(params: ShouldTriggerBumpParams): boolean;
/**
* 把 myTempId / seenPeerId 组装为广播 payload 字符串。
* 固定长度,便于解析:`${myTempId}|${seenPeerId}` → 13 字节。
*
* - myTempId 如果不足 TEMP_ID_LENGTH 位会自动补 '-'(防御性处理)
* - seenPeerId 为空时填占位符 '------'
*/
export declare function encodePayload(myTempId: string, seenPeerId?: string | null): string;
/**
* 把 payload 编码进设备名(iOS Peripheral 唯一可控的广播字段)。
* `BUMP_<myTempId>_<seenPeerId>` → 例 `BUMP_ABC123_------`(19 字符)
*
* 不少机型对 localName 长度有限制(iOS Peripheral 推荐 ≤ 28 字节),这里 19 字符够用。
*/
export declare function encodeBumpName(myTempId: string, seenPeerId?: string | null): string;
/**
* 解析设备名形如 `BUMP_ABC123_XYZ789` → { myTempId, seenPeerId }。
* 仅需 myTempId 时(旧格式 `BUMP_ABC123`)也兼容,seenPeerId 返回空串。
*/
export declare function parseBumpName(name: string | undefined | null): BluetoothBumpPayload | null;
/**
* 解析广播 payload 字符串 → { myTempId, seenPeerId }
* 解析失败返回 null(payload 不是本协议)。
*
* seenPeerId 为占位符 '------' 时返回空字符串,方便上层 `if (seenPeerId)` 判断。
*/
export declare function parsePayloadString(raw: string | undefined | null): BluetoothBumpPayload | null;
/**
* 从扫描到的设备里提取 mutual 协议 payload。
*
* 解析顺序(按"iOS 上能拿到的可能性"由高到低):
* 1. 设备名 / localName 前缀 `BUMP_` —— iOS↔iOS 唯一可靠通道
* 2. serviceData[serviceUuid] —— Android 标准方案
* 3. advertisData 整段 —— 部分机型把 payload 塞这里
* 4. 设备名按旧格式 `myTempId|seenPeerId` 解析(向后兼容)
*/
export declare function parsePayload(dev: BluetoothDeviceInfo, serviceUuid: string): BluetoothBumpPayload | null;
/** 候选 peer 的内存记录 */
export interface PeerRecord {
peerTempId: string;
/** 对方广播里携带的"它看到的对方 ID"(用于判断是否是双向互认) */
seenPeerId: string;
rssi: number;
/** 最近一次见到的时间戳 */
lastSeen: number;
/** 对应的原始设备,便于回传给业务方 */
dev: BluetoothDeviceInfo;
}
/** 从候选池里挑选"信号最强且在 TTL 内"的 peer(用于决定广播里要"点名"谁) */
export declare function pickBestPeer(peers: Map<string, PeerRecord>, now: number, ttlMs: number, rssiThreshold: number): PeerRecord | null;
/** 清理候选池里过期的 peer(就地修改) */
export declare function pruneExpiredPeers(peers: Map<string, PeerRecord>, now: number, ttlMs: number): void;