1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-19 00:05:43 +00:00

[bthome_ble] Refactor to list-based sensor configuration

Refactored the component to use a list-based configuration structure that
reduces duplication and makes it clearer that multiple sensors come from
the same device.

New configuration format:

sensor:
  - platform: bthome_ble
    mac_address: "A4:C1:38:12:34:56"
    bindkey: "..." # optional
    sensors:
      - type: temperature
        name: "Temperature"
      - type: humidity
        name: "Humidity"

binary_sensor:
  - platform: bthome_ble
    mac_address: "A4:C1:38:9A:BC:DE"
    binary_sensors:
      - type: motion
        name: "Motion"
      - type: door
        name: "Door"

Benefits:
- MAC address and bind key are specified once per device
- More efficient (one BLE listener per device instead of per sensor)
- Clearer relationship between sensors from the same device
- Matches user expectations for multi-sensor devices

Updated test configurations to demonstrate the new format.
This commit is contained in:
Claude
2025-11-18 20:36:06 +00:00
parent 21539bdeba
commit d6ee57a7b9
4 changed files with 135 additions and 156 deletions

View File

@@ -2,8 +2,10 @@ import esphome.codegen as cg
from esphome.components import binary_sensor, esp32_ble_tracker from esphome.components import binary_sensor, esp32_ble_tracker
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import ( from esphome.const import (
CONF_BINARY_SENSORS,
CONF_BINDKEY, CONF_BINDKEY,
CONF_ID, CONF_ID,
CONF_MAC_ADDRESS,
CONF_TYPE, CONF_TYPE,
DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY,
DEVICE_CLASS_BATTERY_CHARGING, DEVICE_CLASS_BATTERY_CHARGING,
@@ -34,7 +36,7 @@ from esphome.const import (
) )
CODEOWNERS = ["@esphome/core"] CODEOWNERS = ["@esphome/core"]
DEPENDENCIES = ["bthome_ble"] DEPENDENCIES = ["esp32_ble_tracker"]
bthome_ble_ns = cg.esphome_ns.namespace("bthome_ble") bthome_ble_ns = cg.esphome_ns.namespace("bthome_ble")
BTHomeBinarySensor = bthome_ble_ns.class_( BTHomeBinarySensor = bthome_ble_ns.class_(
@@ -114,25 +116,36 @@ def apply_defaults(config):
return config return config
CONFIG_SCHEMA = cv.All( # Schema for individual binary sensors in the list
binary_sensor.binary_sensor_schema(BTHomeBinarySensor) BINARY_SENSOR_SCHEMA = cv.All(
.extend( binary_sensor.binary_sensor_schema(BTHomeBinarySensor).extend(
{ {
cv.Required(CONF_TYPE): cv.enum(BINARY_SENSOR_TYPES, lower=True), cv.Required(CONF_TYPE): cv.enum(BINARY_SENSOR_TYPES, lower=True),
cv.Optional(CONF_BINDKEY): cv.bind_key,
} }
) ),
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA),
apply_defaults, apply_defaults,
) )
# Platform schema with list of binary sensors
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.use_id(esp32_ble_tracker.ESP32BLETracker),
cv.Required(CONF_MAC_ADDRESS): cv.mac_address,
cv.Optional(CONF_BINDKEY): cv.bind_key,
cv.Required(CONF_BINARY_SENSORS): cv.ensure_list(BINARY_SENSOR_SCHEMA),
}
)
async def to_code(config): async def to_code(config):
var = await binary_sensor.new_binary_sensor(config) tracker = await cg.get_variable(config[CONF_ID])
await esp32_ble_tracker.register_ble_device(var, config)
object_id = BINARY_SENSOR_TYPES[config[CONF_TYPE]] for sensor_config in config[CONF_BINARY_SENSORS]:
cg.add(var.set_object_id(object_id)) var = await binary_sensor.new_binary_sensor(sensor_config)
await esp32_ble_tracker.register_ble_device(var, config)
if bindkey := config.get(CONF_BINDKEY): object_id = BINARY_SENSOR_TYPES[sensor_config[CONF_TYPE]]
cg.add(var.set_bindkey(bindkey)) cg.add(var.set_object_id(object_id))
if bindkey := config.get(CONF_BINDKEY):
cg.add(var.set_bindkey(bindkey))

