Skip to content

Protocol BTHome

stephan-xyz edited this page Sep 13, 2026 · 4 revisions

Protocol: BTHome (BLE Sensor Broadcasts)

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)

1. Why BTHome?

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).

2. Prominent BTHome Devices

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

3. Protocol Versions & Service UUIDs

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) or 0x181E (Bond Management)

BTHome V2 Packet Structure

[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)

Measurement Object Types (IDs)

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 (0 or 1, 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)

4. Encryption (AES-CCM)

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.

5. HomeNode Integration Architecture (Shelly BLE Gateway First)

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)

Advantages of the Shelly Gateway Approach:

  1. Whole-Home Coverage: Shelly relays are already installed in walls and ceilings across multiple rooms and floors, completely eliminating Bluetooth range issues.
  2. 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.
  3. Server-Side Deduplication: BTHome packets include an incrementing packet_id (counter). When 3 or 4 Shellys receive the same broadcast simultaneously, homenode-module-bthome deduplicates them in memory and processes the event exactly once (using the strongest RSSI).
  4. Server Hardware Independence: HomeNode Server can run on a virtual machine, NAS, or Mac without needing direct Bluetooth hardware access.
  5. 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.

6. Shelly BLE Gateway Script Setup

The script runs directly on any Shelly Gen2, Gen3, or Pro device (Plus 1PM, Pro 3EM, Plus 2PM, etc.).

Step-by-Step Installation:

  1. Open the Shelly device web interface in your browser (e.g. http://192.168.178.xx).
  2. Go to Settings -> Bluetooth: Ensure Bluetooth and Bluetooth Gateway are enabled.
  3. In the sidebar, select Scripts -> Add Script.
  4. Set the script name to HomeNode BLE Gateway.
  5. 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);
  1. Click Save, click Start, and toggle Run on startup to ON.
  2. Repeat for any Shelly relays throughout the house to achieve seamless mesh coverage.

Clone this wiki locally