Skip to content

DynamicDevices/lcd-badge-ble

Repository files navigation

lcd-badge-ble

BLE tooling and protocol / reverse-engineering notes for DG01-class LCD pins (SuperBand / FitPro-style OEM apps). Primary reference: PROTOCOL.md.

Repository layout

Path Purpose
dg01-ble/ Rust CLI on Linux (BlueZ via bluer): scan, find, sync-time, query, device-info, battery-watch, dial-dims, dial-status, file-send-status, upload-dial — see PROTOCOL.md; APK ↔ tool parity notes: dg01-ble/APK_PARITY.md
PROTOCOL.md GATT map, framing, command IDs from APK analysis and local captures
ebadge_inspect.py, superband_find_device.py Python helpers (Bleak path; flaky vs BlueZ in practice)
capture_le_passive.sh, apk-get Shell helpers

Not tracked in git: APKs, JADX output tree (superband_jadx_src/), and the whole tools/ tree (local JADX install / zip) — download or regenerate locally.

Requirements

  • dg01-ble: Rust toolchain, Bluetooth adapter managed by BlueZ (typical Linux desktop / Pi).

BlueZ connect / disconnect (Linux)

The connect and disconnect subcommands use the same D-Bus methods as the Ubuntu Bluetooth settings toggle: org.bluez.Device1.Connect and Disconnect (via bluer, same path as bluetoothctl). Before connect, the tool sets Trusted=true when BlueZ allows it (helps unpaired LE peripherals — the panel shows Paired: No for some devices).

  • Default: no extra LE scan before connect (--warm-scan-secs defaults to 0). Use --warm-scan-secs N only if the device has never been seen by BlueZ and the D-Bus device object is missing.
  • If generic Connect hangs on LE-only gear, try --nus-profile-connect ( ConnectProfile on the NUS service UUID).
cd dg01-ble && cargo run --release -- connect --addr 0A:93:79:0C:DD:20
cd dg01-ble && cargo run --release -- disconnect --addr 0A:93:79:0C:DD:20

Find device (Linux)

dg01-ble find opens the link with Device1.Connect, then writes the find payload to the NUS TX characteristic. BlueZ returns quickly if the ACL is already up. --connect-timeout-secs, --nus-profile-connect, and --reconnect cover flaky links. See PROTOCOL.md.

cd dg01-ble && cargo run --release -- find --addr 0A:93:79:0C:DD:20

Optional --warm-scan-secs N ( N > 0 ): run LE discovery only when the address is not yet in BlueZ’s cache and you need to populate the device before Connect.

If the phone app holds the only LE link, disconnect it or turn phone Bluetooth off so Linux can connect.

Quick BlueZ check (no Connect): cargo run --release -- is-connected --addr 0A:93:79:0C:DD:20. Exit status 1 if Connected is false (prints ServicesResolved for info only).

Standard GATT: Device Information + Battery (device-info)

Subcommand device-info connects and reads:

  • Device Information (0x180A): manufacturer, model, serial, firmware, hardware, software, system ID, IEEE regulatory, PnP ID — decoded like nRF Connect (UTF-8 strings; PnP fields broken out).
  • Battery Service (0x180F): Battery Level (0x2A19) — SIG defines one octet 0–100 as %; some OEMs return extra octets; the decoded Value uses the first octet only; device-info still prints a Raw hex line for the full read.

If 0x180F is absent, a one-line notice is printed; 0x180A is still required for the command to succeed.

cd dg01-ble && cargo run --release -- device-info --addr 0A:93:79:0C:DD:20
cd dg01-ble && cargo run --release -- device-info --addr 0A:93:79:0C:DD:20 --disconnect

Vendor UART query (cmd 26) is separate from SIG GATT — use both if you want APK-style keys and standard DIS/battery reads.

Battery level while charging (battery-watch)

Subcommand battery-watch connects, subscribes to Battery Level (0x2A19) NOTIFY, and prints a line only when the device pushes a new value (no periodic GATT reads). If NOTIFY is missing or subscribe fails, it falls back to polling with --interval-secs (default 10).

Use --duration-secs N to stop after N seconds, or 0 to run until Ctrl+C. --disconnect ends the BLE session when the command exits so the adapter does not leave the link up (same idea as device-info --disconnect).

cd dg01-ble && cargo run --release -- battery-watch --addr 0A:93:79:0C:DD:20 --duration-secs 300 --disconnect
cd dg01-ble && cargo run --release -- battery-watch --addr 0A:93:79:0C:DD:20 --duration-secs 0 --disconnect

