A lightweight, dependency-free Rust application designed for the Raspberry Pi Zero W (or any Linux machine) to read advertising beacons from various BLE thermometers and export their metrics to Prometheus and OpenTelemetry (OTLP).
- Broad Device Support:
- Govee: H5075 and other H-series BLE beacons.
- Xiaomi Mijia (LYWSD03MMC): Custom ATC or PVVX firmwares (broadcasting Environmental Sensing data under UUID
0x181A). - Inkbird: IBS-TH1 and IBS-TH2 temperature/humidity beacons.
- RuuviTag: RAWv2 (Data Format 5) environmental beacons.
- Zero-Dependency Bluetooth Parsing: Spawns and streams output from
hcitoolandbtmon, bypassing complex Bluetooth C library dependency chains to ensure simple, robust cross-compilation. - Built-in Prometheus Exporter: Exposes a lightweight Prometheus HTTP scraper endpoint (default port:
9103). - OTLP Metrics Pushing: Pushes gauge metrics directly to any standard OpenTelemetry HTTP JSON receiver (e.g.
http://loki:4318/v1/metrics). - Autodiscovery: Auto-discovers any broadcasting supported BLE sensor in range, or can be restricted to specific target MAC addresses.
- Custom Naming Labels: Allows associating user-friendly location names (like
living_room) with device MAC addresses.
| Metric Name | Type | Description | Labels |
|---|---|---|---|
sensor_temperature_celsius |
Gauge | Temperature in Celsius | location, mac, brand |
sensor_temperature_fahrenheit |
Gauge | Temperature in Fahrenheit | location, mac, brand |
sensor_humidity_percent |
Gauge | Relative humidity percentage | location, mac, brand |
sensor_battery_percent |
Gauge | Battery level percentage | location, mac, brand |
sensor_rssi_dbm |
Gauge | Bluetooth signal strength (RSSI) | location, mac, brand |
sensor_last_seen_seconds |
Gauge | Timestamp of last received packet | location, mac, brand |
| OTLP Metric | Unit | Description | Resource / Attributes |
|---|---|---|---|
sensor.temperature.celsius |
Cel |
Temperature in Celsius | location, mac, brand |
sensor.temperature.fahrenheit |
F |
Temperature in Fahrenheit | location, mac, brand |
sensor.humidity |
% |
Relative humidity percentage | location, mac, brand |
sensor.battery |
% |
Battery level percentage | location, mac, brand |
sensor.rssi |
dBm |
BLE signal strength | location, mac, brand |
The exporter relies on the standard Linux Bluetooth tools (hcitool and btmon). Install them on the target Raspberry Pi:
sudo apt update
sudo apt install bluezIf the target Pi has Rust installed, compile the binary natively:
make buildIf compiling from your local machine to deploy to a Pi Zero W (which uses the 32-bit ARMv6 architecture), cross-compile using the musl toolchain:
cargo build --release --target arm-unknown-linux-musleabihf- Copy the compiled binary to
/usr/local/bin/ble-sensor-exporteron the target Pi and ensure it is executable:chmod +x /usr/local/bin/ble-sensor-exporter
- Copy the defaults file
ble-sensor-exporter.defaultto/etc/default/ble-sensor-exporterand customize it:sudo cp ble-sensor-exporter.default /etc/default/ble-sensor-exporter sudo nano /etc/default/ble-sensor-exporter
- Copy the service definition
ble-sensor-exporter.serviceto/etc/systemd/system/ble-sensor-exporter.service. - Install and enable the systemd service:
sudo make setup-service
You can configure the exporter to monitor multiple sensors in two different modes by editing /etc/default/ble-sensor-exporter on the target Pi:
Restricts decoding to only the specified MAC addresses and assigns custom location labels to each:
BLE_SENSOR_EXPORTER_OPTS="-prom-port 9103 \
-mac A4:C1:38:54:6B:55 -location A4:C1:38:54:6B:55=first_floor_office \
-mac A4:C1:38:12:34:56 -location A4:C1:38:12:34:56=living_room \
-mac A4:C1:38:78:90:AB -location A4:C1:38:78:90:AB=master_bedroom \
-otlp-endpoint http://prom.k.net:4318/v1/metrics \
-interval 15"Omits the -mac filters entirely. The exporter will automatically detect, decode, and push metrics for every supported BLE sensor it hears in Bluetooth range. You can still supply optional location mappings for known devices:
BLE_SENSOR_EXPORTER_OPTS="-prom-port 9103 \
-location A4:C1:38:54:6B:55=first_floor_office \
-location A4:C1:38:12:34:56=living_room \
-otlp-endpoint http://prom.k.net:4318/v1/metrics \
-interval 15"Any discovered sensor without an explicit location mapping will default to using its MAC address as its location label value.
After saving your configuration changes, restart the service to apply them:
sudo systemctl restart ble-sensor-exporterThe exporter is highly optimized for resource-constrained environments like the Raspberry Pi Zero W:
- Binary Size: ~860 KB (statically linked, fully stripped, compiled with Link-Time Optimization (LTO) and size optimizations enabled).
- Exporter Memory (RAM): ~790 KB RSS (0.1% memory).
- Exporter CPU Usage: ~1.5% CPU on a single-core Pi Zero W.
- Helper Tool (
btmon): ~2.9 MB RAM, ~12% CPU.
BLE Sensor Exporter
Usage: ble-sensor-exporter [options]
Options:
-prom-port <port> Port for Prometheus metrics (default: 9103)
-enable-prom <true|false> Enable/disable Prometheus endpoint (default: true)
-otlp-endpoint <url> OTLP HTTP receiver endpoint
-interval <secs> OTLP metric push interval in seconds (default: 15)
-mac <address> Target MAC address to monitor (can specify multiple times)
-location <mac=location_name> Custom location label for a MAC address (can specify multiple times)
-debug Enable verbose debug logging
-h, --help Print this help menu