Skip to content

Instantly share code, notes, and snippets.

@haxrob
Created June 1, 2023 23:04
Show Gist options
  • Save haxrob/3af7efdcd3465aac09093081c32ba321 to your computer and use it in GitHub Desktop.
Save haxrob/3af7efdcd3465aac09093081c32ba321 to your computer and use it in GitHub Desktop.
Read voltage levels from BM2 Battery Monitor over BLE
#!/usr/bin/python3
import asyncio
import sys
from bleak import BleakClient
import binascii
from Crypto.Cipher import AES
from datetime import datetime
key = bytearray([(b&255) for b in [108,101,97,103,101,110,100,-1,-2,49,56,56,50,52,54,54]])
char = "0000fff4-0000-1000-8000-00805f9b34fb"
async def main(address, char):
async with BleakClient(address, char) as client:
print("[+] connected")
await client.start_notify(char, callback_handler)
await asyncio.sleep(100000.0)
await client.stop_notify(char)
async def callback_handler(_, data):
cipher = AES.new(key, AES.MODE_CBC, 16 * b'\0')
ble_msg = cipher.decrypt(data)
raw = binascii.hexlify(ble_msg).decode()
voltage = int(raw[2:5],16) / 100.0
power = int(raw[6:8],16)
now = datetime.utcnow().strftime('%F %T.%f')[:-3]
print("[%s] voltage: %.2f, power: %d" % (now, voltage, power))
if __name__ == "__main__":
if len(sys.argv) != 2 :
print("Usage: %s <mac address>\n" % sys.argv[0])
else :
address = sys.argv[1]
asyncio.run(main(address, char))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment