BM2 battery monitoring using ble tracker component

It works! I guess I was stupidly assuming the ESP32 had similar bluetooth range as the latest iPhone. I reinstalled the yaml and plugged the ESP32 into a USB battery for portability and left it on the car’s dashboard. Now when I check the logs in Esphome I am seeing voltages with 2 decimal places of accuracy! HOORAAYY!

To be clear, I got it through ESPHome, not through OpenMQTTGateway.

First Post ! yay
I’ve setup a BM2 and the esp32 config above and it’s working well, thank you !
My only question is how to adjust the config to allow me to monitor two BM2 devices?
Do i just replicate the BLE_Client and Sensor config below the current code with the second mac address and a new name ?


Yes, exactly that. See below.

Screenshot 2024-04-01 at 06.06.04.jpeg

1 Like

Glad you go it working.

Is this the ESPHome code you used?

Did you have to change anything?

Yes, its working. That’s prettymuch the code I used. I think I just updated the bluetooth address and name.

I have mine connected and partially working but no reporting of Voltage.

13:34:01	[D]	[esp32_ble_client:110]	
[0] [50:54:7B:5D:A4:40] Found device
13:35:34	[D]	[esp32_ble_client:110]	
[0] [50:54:7B:5D:A4:40] Found device
13:35:34	[D]	[esp32_ble_tracker:665]	
Found device 50:54:7B:5D:A4:40 RSSI=-70
13:35:34	[D]	[esp32_ble_tracker:686]	
  Address Type: PUBLIC
13:35:34	[D]	[esp32_ble_tracker:688]	
  Name: 'Battery Monitor'
13:51:26	[I]	[app:062]	
setup() finished successfully!
13:51:26	[D]	[text_sensor:064]	
'Dryderdale vehicle battery monitor IP Address': Sending state ''
13:52:58	[D]	[esp32_ble_client:110]	
[0] [50:54:7B:5D:A4:40] Found device
13:52:58	[D]	[esp32_ble_tracker:665]	
Found device 50:54:7B:5D:A4:40 RSSI=-70
13:52:58	[D]	[esp32_ble_tracker:686]	
  Address Type: PUBLIC
13:54:17	[I]	[mqtt:274]	
MQTT Connected!
14:00:29	[W]	[ble_sensor:123]	
[F12 Battery Voltage] Cannot poll, not connected

It reports the address type and device name correctly but I’m seeing cannot poll for voltage.

I have this working OK using OMG although voltage and percentage don’t report very often.

Any ideas?

Get closer to the BM2.
The bluetooth signal is not very strong. I have to keep the ESP32 pretty close to the BM2 to get them connected.

Before you drive yourself crazy in the software, get those two devices right next to each other and see if it works. If so, start experimenting to see how far away the connection stays solid.

This looks far better than BM2…

Guys, I found the voltage in the advertised messages of the BM2 (so no need to connect, no impact on the battery, and so on).

I don’t know if it’s a new feature (firmware V9), but I noticed that the app was receiving the data on the screen where you can choose the device, even when not connected (I was sure because the BM2 has different power consumption when connected and when not). So I searched deeper and found that the packets with service UUID 0xFFF0 have the voltage in the decrypted manufacturer data (decrypted as always, same key) in bytes 7 and 8, multiplied by 100.

@1technophile It should be pretty easy to implement if you like; you already have everything you need in OpenMQTTGateway.

I wanted to give back to the community, so I hope this helps someone!

Nice, could you share some samples of advertisement data and the expected values?
It would help the integration.

Sure! Unfortunately I don’t have samples available right now, but if someone provides me with a 32-character manufacturerdata string, I can post a practical example. Also for the BM6 if you want, so we can verify if the same applies.

You can find the messages using OpenMQTTGateway and any MQTT client under Home/esp32_device_name/BTtoMQTT/.

Something like this is published every few seconds (maybe 20?)

    "id": "XX:XX:XX:XX:XX:XX",
    "mac_type": 0,
    "adv_type": 0,
    "name": "Battery Monitor",
    "manufacturerdata": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "rssi": -50,
    "txpower": 0

At this point, it would also be interesting to try to understand what is in the rest of the data.

Is there any way to merge code with existing ESP32 bluetooth proxy build or I need use separate ESP32 unit just for BM2?

UPDATE: done it and it’s working like it should on one ESP32-C3 unit.

@longer can you explain or show me your code, how you have both BM2 and ble proxy on the ESP32

Thanks for all the info here, I can say the example code still works. (Using latest HA as of July 2024)

I have two networks, so had to add mDNS to config file and the network for the ESP to be picked up if that helps anybody.
And proximity is important, I also got errors not able to read values until I moved closer than where my phone worked.

My only remaining issue is frequency. I get a MQTT message every second, and I can’t seem to reduce it. (And I assume this is making a connection and reading the data every time) I really only need a measurement every 6 hours or so. Surely for a battery monitor something similar would be the case for most people.

Tried the below without luck. Tried various formats for the time as well. Any suggestions would be appreciated.


  • platform: ble_client
    type: characteristic
    update_interval: 2min

In my setup, update interval is the frequency the ESP tries to make the bluetooth connection. Once connected, it keeps measuring and sending once a second. It does not seem to disconnect.
I can see this when out of reach from the BM2, and it retries to connect.

  - mac_address: 12:34:56:78:90:CD
    id: bm2_battery_meter

  - platform: ble_client   
    type: characteristic
    update_interval: 3min
    ble_client_id: bm2_battery_meter
    name: Voltage
    service_uuid: 'fff0'
    characteristic_uuid: 'fff4'
    icon: 'mdi:battery'
    unit_of_measurement: 'V'
    accuracy_decimals: 2
    state_class: measurement
    device_class: voltage
    force_update: true
    expire_after: 240min
    notify: true

    lambda: |-
      mbedtls_aes_context 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);
      return ((output[2] | (output[1] << 8)) >> 4) / 100.0f;

Not sure how to change the update interval. But the point about proximity does have me wondering about powering the esp from a battery bank and putting it in the car.

Just a shame it wouldn’t be able to send data back to my HA server when the cars in the office car park.