# ATS3089P 设备查找与防丢报警
本功能用于手机 BLE App 查找附近开发板,以及 BLE 连接丢失后的本机声音报警。PC 直接使用原有普通 UART 串口发送指令。这里的“Find My”是本地 BLE 查找功能,没有接入 Apple 查找网络。
查找声音由固件实时合成,无需向 U 盘复制 MP3、WAV 或 PCM 文件。防丢默认关闭,开启状态保存到 NVRAM,断电重启后保留;每次开机仍须先连接手机,才开始监护该手机的 BLE 连接。
## 1. PC 串口直接查找
使用当前能看到 `uart:~$` 提示符的普通 UART 串口,沿用原串口参数,按文本发送,指令后加回车即可。不需要开启 USB CDC 或切换 USB 模式。
```text
app findmy start
app findmy status
app findmy stop
```
| 指令 | 作用 |
| --- | --- |
| `app findmy start` | 播放查找声音,默认 30 秒 |
| `app findmy start 10` | 播放 10 秒,可指定 1~300 秒 |
| `app findmy stop` | 停止当前查找、防丢报警或断连确认等待 |
| `app findmy status` | 查看连接、布防、播放和错误状态 |
| `app findmy anti_loss on` | 开启防丢并保存,当前已连接的手机作为监护对象 |
| `app findmy anti_loss off` | 关闭防丢并保存,取消断连确认等待和防丢报警 |
手动查找不要求 BLE 已连接,PC 可以独立验证声音。重复发送 `start` 会重新计算本次查找的结束时间。`stop` 只结束当前报警,不修改保存的防丢开关;若要长期关闭,使用 `anti_loss off`。
查找或防丢报警期间,单击开发板 **K2** 也可以停止声音,包括取消尚未结束的 5 秒确认等待。没有查找或防丢任务时,K2 继续原有的内置铃声切歌操作。
## 2. 手机 BLE App 查找
沿用 [BLE_RECORD_CONTROL.md](BLE_RECORD_CONTROL.md) 的服务、特征、通知订阅和四字节 CRC-8 格式。录音原来的 `00~03` 控制值不变,查找使用 `10/11`,防丢使用 `20/21`(均为十六进制)。使用通用 BLE 调试 App 时:
1. 扫描并连接开发板的 BLE 设备,发现 GATT 服务。
2. 找到服务 `7b2e1000-8e7f-4d3a-9c61-2a3089c00001` 和特征 `7b2e1001-8e7f-4d3a-9c61-2a3089c00001`。
3. 开启该特征 Notify(CCC 写入 `01 00`),选择 HEX 输入。
4. 向该特征写入 `AA 01 11 AD`,开发板开始播放 30 秒查找声音;写入 `AA 01 10 AA` 停止。
帧格式为 `AA + SET/GET + 控制字段 + CRC8`,`00=GET`,`01=SET`。CRC 参数与原录音协议完全相同:多项式 `07`、初值 `00`,计算前 3 字节。
| 操作 | 发送 HEX 字节 | 固件行为 |
| --- | --- | --- |
| 开始查找 | `AA 01 11 AD` | 播放 30 秒查找声音 |
| 停止声音 | `AA 01 10 AA` | 停止当前查找、防丢报警或确认等待 |
| 查询查找状态 | `AA 00 10 BF` | 通知当前查找状态 |
| 开启防丢 | `AA 01 21 3D` | 保存开启状态,监护发送指令的手机 |
| 关闭防丢 | `AA 01 20 3A` | 保存关闭状态,取消防丢任务 |
| 查询防丢状态 | `AA 00 20 2F` | 通知当前防丢与布防状态 |
通知同样为 4 字节,SET/GET 字节沿用请求,控制字段表示执行后的状态,CRC 重新计算:
| 通知控制字段 | 含义 |
| --- | --- |
| `10` / `11` / `12` / `13` | 空闲 / 查找中 / 防丢报警窗口 / 断连确认等待 |
| `20` / `21` / `22` / `23` | 防丢关闭 / 已开尚未布防 / 已布防且已连接 / 已布防且已断连 |
| `81` / `82` / `83` | 音频忙 / 执行或保存失败 / 请求来源连接已失效 |
App 应发送二进制 HEX 字节,不发送 ASCII 字符串。每次只写一帧 4 字节;长度、offset、操作、控制值和 CRC 均会校验。BLE 回调只接收并排队,应用线程处理后通知结果。请等通知后再发送下一条;查询查找和防丢使用上表 GET 帧,直接 Read 仍返回原有录音状态。开关保存到 NVRAM,`anti_loss on` 和 BLE 开启均使用等级 `02`。
原先的标准 IAS `1802/2A06` 和 LLS `1803/2A06` 单字节入口仍兼容,当前 App 对接统一使用上表四字节指令即可。
## 3. 防丢使用流程
建议先将手机和开发板放在一起,保持 App 的 BLE 连接,再开启防丢:
```text
app findmy anti_loss on
app findmy status
```
或由手机向原录音控制特征写入 **`AA 01 21 3D`**。状态应显示 `anti_loss=2 connected=1 armed=1`。
随后保持 App 连接,逐渐远离开发板。当蓝牙控制器报告连接超时 `0x08` 或 LL 响应超时 `0x22` 时,固件进入 **5 秒确认等待**。等待期间同一监护手机恢复连接,会取消报警;5 秒后仍未连接,则进入 **60 秒防丢报警窗口**。
```text
findmy: LINK_LOSS reason=0x08 confirm in 5s
findmy: ANTI_LOSS alarm 60s
findmy: tone started 2500/3200 Hz, 16 kHz mono
```
5 秒从**固件收到超时断连事件**开始计算。蓝牙自身还有连接监督超时,所以从实际走远到发声通常会更久,不能理解为离开范围后立即开始 5 秒倒计时。
以下操作可以结束防丢报警或确认等待:
- 同一监护手机重新连接 BLE。
- PC 执行 `app findmy stop`,或手机发送 `AA 01 10 AA`。
- 开发板单击 K2。
- 执行 `app findmy anti_loss off`,或手机发送 `AA 01 20 3A`。
- 60 秒报警窗口结束。
停止一次报警后,防丢开关仍可保持开启;手机再次连接后,后续超时断连仍会触发新的监护流程。若需要换一部手机,在新手机已连接 BLE 时重新执行 `anti_loss on`,或发送 `AA 01 21 3D`,监护对象改为当前手机。
主动断连 `0x13`(对端主动断开)和 `0x16`(本机主动断开)不触发防丢。断电重启时即使已保存开启状态,尚未连接过手机也不会报警,以免手机不在身边时开机误响。
防丢依赖 **App 持续保持 BLE 连接**,手机系统应允许 App 在后台运行。只在手机系统中连接传统蓝牙音乐或 HFP 通话,不代表 App 的 BLE 连接仍存在。App 被系统结束、手机关机或信号被遮挡,也可能出现超时断连,不能单凭报警判断一定是距离变远。本功能按连接丢失报警,没有把 RSSI 换算为米数。
## 4. 声音、音频优先级与状态
固件以 16 kHz、16 bit、单声道 PCM 实时合成以下节奏并循环:
```text
2500 Hz 120 ms → 静音 100 ms → 2500 Hz 120 ms → 静音 100 ms
→ 3200 Hz 240 ms → 静音 800 ms → 重复
```
声音经过开发板现有 DAC 和扬声器输出,不需要单独蜂鸣器。短音首尾做幅度渐变,减少突然开始和停止时的爆音。报警期间使用 PARTIAL 唤醒锁,保持 CPU 和音频运行,不要求屏幕常亮。
通话和其他音频优先:正在通话、播放 MP3、PCM 或其他占用音轨的音频时,手动查找返回 `-EBUSY`(通常为 `-16`),不会强行停掉它们。允许查找接管原有内置铃声。防丢触发时若音频忙碌,会在剩余 60 秒窗口内等待音轨可用;窗口不会因为等待而延长。查找报警已经播放后,其他播放器新建音轨会结束本次报警并释放资源,让原功能正常播放。
`app findmy status` 示例:
```text
findmy: version=261014-v2 ret=0 anti_loss=2 connected=1 armed=1 pending=0 source=0 playing=0 remaining=0s reason=0x00 error=0
```
| 字段 | 含义 |
| --- | --- |
| `version` | 本次功能版本 `261014-v2`,用于核对实际烧录版本 |
| `ret` | 本次 shell 操作结果,`0` 成功;如 `-16` 表示音频忙碌 |
| `anti_loss` | 保存的防丢等级,`0` 关闭,`1/2` 开启 |
| `connected` | 监护手机当前是否 BLE 已连接 |
| `armed` | 本次开机是否已连接手机并进入防丢监护 |
| `pending` | 是否正在等待超时断连后的 5 秒确认 |
| `source` | `0` 空闲,`1` 手动/手机查找,`2` 防丢报警窗口 |
| `playing` | 查找声音线程当前是否正在执行播放任务 |
| `remaining` | 确认等待或本次报警窗口的剩余秒数 |
| `reason` | 最近监护手机的断连原因,`0x08/0x22` 可触发防丢 |
| `error` | 核心或声音播放最近的错误码,`0` 无错误 |
播放在后台启动,刚执行 `start` 时可能先看到 `source=1 playing=0`;稍后查看应进入播放。`source=2 playing=0` 也可能表示防丢窗口正在等待其他音频释放。
## 5. 代码入口与流程
| 文件 | 作用 |
| --- | --- |
| `src/main/findmy.c` / `findmy.h` | 查找时长、监护手机、5 秒确认、60 秒窗口、状态和 NVRAM 设置 |
| `src/main/ble_record_protocol.h` / `ble_record_service.c` | 原四字节协议、查找/防丢扩展、统一排队和通知 |
| `src/main/findmy_service.c` / `findmy_service.h` | 查找/防丢 BLE 执行、连接事件及标准服务兼容入口 |
| `src/main/findmy_tone.c` / `findmy_tone.h` | 后台声音线程、PCM 合成、音轨清理与唤醒锁 |
| `src/main/system_app_shell.c` | `app findmy` 串口指令入口 |
| `src/main/system_app_main.c` | 蓝牙就绪后注册服务,处理 BLE 查找消息 |
| `src/main/ringtone_play.c` | K2 单击停止查找、防丢报警 |
| `framework/audio/audio_track.c` | 新音轨建立前调用准备钩子,让其他播放器优先并释放报警音轨 |
功能开关为 `CONFIG_APP_FINDMY`,ATS3089P 的 `prj.conf` 启用该配置。防丢等级通过属性 `FINDMY_LEVEL` 保存,监护对象和当次报警时间为本次运行状态,不保存到 NVRAM。
立即查找流程:BLE 四字节写入或串口 `start` → 校验及应用处理 → 设置时长 → 后台声音线程 → 到时、指令或 K2 停止 → 关闭音轨并释放唤醒锁。
防丢流程:启用并保存 → 连接手机后布防 → 过滤真实 BLE 超时断连 → 确认 5 秒 → 进入 60 秒窗口 → 音频可用时发声 → 重连、停止或到时清理。
## 6. 上板验证与固件
建议依次验证:
1. PC 执行 `start 5`,听到“滴滴哒”循环并约 5 秒后停止;执行 `start` 后单击 K2,确认停止。
2. 手机连接 BLE,订阅原录音特征 Notify,发送 `AA 01 11 AD` 开始查找、`AA 01 10 AA` 停止。
3. 发送 `AA 01 21 3D` 开启防丢,再发送 `AA 00 20 2F` 查询,串口确认 `connected=1 armed=1`。
4. 保持 App 后台 BLE 连接,远离直至日志出现 `LINK_LOSS`,确认约 5 秒后报警。
5. 确认等待内重新连回、报警中重新连回,都应停止;主动在 App 断开连接,应打印 `no alarm`。
6. 断电重启确认 `anti_loss` 仍开启,而手机未连接前 `armed=0`、不会误响。
7. 通话或其他音乐播放期间发起查找,应返回忙碌;报警中开始其他音频,应结束报警,原播放和多次通话继续正常。
2026-10-14 已完成 ATS3089P 开发板固件编译与打包,烧录包如下(路径相对于 `application/bt_watch`):
```text
outdir/ats3089p_dev_watch/_firmware/ats3089p_dev_watch_261014_findmy_v2.fw
outdir/ats3089p_dev_watch/_firmware/ats3089p_dev_watch_261014_findmy_v2_debug.fw
```
软件验证已通过:Find My 状态与 BLE 四字节指令共 66,393 项断言,包括原录音指令兼容性、完整操作/控制值校验,以及真实 ARM ELF 的声音频率、节奏、短写、停止取消、音轨清理和抢占测试。原有 BLE 录音、HFP 多次通话路由、K2 铃声及 MP3 播放器回归也通过。
在 SDK 根目录可运行以下脚本复查,详细依赖见 `tests/findmy/README.md`:
```text
python application/bt_watch/tests/findmy/run_tests.py
python application/bt_watch/tests/findmy/run_tone_tests.py --wav application/bt_watch/outdir/findmy_tests/preview.wav
python application/bt_watch/tests/findmy/run_shell_tests.py
```
声音测试生成 `outdir/findmy_tests/preview.wav`,可在电脑试听三轮“滴滴哒”。扬声器实际响度、手机 App 后台连接和远离后的报警仍需按上述步骤上板确认。
## 7. 烧录后核对版本与串口入口
本次新包文件名带 `findmy_v2`,烧录后重新启动,在原普通 UART 执行:
```text
app findmy status
app findmy start 5
```
状态首行应包含 `findmy: version=261014-v2`;蓝牙就绪后会打印
`Find My v2 261014 UART / BLE AA control ready`。
当前真实 ELF 已执行 Shell 根命令、子命令查找和处理函数测试,合法 `app findmy`
不会进入 `app unknown parameter`;还逐字节核对了 ELF 导出的 `zephyr.bin` 和打包
`app.bin` 中的命令表及代码。若板上仍返回 `unknown parameter: findmy`,说明运行中的
命令表与该构建不一致,需要核对烧录工具选择的完整文件名、烧录是否成功和冷启动版本。
单凭运行中日志无法确认板上实际固件。