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 ?

Thanks,

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 '10.0.0.62'
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.

sensor:

  • platform: ble_client
    type: characteristic
    update_interval: 2min

Update
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.

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

sensor:
  - 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;
      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;

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.

Edit: I figured it out. Here’s a gist with the code that I’m using: BM2 PyScript Home Assistant Integration · GitHub

This works with a plain ESPHome Bluetooth Proxy and is completely passive.

Original message:

Do you have any more details or sample code for this? I’m trying to figure out how to do this from Home Assistant. I can see the advertisements from the device and I can see a series of manufacturer data blocks, but they’re 14 bytes and I can’t seem to decrypt them.

Thanks Pete - I’m trying this out! I had the ESPHome solution working, but your method will be much better for me if it works.

Hi Peter. I am trying to use your method, and think I have followed the instructions, but am not getting any data. The first apparently related error in my HA log is “ModuleNotFoundError: import from homeassistant.components not allowed” related to your “from homeassistant.components import bluetooth” - any ideas how to move past that?

Oh interesting. I just checked and I have these settings set in my Pyscript integration:

You probably only need “allow all imports”. Before you enable that please verify that I’m not doing anything weird! The only import should be the bluetooth one.

That fixed it, thanks! I need to tick both boxes - just the “imports” left another error that was fixed by selecting the other box too.

Thanks so much for working this out! This is the type of solution I have been wanting all along, but lacked the knowledge to develop myself. I was easily able to add my additional BM2 (main and aux batteries) using your work, and have all the template code in a package file to help keep track of it.