mirror of
https://github.com/esphome/esphome.git
synced 2026-08-17 10:52:56 +08:00
[bluetooth_proxy] Deliver esp32 advertisements through the hub callback (#18173)
This commit is contained in:
@@ -159,7 +159,7 @@ void BK72xxBLETracker::dump_config() {
|
||||
void BK72xxBLETracker::on_scan_report(const bk72xx_ble::BLEScanReport &report) {
|
||||
// Raw callback (the raw-advertisement path).
|
||||
if (this->raw_advertisement_callback_.is_set()) {
|
||||
const ble_device_base::RawAdvertisement adv{.mac = report.mac,
|
||||
const ble_device_base::RawAdvertisement adv{.address = ble_device_base::mac_lsb_first_to_uint64(report.mac),
|
||||
.data = report.data,
|
||||
.data_len = report.data_len,
|
||||
.rssi = report.rssi,
|
||||
|
||||
@@ -154,12 +154,9 @@ class ESPBLEiBeacon {
|
||||
};
|
||||
|
||||
/// Pack a controller-order (LSB-first) MAC into the uint64 the API speaks.
|
||||
///
|
||||
/// The result is the printable-order value esp32 has always sent
|
||||
/// (esp32_ble::ble_addr_to_uint64), so both proxy paths agree on the wire.
|
||||
/// This takes the raw controller order delivered by BLEHub's raw-advertisement
|
||||
/// callback; ESPBTDevice::address_uint64() is the equivalent for an already
|
||||
/// parsed device, whose address is stored MSB-first.
|
||||
/// Trackers with LSB-native SDKs call this at the emit site before filling
|
||||
/// RawAdvertisement::address; ESPBTDevice::address_uint64() is the equivalent
|
||||
/// for an already parsed device, whose address is stored MSB-first.
|
||||
inline uint64_t mac_lsb_first_to_uint64(const uint8_t *mac) {
|
||||
uint64_t addr = 0;
|
||||
for (int i = 0; i < 6; i++)
|
||||
|
||||
@@ -23,8 +23,9 @@ namespace esphome::ble_device_base {
|
||||
/// One raw advertisement as delivered by the controller — a borrowed view,
|
||||
/// valid only for the duration of the invoke() callback.
|
||||
struct RawAdvertisement {
|
||||
/// Least-significant octet first (BLE controller convention).
|
||||
const uint8_t *mac;
|
||||
/// Producers convert their native byte order at the emit site, so no
|
||||
/// byte-order convention crosses this contract.
|
||||
uint64_t address;
|
||||
const uint8_t *data;
|
||||
uint16_t data_len;
|
||||
int8_t rssi; // signed dBm
|
||||
|
||||
@@ -480,7 +480,9 @@ esp_err_t BluetoothConnection::notify_characteristic(uint16_t handle, bool enabl
|
||||
}
|
||||
|
||||
esp32_ble_tracker::AdvertisementParserType BluetoothConnection::get_advertisement_parser_type() {
|
||||
return this->proxy_->get_advertisement_parser_type();
|
||||
// RAW keeps the tracker from building parsed ESPBTDevice objects for the
|
||||
// proxy's connections (the proxy itself consumes the hub raw callback).
|
||||
return esp32_ble_tracker::AdvertisementParserType::RAW_ADVERTISEMENTS;
|
||||
}
|
||||
|
||||
} // namespace esphome::bluetooth_connection
|
||||
|
||||
@@ -374,7 +374,11 @@ async def _to_code_esp32(config: ConfigType) -> None:
|
||||
await cg.register_component(var, config)
|
||||
|
||||
cg.add(var.set_active(config[CONF_ACTIVE]))
|
||||
await esp32_ble_tracker.register_raw_ble_device(var, config)
|
||||
# Advertisements arrive through the hub raw callback (installed in
|
||||
# setup()); only the scanner-state listener still registers with the
|
||||
# tracker directly.
|
||||
tracker = await cg.get_variable(config[esp32_ble_tracker.CONF_ESP32_BLE_ID])
|
||||
cg.add(var.set_parent(tracker))
|
||||
await esp32_ble_tracker.register_scanner_state_listener(var, config)
|
||||
|
||||
# Define max connections for protobuf fixed array
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "esphome/core/macros.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
@@ -26,14 +27,6 @@ BluetoothProxy::BluetoothProxy() { global_bluetooth_proxy = this; }
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
void BluetoothProxy::setup() {
|
||||
this->connections_free_response_.limit = BLUETOOTH_PROXY_MAX_CONNECTIONS;
|
||||
this->connections_free_response_.free = BLUETOOTH_PROXY_MAX_CONNECTIONS;
|
||||
|
||||
// Capture the configured scan mode from YAML before any API changes
|
||||
this->configured_scan_active_ = this->parent_->get_scan_active();
|
||||
}
|
||||
|
||||
void BluetoothProxy::on_scanner_state(esp32_ble_tracker::ScannerState state) {
|
||||
if (this->api_connection_ != nullptr) {
|
||||
this->send_bluetooth_scanner_state_(state);
|
||||
@@ -43,8 +36,8 @@ void BluetoothProxy::on_scanner_state(esp32_ble_tracker::ScannerState state) {
|
||||
void BluetoothProxy::send_bluetooth_scanner_state_(esp32_ble_tracker::ScannerState state) {
|
||||
api::BluetoothScannerStateResponse resp;
|
||||
resp.state = static_cast<api::enums::BluetoothScannerState>(state);
|
||||
resp.mode = this->parent_->get_scan_active() ? api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE
|
||||
: api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_PASSIVE;
|
||||
resp.mode = this->hub_->scan_active() ? api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE
|
||||
: api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_PASSIVE;
|
||||
resp.configured_mode = this->configured_scan_active_
|
||||
? api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE
|
||||
: api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_PASSIVE;
|
||||
@@ -53,45 +46,6 @@ void BluetoothProxy::send_bluetooth_scanner_state_(esp32_ble_tracker::ScannerSta
|
||||
|
||||
#else // !USE_ESP32
|
||||
|
||||
void BluetoothProxy::setup() {
|
||||
// BLUETOOTH_PROXY_MAX_CONNECTIONS is 0 on an advertisement-only proxy.
|
||||
this->connections_free_response_.limit = BLUETOOTH_PROXY_MAX_CONNECTIONS;
|
||||
this->connections_free_response_.free = BLUETOOTH_PROXY_MAX_CONNECTIONS;
|
||||
|
||||
// Capture the configured scan mode from YAML before any API changes
|
||||
this->configured_scan_active_ = this->hub_->scan_active();
|
||||
|
||||
// The hub delivers raw advertisements on the ESPHome main loop:
|
||||
// mac is least-significant octet first (BLE controller convention).
|
||||
this->hub_->set_raw_advertisement_callback({this, [](void *self, const ble_device_base::RawAdvertisement &adv) {
|
||||
static_cast<BluetoothProxy *>(self)->on_raw_advertisement_(adv);
|
||||
}});
|
||||
}
|
||||
|
||||
void BluetoothProxy::on_raw_advertisement_(const ble_device_base::RawAdvertisement &raw) {
|
||||
if (!api::global_api_server->is_connected() || this->api_connection_ == nullptr)
|
||||
return;
|
||||
|
||||
auto &adv = this->response_.advertisements[this->response_.advertisements_len];
|
||||
// raw.mac is LSB-first; this yields the same uint64 the esp32 proxy sends.
|
||||
adv.address = ble_device_base::mac_lsb_first_to_uint64(raw.mac);
|
||||
adv.rssi = raw.rssi;
|
||||
adv.address_type = raw.addr_type;
|
||||
uint8_t length = raw.data_len > sizeof(adv.data) ? sizeof(adv.data) : static_cast<uint8_t>(raw.data_len);
|
||||
adv.data_len = length;
|
||||
std::memcpy(adv.data, raw.data, length);
|
||||
|
||||
this->response_.advertisements_len++;
|
||||
|
||||
ESP_LOGV(TAG, "Queuing raw packet from %02X:%02X:%02X:%02X:%02X:%02X, length %d. RSSI: %d dB", raw.mac[5], raw.mac[4],
|
||||
raw.mac[3], raw.mac[2], raw.mac[1], raw.mac[0], length, raw.rssi);
|
||||
|
||||
// Flush if we have reached BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE
|
||||
if (this->response_.advertisements_len >= BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE) {
|
||||
this->flush_pending_advertisements_();
|
||||
}
|
||||
}
|
||||
|
||||
void BluetoothProxy::send_bluetooth_scanner_state_() {
|
||||
// One read feeds both the frame and the change detector; the detector only
|
||||
// advances if the frame was accepted, so a dropped send (WOULD_BLOCK on a
|
||||
@@ -112,6 +66,42 @@ void BluetoothProxy::send_bluetooth_scanner_state_() {
|
||||
|
||||
#endif // USE_ESP32
|
||||
|
||||
void BluetoothProxy::setup() {
|
||||
// BLUETOOTH_PROXY_MAX_CONNECTIONS is 0 on an advertisement-only proxy.
|
||||
this->connections_free_response_.limit = BLUETOOTH_PROXY_MAX_CONNECTIONS;
|
||||
this->connections_free_response_.free = BLUETOOTH_PROXY_MAX_CONNECTIONS;
|
||||
|
||||
// Capture the configured scan mode from YAML before any API changes
|
||||
this->configured_scan_active_ = this->hub_->scan_active();
|
||||
|
||||
this->hub_->set_raw_advertisement_callback({this, [](void *self, const ble_device_base::RawAdvertisement &adv) {
|
||||
static_cast<BluetoothProxy *>(self)->on_raw_advertisement_(adv);
|
||||
}});
|
||||
}
|
||||
|
||||
// The hub delivers raw advertisements on the ESPHome main loop.
|
||||
void BluetoothProxy::on_raw_advertisement_(const ble_device_base::RawAdvertisement &raw) {
|
||||
if (!api::global_api_server->is_connected() || this->api_connection_ == nullptr)
|
||||
return;
|
||||
|
||||
auto &adv = this->response_.advertisements[this->response_.advertisements_len];
|
||||
adv.address = raw.address;
|
||||
adv.rssi = raw.rssi;
|
||||
adv.address_type = raw.addr_type;
|
||||
uint8_t length = raw.data_len > sizeof(adv.data) ? sizeof(adv.data) : static_cast<uint8_t>(raw.data_len);
|
||||
adv.data_len = length;
|
||||
std::memcpy(adv.data, raw.data, length);
|
||||
|
||||
this->response_.advertisements_len++;
|
||||
|
||||
ESP_LOGV(TAG, "Queuing raw packet from %012" PRIX64 ", length %d. RSSI: %d dB", raw.address, length, raw.rssi);
|
||||
|
||||
// Flush if we have reached BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE
|
||||
if (this->response_.advertisements_len >= BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE) {
|
||||
this->flush_pending_advertisements_();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BLUETOOTH_CONNECTION_HAS_GATT
|
||||
void BluetoothProxy::log_connection_request_ignored_(BluetoothConnection *connection, ClientState state) {
|
||||
ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, state: %s", connection->get_connection_index(),
|
||||
@@ -133,50 +123,6 @@ void BluetoothProxy::handle_gatt_not_connected_(uint64_t address, uint16_t handl
|
||||
this->send_gatt_error(address, handle, GATT_NOT_CONNECTED);
|
||||
}
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#ifdef USE_ESP32_BLE_DEVICE
|
||||
bool BluetoothProxy::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
|
||||
// This method should never be called since bluetooth_proxy always uses raw advertisements
|
||||
// but we need to provide an implementation to satisfy the virtual method requirement
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool BluetoothProxy::parse_devices(const esp32_ble::BLEScanResult *scan_results, size_t count) {
|
||||
if (!api::global_api_server->is_connected() || this->api_connection_ == nullptr)
|
||||
return false;
|
||||
|
||||
auto &advertisements = this->response_.advertisements;
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
auto &result = scan_results[i];
|
||||
uint8_t length = result.adv_data_len + result.scan_rsp_len;
|
||||
|
||||
// Fill in the data directly at current position
|
||||
auto &adv = advertisements[this->response_.advertisements_len];
|
||||
adv.address = esp32_ble::ble_addr_to_uint64(result.bda);
|
||||
adv.rssi = result.rssi;
|
||||
adv.address_type = result.ble_addr_type;
|
||||
adv.data_len = length;
|
||||
std::memcpy(adv.data, result.ble_adv, length);
|
||||
|
||||
this->response_.advertisements_len++;
|
||||
|
||||
ESP_LOGV(TAG, "Queuing raw packet from %02X:%02X:%02X:%02X:%02X:%02X, length %d. RSSI: %d dB", result.bda[0],
|
||||
result.bda[1], result.bda[2], result.bda[3], result.bda[4], result.bda[5], length, result.rssi);
|
||||
|
||||
// Flush if we have reached BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE
|
||||
if (this->response_.advertisements_len >= BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE) {
|
||||
this->flush_pending_advertisements_();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // USE_ESP32
|
||||
|
||||
void BluetoothProxy::log_advertisement_flush_() {
|
||||
ESP_LOGV(TAG, "Sent batch of %u BLE advertisements", this->response_.advertisements_len);
|
||||
}
|
||||
@@ -236,10 +182,6 @@ void BluetoothProxy::loop() {
|
||||
}
|
||||
}
|
||||
|
||||
esp32_ble_tracker::AdvertisementParserType BluetoothProxy::get_advertisement_parser_type() {
|
||||
return esp32_ble_tracker::AdvertisementParserType::RAW_ADVERTISEMENTS;
|
||||
}
|
||||
|
||||
#endif // USE_ESP32
|
||||
|
||||
#ifdef BLUETOOTH_CONNECTION_HAS_GATT
|
||||
@@ -522,13 +464,13 @@ void BluetoothProxy::bluetooth_set_connection_params(const api::BluetoothSetConn
|
||||
#ifdef USE_ESP32
|
||||
|
||||
void BluetoothProxy::bluetooth_scanner_set_mode(bool active) {
|
||||
if (this->parent_->get_scan_active() == active) {
|
||||
if (this->parent_()->get_scan_active() == active) {
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG, "Setting scanner mode to %s", active ? "active" : "passive");
|
||||
this->parent_->set_scan_active(active);
|
||||
this->parent_->stop_scan();
|
||||
this->parent_->set_scan_continuous(
|
||||
this->parent_()->set_scan_active(active);
|
||||
this->parent_()->stop_scan();
|
||||
this->parent_()->set_scan_continuous(
|
||||
true); // Set this to true to automatically start scanning again when it has cleaned up.
|
||||
}
|
||||
|
||||
@@ -675,8 +617,7 @@ void BluetoothProxy::subscribe_api_connection(api::APIConnection *api_connection
|
||||
}
|
||||
this->api_connection_ = api_connection;
|
||||
#ifdef USE_ESP32
|
||||
this->parent_->recalculate_advertisement_parser_types();
|
||||
this->send_bluetooth_scanner_state_(this->parent_->get_scanner_state());
|
||||
this->send_bluetooth_scanner_state_(this->parent_()->get_scanner_state());
|
||||
#else
|
||||
this->send_bluetooth_scanner_state_();
|
||||
#endif
|
||||
@@ -688,9 +629,6 @@ void BluetoothProxy::unsubscribe_api_connection(api::APIConnection *api_connecti
|
||||
return;
|
||||
}
|
||||
this->api_connection_ = nullptr;
|
||||
#ifdef USE_ESP32
|
||||
this->parent_->recalculate_advertisement_parser_types();
|
||||
#endif
|
||||
}
|
||||
|
||||
void BluetoothProxy::send_device_connection(uint64_t address, bool connected, uint16_t mtu, conn_err_t error) {
|
||||
|
||||
@@ -73,9 +73,7 @@ enum BluetoothProxySubscriptionFlag : uint32_t {
|
||||
};
|
||||
|
||||
#ifdef USE_ESP32
|
||||
class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener,
|
||||
public esp32_ble_tracker::BLEScannerStateListener,
|
||||
public Component {
|
||||
class BluetoothProxy final : public esp32_ble_tracker::BLEScannerStateListener, public Component {
|
||||
#else
|
||||
class BluetoothProxy final : public Component {
|
||||
#endif
|
||||
@@ -86,11 +84,9 @@ class BluetoothProxy final : public Component {
|
||||
public:
|
||||
BluetoothProxy();
|
||||
#ifdef USE_ESP32
|
||||
#ifdef USE_ESP32_BLE_DEVICE
|
||||
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
|
||||
#endif
|
||||
bool parse_devices(const esp32_ble::BLEScanResult *scan_results, size_t count) override;
|
||||
esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override;
|
||||
// Advertisements arrive through the hub's raw callback; parent_() below
|
||||
// recovers the tracker type for the esp32-only scan-mode calls.
|
||||
void set_parent(esp32_ble_tracker::ESP32BLETracker *parent) { this->hub_ = parent; }
|
||||
#endif // USE_ESP32
|
||||
void dump_config() override;
|
||||
void setup() override;
|
||||
@@ -221,8 +217,8 @@ class BluetoothProxy final : public Component {
|
||||
void send_bluetooth_scanner_state_(esp32_ble_tracker::ScannerState state);
|
||||
#else
|
||||
void send_bluetooth_scanner_state_();
|
||||
void on_raw_advertisement_(const ble_device_base::RawAdvertisement &raw);
|
||||
#endif
|
||||
void on_raw_advertisement_(const ble_device_base::RawAdvertisement &raw);
|
||||
|
||||
/// Caller must ensure api_connection_ is non-null and API server is connected.
|
||||
void flush_pending_advertisements_() {
|
||||
@@ -288,8 +284,13 @@ class BluetoothProxy final : public Component {
|
||||
// Group 2: Fixed-size array of connection pointers
|
||||
std::array<BluetoothConnection *, BLUETOOTH_PROXY_MAX_CONNECTIONS> connections_{};
|
||||
#endif
|
||||
#ifndef USE_ESP32
|
||||
ble_device_base::BLEHub *hub_{nullptr};
|
||||
#ifdef USE_ESP32
|
||||
// set_parent() is the only writer of hub_ on esp32, so the downcast is
|
||||
// exact; ESP32BLETracker derives from BLEHub non-virtually.
|
||||
esp32_ble_tracker::ESP32BLETracker *parent_() {
|
||||
return static_cast<esp32_ble_tracker::ESP32BLETracker *>(this->hub_);
|
||||
}
|
||||
#endif
|
||||
|
||||
// BLE advertisement batching
|
||||
|
||||
@@ -374,20 +374,6 @@ async def register_client(var: cg.SafeExpType, config: ConfigType) -> cg.SafeExp
|
||||
return var
|
||||
|
||||
|
||||
async def register_raw_ble_device(
|
||||
var: cg.SafeExpType, config: ConfigType
|
||||
) -> cg.SafeExpType:
|
||||
"""Register a BLE device listener that only needs raw advertisement data.
|
||||
|
||||
This does NOT register the ESP_BT_DEVICE feature, meaning ESPBTDevice
|
||||
will not be compiled in if this is the only registration method used.
|
||||
"""
|
||||
_request_listener_slot()
|
||||
paren = await cg.get_variable(config[CONF_ESP32_BLE_ID])
|
||||
cg.add(paren.register_listener(var))
|
||||
return var
|
||||
|
||||
|
||||
async def register_raw_client(
|
||||
var: cg.SafeExpType, config: ConfigType
|
||||
) -> cg.SafeExpType:
|
||||
|
||||
@@ -462,6 +462,17 @@ void ESP32BLETracker::print_bt_device_info(const ESPBTDevice &device) {
|
||||
#endif // USE_ESP32_BLE_DEVICE
|
||||
|
||||
void ESP32BLETracker::process_scan_result_(const BLEScanResult &scan_result) {
|
||||
// Neutral raw-advertisement subscriber (the bluetooth_proxy path).
|
||||
if (this->raw_advertisement_callback_.is_set()) {
|
||||
ble_device_base::RawAdvertisement adv;
|
||||
adv.address = esp32_ble::ble_addr_to_uint64(scan_result.bda);
|
||||
adv.data = scan_result.ble_adv;
|
||||
adv.data_len = static_cast<uint16_t>(scan_result.adv_data_len) + scan_result.scan_rsp_len;
|
||||
adv.rssi = scan_result.rssi;
|
||||
adv.addr_type = scan_result.ble_addr_type;
|
||||
this->raw_advertisement_callback_.invoke(adv);
|
||||
}
|
||||
|
||||
// Process raw advertisements
|
||||
if (this->raw_advertisements_) {
|
||||
#ifdef ESPHOME_ESP32_BLE_TRACKER_LISTENER_COUNT
|
||||
|
||||
@@ -240,8 +240,11 @@ void LN882HBLETracker::process_adv_(const uint8_t *mac, int8_t rssi, uint8_t add
|
||||
// Raw callback (the raw-advertisement path). Both full advertisements and
|
||||
// unmatched scan responses (raw_only) are forwarded.
|
||||
if (this->raw_advertisement_callback_.is_set()) {
|
||||
const ble_device_base::RawAdvertisement adv{
|
||||
.mac = mac, .data = data, .data_len = data_len, .rssi = rssi, .addr_type = addr_type};
|
||||
const ble_device_base::RawAdvertisement adv{.address = ble_device_base::mac_lsb_first_to_uint64(mac),
|
||||
.data = data,
|
||||
.data_len = data_len,
|
||||
.rssi = rssi,
|
||||
.addr_type = addr_type};
|
||||
this->raw_advertisement_callback_.invoke(adv);
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ void RP2BLETracker::dump_config() {
|
||||
void RP2BLETracker::on_scan_report(const rp2040_ble::BLEScanReport &report) {
|
||||
// Raw callback (the raw-advertisement path).
|
||||
if (this->raw_advertisement_callback_.is_set()) {
|
||||
const ble_device_base::RawAdvertisement adv{.mac = report.mac,
|
||||
const ble_device_base::RawAdvertisement adv{.address = ble_device_base::mac_lsb_first_to_uint64(report.mac),
|
||||
.data = report.data,
|
||||
.data_len = report.data_len,
|
||||
.rssi = report.rssi,
|
||||
|
||||
@@ -107,14 +107,15 @@ def test_esp32_bluetooth_proxy_requests_scanner_state_slot(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
component_config_path: Callable[[str], Path],
|
||||
) -> None:
|
||||
"""The proxy requests one scanner state slot, one raw listener slot and a
|
||||
client slot per connection (three by default with active: true)."""
|
||||
"""The proxy requests one scanner state slot and a client slot per
|
||||
connection (three by default with active: true); advertisements arrive
|
||||
through the hub raw callback, so no listener slot exists."""
|
||||
generate_main(component_config_path("esp32_bluetooth_proxy.yaml"))
|
||||
assert (
|
||||
get_define_value("ESPHOME_ESP32_BLE_TRACKER_SCANNER_STATE_LISTENER_COUNT")
|
||||
== "1"
|
||||
)
|
||||
assert get_define_value("ESPHOME_ESP32_BLE_TRACKER_LISTENER_COUNT") == "1"
|
||||
assert get_define_value("ESPHOME_ESP32_BLE_TRACKER_LISTENER_COUNT") is None
|
||||
assert get_define_value("ESPHOME_ESP32_BLE_TRACKER_CLIENT_COUNT") == "3"
|
||||
|
||||
|
||||
|
||||
@@ -46,13 +46,13 @@ struct CapturingSubscriber {
|
||||
}
|
||||
};
|
||||
|
||||
// Device AA:BB:CC:DD:EE:FF — controller order delivers FF first.
|
||||
const uint8_t MAC_LSB_FIRST[6] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa};
|
||||
// Device AA:BB:CC:DD:EE:FF, packed the way the API speaks it.
|
||||
constexpr uint64_t TEST_ADDRESS = 0xAABBCCDDEEFFULL;
|
||||
const uint8_t ADV_DATA[4] = {0x02, 0x01, 0x06, 0x00};
|
||||
|
||||
RawAdvertisement make_test_adv() {
|
||||
return RawAdvertisement{
|
||||
.mac = MAC_LSB_FIRST, .data = ADV_DATA, .data_len = sizeof(ADV_DATA), .rssi = -63, .addr_type = 1};
|
||||
.address = TEST_ADDRESS, .data = ADV_DATA, .data_len = sizeof(ADV_DATA), .rssi = -63, .addr_type = 1};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -70,7 +70,7 @@ TEST(RawAdvertisementCallback, SubscriberSeesFieldsUnchanged) {
|
||||
hub.emit(make_test_adv());
|
||||
|
||||
ASSERT_EQ(subscriber.calls, 1);
|
||||
EXPECT_EQ(subscriber.last.mac, MAC_LSB_FIRST);
|
||||
EXPECT_EQ(subscriber.last.address, TEST_ADDRESS);
|
||||
EXPECT_EQ(subscriber.last.data, ADV_DATA);
|
||||
EXPECT_EQ(subscriber.last.data_len, sizeof(ADV_DATA));
|
||||
EXPECT_EQ(subscriber.last.rssi, -63);
|
||||
|
||||
Reference in New Issue
Block a user