A MicroPython module to format sensor readings for BTHome BLE advertising payloads.
BTHome-MicroPython provides an easy way to send sensor readings from MicroPython-based microcontrollers, via Bluetooth Low Energy (BLE) advertisements, to home automation systems like Home Assistant that support the BTHome data format.
The sample main.py shows how to transmit mocked-up temperature and humidity data in BTHome format using this module.
While many popular Bluetooth devices can have their stock firmware flashed to use BTHome and therefore easily integrate with Home Assistant, this does not help the hobbyist who wants to create a DIY sensor using an easily learned language like MicroPython. With this module, you can create custom sensors that act as Bluetooth beacons. Where you take it from there is up to your imagination.
The use case I had in mind when creating this is an ESP32 that sits on my front porch and measures outdoor temperature, humidity, and sunlight levels.
You could, but do you really want a device containing your WiFi credentials in an unsecured location outside your home? I don't. I'd rather broadcast BLE advertisements I can read from indoors. If the device sending them is lost or stolen, I'm out a few dollars, but no data is compromised.
Install this module and the aioble module to your microcontroller's /lib directory.
With mpremote's mip, it's like this:
mpremote connect PORT mip install github:DavesCodeMusings/BTHome-MicroPython
mpremote connect PORT mip install aioble-peripheral
Once you've got the modules installed, have a look at the code sample in main.py here in this repository.
Building your own sensor beacon boils down to this...
- Import the bthome module.
- Create a new instance of the BTHome class, passing in the device name you want.
- Read the sensors and write their values to the BTHome properties you want to communicate.
- Call the
pack_advertisement()
method with parameters to indicate what data to broadcast. - Send that advertising data to
aioble.advertise()
.
As MicroPython statements, those steps would be something like this:
from bthome import BTHome
beacon = BTHome("myBeacon")
beacon.temperature = dht.temperature()
beacon.humidity = dht.humidity()
advert = beacon.pack_advertisement(BTHome.TEMPERATURE_SINT16, BTHome.HUMIDITY_UINT16)
await aioble.advertise(BLE_ADV_INTERVAL_uS, adv_data=advert, connectable=False)
See main.py for a more robust example.
If the device has Bluetooth and can run recent versions of MicroPython, it should work.
My goal was to create an outdoor sensor to measure temperature, humidity, and illuminance so I could make automation decsions in Home Assistant. I've included nearly the entire list of object_ids described in the BTHome v2 format, but those outside of temperature, humidity, and battery level are untested in real world scenarios.
Sorry. Although BTHome offers encrypted communication, the MicroPython AES encryption implementation does not support the CCM mode required for BTHome encryption.
The number of bytes reserved for BLE advertising is extremely limited. You get 31 bytes. That's it. And you have to subtract things like advertising flags, service UUID, and length bytes from that total. So in the end you get 17 bytes to split between device name and sensor data.
Because of this, device name is silently truncted to 10 characters in length. If you try naming your device MySuperSensor, you will end up with MySuperSen instead.
If you try to pack too much sensor data, you'll get an exception. For example, using all 10 characters for a device name like DIY-Sensor and communiating BATTERY_UINT8_X1, TEMPERATURE_SINT16_X100, HUMIDITY_UINT16_X100, and PRESSURE_UINT24_X100 will be enough to exceed the allowable advertising payload size and result in an exception.
ValueError: BLE advertisement exceeds max length
If this happens, use the debugging output to determine the length of your advertising payload. You may be able to shorten the device name or limit the number of object IDs you're communicating to make it fit.
Test, test, test! I'm always happy to get bug reports in the GitHub issues for the project. The more detail you give, the easier it is to find and fix.
As for enhancements, unless the BTHome format undergoes significant changes (like a v3 release) I can't imagine there's much to add.