Dial dimensions (dial-dims)

dial-dims sends the same getDialClockInfo frame as the Android app (cmd 32 sub 2), reassembles 0xCD notifications if split, and prints width, height, and expected RGB565 payload size. Use this before upload-dial or pass --use-device-dial-dims on upload so image size is not guessed.

cd dg01-ble && cargo run --release -- dial-dims --addr 0A:93:79:0C:DD:20 --disconnect

There is no CLI command to list the phone-style catalogue of installed watch faces — that UI is driven by the app’s HTTP API; see PROTOCOL.md (watchface section).

Uploading splash on the badge: the stock app waits for a start ACK (status 1000) after cmd 31/2 before sending chunks; --skip-start-ack skips that wait and may mean the device never shows the uploading screen even if data still transfers — see PROTOCOL.md.

DG01 hardware vs FitPro APK UART UUIDs

The DG01 exposes Nordic UART Service with UUIDs 7e400001 / 7e400002 / 7e400003 (see PROTOCOL.md). The SuperBand / FitPro Android build uses the same 128-bit layout but with 6e40… instead of 7e40….

  • Talking to a real DG01 from Linux: use defaults — do not pass --apk-uart on query, upload-dial, dial-status, etc. Wrong UUIDs produce “characteristic not found” even when the link is up.
  • --apk-uart: only when emulating APK wire captures or a peripheral that actually exposes 6e400002.

APK-style status reads and upload tuning (dial-status, file-send-status, upload-dial)

FitPro uses periodic readStatus()-style UART polls during long transfers. dg01-ble exposes the same no-payload frames for debugging stalls:

Subcommand Frame (APK) Use
dial-status getNoValueProtocol(32, 1)getDialUpdateStatus() Dial (cmd 31) path
file-send-status getNoValueProtocol(35, 1)getFileSendStatus() File (cmd 34) path
# DG01 on Linux — omit --apk-uart (defaults use 7e400002/7e400003)
cd dg01-ble && cargo run --release -- dial-status --addr 0A:93:79:0C:DD:20 --disconnect
cd dg01-ble && cargo run --release -- file-send-status --addr 0A:93:79:0C:DD:20 --disconnect

Watchface upload (DG01, solid test pattern) — phone Bluetooth off; if Connect() hangs, disconnect the badge once (bluetoothctl or dg01-ble disconnect) and retry:

cd dg01-ble && cargo run --release -- upload-dial \
  --addr 0A:93:79:0C:DD:20 \
  --solid --use-device-dial-dims \
  --preflight-upload2 \
  --apk-parity \
  --disconnect

Omit --reconnect if the link is already stable; add --reconnect if GATT was stale. Use --skip-start-ack only for debugging (see PROTOCOL.md).

Automated matrix (iPhone / APK order, uploading UI checks): run dg01-ble/scripts/run_upload_like_app_tests.sh from the dg01-ble directory after cargo build --release. It runs is-connected, device-info, dial-dims, several dial-start-probe sequences with --preflight-upload2, then optional full solid uploads. Set SKIP_FULL_UPLOAD=1 to skip long transfers; DG01_ADDR=… to override the MAC.

Extra probes (no capture needed): dg01-ble/scripts/run_extra_ble_probes.sh runs sync-time, query, dial-status, small 64×64 upload attempts (often fail start ACK if firmware expects 360×360 — see script header), and optional RUN_DIM_MATCH_UPLOAD=1 for a full–screen solid with --skip-start-ack (debug only; long run).

upload-dial defaults are tuned toward phone captures: --gatt-fragment-gap-ms 3, --step-timeout-ms 10000. --apk-parity enforces at least 10 s step timeout and 3 ms fragment gap. Other useful flags:

  • --min-battery-percent N — read BAS (same service as device-info) before sending payload; abort if level is below N (0 = off).
  • --chunk-write-retries — optional resend of the same chunk after an ACK timeout (default 1 extra attempt).
  • --dial-read-status-after-start / --file-read-status-after-start — after start ACK 1000, send cmd 32/1 or cmd 35/1 and drain notifies (matches APK status-poll style).

Full behaviour and backlog: dg01-ble/APK_PARITY.md.

License

Tooling and documentation in this repository are provided as-is for interoperability research. Third-party apps and firmware remain under their respective terms.

About

BLE protocol notes and Linux tooling (Rust/bluer) for DG01-style LCD badges — SuperBand / FitPro OEM companion reverse-engineering.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

No contributors