I’ve been working on a custom integration that discovers Bluetooth devices and creates sensors from them automatically
What does it do?
Most Bluetooth devices should use the Bluetooth SIG specifications if they are transmitting standard data like temperature, atmospheric pressure, blood pressure, energy meters, etc. The standard defines exactly what each reading means, what unit it uses, and what it should be called. This integration reads the standard data and turns it into HA entities automatically.
When a compatible device is nearby, it shows up in the integration discovery panel for one-click confirmation. After that, sensors appear with correct units, device classes, and state classes already set. No YAML, no address configuration, no device-specific setup. You can do some extra configuration later, such as for connected devices, the polling interval or if you only want to use the advertisement data.
Example device screenshot at the bottom of the post
There are two ways data arrives.
- Advertisements: If a device is broadcasting its readings in advertisements, those updates are parsed without any connection.
- Connected Data: For characteristics that require a direct read, the integration connects periodically and polls them.
Both end up in the same entities.
What devices work?
Anything following standard Bluetooth SIG GATT profiles.
Common examples:
- Environmental sensors (temperature, humidity, CO₂, VOC, particulates, pressure, light)
- Health devices (heart rate, blood pressure, glucose, weight scales)
- Battery level from practically any BLE device
- Power and energy meters using IEC standard profiles
- Fitness equipment (treadmills, bikes, rowers)
If your device uses a proprietary protocol like BTHome or Xiaomi BLE, this is not the integration for it. Those have their own dedicated integrations that handle them much better.
A note on what shows up
The Bluetooth standard covers a huge range of characteristics, and not all of them are useful as everyday sensors. Things like firmware revision, device name, and feature capability flags are surfaced as diagnostic entities.
As there are ~500 characteristics, I am not sorting each into its own list, but there is some logic to sort them. At a high level, if the characteristic has units, it’s a sensor, otherwise, it’s a diagnostic entity.
Known limitations
- Encrypted characteristics are not supported. If a device requires pairing or an encrypted connection to expose its readings, this integration will not be able to read them.
- Devices with rotating Bluetooth addresses will not be discovered. Many phones and some devices randomise their MAC address periodically for privacy reasons. Those are filtered out by design since they cannot be reliably tracked across reboots.
- SIG standard UUIDs with custom implementations: This is a common problem, but some manufacturers will use the spec standard UUID but modify it for their custom implementation. This UUID will be scanned by the integration, but won’t show up as the code would’ve failed to parse the characteristic
- This is not intended for devices that need a persistent connection. The integration connects briefly to poll characteristics and then disconnects. If your device is intended to use persistent connections and updates data quickly/using notifications, this is not the correct integration for that device
The bluetooth SIG implementation is handled by RonanB96/bluetooth-sig-python which is a lib I wrote to handle this. Any issues around parsing SIG-compliant characteristics should be raised here. The integration will automatically handle it on an update of the dependency.
Installation:
Installation instructions are in the README, and configuration options are covered in the docs on that repo.
Links at the top, limited to two links in post
Examples
Example discovery of a Xiaomi temp and humidity sensor:
In this instance, Xiaomi implemented a custom and encrypted temperature and humidity characteristic, so it has not surfaced through this integration. But this info complements the characteristics that the Xiaomi integration doesn’t surface.
Limited to one media item in this post
