ESPHome 2026.8.0-dev
Loading...
Searching...
No Matches
ble_device.h
Go to the documentation of this file.
1// ble_device.h
2//
3// Platform-neutral BLE advertisement types — the generic base every BLE consumer
4// (sensor components, bluetooth_proxy, automation triggers) builds against:
5// ESPBTUUID / ServiceData / ESPBLEiBeacon / ESPBTDevice / ESPBTDeviceListener
6//
7// These types are owned here on EVERY platform, with no chip-SDK types in their
8// public surface. Platform trackers produce them:
9// - esp32_ble_tracker adapts ESP-IDF scan results into ESPBTDevice and
10// re-exports these names (esp32 only) for backward compatibility;
11// - the LibreTiny trackers (bk72xx / ln882h) feed from_scan_result() directly.
12
13#pragma once
14
17
18#include <cstdint>
19#include <cstring>
20#include <initializer_list>
21#include <string>
22#include <vector>
23
24#if defined(__cpp_lib_span)
25#include <span>
26#endif
27
28#ifdef USE_ESP32
29// Historical esp32_ble API surface (below, under the same define) uses the
30// ESP-IDF UUID/address/scan-result types directly; never referenced off-esp32.
32#include <esp_bt_defs.h>
33#endif
34
36
37using adv_data_t = std::vector<uint8_t>;
38
39// Bluetooth Core address types (spec values; matches ESP-IDF's esp_ble_addr_type_t).
40static constexpr uint8_t BLE_ADDR_TYPE_PUBLIC = 0;
41static constexpr uint8_t BLE_ADDR_TYPE_RANDOM = 1;
42static constexpr uint8_t BLE_ADDR_TYPE_RPA_PUBLIC = 2;
43static constexpr uint8_t BLE_ADDR_TYPE_RPA_RANDOM = 3;
44
46static constexpr size_t UUID_STR_LEN = 37;
47
48// ---------------------------------------------------------------------------
49// ESPBTUUID — 16/32/128-bit Bluetooth UUID value type.
50// API-compatible with the historical esp32_ble::ESPBTUUID; the esp_bt_uuid_t
51// conversions live in esp32_ble (esp32-only adapters), not here.
52// ---------------------------------------------------------------------------
53
54class ESPBTUUID {
55 public:
56 ESPBTUUID() = default;
57
58 static ESPBTUUID from_uint16(uint16_t uuid);
59 static ESPBTUUID from_uint32(uint32_t uuid);
61 static ESPBTUUID from_raw(const uint8_t *data);
63 static ESPBTUUID from_raw_reversed(const uint8_t *data);
66 static ESPBTUUID from_raw(const char *data, size_t length);
67 static ESPBTUUID from_raw(const char *data) { return from_raw(data, strlen(data)); }
68 static ESPBTUUID from_raw(const std::string &data) { return from_raw(data.c_str(), data.length()); }
69 static ESPBTUUID from_raw(std::initializer_list<uint8_t> data) {
70 return from_raw(reinterpret_cast<const char *>(data.begin()), data.size());
71 }
72
73#ifdef USE_ESP32
75 static ESPBTUUID from_uuid(esp_bt_uuid_t uuid);
76 esp_bt_uuid_t get_uuid() const;
77#endif
78
80 ESPBTUUID as_128bit() const;
81
83 bool contains(uint8_t data1, uint8_t data2) const;
84
85 bool operator==(const ESPBTUUID &other) const;
86 bool operator!=(const ESPBTUUID &other) const { return !(*this == other); }
87
90 const char *to_str(char *buf) const;
91#if defined(__cpp_lib_span)
92 const char *to_str(std::span<char, UUID_STR_LEN> output) const { return this->to_str(output.data()); }
93#endif
94 enum class Type : uint8_t { UUID16, UUID32, UUID128 };
95 Type type() const { return this->type_; }
96 uint16_t uuid16() const { return this->uuid_.uuid16; }
97 uint32_t uuid32() const { return this->uuid_.uuid32; }
98 const uint8_t *uuid128() const { return this->uuid_.uuid128; }
99
100 protected:
101 // Expand to the 128-bit Bluetooth Base UUID byte form (out is 16 bytes, little-endian).
102 void to_128bit_(uint8_t out[16]) const;
103
105 union {
106 uint16_t uuid16;
108 uint8_t uuid128[16];
109 } uuid_{};
110};
111
112// ---------------------------------------------------------------------------
113// ServiceData — UUID-tagged advertisement payload (0x16 / 0xFF AD types)
114// ---------------------------------------------------------------------------
115
120
121// ---------------------------------------------------------------------------
122// ESPBLEiBeacon
123// ---------------------------------------------------------------------------
124
126 public:
127 ESPBLEiBeacon() { memset(&this->beacon_data_, 0, sizeof(this->beacon_data_)); }
128 explicit ESPBLEiBeacon(const uint8_t *data);
129 static optional<ESPBLEiBeacon> from_manufacturer_data(const ServiceData &data);
130
131 uint16_t get_major() const { return byteswap(this->beacon_data_.major); }
132 uint16_t get_minor() const { return byteswap(this->beacon_data_.minor); }
133 int8_t get_signal_power() const { return this->beacon_data_.signal_power; }
135
136 protected:
137 struct PACKED BeaconData {
138 uint8_t sub_type;
139 uint8_t length;
140 uint8_t proximity_uuid[16];
141 uint16_t major;
142 uint16_t minor;
145};
146
147// ---------------------------------------------------------------------------
148// ESPBTDevice — parsed BLE advertisement
149// ---------------------------------------------------------------------------
150
152 public:
155 void from_scan_result(const uint8_t *mac, int rssi, uint8_t addr_type, const uint8_t *data, uint16_t data_len);
156
157 // Alias the core constant so the two cannot drift apart.
158 static constexpr size_t MAC_ADDRESS_PRETTY_BUFFER_SIZE = esphome::MAC_ADDRESS_PRETTY_BUFFER_SIZE;
159
161 std::string address_str() const;
163 const char *address_str_to(char *buf) const;
164#if defined(__cpp_lib_span)
165 const char *address_str_to(std::span<char, MAC_ADDRESS_PRETTY_BUFFER_SIZE> buf) const {
166 return this->address_str_to(buf.data());
167 }
168#endif
170 uint64_t address_uint64() const;
173 const uint8_t *address() const { return address_; }
174#ifdef USE_ESP32
175 // Historical esp32 signature: consumers assign the result to esp_ble_addr_type_t.
176 esp_ble_addr_type_t get_address_type() const { return static_cast<esp_ble_addr_type_t>(this->address_type_); }
178 void parse_scan_rst(const esp32_ble::BLEScanResult &scan_result);
179 // Exposed through a function for use in lambdas
180 const esp32_ble::BLEScanResult &get_scan_result() const { return *scan_result_; }
181#else
182 uint8_t get_address_type() const { return this->address_type_; }
183#endif
184
185 int get_rssi() const { return rssi_; }
186 const std::string &get_name() const { return name_; }
187
188 const std::vector<ESPBTUUID> &get_service_uuids() const { return service_uuids_; }
189 const std::vector<ServiceData> &get_manufacturer_datas() const { return manufacturer_datas_; }
190 const std::vector<ServiceData> &get_service_datas() const { return service_datas_; }
191 const std::vector<int8_t> &get_tx_powers() const { return tx_powers_; }
192 const optional<uint16_t> &get_appearance() const { return appearance_; }
193 const optional<uint8_t> &get_ad_flag() const { return ad_flag_; }
194
198 bool resolve_irk(const uint8_t *irk) const;
199
200 optional<ESPBLEiBeacon> get_ibeacon() const {
201 for (const auto &it : this->manufacturer_datas_) {
203 if (res.has_value())
204 return res;
205 }
206 return {};
207 }
208
209 protected:
210 void parse_adv_(const uint8_t *payload, uint16_t len);
211
212 uint8_t address_[6]{0};
213 uint8_t address_type_{0};
214 int rssi_{0};
215 std::string name_{};
216 std::vector<ESPBTUUID> service_uuids_{};
217 std::vector<ServiceData> manufacturer_datas_{};
218 std::vector<ServiceData> service_datas_{};
219#ifdef USE_ESP32
220 const esp32_ble::BLEScanResult *scan_result_{nullptr};
221#endif
222 std::vector<int8_t> tx_powers_{};
223 optional<uint16_t> appearance_{};
224 optional<uint8_t> ad_flag_{};
225};
226
227// ---------------------------------------------------------------------------
228// ESPBTDeviceListener — base class for BLE consumers (sensors, proxy, triggers)
229// ---------------------------------------------------------------------------
230
232 public:
233 virtual ~ESPBTDeviceListener() = default;
235 virtual void on_scan_end() {}
236 virtual bool parse_device(const ESPBTDevice &device) = 0;
237};
238
239} // namespace esphome::ble_device_base
struct PACKED esphome::ble_device_base::ESPBLEiBeacon::BeaconData beacon_data_
static optional< ESPBLEiBeacon > from_manufacturer_data(const ServiceData &data)
const char * address_str_to(char *buf) const
Buffer overload: writes "XX:XX:XX:XX:XX:XX\0" into buf (>= 18 bytes), returns buf.
void parse_scan_rst(const esp32_ble::BLEScanResult &scan_result)
Historical esp32 ingest (esp32 builds only): parse an ESP-IDF scan result.
const optional< uint8_t > & get_ad_flag() const
Definition ble_device.h:193
const std::vector< ESPBTUUID > & get_service_uuids() const
Definition ble_device.h:188
const uint8_t * address() const
Raw MAC bytes in printable (MSB-first) order — matches the historical esp32 layout (ESP-IDF bda order...
Definition ble_device.h:173
std::vector< ESPBTUUID > service_uuids_
Definition ble_device.h:216
const optional< uint16_t > & get_appearance() const
Definition ble_device.h:192
const std::vector< int8_t > & get_tx_powers() const
Definition ble_device.h:191
void from_scan_result(const uint8_t *mac, int rssi, uint8_t addr_type, const uint8_t *data, uint16_t data_len)
Populate from a raw scan result delivered by a BLE tracker backend.
static constexpr size_t MAC_ADDRESS_PRETTY_BUFFER_SIZE
Definition ble_device.h:158
esp_ble_addr_type_t get_address_type() const
Definition ble_device.h:176
void parse_adv_(const uint8_t *payload, uint16_t len)
std::vector< ServiceData > service_datas_
Definition ble_device.h:218
const esp32_ble::BLEScanResult * scan_result_
Definition ble_device.h:220
std::vector< ServiceData > manufacturer_datas_
Definition ble_device.h:217
std::string address_str() const
Return MAC as "XX:XX:XX:XX:XX:XX" string.
const char * address_str_to(std::span< char, MAC_ADDRESS_PRETTY_BUFFER_SIZE > buf) const
Definition ble_device.h:165
optional< ESPBLEiBeacon > get_ibeacon() const
Definition ble_device.h:200
uint64_t address_uint64() const
Return MAC as packed uint64 (byte 0 in LSB — matches esp32's address_uint64).
const std::vector< ServiceData > & get_service_datas() const
Definition ble_device.h:190
const std::vector< ServiceData > & get_manufacturer_datas() const
Definition ble_device.h:189
const esp32_ble::BLEScanResult & get_scan_result() const
Definition ble_device.h:180
bool resolve_irk(const uint8_t *irk) const
Resolve a Resolvable Private Address against a 16-byte IRK (Bluetooth "ah" function,...
const std::string & get_name() const
Definition ble_device.h:186
virtual void on_scan_end()
Called at the end of each scan duration period.
Definition ble_device.h:235
virtual bool parse_device(const ESPBTDevice &device)=0
static ESPBTUUID from_uuid(esp_bt_uuid_t uuid)
Source compatibility with the historical esp32_ble API (esp32 builds only).
const char * to_str(std::span< char, UUID_STR_LEN > output) const
Definition ble_device.h:92
static ESPBTUUID from_uint16(uint16_t uuid)
static ESPBTUUID from_raw(const char *data)
Definition ble_device.h:67
static ESPBTUUID from_raw(const std::string &data)
Definition ble_device.h:68
static ESPBTUUID from_raw(const uint8_t *data)
Construct from raw 16-byte little-endian UUID.
bool contains(uint8_t data1, uint8_t data2) const
True if the UUID value contains the adjacent byte pair (data1, data2).
void to_128bit_(uint8_t out[16]) const
static ESPBTUUID from_raw_reversed(const uint8_t *data)
Construct from raw 16-byte big-endian UUID (reversed on store).
union esphome::ble_device_base::ESPBTUUID::@21 uuid_
static ESPBTUUID from_raw(std::initializer_list< uint8_t > data)
Definition ble_device.h:69
static ESPBTUUID from_uint32(uint32_t uuid)
bool operator!=(const ESPBTUUID &other) const
Definition ble_device.h:86
ESPBTUUID as_128bit() const
Expand to the 128-bit Bluetooth Base UUID form.
const uint8_t * uuid128() const
Definition ble_device.h:98
bool operator==(const ESPBTUUID &other) const
const char * to_str(char *buf) const
Write "0xABCD" / "0xABCDEF01" / the dashed 128-bit form into buf (>= UUID_STR_LEN bytes) and return b...
std::vector< uint8_t > adv_data_t
Definition ble_device.h:37
const void size_t len
Definition hal.h:64
static void uint32_t
void byteswap()
uint16_t length
Definition tt21100.cpp:0