Files
berger-ble-commands/docs/ble-flow.md
T

3.0 KiB

Berger LFP BLE Flow

This is the app flow used to obtain battery information such as discharge current, SOC, voltage, temperatures, cell voltages, MOS state, and estimated charge/discharge time.

Evidence

  • App package: com.jbd.berger
  • Version: 1.0.3
  • Main bundle: assets/apps/__UNI__F61076D/www/app-service.js
  • Source-map style log labels embedded in bundle:
    • utils/BLE.ts
    • App.vue
    • dashboard/control/parameter pages

Connection Sequence

  1. uni.openBluetoothAdapter()
  2. uni.startBluetoothDevicesDiscovery() with service filter ff00
  3. uni.onBluetoothDeviceFound() records devices and RSSI
  4. uni.createBLEConnection() with 10 second timeout
  5. uni.getBLEDeviceServices()
  6. uni.getBLEDeviceCharacteristics()
  7. uni.notifyBLECharacteristicValueChange() on ff01
  8. uni.onBLECharacteristicValueChange() buffers incoming bytes
  9. uni.writeBLECharacteristicValue() sends command chunks to ff02 with writeType: "writeNoResponse"

The app chunks outgoing buffers into 20-byte pieces before writing.

Services And Characteristics

  • Service: 0000ff00-0000-1000-8000-00805f9b34fb
  • Notify/read: 0000ff01-0000-1000-8000-00805f9b34fb
  • Write: 0000ff02-0000-1000-8000-00805f9b34fb

Pairing / Bonding

  • Needs Android bond before normal telemetry: likely no.
  • Evidence: the app uses uni-app BLE APIs for connection, service discovery, notifications, and writes. I did not find a normal-path bond request in the app bundle.
  • Caveat: a peripheral firmware could still enforce encryption independently, but the app flow itself does not show pairing as a telemetry prerequisite.

Getting Live Values

The app sends:

DD A5 03 00 FF FD 77

The response uses:

DD 03 <status> <length> <payload> <checksum> 77

Important payload fields for command 0x03:

Payload bytes Formula Unit Field
0..1 big-endian / 100 V pack voltage
2..3 signed big-endian / 100 A current
4..5 big-endian / 100 Ah remaining capacity
6..7 big-endian / 100 Ah nominal capacity
8..9 raw cycles cycle count
10..11 JBD bitfield date production date
12..13 nonzero bitmap boolean balancing
16..17 nonzero bitmap boolean protection
18 decimal digits version software version
19 raw % SOC
20 1 = charge, 2 = discharge, 3 = both boolean MOS state
22 raw count count temperature sensor count
23.. (raw - 2731) / 10 deg C temperatures

Production date bitfield:

day = value & 0x1F
month = (value >> 5) & 0x0F
year = 2000 + (value >> 9)

Estimated time is computed locally:

if current_A > 0:
  time_to_full = (nominal_Ah - remaining_Ah) / current_A
if current_A < 0:
  time_to_empty = remaining_Ah / abs(current_A)

Cell Voltages

The app sends:

DD A5 04 00 FF FC 77

The response command 0x04 payload is a sequence of big-endian 16-bit cell voltages scaled by 0.001 V.