ESPHome 2026.8.0b4
Loading...
Searching...
No Matches
rp2040_ble.h
Go to the documentation of this file.
1#pragma once
2
3#include "esphome/core/defines.h" // Must be included before conditional includes
4
5#ifdef USE_RP2040_BLE
6
11
12#include <btstack.h>
13
14#include <cstdint>
15
16namespace esphome::rp2040_ble {
17
18enum class BLEComponentState : uint8_t {
19 STATE_OFF = 0,
21 ACTIVE,
24};
25
28 uint8_t mac[MAC_ADDRESS_SIZE]; // LSB-first, as the controller delivers it
29 int8_t rssi; // signed dBm
30 uint8_t addr_type;
31 uint8_t adv_event_type; // GAP advertising event type (ADV_IND .. SCAN_RSP); lets a merger tell the two apart
32 uint8_t data_len; // bytes valid in data[]
33 // Legacy advertisement (31) + scan response (31). BTstack delivers the two
34 // as separate reports, so each report fills at most 31 bytes today; the 62
35 // matches the API raw-advertisement contract. adv_event_type is what lets a
36 // future merge point tell the two frames apart — carrying it beyond this
37 // struct (RawAdvertisement) is deferred until a consumer needs the merge.
38 uint8_t data[62];
39
40 // EventPool contract: nothing is heap-allocated inside a report.
41 void release() {}
42};
43
50 public:
51 virtual void on_scan_report(const BLEScanReport &report) = 0;
52
53 protected:
54 ~BLEScanListener() = default; // deletion via this interface is not part of the contract
55};
56
57// Maximum reports buffered between the packet handler and loop(). The producer
58// is a same-core IRQ and loop() drains the ring every iteration, so only the
59// advertisements of a single loop period can accumulate.
60static constexpr uint8_t MAX_SCAN_REPORT_QUEUE_SIZE = 32;
61
62class RP2040BLE final : public Component {
63 public:
64 void setup() override;
65 void loop() override;
66 void dump_config() override;
67 float get_setup_priority() const override;
68
69 void enable();
70 void disable();
71 bool is_active() const { return this->state_ == BLEComponentState::ACTIVE; }
72
73 void set_enable_on_boot(bool enable_on_boot) { this->enable_on_boot_ = enable_on_boot; }
74
80 void get_mac_msb_first(uint8_t out[MAC_ADDRESS_SIZE]) const;
81
82#ifdef RP2040_BLE_SCAN_LISTENER_COUNT
86 void register_scan_listener(BLEScanListener *listener) { this->scan_listeners_.push_back(listener); }
87#endif
88
99 bool scan_start(uint16_t interval, uint16_t window, bool active);
101 void scan_stop();
102
103#ifdef USE_BLE_GATT_CLIENT
109 void inhibit_scan();
111#endif
112
113 protected:
114 static void packet_handler(uint8_t type, uint16_t channel, uint8_t *packet, uint16_t size);
115
118 void enqueue_scan_report_(const uint8_t *mac_lsb_first, int8_t rssi, uint8_t addr_type, uint8_t adv_event_type,
119 const uint8_t *data, uint16_t data_len);
120
121#ifdef RP2040_BLE_SCAN_LISTENER_COUNT
122 // Codegen-sized: no heap allocation, no std::vector template instantiation —
123 // the same StaticVector pattern as the tracker's ble_device_base listeners.
125#endif
126 // Report ring: the BTstack packet handler (async-context IRQ) allocates a
127 // report from the pool, fills it and pushes the pointer; loop() pops,
128 // dispatches and releases. Lock-free SPSC — the esp32_ble/bk72xx_ble pattern.
130 // Pool sized to queue capacity (SIZE-1): the ring reserves one slot, so
131 // allocate() returns nullptr before push() can fail. This prevents leaking a
132 // pool slot on a failed push and keeps release() off the producer path.
133 esphome::EventPool<BLEScanReport, MAX_SCAN_REPORT_QUEUE_SIZE - 1> report_pool_;
134
135 btstack_packet_callback_registration_t hci_event_callback_registration_{};
136 btstack_packet_callback_registration_t sm_event_callback_registration_{};
137
138 uint8_t ble_mac_[MAC_ADDRESS_SIZE]{0}; // printable (MSB-first) order; zeros until ACTIVE
140 bool enable_on_boot_{true};
142 bool active_logged_{false};
143#ifdef USE_BLE_GATT_CLIENT
144 // Remembered scan intent, so connect attempts can pause the physical scan
145 // and restore it afterwards without involving the tracker. Counted so
146 // overlapping connect attempts compose once multiple slots exist.
147 uint16_t scan_interval_{0};
148 uint16_t scan_window_{0};
150 bool scan_active_mode_{false};
151 bool scan_desired_{false};
152#endif
153};
154
155// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
156extern RP2040BLE *global_ble;
157
158} // namespace esphome::rp2040_ble
159
160#endif // USE_RP2040_BLE
Minimal static vector - saves memory by avoiding std::vector overhead.
Definition helpers.h:227
Consumer interface for controller scan reports.
Definition rp2040_ble.h:49
virtual void on_scan_report(const BLEScanReport &report)=0
static void packet_handler(uint8_t type, uint16_t channel, uint8_t *packet, uint16_t size)
void scan_stop()
Stop the controller scan (no-op when not scanning).
uint8_t ble_mac_[MAC_ADDRESS_SIZE]
Definition rp2040_ble.h:138
float get_setup_priority() const override
StaticVector< BLEScanListener *, RP2040_BLE_SCAN_LISTENER_COUNT > scan_listeners_
Definition rp2040_ble.h:124
esphome::EventPool< BLEScanReport, MAX_SCAN_REPORT_QUEUE_SIZE - 1 > report_pool_
Definition rp2040_ble.h:133
void inhibit_scan()
Pause the physical scan for the duration of a GATT connect attempt (initiating and scanning contend f...
void register_scan_listener(BLEScanListener *listener)
Register a consumer for scan reports (delivered on the main loop via loop()).
Definition rp2040_ble.h:86
void get_mac_msb_first(uint8_t out[MAC_ADDRESS_SIZE]) const
Controller BLE address in printable (MSB-first) order, as gap_local_bd_addr() delivers it — note BLES...
esphome::LockFreeQueue< BLEScanReport, MAX_SCAN_REPORT_QUEUE_SIZE > report_queue_
Definition rp2040_ble.h:129
void set_enable_on_boot(bool enable_on_boot)
Definition rp2040_ble.h:73
btstack_packet_callback_registration_t hci_event_callback_registration_
Definition rp2040_ble.h:135
void enqueue_scan_report_(const uint8_t *mac_lsb_first, int8_t rssi, uint8_t addr_type, uint8_t adv_event_type, const uint8_t *data, uint16_t data_len)
Buffer one controller report (BTstack packet handler, CYW43 async-context IRQ — bounded copy into the...
btstack_packet_callback_registration_t sm_event_callback_registration_
Definition rp2040_ble.h:136
uint16_t type
RP2040BLE * global_ble
uint16_t size
Definition helpers.cpp:25
uint32_t * scan_start
One advertisement report from the controller.
Definition rp2040_ble.h:27
uint8_t mac[MAC_ADDRESS_SIZE]
Definition rp2040_ble.h:28