View File

@@ -4,6 +4,8 @@ import esphome.config_validation as cv
from esphome.const import ( from esphome.const import (
CONF_BINDKEY, CONF_BINDKEY,
CONF_ID, CONF_ID,
CONF_MAC_ADDRESS,
CONF_SENSORS,
CONF_TYPE, CONF_TYPE,
DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY,
DEVICE_CLASS_CO2, DEVICE_CLASS_CO2,
@@ -24,14 +26,11 @@ from esphome.const import (
UNIT_CELSIUS, UNIT_CELSIUS,
UNIT_EMPTY, UNIT_EMPTY,
UNIT_KILOGRAM, UNIT_KILOGRAM,
UNIT_KILOVOLT_AMPS_REACTIVE_HOURS,
UNIT_KILOWATT_HOURS, UNIT_KILOWATT_HOURS,
UNIT_LUX, UNIT_LUX,
UNIT_METER, UNIT_METER,
UNIT_MICROGRAMS_PER_CUBIC_METER, UNIT_MICROGRAMS_PER_CUBIC_METER,
UNIT_MILLIGRAM_PER_CUBIC_METER,
UNIT_MILLIMETER, UNIT_MILLIMETER,
UNIT_PARTS_PER_BILLION,
UNIT_PARTS_PER_MILLION, UNIT_PARTS_PER_MILLION,
UNIT_PASCAL, UNIT_PASCAL,
UNIT_PERCENT, UNIT_PERCENT,
@@ -40,7 +39,7 @@ from esphome.const import (
) )
CODEOWNERS = ["@esphome/core"] CODEOWNERS = ["@esphome/core"]
DEPENDENCIES = ["bthome_ble"] DEPENDENCIES = ["esp32_ble_tracker"]
bthome_ble_ns = cg.esphome_ns.namespace("bthome_ble") bthome_ble_ns = cg.esphome_ns.namespace("bthome_ble")
BTHomeSensor = bthome_ble_ns.class_( BTHomeSensor = bthome_ble_ns.class_(
@@ -232,25 +231,36 @@ def apply_defaults(config):
return config return config
CONFIG_SCHEMA = cv.All( # Schema for individual sensors in the list
sensor.sensor_schema(BTHomeSensor) SENSOR_SCHEMA = cv.All(
.extend( sensor.sensor_schema(BTHomeSensor).extend(
{ {
cv.Required(CONF_TYPE): cv.enum(SENSOR_TYPES, lower=True), cv.Required(CONF_TYPE): cv.enum(SENSOR_TYPES, lower=True),
cv.Optional(CONF_BINDKEY): cv.bind_key,
} }
) ),
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA),
apply_defaults, apply_defaults,
) )
# Platform schema with list of sensors
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.use_id(esp32_ble_tracker.ESP32BLETracker),
cv.Required(CONF_MAC_ADDRESS): cv.mac_address,
cv.Optional(CONF_BINDKEY): cv.bind_key,
cv.Required(CONF_SENSORS): cv.ensure_list(SENSOR_SCHEMA),
}
)
async def to_code(config): async def to_code(config):
var = await sensor.new_sensor(config) tracker = await cg.get_variable(config[CONF_ID])
await esp32_ble_tracker.register_ble_device(var, config)
object_id = SENSOR_TYPES[config[CONF_TYPE]] for sensor_config in config[CONF_SENSORS]:
cg.add(var.set_object_id(object_id)) var = await sensor.new_sensor(sensor_config)
await esp32_ble_tracker.register_ble_device(var, config)
if bindkey := config.get(CONF_BINDKEY): object_id = SENSOR_TYPES[sensor_config[CONF_TYPE]]
cg.add(var.set_bindkey(bindkey)) cg.add(var.set_object_id(object_id))
if bindkey := config.get(CONF_BINDKEY):
cg.add(var.set_bindkey(bindkey))

View File

@@ -5,137 +5,86 @@ esp32_ble_tracker:
active: true active: true
sensor: sensor:
# Temperature sensor without encryption # Multiple sensors from the same device without encryption
- platform: bthome_ble - platform: bthome_ble
mac_address: "A4:C1:38:12:34:56" mac_address: "A4:C1:38:12:34:56"
type: temperature sensors:
name: "BTHome Temperature" - type: temperature
name: "BTHome Temperature"
- type: humidity
name: "BTHome Humidity"
- type: pressure
name: "BTHome Pressure"
- type: illuminance
name: "BTHome Illuminance"
# Humidity sensor without encryption # Sensors from encrypted device
- platform: bthome_ble
mac_address: "A4:C1:38:12:34:56"
type: humidity
name: "BTHome Humidity"
# Battery sensor with encryption
- platform: bthome_ble - platform: bthome_ble
mac_address: "A4:C1:38:78:90:AB" mac_address: "A4:C1:38:78:90:AB"
bindkey: "231d39c1d7cc1ab1aee224cd096db932" bindkey: "231d39c1d7cc1ab1aee224cd096db932"
type: battery sensors:
name: "BTHome Battery Encrypted" - type: battery
name: "BTHome Battery Encrypted"
- type: temperature
name: "BTHome Temperature Encrypted"
# Pressure sensor # Power monitoring device
- platform: bthome_ble
mac_address: "A4:C1:38:12:34:56"
type: pressure
name: "BTHome Pressure"
# Illuminance sensor
- platform: bthome_ble
mac_address: "A4:C1:38:12:34:56"
type: illuminance
name: "BTHome Illuminance"
# Power sensor
- platform: bthome_ble - platform: bthome_ble
mac_address: "A4:C1:38:CD:EF:12" mac_address: "A4:C1:38:CD:EF:12"
type: power sensors:
name: "BTHome Power" - type: power
name: "BTHome Power"
- type: energy
name: "BTHome Energy"
- type: voltage
name: "BTHome Voltage"
- type: current
name: "BTHome Current"
# Energy sensor # Air quality device
- platform: bthome_ble
mac_address: "A4:C1:38:CD:EF:12"
type: energy
name: "BTHome Energy"
# Voltage sensor
- platform: bthome_ble
mac_address: "A4:C1:38:CD:EF:12"
type: voltage
name: "BTHome Voltage"
# Current sensor
- platform: bthome_ble
mac_address: "A4:C1:38:CD:EF:12"
type: current
name: "BTHome Current"
# PM2.5 sensor
- platform: bthome_ble - platform: bthome_ble
mac_address: "A4:C1:38:34:56:78" mac_address: "A4:C1:38:34:56:78"
type: pm25 sensors:
name: "BTHome PM2.5" - type: pm25
name: "BTHome PM2.5"
# PM10 sensor - type: pm10
- platform: bthome_ble name: "BTHome PM10"
mac_address: "A4:C1:38:34:56:78" - type: co2
type: pm10 name: "BTHome CO2"
name: "BTHome PM10" - type: voc
name: "BTHome VOC"
# CO2 sensor - type: moisture
- platform: bthome_ble name: "BTHome Moisture"
mac_address: "A4:C1:38:34:56:78"
type: co2
name: "BTHome CO2"
# VOC sensor
- platform: bthome_ble
mac_address: "A4:C1:38:34:56:78"
type: voc
name: "BTHome VOC"
# Moisture sensor
- platform: bthome_ble
mac_address: "A4:C1:38:34:56:78"
type: moisture
name: "BTHome Moisture"
binary_sensor: binary_sensor:
# Motion sensor without encryption # Motion and occupancy sensors
- platform: bthome_ble - platform: bthome_ble
mac_address: "A4:C1:38:9A:BC:DE" mac_address: "A4:C1:38:9A:BC:DE"
type: motion binary_sensors:
name: "BTHome Motion" - type: motion
name: "BTHome Motion"
- type: occupancy
name: "BTHome Occupancy"
# Door sensor with encryption # Door and window sensors with encryption
- platform: bthome_ble - platform: bthome_ble
mac_address: "A4:C1:38:9A:BC:DE" mac_address: "A4:C1:38:AB:CD:EF"
bindkey: "231d39c1d7cc1ab1aee224cd096db932" bindkey: "231d39c1d7cc1ab1aee224cd096db932"
type: door binary_sensors:
name: "BTHome Door Encrypted" - type: door
name: "BTHome Door Encrypted"
- type: window
name: "BTHome Window Encrypted"
- type: battery_low
name: "BTHome Battery Low"
# Window sensor # Safety sensors
- platform: bthome_ble - platform: bthome_ble
mac_address: "A4:C1:38:9A:BC:DE" mac_address: "A4:C1:38:FE:DC:BA"
type: window binary_sensors:
name: "BTHome Window" - type: smoke
name: "BTHome Smoke"
# Battery low sensor - type: opening
- platform: bthome_ble name: "BTHome Opening"
mac_address: "A4:C1:38:9A:BC:DE" - type: moisture
type: battery_low name: "BTHome Moisture Binary"
name: "BTHome Battery Low"
# Occupancy sensor
- platform: bthome_ble
mac_address: "A4:C1:38:9A:BC:DE"
type: occupancy
name: "BTHome Occupancy"
# Smoke sensor
- platform: bthome_ble
mac_address: "A4:C1:38:9A:BC:DE"
type: smoke
name: "BTHome Smoke"
# Moisture binary sensor
- platform: bthome_ble
mac_address: "A4:C1:38:9A:BC:DE"
type: moisture
name: "BTHome Moisture Binary"
# Opening sensor
- platform: bthome_ble
mac_address: "A4:C1:38:9A:BC:DE"
type: opening
name: "BTHome Opening"

View File

@@ -7,28 +7,35 @@ esp32_ble_tracker:
sensor: sensor:
- platform: bthome_ble - platform: bthome_ble
mac_address: "A4:C1:38:12:34:56" mac_address: "A4:C1:38:12:34:56"
type: temperature sensors:
name: "BTHome Temperature" - type: temperature
name: "BTHome Temperature"
- platform: bthome_ble - type: humidity
mac_address: "A4:C1:38:12:34:56" name: "BTHome Humidity"
type: humidity
name: "BTHome Humidity"
- platform: bthome_ble - platform: bthome_ble
mac_address: "A4:C1:38:78:90:AB" mac_address: "A4:C1:38:78:90:AB"
bindkey: "231d39c1d7cc1ab1aee224cd096db932" bindkey: "231d39c1d7cc1ab1aee224cd096db932"
type: battery sensors:
name: "BTHome Battery" - type: battery
name: "BTHome Battery"
- type: pressure
name: "BTHome Pressure"
binary_sensor: binary_sensor:
- platform: bthome_ble - platform: bthome_ble
mac_address: "A4:C1:38:9A:BC:DE" mac_address: "A4:C1:38:9A:BC:DE"
type: motion binary_sensors:
name: "BTHome Motion" - type: motion
name: "BTHome Motion"
- type: window
name: "BTHome Window"
- platform: bthome_ble - platform: bthome_ble
mac_address: "A4:C1:38:9A:BC:DE" mac_address: "A4:C1:38:AB:CD:EF"
bindkey: "231d39c1d7cc1ab1aee224cd096db932" bindkey: "231d39c1d7cc1ab1aee224cd096db932"
type: door binary_sensors:
name: "BTHome Door" - type: door
name: "BTHome Door"
- type: occupancy
name: "BTHome Occupancy"