BTHome Binding [4.0.0.0;6.0.0.0)

NOTE: Ensure that the Bluetooth binding is installed on your system as well, or the binding will not start

Bluetooth binding for any BTHome device. Examples include

  • b-parasite plant sensor
  • Shelly BLU Button
  • Shelly BLU Door/window
  • ATC MiThermometer

.. and more.

Latest OH jars can be found here

README

Take a look at https://bthome.io/ for more information.

The binding is mostly complete with just encryption support missing.

To see what’s happening, read the commit log

Arne

Update: Added datatypes used by all Shelly BLU products

First thanks for this binding. I’m seeing odd behaviour with thing channels using it though (4.1.0 snapshot) on openhab 5.2. I have 10 or so ATC Mithermometers and a couple of esp32 bluetooth proxies, some work ok others keep changing available channels. The channels detected switch between temp, humidity and battery like this (when working ok):

UID: bluetooth:bthome:proxy:ATCbasement
label: BTHome basement thermometer
thingTypeUID: bluetooth:bthome
configuration:
  expectedReportingIntervalSeconds: 1200
  address: A4:C1:38:05:76:16
bridgeUID: bluetooth:esphome:proxy
channels:
  - id: humidity
    channelTypeUID: bluetooth:bthome-ATCbasement-humidity
    label: Humidity
    configuration: {}
  - id: temperature
    channelTypeUID: bluetooth:bthome-ATCbasement-temperature
    label: Temperature
    configuration: {}
  - id: packet-id
    channelTypeUID: bluetooth:bthome-ATCbasement-packet-id
    label: Packet-id
    configuration: {}
  - id: battery
    channelTypeUID: bluetooth:bthome-ATCbasement-battery
    label: Battery
    configuration: {}

and the following for the same device when not working:

UID: bluetooth:bthome:proxy:ATCbasement
label: BTHome basement thermometer
thingTypeUID: bluetooth:bthome
configuration:
  expectedReportingIntervalSeconds: 1200
  address: A4:C1:38:05:76:16
bridgeUID: bluetooth:esphome:proxy
channels:
  - id: opening
    channelTypeUID: bluetooth:bthome-ATCbasement-opening
    label: Opening
    configuration: {}
  - id: voltage
    channelTypeUID: bluetooth:bthome-ATCbasement-voltage
    label: Voltage
    configuration: {}
  - id: power-on
    channelTypeUID: bluetooth:bthome-ATCbasement-power-on
    label: Power-on
    configuration: {}
  - id: packet-id
    channelTypeUID: bluetooth:bthome-ATCbasement-packet-id
    label: Packet-id
    configuration: {}

Is there any way to prevent this? I have tried coding the channels I want in bthome.things below but that doesn’t do it:

bthome ATCbasement "BTHome basement thermometer" [ address="A4:C1:38:05:76:16", expectedReportingIntervalSeconds = 1200]{

    Channels:

       Type bthome-ATCbasement-temperature : temperature "Temperature" [pattern="%.1f °C"]

       Type bthome-ATCbasement-humidity : humidity "Humidity"

       Type bthome-ATCbasement-battery : battery "Battery"

} 

Funky.

Initial guess; the data is somehow corrupted - either coming from the device itself or somewhere along the data path (device → proxy → esphome binding → bthome binding).

If you could try to capture TRACE level logs for both the bthome and esphome binding around the time a device changes channels, that might be a clue where it goes wrong.

BRG

here are a couple of extracts from the trace log of things going wrong and right (should i attach this)

