Flipper Zero Unleashed 固件 FindMy Flipper 应用实战:将 Flipper Zero 模拟为 AirTag / SmartTag 追踪信标
【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware
FindMy Flipper 是 Unleashed 固件内置的一款蓝牙信标模拟应用,它利用 Flipper Zero 的 BLE 扩展广播(Extra Beacon)能力,让设备化身 Apple AirTag、Samsung SmartTag、Tile 乃至 Google FindMy Device 追踪标签。本文以应用自带的 README.md 为主体,结合本仓库内applications/system/find_my_flipper/下的完整源码实现,系统讲解从标签数据获取、固件内配置到后台追踪的完整流程,帮助你掌握信标广播的底层机制与可调参数的真实取值范围。
应用定位与核心能力
该应用由 Matthew KuKanich 开发并合入 Unleashed 固件,通过 application.fam 可以确认它的两个组成部分:
findmy(appid=findmy):类型为FlipperAppType.EXTERNAL的外部 FAP 应用,入口函数findmy_main,依赖gui,栈大小 2KB,属于 Bluetooth 分类,图标为location_icon.png,版本 3.5;findmy_startup(appid=findmy_startup):类型为FlipperAppType.STARTUP,仅面向 f7 目标,入口findmy_startup,负责在设备开机时自动恢复信标状态。
概括而言,它扩展了 Flipper Zero 的蓝牙能力,提供以下三类核心功能(对应 README 的 Features 部分):
- 标签模拟(Tag Emulation):克隆已有的 Apple AirTag / Samsung SmartTag 到 Flipper Zero,或在不拥有实体 AirTag 的情况下,生成 OpenHaystack 密钥对接入 Apple 的 FindMy 网络;
- 高度可定制(Customization):调节信标广播间隔与发射功率,在可见性与续航之间取得平衡;
- 高效后台运行(Efficient Background Operation):针对后台持续广播做了优化,低功耗地保持可追踪状态而不影响正常使用。
从源码看,应用实际上支持四种标签类型(见 findmy_state.h 中的FindMyType枚举):FindMyTypeApple、FindMyTypeSamsung、FindMyTypeTile、FindMyTypeGoogle,主界面会据此显示对应的网络名称(Apple / Samsung / Tile / Google Network)。
安装与固件要求
README 明确给出了两种安装途径:
- 方案 A:直接使用随固件发布/预编译的 FAP 文件(
findmy.fap); - 方案 B:使用
fbt或ufbt自行编译。
无论哪种方式,都必须运行 dev(开发)版固件,因为该功能依赖的额外 BLE 广播接口(extra beacon)仅在开发构建中开放;README 提到当正式版固件开放该接口后此限制会解除。同时,当前 main 分支固件已完整支持本应用,包括全部图标资源。
值得说明的是,FAP 类型的findmy应用与 STARTUP 类型的findmy_startup是分离的:FAP 提供图形界面供用户配置,而 STARTUP 组件在开机阶段静默恢复信标,二者共享同一份状态文件,因此即使不打开应用,只要此前开启了信标,重启后依然会自动广播。
第一步:获取 SmartTag 数据
无论采用哪种配置方式,都需要先取得标签的身份数据(MAC 地址与广播载荷 Payload)。README 提供了两种获取途径。
方式 A:克隆现有标签(推荐,免额外服务端配置)
克隆方式的好处是无需 OpenHaystack 等额外服务端即可直接追踪,具体步骤:
- 配对标签:先让 AirTag 或 Samsung SmartTag 与你的手机完成配对;
- 进入"丢失"模式:将标签远离其注册设备约 15 分钟,使其进入可被发现的状态;
- 安装 nRF Connect:从 Google Play 安装 nRF Connect 应用(README 注明 Apple 版本不暴露所需的 Raw 数据,作者仍在寻找替代方案);
- 过滤与扫描:
- 打开应用,进入过滤器,只保留目标标签品牌(Apple/Samsung),排除其余类型;
- 将 RSSI 阈值调到最低(-40 dBm);
- 开始扫描,等待 SmartTag 以 "FindMy" 设备形式出现;
- 抓取数据:点击Raw或View Raw复制payload,并记下标签的MAC 地址。抓取后立即取下标签电池,防止密钥/MAC 轮换导致数据失效;
- 录入 Flipper Zero:将 payload 与 MAC 输入到 FindMy Flipper 应用中。
方式 B:OpenHaystack 密钥生成(无实体标签)
- 下载
generate_keys.py脚本并在终端执行(需要 Python cryptography 库:python3 -m pip install cryptography); - 按脚本提示输入,最终会得到Private Key(私钥)、Public Key(公钥)、Payload(载荷)与MAC 地址;
- Private Key用于从 Apple 接收位置报告,必须妥善保管;
- MAC Address需注册到 Flipper Zero 应用中:
- 打开应用进入配置菜单;
- 选择 "register tag",按提示输入 MAC 地址;
- 在随后弹出的载荷对话框中输入Payload;
- 保存。
- 配置完成后设备即可用于 OpenHaystack 生态,之后按 OpenHaystack 或 Macless Haystack 的流程继续。
README 特别提示了兼容性限制:使用 OpenHaystack 追踪需要 macOS低于 14 的版本(MacOS 14+ 的邮件插件存在兼容性问题)。如果你没有 Mac,或系统已升级到 14 及以上,可选用替代方案:
- Macless Haystack(README 推荐):无需 Mac 的 OpenHaystack 替代实现;
- FindMy(python + docker 后端):一个用 Python 和 Docker 提供位置查询后端服务的项目。
(上述均为外部项目,本文仅作名称引用,具体请自行查阅对应项目文档。)
第二步:在 Flipper Zero 上配置标签
启动应用后进入配置菜单(Config),可以看到"Import Tag From File"(从文件导入)与"Register Tag Manually"(手动注册)两条路径。
从文件导入(.keys / .txt)
README 建议将生成的.keys文件放到 Flipper Zero SD 卡中导入。克隆方式下,则可在 nRF Connect 中点击保存按钮导出.txt文件放到同一目录。从当前仓库源码看,导入对话框的默认目录实际由 findmy_state.h 中的FINDMY_STATE_DIR决定,即/ext/apps_data/findmy(README 中描述的 AppsData/FindMyFlipper 目录为较早版本约定,当前源码以apps_data/findmy为准),导入前代码会通过storage_simply_mkdir自动创建该目录。
findmy_scene_config_import.c 实现了两种文件格式的解析,可直接反推文件规范:
nRF Connect (.txt) 格式:
- 文件名必须包含 MAC 地址,格式形如
XX-XX-XX-XX-XX-XX_YYYY-MM-DD HH_MM_SS.txt,MAC 从文件名中解析并反转(findmy_reverse_mac_addr); - 文件首行形如
YYYY-MM-DD HH:MM:SS.ms, XX dBm, 0xXXXXX,程序定位" dBm, 0x"标记后截取十六进制载荷; - 载荷的十六进制字符长度必须与当前标签类型的数据长度严格匹配(如 Apple/Samsung 为 31 字节,即 62 个十六进制字符),否则报 "Wrong payload size"。
OpenHaystack (.keys) 格式:
- 文件内需包含以
"Public key: "或"Advertisement key: "开头的行; - 将该行的 Base64 内容解码为 28 字节公钥:前 6 字节作为 MAC 地址(第 0 字节置
0b11000000高位后反转),剩余字节按 Apple FindMy 广播模板填入载荷区,data[29]存放公钥首字节的高 2 位(版本信息)。
手动注册标签
选择手动注册后,应用通过 ByteInput 界面依次引导输入 MAC 地址(findmy_scene_config_mac.c)与广播载荷(findmy_scene_config_packet.c),最后保存生效。
配置项详解:广播间隔与发射功率
README 在 Customization 一节概述了两项可调参数,而 findmy_scene_config.c 给出了它们的精确取值范围:
| 配置项 | 取值范围 | 默认值 | 说明 |
|---|---|---|---|
| Broadcast Interval(广播间隔) | 1~10 秒 | 5 秒 | 选项列表共 10 档,索引 +1 即为秒数;Google 标签类型下仅 1~2 秒两档 |
| Transmit Power(发射功率) | 0~6 dBm | 6 dBm | 7 档可选,叠加在 0 dBm 基准上,即实际 -1~+6 dBm 之外的 0~+6 dBm |
| Show MAC(显示 MAC) | Yes / No | No | 主界面是否明文显示 MAC 地址 |
| Tag Type(标签类型) | Apple / Samsung / Tile / Google | Apple | 决定载荷长度与广告格式 |
关于广播间隔,源码注释引用了 Google FMDN(Find My Device Network)规范:Google 要求广播间隔至少每 2 秒一次,因此当标签类型为 Google 时,间隔选项被收敛为 1s / 2s 两档(见findmy_scene_config.c中对FindMyTypeGoogle的分支处理)。
参数如何真正生效
设置项并非只改界面显示,findmy.c 中的findmy_change_broadcast_interval会做范围校验(1~10),随后调用findmy_state_save_and_apply持久化并立即应用。真正落到硬件层的是 findmy_state.c 的findmy_state_apply:
GapExtraBeaconConfig config = { .min_adv_interval_ms = state->broadcast_interval * 1000, // 秒转毫秒 .max_adv_interval_ms = (state->broadcast_interval * 1000) + 150, .adv_channel_map = GapAdvChannelMapAll, // 全信道广播 .adv_power_level = GapAdvPowerLevel_0dBm + state->transmit_power, .address_type = GapAddressTypePublic, // 公共地址 }; memcpy(config.address, state->mac, sizeof(config.address)); furi_check(furi_hal_bt_extra_beacon_set_config(&config));即:间隔以秒为单位配置后乘以 1000 转为毫秒,实际广播窗口为[interval×1000, interval×1000+150]ms;发射功率为 0 dBm 基准 + 用户设定值(0~6 dBm);MAC 使用公共地址类型。可见 README 所述"优化可见性与续航",底层正是通过这两个参数的硬件级配置实现的。
此外,应用还会实时将 Flipper Zero 的电量写入 Apple 广播载荷:findmy_state_update_payload_battery读取电池满容量与剩余容量计算百分比,超过 80% 置BATTERY_FULL(0x00),50% 以上BATTERY_MEDIUM(0x50),20% 以上BATTERY_LOW(0xA0),否则BATTERY_CRITICAL(0xF0),写入data[6]位置。这样在 FindMy 网络中即可反映设备电量。
主界面操作与状态理解
应用主视图由 views/findmy_main.c 绘制,按键映射清晰:
| 按键 | 功能 |
|---|---|
| OK | 切换信标广播开关(Broadcast Active / Inactive) |
| Left(←) | 进入后台运行模式(界面提示 "Press <- to run in background") |
| Right(→) | 打开 Config 配置菜单 |
| Up / Down | 直接调整广播间隔(Ping Interval) |
| Back | 退出应用 |
主界面会展示当前网络名称(Apple/Samsung/Tile/Google Network,带锁形图标表示地址隐私)、MAC 地址(当 Show MAC 开启时以MAC: XX:XX:...格式显示,并执行字节反转以符合实际广播地址)、信标开关状态与当前 Ping Interval 秒数。
各按钮回调最终汇聚到 findmy.c 中的状态变更函数(findmy_toggle_beacon、findmy_change_transmit_power、findmy_set_tag_type、findmy_toggle_show_mac等),每次修改都会save_and_apply,保证重启后配置不丢失。
后台运行与开机自动恢复机制
README 强调应用"针对后台运行做了优化,对电池影响可忽略"。这一承诺的实现分两个层面:
1. 界面层后台化:主界面按 Left 键即可退到后台,信标由蓝牙控制器独立持续广播,不占用 CPU 持续运转;
2. 开机自动恢复:这是最关键的机制。findmy_startup.c 作为 STARTUP 组件(order=1210)在系统启动早期运行:
- 首先判断是否为正常启动模式(非 DFU/恢复模式);
- 打开并关闭 BT 记录以等待蓝牙初始化完成,并检查
furi_hal_bt_is_gatt_gap_supported()(core2 是否支持 GATT/GAP 扩展广播),不支持则直接退出; - 调用
findmy_state_load读取状态,若此前beacon_active为 true 则调用findmy_state_apply自动重启信标; - 同时订阅存储卡挂载事件(
StorageEventTypeCardMount),若开机时 SD 卡尚未就绪,会在挂载完成后通过run_parallel再次尝试加载——因为状态文件存放在 SD 卡上。
因此,只要开启过一次信标,之后的每次开机设备都会自动进入可追踪状态,无需手动打开应用。
状态文件与数据格式
所有配置与标签数据持久化在 SD 卡的apps_data/findmy/findmy_state.txt(路径定义见 findmy_state.h),使用 FlipperFormat 键值格式,文件头为"FindMy Flipper State"、版本 1。字段包括:
| 字段 | 类型 | 说明 |
|---|---|---|
beacon_active | bool | 信标是否启用 |
broadcast_interval | uint32 | 广播间隔(秒) |
transmit_power | uint32 | 发射功率 |
tag_type | uint32 | 标签类型(0=Apple,1=Samsung,2=Tile,3=Google) |
show_mac | bool | 是否显示 MAC |
mac | hex | 6 字节 MAC 地址 |
data | hex | 广播载荷数据 |
findmy_state_load对旧配置做了向后兼容处理:文件缺失tag_type或show_mac字段时自动回退默认值(Apple / false)。文件不存在时则采用默认状态:间隔 5s、功率 6、默认 MAC66:55:44:33:22:11,并构造一段空的 Apple AirTag 载荷模板——依次为长度0x1E、厂商数据标记0xFF、Apple 公司 ID0x4C 0x00、FindMy 类型0x12、长度0x19、电池状态字节,以及 22 字节占位公钥和版本/hint 字节,见 findmy_state.c。
不同标签类型的载荷长度由findmy_state_data_size决定:Apple 与 Samsung 为 31 字节,Google 为 29 字节,Tile 为 21 字节。导入时对载荷长度的严格校验正是基于这一函数。
第三步:开始追踪
配置完成后,根据标签来源选择追踪渠道(README 的 Tracking 部分):
- 克隆的 Apple AirTag:使用苹果 FindMy 应用;
- 克隆的 Samsung SmartTag:使用 Samsung SmartThings 应用,以及支持 SmartTag 追踪的各类浏览器端服务;
- 生成的密钥 + OpenHaystack:在 OHS 应用或 Macless Haystack 设置中追踪(链接见上文)。
Mac 上使用 OpenHaystack 应用的完整配置步骤
如果你拥有 Mac,README 给出了在 OpenHaystack(OHS)应用中导入自生成密钥的详细流程(感谢 Wr3nch 提供的帮助):
- 创建新设备:在 OpenHaystack 应用中创建一个新设备,但创建后先不要立即部署(deploy);
- 导出配置:选择EXPORT,以 "all accessories as file" 方式导出。为简化后续操作,请确保导出前列表中只有一个条目。导出格式必须是 JSON;
- 修改 JSON 文件:用文本编辑器打开导出的 JSON,做如下替换(左侧为 OHS 字段,右侧为
generate_keys.py脚本输出的值):symmetricKey→ 设为Hashed adv key(哈希广告密钥);privateKey→ 替换为你的Private Key;oldestRelevantSymmetricKey→ 同样使用Hashed adv key;- 另将以下两个属性改为
true:"isDeployed": true"isActive": true
- 重新导入:保存修改后将 JSON 重新导入 OpenHaystack;
- 调整 OHS 应用设置:在 Mac 端 OpenHaystack 应用的顶栏中,将时间设置从
1 Day改为30min,留出时间让新设置生效。
完成上述步骤后,设备即完成 OpenHaystack 侧的接入,可在 OHS 应用内查看位置报告。
兼容性与使用注意事项
兼容性(Compatibility):
- Apple 设备:通过 FindMy 网络进行 AirTag 追踪;
- 支持 Samsung SmartTag 追踪的任何设备,包括浏览器(前身 FindMyMobile)。
法律与隐私(Legal and Privacy):README 明确声明本应用仅用于个人与教育用途,用户有责任遵守当地关于追踪设备的隐私法律法规;克隆与模拟追踪标签应当负责任地进行,并尊重原设备的归属权。
免责声明(Disclaimer):本项目与 Apple Inc. 和 Samsung 无任何隶属关系,所有产品名称、Logo 与品牌均归其各自所有者。请负责任、合规地使用本应用。
最后再次提醒:克隆真实标签时,抓取到 Raw 数据后应立即拆除标签电池,以阻止密钥/MAC 轮换,确保录入 Flipper Zero 的数据长期有效;而通过generate_keys.py生成的密钥对则不存在此问题,可随时重复生成。两者在 FindMy 网络中的追踪体验一致,区别仅在于克隆方式无需搭建任何服务端。
【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考