今天在 GitHub Trending 上看到一个有意思的项目:findphone,一个用蓝牙信号强度在命令行里定位苹果设备的 macOS 工具,专为 Find My 无法使用但设备仍在蓝牙范围内的场景设计。

一、项目概述

findphone 由开发者 ben-z 创建,解决了这样一个痛点:公司配发的 Mac/iPad 加入了 MDM 管理,Find My 功能被禁用,但设备明明就在附近(比如落在会议室的某个角落),却无法让设备发出声音来定位它。

它通过持续监测目标设备的蓝牙 RSSI(Received Signal Strength Indicator)值,转换成可读的信号强度条形图,让你「听着」接近目标:

  • survey 模式findphone):扫描周围所有 Apple 设备,按信号强度排序
  • hunt 模式findphone iphone):追踪指定设备,添加 --sound 参数后接近目标时发出加速的蜂鸣声,类似倒车雷达效果
  • 列表模式findphone --list):列出所有已配对设备的蓝牙地址

核心特性:

  • 通用二进制(arm64 + x86_64),无需 Swift 环境即可运行
  • 支持 --redact 脱敏模式,录制屏幕时自动屏蔽蓝牙地址和设备名
  • 三种 RSSI 数据源自动降级,信号测量诚实可靠

二、技术原理

2.1 RSSI 信号强度数据源

findphone 的信号测量按质量从高到低依赖三个数据来源:

① GATT 连接(最准确)

一旦通过 BLE 连接到目标设备,调用 readRSSI() 每秒可获得约 3 次新鲜测量值。这是最可靠的数据源。

// 建立 GATT 连接后读取 RSSI
peripheral.readRSSI()

② BLE 广告被动监听

macOS 会被动接收附近 BLE 设备的广播包,从中解析设备名和 RSSI。但 Apple 设备大约每 15 分钟轮换一次广告地址,且只在部分广播包里包含设备名,因此数据稀疏。

③ 经典蓝牙配对列表(最常用 fallback)

通过 system_profiler SPBluetoothDataType 命令读取已配对设备的 RSSI:

let output = Process()
output.executableURL = URL(fileURLWithPath: "/usr/sbin/system_profiler")
output.arguments = ["SPBluetoothDataType", "-json"]

这里有一个关键陷阱:macOS 对这个值的刷新间隔是 3~12 秒,中间多次轮询返回的都是同一个缓存值。findphone 的做法是仅在新值实际变化时才计入测量,这解释了为什么报告的测量数远低于实际轮询频率——这是诚实的设计。

2.2 信号强度参考表

dBm 值粗略含义
-45 及以上伸手可及的距离
-60同一张桌子上
-72同一个房间里
-85较远,或有遮挡
更低非常远或被屏蔽

2.3 Swift 构建方式

项目使用 Swift Package Manager 管理,核心 Package.swift 极为简洁:

// swift-tools-version:5.9
import PackageDescription

let package = Package(
    name: "findphone",
    platforms: [.macOS(.v13)],
    targets: [
        .executableTarget(name: "findphone", path: "Sources/findphone")
    ]
)

发布版本通过 CI 构建通用二进制(arm64 + x86_64),保证开箱即用。

三、安装与快速开始

环境要求

  • macOS 13 (Ventura) 及以上
  • 需授予蓝牙访问权限(首次运行时会提示)

安装步骤

Releases 下载通用二进制:

tar -xzf findphone-macos-universal.tar.gz
xattr -dr com.apple.quarantine findphone  # 清除下载 quarantine 标记
./findphone --help

从源码构建

git clone https://github.com/ben-z/findphone.git
cd findphone
swift build -c release
cp .build/release/findphone ~/bin/findphone

四、使用方法与实战

基础用法

# 扫描附近所有 Apple 设备(survey 模式)
findphone

# 追踪名为 "iphone" 的设备(hunt 模式)
findphone iphone

# 带声音的追踪模式,越近蜂鸣越快
findphone iphone --sound

录制屏幕时的安全模式

# 脱敏模式:屏蔽蓝牙地址,设备名用类别替代
findphone --redact
findphone iphone --redact --sound

信号强度解读实战

当你拿着 MacBook 在会议室里找 iPad 时:

findphone ipad --sound
# 输出示例:
# [████████░░] -45 dBm  ← 几乎贴在一起了
# [██████░░░░] -55 dBm  ← 同一张桌子
# [████░░░░░░] -68 dBm  ← 同房间,稍远
# [██░░░░░░░░] -82 dBm  ← 信号已经很弱

⚠️ 金属材质、墙壁和人体都会大幅衰减信号,所以金属文件柜里 2 米远的设备和开放空间里 15 米远的设备可能读数相同。看趋势,不看单次读数

五、常见问题与解决方案

Q1: 下载后提示「无法打开,因为无法验证开发者」

xattr -dr com.apple.quarantine findphone

Q2: 运行提示「Bluetooth access denied」

前往 系统设置 → 隐私与安全性 → 蓝牙,为你的终端应用(如 Terminal 或 iTerm2)开启蓝牙权限。

Q3: hunt 模式下设备信号突然消失(读数归零)

说明设备已超出蓝牙有效范围(约 10~20 米室内),或者设备的蓝牙被关闭了。findphone 在连接丢失时会停止蜂鸣,蜂鸣停止 ≠ 设备不在附近,而是「检测不到信号」。

Q4: 配对列表里有设备但找不到

使用 --list 查看该设备的蓝牙地址是否稳定公共地址(不会轮换),地址不稳定的设备可能因地址变化而追踪失败。

Q5: build 失败,提示找不到 swift

确保已安装 Xcode Command Line Tools:

xcode-select --install

六、总结

findphone 解决的是一个很垂直但真实存在的痛点:当你无法使用 Find My(比如 MDM 禁用),设备又在蓝牙可及的范围内时,它是目前最优雅的「盲找」方案。设计上有几个亮点值得关注:

  1. 三种 RSSI 数据源自动降级,确保在各种设备状态下都能工作
  2. 对缓存数据的诚实处理,避免测量数虚高
  3. 脱敏模式的细致考量,兼顾隐私安全和录制分享需求

如果你的工作环境中 macOS 设备被 MDM 管理,findphone 值得加入你的终端工具链。一个约 3MB 的通用二进制,无需任何依赖,一行命令就能开始「寻宝」。