Repository navigation
Protocol BTHome
BTHome is an open, energy-efficient Bluetooth Low Energy (BLE) payload standard designed for battery-powered smart home sensors and IoT devices.
- Official Website: https://bthome.io/
-
HomeNode Module:
modules/bthome(homenode-module-bthome) - Transport: Bluetooth Low Energy (BLE) Advertising Data (Non-connectable broadcasts)
- Encryption: Optional pre-shared key (AES-CCM 128-bit with 4-byte counter and 4-byte MIC)
Traditional BLE devices require a bilateral connection (GATT connection), which drains battery power and limits the number of simultaneously connected sensors.
BTHome operates entirely via passive BLE advertisements:
- Sensors broadcast their data payload every few seconds or when an event occurs (e.g. button click, motion detected).
- Receivers (like HomeNode Server via a local Bluetooth adapter or ESP32 Bluetooth Proxies) passively listen and decode the packets.
- Sensor batteries last 1 to 5 years (e.g. CR2032 coins).
| Device Family | Examples | Broadcast Data |
|---|---|---|
| Shelly BLU | Shelly BLU Button 1, BLU Door/Window, BLU Motion, BLU H&T | Battery %, Button click (single, double, triple, long), Window open/close, Lux, Temperature, Humidity |
| BTHome DIY Sensors | ESPHome BTHome, Arduino BLE, Zephyr, Nordic nRF52 | Any custom sensor values |
| Environmental Beacons | Xiaomi Mijia with BTHome custom firmware, Qingping | Temperature, Humidity, Pressure, Battery |
BTHome defines standardized Service Data UUIDs in the BLE advertisement:
-
BTHome V2 (Latest): Service Data UUID
0xFCD2(16-bit) -
BTHome V1 (Legacy): Service Data UUID
0x181C(Ambient Temperature) or0x181E(Bond Management)
[Length] [Service Data Type (0x16)] [UUID: 0xD2, 0xFC] [BTHome BExt Byte] [Object 1: ID, Data...] [Object 2...]
The BTHome header byte (BExt) defines flags:
- Bit 0: Encryption enabled (
0= plaintext,1= encrypted payload) - Bit 2-4: BTHome version (
010= Version 2)
Standard object IDs encode measurement types with explicit units:
-
0x00: Packet ID (counter) -
0x01: Battery percentage (%, uint8) -
0x02: Temperature (0.01 °C, sint16) -
0x03: Humidity (0.01 %, uint16) -
0x04: Pressure (0.01 hPa, uint24) -
0x05: Illuminance (0.01 lux, uint24) -
0x0F: Generic Boolean (0or1, uint8) -
0x1A: Door/Window contact sensor (0= closed,1= open) -
0x21: Motion sensor (0= clear,1= detected) -
0x3A: Button press event (1= press,2= double,3= triple,4= long press)
For tamper-resistant and privacy-preserving sensors (like door/window sensors and buttons), BTHome supports payload encryption:
- Cipher: AES-128-CCM
- Key: 16-byte pre-shared encryption key (bind key provided by manufacturer app, e.g. Shelly Smart Control)
- Nonce: 13 bytes formed by device MAC address (6 bytes), Service UUID (2 bytes), BTHome Header (1 byte), and 4-byte Counter.
- Verification: 4-byte MIC tag ensures packets cannot be spoofed or replayed.
Instead of requiring dedicated Bluetooth hardware or dongles on the HomeNode host server, HomeNode utilizes the existing Shelly Gen2 / Gen3 / Pro devices throughout the house as distributed BLE gateways.
[ Shelly BLU Sensors ] (BLE)
│
▼
[ Shelly Gen2/Gen3/Pro Relays ] (BLE Gateway Script / RPC Forwarder)
│
▼ (LAN WebSockets / HTTP Webhooks over Wi-Fi)
[ HomeNode Server: bthome-module ]
│
▼ (gRPC UDS)
[ HomeNode Supervisor ]
│
├─────────────────────────────────────────┐
▼ ▼
[ Web Dashboard & HMI ] [ Matter Bridge ]
(Live Battery, Lux, Temp, Door, Click) (Exposed as Native Matter Sensors)
- Whole-Home Coverage: Shelly relays are already installed in walls and ceilings across multiple rooms and floors, completely eliminating Bluetooth range issues.
- Multi-Gateway Mesh & Roaming: Multiple Shellys can listen simultaneously. If a sensor is carried through the house (e.g. BLU Button) or sits between rooms, whichever Shelly hears the signal forwards it.
-
Server-Side Deduplication: BTHome packets include an incrementing
packet_id(counter). When 3 or 4 Shellys receive the same broadcast simultaneously,homenode-module-bthomededuplicates them in memory and processes the event exactly once (using the strongest RSSI). - Server Hardware Independence: HomeNode Server can run on a virtual machine, NAS, or Mac without needing direct Bluetooth hardware access.
- Zero Battery Drain on Host: Shelly devices do the continuous radio scanning and deliver pre-filtered BTHome packets over local Ethernet/Wi-Fi to HomeNode Server.
The script runs directly on any Shelly Gen2, Gen3, or Pro device (Plus 1PM, Pro 3EM, Plus 2PM, etc.).
- Open the Shelly device web interface in your browser (e.g.
http://192.168.178.xx). - Go to Settings -> Bluetooth: Ensure Bluetooth and Bluetooth Gateway are enabled.
- In the sidebar, select Scripts -> Add Script.
- Set the script name to
HomeNode BLE Gateway. - Paste the following script:
let CONFIG = {
// Replace with the IP address of your HomeNode Server (port 8124)
homenode_url: "http://192.168.178.100:8124/bthome",
min_rssi: -90,
debug: false,
};
let BTHOME_SVC_ID_STR = "fcd2";
let SHELLY_DEVICE_ID = (Shelly.getDeviceInfo && Shelly.getDeviceInfo().id) ? Shelly.getDeviceInfo().id : "shelly-gateway";
function onScanResult(ev, res) {
if (ev !== BLE.Scanner.SCAN_RESULT) return;
if (!res.service_data || typeof res.service_data[BTHOME_SVC_ID_STR] === "undefined") return;
if (typeof res.rssi === "number" && res.rssi < CONFIG.min_rssi) return;
Shelly.call("HTTP.Request", {
method: "POST",
url: CONFIG.homenode_url,
timeout: 3,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
gateway: SHELLY_DEVICE_ID,
mac: res.addr,
rssi: res.rssi,
data: res.service_data[BTHOME_SVC_ID_STR]
})
}, function () {});
}
BLE.Scanner.Start({ duration_ms: BLE.Scanner.INFINITE_SCAN, active: false }, onScanResult);- Click Save, click Start, and toggle Run on startup to
ON. - Repeat for any Shelly relays throughout the house to achieve seamless mesh coverage.
(c) Stephan Zehrer 2025