brendangooden/j2208-band-tools
GitHub: brendangooden/j2208-band-tools
面向 J2208 系列手环的开源 BLE 客户端及协议文档,支持脱离厂商 App 直接读取设备历史与实时健康数据。
Stars: 1 | Forks: 0
# j2208-band-tools
直接通过原始 BLE 访问 **J2208 系列手环** —— 这些设备以多个品牌销售,
包括 Hume Band V2 以及原始的 ODM 型号代码 `2301B` 和 `X3B`。支持直接读取
存储的历史记录和实时传感器数值,无需配套 App,也无需云账户。请参阅 [PROTOCOL.md](PROTOCOL.md) 了解协议本身。
这些手环**不使用加密,也没有身份验证** —— 任何 BLE central 都可以
连接并发送命令。
## 支持的设备
其硬件是深圳 ODM 的参考设计,由各家品牌贴牌生产;配套 App(`com.elink.fittrackhealth.pro`,即“FitTrack Health”)提供了一个适配多种设备的单一二进制文件。其自身的设备解析器会根据广播名称进行匹配:
```
startsWith "hume band v2" | "2301b" | "x3b" -> V2 generation
otherwise -> V1 generation
```
这两代设备共享相同的数据协议;唯一的区别在于固件升级路径。如果你的手环广播了上述名称之一 —— 或者在 `fff0/fff6/fff7` GATT profile 上响应了带有 16 字节校验和的数据帧 —— 本工具应该就能正常工作。
**已验证设备:** 一台 Hume Band V2,固件版本 v0.0.3.9。该系列中的其他设备信息均是通过 App 自身的型号列表推断出来的,本人并未全部测试过。欢迎提供其他设备的测试反馈。
下文示例中的 `AA:BB:CC:DD:EE:FF` 仅为占位符;请使用 `j2208.py scan` 获取到的你本人手环的地址进行替换。
## 环境配置
```
python -m pip install bleak
```
## 使用说明
同一时间只能有一个 central 占用手环。**请先关闭配套 App(或直接关闭手机的蓝牙)**,否则手环会一直保持与手机的连接,从而停止广播。
查找手环:
```
python tools/j2208.py scan --seconds 20
```
读取版本、电量、MAC 地址和时钟:
```
python tools/j2208.py info AA:BB:CC:DD:EE:FF
```
导出 GATT 树:
```
python tools/j2208.py probe AA:BB:CC:DD:EE:FF
```
下载存储的历史记录(无需佩戴 —— 这是最核心的功能):
```
python tools/j2208.py history AA:BB:CC:DD:EE:FF --type hr
```
数据类型:`total`, `steps`, `sleep`, `hr`, `hrv`, `spo2_auto`, `temp_axil`
(另外还有 `hr_dynamic`, `spo2`, `temp`,但它们在 V2 固件上为空)。可以添加 `--since 2026-07-25T00:00:00` 来限制时间范围;默认会拉取手环中存储的所有数据 —— 大约是最近 4–5 天的内容。
获取全部数据:
```
for t in total steps sleep hr hrv spo2_auto temp_axil; do python tools/j2208.py history AA:BB:CC:DD:EE:FF --type $t; done
```
读取或更改手环向自身历史记录写入数据的频率。这是提升数据分辨率最简单的方法 —— 无论是否有设备连接,手环都会按照自身设定的频率进行记录:
```
python tools/j2208.py auto AA:BB:CC:DD:EE:FF
python tools/j2208.py auto AA:BB:CC:DD:EE:FF --set hr --interval 5
```
出厂默认值为:心率 (HR) 10 分钟,血氧 (SpO2) 30 分钟,体温 5 分钟,心率变异性 (HRV) 60 分钟。间隔越短,意味着光学测量的次数越多,因此耗电量也会越大。
实时流式读取数据(佩戴时频率约为 0.7 Hz):
```
python tools/j2208.py live AA:BB:CC:DD:EE:FF --type heart --seconds 60 --out captures/live.csv
```
类型:`heart`(最快,仅包含 HR),`spo2`,`temp`,`hrv`。`spo2` 和 `temp` 模式需要约 30 秒的预热时间,随后会同时输出 HR、SpO2、HRV、压力值和体温。
原始 PPG 数据 —— **在 V2 固件上无法使用**,即使确有脉搏,`0x3A` 返回的也全是零。保留此命令仅用于测试其他设备:
```
python tools/j2208.py ppg AA:BB:CC:DD:EE:FF --seconds 60 --out captures/ppg.csv
```
在探索时发送任意自定义命令:
```
python tools/j2208.py send AA:BB:CC:DD:EE:FF --cmd 0x99:1,0,0,0 --cmd 0x3a:1
```
## 桌面数据采集器
`tools/j2208_daemon.py` 会保持持久连接,在断开时自动重连,并将数据写入 SQLite(包含 `live`、`history`、`battery`、`events` 表)。该过程完全不会接触手机或厂商的服务器。
```
python tools/j2208_daemon.py AA:BB:CC:DD:EE:FF --mode history --interval 60
```
如果仅需心率数据,可设置为每 5 分钟同步一次,以匹配 5 分钟的记录间隔
(完整扫描全部七种类型大约需要 90 秒,因此建议缩小采集范围):
```
python tools/j2208_daemon.py AA:BB:CC:DD:EE:FF --mode history --types hr --interval 300 --history-every 1
```
包含两种模式,其耗电量差异巨大:
| 模式 | 分辨率 | 代价 |
| --- | --- | --- |
| `history` | 心率 10 分钟,体温 5 分钟 | 可忽略不计 —— 手环本身也会记录这些数据 |
| `live` | 每次脉冲采集期间约为 0.7 Hz | 需开启光学传感器;这是非常耗电的模式 |
`--interval` 用于控制轮询频率;在 `history` 模式下,它**并不能**提升数据分辨率,因为采样率已经在固件中写死了。如果轮询频率高于固件的记录频率,只会重复读取相同的数据行(这些数据在插入时会被自动去重)。
对于 `live` 模式,传感器需要**约 9 秒才能锁定信号**,在此之前心率读取值会为零,因此如果设置 `--burst` 低于约 15 秒将获取不到任何数据。设置 `--burst 0` 会让传感器保持常开状态(无需重复预热,耗电量达到最大)。
由于电量百分比在每个周期都会被记录,因此建议运行几个小时后查看实际的耗电量,而不是凭空猜测 —— 数据会在程序退出时打印,或者你可以通过以下命令查看:
```
SELECT ts, pct FROM battery ORDER BY ts;
```
## 仓库结构
| 路径 | 说明 |
| --- | --- |
| `tools/j2208.py` | BLE 客户端 —— 扫描 / 探测 / 信息 / 实时数据 / 历史记录 / PPG / 发送指令 |
| `tools/j2208_daemon.py` | 长期运行的数据采集器,输出至 SQLite |
| `tools/probe190e.py` | 探测未使用的 `0x190e` 厂商服务 |
| `tools/dexstrings.py` | 纯 Python 实现的 DEX 字符串 + UUID 提取工具(无需 Java 环境) |
| `PROTOCOL.md` | 协议文档 |
| `apk/`, `jadx-out/` | 提取的 APK 及反编译源码(已 gitignore,从未发布) |
| `captures/` | 抓取的输出数据,即个人健康数据(已 gitignore,从未发布) |
## 特意未包含的内容
- **不包含任何 APK、反编译源码或固件镜像。** 这些文件归 App 发布者及其背后的 ODM 厂商所有。它们已被 gitignore,从未被提交到仓库中。请参考下方步骤,自行从你的设备中提取。
- **不包含任何健康数据。** 所有抓取的数据都保留在本地。文档中的示例读数仅为说明用的占位符,并非真实的测量数据。
- **不包含设备标识符。** 文档中的 MAC 地址和广播名称均为占位符。
## 反编译复现步骤
```
adb shell pm path com.elink.fittrackhealth.pro
adb pull apk/base.apk
winget install Microsoft.OpenJDK.21
winget install Skylot.jadx
java -cp "$env:LOCALAPPDATA\Microsoft\WinGet\Packages\Skylot.jadx_*\lib\jadx-gui-1.5.5-all.jar" jadx.cli.JadxCLI -d jadx-out --no-res apk/base.apk
```
jadx 在退出时会返回状态码 3,在约 13000 个类中有大约 100 个类反编译失败;但手环的 BLE package 反编译非常顺利。核心代码位于
`jadx-out/sources/com/example/watch_flutter_plugin/humeBandJ2208/`。
## 范围与法律声明
本项目与 Hume Health、eLink、FitTrack 或供应链中的任何 ODM 厂商均无关联、认可或合作。文中出现的品牌和型号名称仅用于标识本代码所适配的硬件设备,这正是兼容性项目的核心意义所在。
有必要明确声明:**此处记录的协议并非由任何一个品牌独立开发。** 它是深圳 ODM 的参考设计,被多个品牌贴牌销售,运行着通用的 SoC 协议栈和标准的 `fff0` profile。手环上的品牌仅仅是获得了授权而已。
- **目的在于实现互操作性。** 本项目的存在是为了让手环所有者能够在厂商不支持平台上,读取由自己设备记录的、关于自己身体的数据。在许多司法管辖区,为实现互操作性而进行的逆向工程是明确允许的 —— 例如澳大利亚版权法第 47D 条、欧盟软件指令第 6 条,以及美国法典第 17 编第 1201 条(f)款。
- **没有突破任何技术保护措施。** 该手环出厂时不包含任何加密、配对要求或身份验证握手。这里没有任何需要绕过的技术保护措施;该协议是通过对未混淆的 App 进行逆向分析恢复出来的,并通过观察开放的明文无线链路进行了验证。
- **未重新分发任何厂商代码或资产。** 详见上文相关部分。
- **保修和账户风险需自行承担。** 无论哪个品牌将手环卖给你,无论上述规定如何,其服务条款可能会禁止此类操作。这属于你与厂商之间的合同问题。更改设备设置(`auto --set`)会写入固件;其他所有操作均为只读。
- **非医疗器械,手环本身也不是。** 请勿将本项目或手环的任何数据用于医疗诊断或治疗。
## 许可证
MIT —— 详见 [LICENSE](LICENSE)。该协议仅适用于本仓库中的代码和文档,不适用于通过反编译厂商 App 所产生的任何内容。
标签:Python, 云资产清单, 可穿戴设备, 无后门, 物联网, 蓝牙低功耗, 逆向工具, 逆向工程