Reverse engineering the popular BM2 BLE car battery monitor

61842QRRRyL._SL1500_.jpg
Someone has taken the time to properly reverse engineer the apps used with these popular BM2 lead acid battery monitoring solutions. As suspected, it phones home and reports data back to Chinese infrastructure, generating major privacy concerns.
A great 3-part article which is worth checking out.

However, there is a work around here for Home Assistant users. Since I have this same hardware, but always refused to install the app, I figured out how to grab this data using an ESP32 running ESPHome. Now I can read the BLE (Bluetooth Low Energy) broadcasts raw data into ESPHome, which can massage the data and output the actual voltage of the battery, no Chinese application required.

I personally use this setup to alert me when my vehicle's (only gets driven once a week at best) lead acid battery drops too low for comfort. This data is more helpful in the winter, where not being able to predict battery performance can be an issue and having it trickle charge is not an option. I may create a write up for this someday, if there's interest.

Taken from my Home Assistant dashboard:
 

Attachments

  • 1688269001750.png
    1688269001750.png
    27.9 KB · Views: 212
Last edited:
I'd be interested in a write up!
I'm here after finding that my car had drained the battery for several days. A warning when it started to get a little low would have been perfect.

Even without a detailed write up, something like a system diagram (can the ESP32 act as a Bluetooth dongle to the HA server, or does there have to be wifi in the mix too?) and an understanding of how you configured the alert would cut down my leg work.

Cheers!
 
I'm just using a standard ESP32 running ESPHome. ESPHome is connected via WiFi, and connects to the vehicle via BLE. Once you added the board to Home Assistant, you can edit the basic configuration via the ESPHome option in the menu, and add the following sensors (replace XX with your actual MAC address):

YAML:
esp32_ble_tracker:

#text_sensor:
  #use this sensor to show all devices within range
  #- platform: ble_scanner
  #  name: "BLE Devices Scanner"

binary_sensor:
    - platform: status
      name: "ESP32 (Garage)"

sensor:
  - platform: uptime
    name: Uptime Sensor
  - platform: wifi_signal
    name: "WiFi Signal Sensor"
    update_interval: 60s
  - platform: ble_client
    type: characteristic
    ble_client_id: bm2_battery_meter
    name: Voltage
    service_uuid: 'fff0'
    characteristic_uuid: 'fff4'
    unit_of_measurement: 'V'
    accuracy_decimals: 2
    state_class: measurement
    device_class: voltage
    force_update: true
    notify: true
    lambda: |-
      mbedtls_aes_context aes;
      mbedtls_aes_init(&aes);
      unsigned char output[16];
      unsigned char key[16] = { 108, 101, 97, 103, 101, 110, 100, 255, 254, 49, 56, 56, 50, 52, 54, 54, };
      unsigned char iv[16] = {};
      mbedtls_aes_setkey_dec(&aes, key, 128);
      mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, 16, iv, (uint8_t*)&x[0], output);
      mbedtls_aes_free(&aes);
      return ((output[2] | (output[1] << 8)) >> 4) / 100.0f;
    filters:
        #delta: .01
        throttle: 60s
  - platform: ble_rssi
    mac_address: XX:XX:XX:XX:XX:XX
    name: "bm2_rssi"
      
ble_client:
  - mac_address: XX:XX:XX:XX:XX:XX
    id: bm2_battery_meter

I have 1 automation which triggers an alert:
Code:
alias: NOTIFY when car 12V battery SoC is LOW (BETA)
description: ""
trigger:
  - type: voltage
    platform: device
    device_id: 5807b6f27d0a93ff1cd94bbd929a9070
    entity_id: sensor.voltage
    domain: sensor
    below: 11.5
    for:
      hours: 0
      minutes: 30
      seconds: 0
      milliseconds: 0
condition: []
action:
  - service: notify.mobile_app_pixel
    data:
      title: "Vehicle Alert: car low battery ({{ states('sensor.voltage')|float }})"
      message: Lead acid battery SoC is below treshold
mode: restart

I'll try to clean this up tomorrow, but this should get you going.
 
Back
Top