131 lines
3.7 KiB
Markdown
131 lines
3.7 KiB
Markdown
# Berger LFP BLE Commands
|
|
|
|
Reverse-engineering notes for the Berger LFP Android app BLE protocol.
|
|
|
|
This repository documents the custom JBD-style BLE GATT protocol used by the
|
|
Berger LFP Android app to read battery telemetry such as SOC, current, voltage,
|
|
remaining capacity, cell voltages, temperatures, MOS state, and estimated
|
|
charge/discharge time.
|
|
|
|
## Target App
|
|
|
|
- App label: Berger LFP
|
|
- Package: `com.jbd.berger`
|
|
- Version analyzed: `1.0.3` / `8`
|
|
- XAPK source: APKPure direct download for Play package `com.jbd.berger`
|
|
- XAPK SHA-256: `962eb7d0c62a34e03bfbe034632fd227e0f352cd66fac9ac3d77166cec0abb5e`
|
|
- Base APK SHA-256: `aa2325cfe3777824657f0ade0c381cf4bc296f9630179e0d33ed4eb56d78c1bb`
|
|
- Signer CN: `Unknown`
|
|
- Signer cert SHA-256: `ec11c6d3260adecb382186a61207e61657834b3b025e3ca31bc6ef4d88f720f9`
|
|
|
|
The XAPK was unpacked and the base APK was decompiled with apktool. The app is
|
|
a DCloud/uni-app package, so the useful BLE logic is in
|
|
`assets/apps/__UNI__F61076D/www/app-service.js`.
|
|
|
|
## Main Finding
|
|
|
|
Berger LFP does not use the standard BLE Battery Service. It connects as a BLE
|
|
GATT client, scans for a custom service `ff00`, subscribes to notifications on
|
|
`ff01`, and writes JBD command frames to `ff02`.
|
|
|
|
Android pairing/bonding does not appear to be required by the app flow. The
|
|
normal path is adapter init, scan, connect, service discovery, notification
|
|
enable, and command writes.
|
|
|
|
## Quick Start
|
|
|
|
Build the main live-data read frame:
|
|
|
|
```sh
|
|
python3 tools/berger_frame.py read 0x03
|
|
```
|
|
|
|
Expected output:
|
|
|
|
```text
|
|
DDA50300FFFD77
|
|
```
|
|
|
|
Send that frame to characteristic `0000ff02-0000-1000-8000-00805f9b34fb`
|
|
after subscribing to notifications on
|
|
`0000ff01-0000-1000-8000-00805f9b34fb`.
|
|
|
|
## Local Desktop App
|
|
|
|
This repo includes a small Python GUI client that can scan for Berger/JBD-style
|
|
BLE devices, connect, poll telemetry, and display decoded values locally.
|
|
|
|
### Debian
|
|
|
|
```sh
|
|
sudo apt update
|
|
sudo apt install python3 python3-venv python3-pip python3-tk bluez
|
|
|
|
python3 -m venv .venv
|
|
. .venv/bin/activate
|
|
python3 -m pip install -r requirements.txt
|
|
python3 berger_gui.py
|
|
```
|
|
|
|
If scanning finds no devices, check that Bluetooth is powered and unblocked:
|
|
|
|
```sh
|
|
rfkill list bluetooth
|
|
bluetoothctl power on
|
|
bluetoothctl scan on
|
|
```
|
|
|
|
### Windows 11
|
|
|
|
```powershell
|
|
py -3 -m venv .venv
|
|
.\.venv\Scripts\Activate.ps1
|
|
python -m pip install --upgrade pip
|
|
python -m pip install -r requirements.txt
|
|
python berger_gui.py
|
|
```
|
|
|
|
The GUI uses native WinRT Bluetooth through `bleak` on Windows.
|
|
|
|
## App Workflow
|
|
|
|
The app's telemetry flow is:
|
|
|
|
1. Open the Bluetooth adapter.
|
|
2. Start BLE discovery filtered to service `0000ff00-0000-1000-8000-00805f9b34fb`.
|
|
3. Connect to the selected peripheral.
|
|
4. Discover services and characteristics.
|
|
5. Subscribe to notifications on `ff01`.
|
|
6. Write JBD read frames to `ff02`.
|
|
7. Buffer notify chunks, split complete `DD ... 77` frames, validate checksum,
|
|
and parse the response payload into UI state.
|
|
|
|
## Minimal BLE Workflow
|
|
|
|
1. Connect to the device over BLE GATT.
|
|
2. Discover services.
|
|
3. Subscribe to notifications on `ff01` under service `ff00`.
|
|
4. Write the base-data read frame to `ff02`:
|
|
|
|
```text
|
|
DDA50300FFFD77
|
|
```
|
|
|
|
5. Write the cell-voltage read frame to `ff02`:
|
|
|
|
```text
|
|
DDA50400FFFC77
|
|
```
|
|
|
|
6. Parse notifications from `ff01`.
|
|
|
|
## Caveats
|
|
|
|
- This catalog is code-derived from the Android app bundle, not yet confirmed
|
|
against a live HCI capture.
|
|
- The desktop app currently implements read-only telemetry. The Android app has
|
|
charge/discharge MOS and factory/name/capacity write paths; those are
|
|
documented, but deliberately not exposed as GUI buttons yet.
|
|
- Only one phone/client can normally hold the battery GATT connection at a time.
|
|
Close the Android app before connecting from a PC.
|