Skip to content

ble

tested on simulator

Tier Tier 1
Protocol Bluetooth Low Energy GATT
Covers environmental sensors, battery powered sensors, BLE LED and relay boards, DIY ESP32, nRF52 and Pico W peripherals
Hazard default low
Conformance control
Tested with fake BleakClient and BleakScanner with a simulated Environmental Sensing peripheral

Estimated reach. Thousands of models. Any BLE peripheral whose characteristics use standard formats can be described in a device file, and describe() maps the SIG Environmental Sensing and Battery services automatically. Billions of BLE devices ship each year, but many use encrypted or undocumented vendor protocols, so the realistic count is the devices with standard services or a documented GATT table, which is still thousands of models.

The ble driver reads and writes GATT characteristics of Bluetooth Low Energy peripherals through bleak, on Linux with BlueZ, macOS and Windows.

Supports

  • Number, bool, enum and string reads. stream: true subscribes to notifications or indications.
  • Writes with or without response, replacing the whole characteristic.
  • Every GATT Specification Supplement number format, including IEEE 11073 sfloat and float.
  • address: auto picks the one advertiser matching match.ble_name and match.ble_services. discover() lists advertisers without connecting.
  • identify() and describe() read the Device Information service.

Setup

uv tool install --compile-bytecode "halkit[ble] @ git+https://github.com/sohan-bhat/OpenHAL"

Linux needs BlueZ 5.55 or newer and the bluetooth group. On macOS the app running the hub needs Bluetooth permission, and peripherals use a CoreBluetooth UUID from discover() instead of a MAC address.

ParameterDefaultMeaning
addressautoMAC address, CoreBluetooth UUID on macOS, or auto. ble: auto is shorthand
scan_timeout5 sScan time for auto
timeout10 sConnect, read and write deadline
pairfalsePair on connect, for encrypted characteristics

Channel maps

read:
  temperature: { unit: degC, stream: true, map: { characteristic: 2a6e, format: sint16, scale: 0.01 } }
  battery: { unit: percent, map: { characteristic: 2a19 } }
write:
  led: { unit: percent, min: 0, max: 100, map: { characteristic: 6e400002-b5a3-f393-e0a9-e50e24dcca9e, scale: 0.5 } }
KeyDefaultMeaning
characteristicrequired16-bit SIG UUID such as 2a6e, or a 128-bit UUID
servicenoneService UUID, when the characteristic is in several services
formatuint8uint8, uint16, uint24, uint32, sint8 to sint32, float32, float64, sfloat, float, utf8
byte0Byte offset. Reads only
byteorderlittleSome vendor characteristics are big-endian
scale, offset1, 0value = raw × scale + offset
on, off1, 0Raw bool values
valuesnoneEnum word to raw value, required for enums
responsedevice defaultWrite with or without response

Writes send raw = (value - offset) / scale, rounded for integer formats, and return the value sent. A value outside the format fails with nothing sent.

A stream: true channel returns the newest notification, or a GATT read before the first one, or None when the characteristic has no read. Other channels read each time. A write-only characteristic reports the last value written.

Describe

CharacteristicChannelFormatScaleUnit
0x2A6E Temperaturetemperaturesint160.01degC
0x2A6F Humidityhumidityuint160.01percent
0x2A6D Pressurepressureuint320.1Pa
0x2A76 UV Indexuv_indexuint81dimensionless
0x2A6C Elevationelevationsint240.01m
0x2A19 Battery Levelbattery_leveluint81percent

describe() suggests these channels, fills device and match.ble_services, and lists vendor characteristics in the notes.

Example

openhal/drivers/ble/examples/environment-sensor.hal.yaml reads a room sensor's Environmental Sensing service.

Errors

  • DriverError for no match or several matches under auto, failed connects, missing characteristics, GATT errors, short values, IEEE 11073 NaN, NRes and infinity, and non-finite floats.
  • TimeoutError past timeout.

Limitations

  • No actions, images or descriptors.
  • Most peripherals take one central, so close the vendor's phone app.
  • Values split across characteristics or behind a flags byte, such as Health Thermometer, need a dedicated driver.
  • No advertisement-only sensors yet.

Hazard default and safe state

Low. safe_state_support is file, and the hub writes safe_state only while the link is up. Many peripherals keep their last state when the link drops.

Sources