[ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 5: airthings_ble, inkbird_ibsth1_mini, radon_eye_ble) (#18165)

Co-authored-by: J. Nick Koston <nick@home-assistant.io>
This commit is contained in:
Edvard Filistovič
2026-08-07 20:46:43 +00:00
committed by GitHub
co-authored by J. Nick Koston
parent ae26483be6
commit 4a7d270494
22 changed files with 119 additions and 64 deletions
+12 -9
View File
@@ -1,23 +1,26 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker
from esphome.components import ble_device_base
import esphome.config_validation as cv
from esphome.const import CONF_ID
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["ble_device_base"]
CODEOWNERS = ["@jeromelaban"]
airthings_ble_ns = cg.esphome_ns.namespace("airthings_ble")
AirthingsListener = airthings_ble_ns.class_(
"AirthingsListener", esp32_ble_tracker.ESPBTDeviceListener
"AirthingsListener", ble_device_base.ESPBTDeviceListener
)
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.declare_id(AirthingsListener),
}
).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("airthings_ble"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(AirthingsListener),
}
).extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
@@ -2,15 +2,13 @@
#include "esphome/core/log.h"
#include <cinttypes>
#ifdef USE_ESP32
namespace esphome::airthings_ble {
static const char *const TAG = "airthings_ble";
bool AirthingsListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool AirthingsListener::parse_device(const ble_device_base::ESPBTDevice &device) {
for (auto &it : device.get_manufacturer_datas()) {
if (it.uuid == esp32_ble_tracker::ESPBTUUID::from_uint32(0x0334)) {
if (it.uuid == ble_device_base::ESPBTUUID::from_uint32(0x0334)) {
if (it.data.size() < 4)
continue;
@@ -29,5 +27,3 @@ bool AirthingsListener::parse_device(const esp32_ble_tracker::ESPBTDevice &devic
}
} // namespace esphome::airthings_ble
#endif
@@ -1,17 +1,13 @@
#pragma once
#ifdef USE_ESP32
#include "esphome/core/component.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
namespace esphome::airthings_ble {
class AirthingsListener final : public esp32_ble_tracker::ESPBTDeviceListener {
class AirthingsListener final : public ble_device_base::ESPBTDeviceListener {
public:
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
};
} // namespace esphome::airthings_ble
#endif
@@ -1,8 +1,6 @@
#include "inkbird_ibsth1_mini.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::inkbird_ibsth1_mini {
static const char *const TAG = "inkbird_ibsth1_mini";
@@ -15,7 +13,7 @@ void InkbirdIbstH1Mini::dump_config() {
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
}
bool InkbirdIbstH1Mini::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool InkbirdIbstH1Mini::parse_device(const ble_device_base::ESPBTDevice &device) {
// The below is based on my research and reverse engineering of a single device
// It is entirely possible that some of that may be inaccurate or incomplete
@@ -32,7 +30,7 @@ bool InkbirdIbstH1Mini::parse_device(const esp32_ble_tracker::ESPBTDevice &devic
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
}
if (device.get_address_type() != BLE_ADDR_TYPE_PUBLIC) {
if (device.get_address_type() != ble_device_base::BLE_ADDR_TYPE_PUBLIC) {
ESP_LOGVV(TAG, "parse_device(): address is not public");
return false;
}
@@ -46,7 +44,7 @@ bool InkbirdIbstH1Mini::parse_device(const esp32_ble_tracker::ESPBTDevice &devic
return false;
}
const auto &mnf_data = mnf_datas[0];
if (mnf_data.uuid.get_uuid().len != ESP_UUID_LEN_16) {
if (mnf_data.uuid.type() != ble_device_base::ESPBTUUID::Type::UUID16) {
ESP_LOGVV(TAG, "parse_device(): manufacturer data element is expected to have uuid of length 16");
return false;
}
@@ -71,7 +69,7 @@ bool InkbirdIbstH1Mini::parse_device(const esp32_ble_tracker::ESPBTDevice &devic
auto external_temperature = NAN;
// Read bluetooth data into variable
auto measured_temperature = ((int16_t) mnf_data.uuid.get_uuid().uuid.uuid16) / 100.0f;
auto measured_temperature = ((int16_t) mnf_data.uuid.uuid16()) / 100.0f;
// Set temperature or external_temperature based on which sensor is in use
if (mnf_data.data[2] == 0) {
@@ -104,5 +102,3 @@ bool InkbirdIbstH1Mini::parse_device(const esp32_ble_tracker::ESPBTDevice &devic
}
} // namespace esphome::inkbird_ibsth1_mini
#endif
@@ -2,17 +2,15 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#ifdef USE_ESP32
#include "esphome/components/ble_device_base/ble_device.h"
namespace esphome::inkbird_ibsth1_mini {
class InkbirdIbstH1Mini final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class InkbirdIbstH1Mini final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; }
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
@@ -29,5 +27,3 @@ class InkbirdIbstH1Mini final : public Component, public esp32_ble_tracker::ESPB
};
} // namespace esphome::inkbird_ibsth1_mini
#endif
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
from esphome.components import ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -18,14 +18,15 @@ from esphome.const import (
)
CODEOWNERS = ["@fkirill"]
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["ble_device_base"]
inkbird_ibsth1_mini_ns = cg.esphome_ns.namespace("inkbird_ibsth1_mini")
InkbirdIbstH1Mini = inkbird_ibsth1_mini_ns.class_(
"InkbirdIbstH1Mini", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"InkbirdIbstH1Mini", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("inkbird_ibsth1_mini"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(InkbirdIbstH1Mini),
@@ -57,15 +58,15 @@ CONFIG_SCHEMA = (
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
+12 -9
View File
@@ -1,23 +1,26 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker
from esphome.components import ble_device_base
import esphome.config_validation as cv
from esphome.const import CONF_ID
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["ble_device_base"]
CODEOWNERS = ["@jeffeb3"]
radon_eye_ble_ns = cg.esphome_ns.namespace("radon_eye_ble")
RadonEyeListener = radon_eye_ble_ns.class_(
"RadonEyeListener", esp32_ble_tracker.ESPBTDeviceListener
"RadonEyeListener", ble_device_base.ESPBTDeviceListener
)
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.declare_id(RadonEyeListener),
}
).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("radon_eye_ble"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(RadonEyeListener),
}
).extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
@@ -2,13 +2,11 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::radon_eye_ble {
static const char *const TAG = "radon_eye_ble";
bool RadonEyeListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool RadonEyeListener::parse_device(const ble_device_base::ESPBTDevice &device) {
// Radon Eye devices have names starting with "FR:"
if (device.get_name().starts_with("FR:")) {
char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
@@ -19,5 +17,3 @@ bool RadonEyeListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device
}
} // namespace esphome::radon_eye_ble
#endif
@@ -1,17 +1,13 @@
#pragma once
#ifdef USE_ESP32
#include "esphome/core/component.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
namespace esphome::radon_eye_ble {
class RadonEyeListener final : public esp32_ble_tracker::ESPBTDeviceListener {
class RadonEyeListener final : public ble_device_base::ESPBTDeviceListener {
public:
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
};
} // namespace esphome::radon_eye_ble
#endif
@@ -0,0 +1 @@
airthings_ble:
@@ -0,0 +1,6 @@
esp32_ble_tracker:
id: ble_tracker_hub
# Explicit ble_hub_id: pins the neutral binding as a declared key.
airthings_ble:
ble_hub_id: ble_tracker_hub
@@ -0,0 +1,3 @@
packages:
ble: !include ../../test_build_components/common/ble/esp32-idf.yaml
airthings_ble: !include common.yaml
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
airthings_ble: !include common-ln.yaml
@@ -0,0 +1,8 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
airthings_ble:
ble_hub_id: ble_tracker_hub
@@ -0,0 +1,7 @@
sensor:
- platform: inkbird_ibsth1_mini
mac_address: 38:81:D7:0A:9C:11
temperature:
name: Inkbird IBS-TH1 Temperature
humidity:
name: Inkbird IBS-TH1 Humidity
@@ -1,7 +1,10 @@
esp32_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: inkbird_ibsth1_mini
ble_hub_id: ble_tracker_hub
mac_address: 38:81:D7:0A:9C:11
temperature:
name: Inkbird IBS-TH1 Temperature
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
inkbird_ibsth1_mini: !include common-ln.yaml
@@ -0,0 +1,22 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: inkbird_ibsth1_mini
ble_hub_id: ble_tracker_hub
mac_address: 38:81:D7:0A:9C:11
temperature:
name: Inkbird IBS-TH1 Temperature
humidity:
name: Inkbird IBS-TH1 Humidity
battery_level:
name: Inkbird IBS-TH1 Battery Level
# No ble_hub_id: exercises the generated binding real configs use.
- platform: inkbird_ibsth1_mini
mac_address: 38:81:D7:0A:9C:12
temperature:
name: BK Inkbird Implicit Temperature
@@ -0,0 +1 @@
radon_eye_ble:
@@ -1,3 +1,6 @@
esp32_ble_tracker:
id: ble_tracker_hub
# Explicit ble_hub_id: pins the neutral binding as a declared key.
radon_eye_ble:
ble_hub_id: ble_tracker_hub
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
radon_eye_ble: !include common-ln.yaml
@@ -0,0 +1,9 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
# Explicit ble_hub_id: pins the neutral binding as a declared key.
radon_eye_ble:
ble_hub_id: ble_tracker_hub