2025-11-15 11:06:24.958 [DEBUG] [uetooth.ESPHomeBluetoothProxyHandler] - Received duplicate BLE advertisement from device 202844586484103 via esphome:device:4d3ab917fe
2025-11-15 11:06:25.002 [TRACE] [ome.internal.comm.ConnectionSelector] - Num selected keys: 1
2025-11-15 11:06:25.002 [TRACE] [ome.internal.comm.ConnectionSelector] - Processing key readable=true, connectable=false
2025-11-15 11:06:25.002 [TRACE] [ome.internal.comm.ConnectionSelector] - Received data
2025-11-15 11:06:25.002 [TRACE] [e.internal.comm.EncryptedFrameHelper] - [esphomeupstairs] Received packet of type 93 with data [10, 30, 8, -16, -18, -35, -61, -109, -104, 41, 16, -87, 1, 34, 17, 2, 1, 6, 13, 22, -46, -4, 64, 0, 64, 12, -47, 11, 16, 0, 17, 1, 10, 37, 8, -121, -61, -106, -4, -58, -113, 46, 16, -77, 1, 34, 24, 2, 1, 6, 20, 22, -107, -2, 113, 32, 19, 1, 125, -121, -95, -123, 111, 124, -72, 9, 5, 16, 2, 0, 20]
2025-11-15 11:06:25.002 [DEBUG] [home.internal.handler.ESPHomeHandler] - [esphomeupstairs] Received message type BluetoothLERawAdvertisementsResponse with content ‘advertisements {
address: 181149782996848
rssi: -85
data: “\002\001\006\r\026\322\374@\000@\f\321\v\020\000\021\001”
}
advertisements {
address: 202844586484103
rssi: -90
data: “\002\001\006\024\026\225\376q \023\001}\207\241\205o|\270\t\005\020\002\000\024”
}’
2025-11-15 11:06:25.002 [DEBUG] [uetooth.ESPHomeBluetoothProxyHandler] - Received BLE advertisement from device A4:C1:38:77:77:70/181149782996848 via esphome:device:esphomeupstairs
2025-11-15 11:06:25.003 [DEBUG] [etooth.bthome.internal.BTHomeHandler] - Received updated BTHome data
2025-11-15 11:06:25.003 [DEBUG] [etooth.bthome.internal.BTHomeHandler] - Created new channel type bluetooth:bthome-ATCpotato-opening
2025-11-15 11:06:25.003 [DEBUG] [etooth.bthome.internal.BTHomeHandler] - Created new channel type bluetooth:bthome-ATCpotato-voltage
2025-11-15 11:06:25.003 [DEBUG] [etooth.bthome.internal.BTHomeHandler] - Created new channel type bluetooth:bthome-ATCpotato-power-on
2025-11-15 11:06:25.004 [DEBUG] [uetooth.ESPHomeBluetoothProxyHandler] - Received duplicate BLE advertisement from device 202844586484103 via esphome:device:esphomeupstairs
2025-11-15 11:06:25.361 [TRACE] [ome.internal.comm.ConnectionSelector] - Num selected keys: 1
2025-11-15 11:06:25.361 [TRACE] [ome.internal.comm.ConnectionSelector] - Processing key readable=true, connectable=false
2025-11-15 11:06:25.361 [TRACE] [ome.internal.comm.ConnectionSelector] - Received data
2025-11-15 11:06:25.361 [TRACE] [e.internal.comm.EncryptedFrameHelper] - [esphomeupstairs] Received packet of type 93 with data [10, 46, 8, -120, -4, -122, -30, -116, -30, 26, 16, -89, 1, 24, 1, 34, 31, 2, 1, 2, 3, 3, -97, -2, 23, 22, -97, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2025-11-15 11:06:25.362 [DEBUG] [home.internal.handler.ESPHomeHandler] - [esphomeupstairs] Received message type BluetoothLERawAdvertisementsResponse with content ‘advertisements {
address: 117719890509320
rssi: -84
address_type: 1
data: “\002\001\002\003\003\237\376\027\026\237\376\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000”
}’


and again when it goes right

2025-11-15 11:07:27.617 [TRACE] [e.internal.comm.EncryptedFrameHelper] - [4d3ab917fe] Received packet of type 93 with data [10, 31, 8, -16, -18, -35, -61, -109, -104, 41, 16, -61, 1, 34, 18, 2, 1, 6, 14, 22, -46, -4, 64, 0, 70, 1, 100, 2, 76, 8, 3, -127, 20, 10, 46, 8, -52, -40, -89, -40, -76, -11, 12, 16, -87, 1, 24, 1, 34, 31, 30, -1, 6, 0, 1, 9, 32, 34, -126, 7, 78, -14, -122, -93, 78, 17, -73, -123, -55, 126, 73, 59, -42, 23, 7, 90, 109, -122, -17, -61, -48]
2025-11-15 11:07:27.617 [DEBUG] [home.internal.handler.ESPHomeHandler] - [4d3ab917fe] Received message type BluetoothLERawAdvertisementsResponse with content ‘advertisements {
address: 181149782996848
rssi: -98
data: “\002\001\006\016\026\322\374@\000F\001d\002L\b\003\201\024”
}
advertisements {
address: 56810791365708
rssi: -85
address_type: 1
data: “\036\377\006\000\001\t "\202\aN\362\206\243N\021\267\205\311~I;\326\027\aZm\206\357\303\320”
}’
2025-11-15 11:07:27.617 [DEBUG] [uetooth.ESPHomeBluetoothProxyHandler] - Received BLE advertisement from device A4:C1:38:77:77:70/181149782996848 via esphome:device:4d3ab917fe
2025-11-15 11:07:27.617 [DEBUG] [etooth.bthome.internal.BTHomeHandler] - Received updated BTHome data
2025-11-15 11:07:27.617 [DEBUG] [etooth.bthome.internal.BTHomeHandler] - Created new channel type bluetooth:bthome-ATCpotato-battery
2025-11-15 11:07:27.617 [DEBUG] [etooth.bthome.internal.BTHomeHandler] - Created new channel type bluetooth:bthome-ATCpotato-humidity
2025-11-15 11:07:27.618 [DEBUG] [etooth.bthome.internal.BTHomeHandler] - Created new channel type bluetooth:bthome-ATCpotato-temperature
2025-11-15 11:07:27.619 [DEBUG] [uetooth.ESPHomeBluetoothProxyHandler] - Received duplicate BLE advertisement from device 56810791365708 via esphome:device:4d3ab917fe
2025-11-15 11:07:27.620 [TRACE] [ome.internal.comm.ConnectionSelector] - Num selected keys: 1
2025-11-15 11:07:27.621 [TRACE] [ome.internal.comm.ConnectionSelector] - Processing key readable=true, connectable=false
2025-11-15 11:07:27.621 [TRACE] [ome.internal.comm.ConnectionSelector] - Received data
2025-11-15 11:07:27.621 [TRACE] [e.internal.comm.EncryptedFrameHelper] - [esphomeupstairs] Received packet of type 93 with data [10, 37, 8, -121, -61, -106, -4, -58, -113, 46, 16, -65, 1, 34, 24, 2, 1, 6, 20, 22, -107, -2, 113, 32, 19, 1, -121, -121, -95, -123, 111, 124, -72, 9, 5, 16, 2, 0, 20]
2025-11-15 11:07:27.621 [DEBUG] [home.internal.handler.ESPHomeHandler] - [esphomeupstairs] Received message type BluetoothLERawAdvertisementsResponse with content ‘advertisements {
address: 202844586484103
rssi: -96
data: “\002\001\006\024\026\225\376q \023\001\207\207\241\205o|\270\t\005\020\002\000\024”
}’

This device apparently sends 2 different packets

  • One with temp, humidity and battery percentage(?)
  • Second packet (less frequently) with more battery information.

Instead of aggregating the channels (4 existing + 3 new), the existing channels were replaced with the new ones. The correct thing to do would to just aggregate the channels.

So after updating expect to find all 7 distinct channels on each thing.

Thanks for testing,
BRG

Thanks for the update! Now I’m seeing 7 (or 8 for one of them) channels for each device. I didn’t guess that the ATC firmware for the Xiaomi LYWSD03MMC was splitting the data despite it making sense to do so.