ESPHome  2024.7.0
ble.cpp
Go to the documentation of this file.
1 #ifdef USE_ESP32
2 
3 #include "ble.h"
4 
5 #ifdef USE_ESP32_VARIANT_ESP32C6
6 #include "const_esp32c6.h"
7 #endif // USE_ESP32_VARIANT_ESP32C6
8 
10 #include "esphome/core/log.h"
11 
12 #include <esp_bt.h>
13 #include <esp_bt_device.h>
14 #include <esp_bt_main.h>
15 #include <esp_gap_ble_api.h>
16 #include <freertos/FreeRTOS.h>
17 #include <freertos/FreeRTOSConfig.h>
18 #include <freertos/task.h>
19 #include <nvs_flash.h>
20 
21 #ifdef USE_ARDUINO
22 #include <esp32-hal-bt.h>
23 #endif
24 
25 namespace esphome {
26 namespace esp32_ble {
27 
28 static const char *const TAG = "esp32_ble";
29 
31  global_ble = this;
32  ESP_LOGCONFIG(TAG, "Setting up BLE...");
33 
34  if (!ble_pre_setup_()) {
35  ESP_LOGE(TAG, "BLE could not be prepared for configuration");
36  this->mark_failed();
37  return;
38  }
39 
41  if (this->enable_on_boot_) {
42  this->enable();
43  }
44 }
45 
48  return;
49 
51 }
52 
55  return;
56 
58 }
59 
61 
63  this->advertising_init_();
64  if (!this->is_active())
65  return;
66  this->advertising_->start();
67 }
68 
69 void ESP32BLE::advertising_set_service_data(const std::vector<uint8_t> &data) {
70  this->advertising_init_();
71  this->advertising_->set_service_data(data);
72  this->advertising_start();
73 }
74 
75 void ESP32BLE::advertising_set_manufacturer_data(const std::vector<uint8_t> &data) {
76  this->advertising_init_();
78  this->advertising_start();
79 }
80 
82  this->advertising_init_();
83  this->advertising_->add_service_uuid(uuid);
84  this->advertising_start();
85 }
86 
88  this->advertising_init_();
89  this->advertising_->remove_service_uuid(uuid);
90  this->advertising_start();
91 }
92 
94  esp_err_t err = nvs_flash_init();
95  if (err != ESP_OK) {
96  ESP_LOGE(TAG, "nvs_flash_init failed: %d", err);
97  return false;
98  }
99  return true;
100 }
101 
103  if (this->advertising_ != nullptr)
104  return;
105  this->advertising_ = new BLEAdvertising(); // NOLINT(cppcoreguidelines-owning-memory)
106 
107  this->advertising_->set_scan_response(true);
109 }
110 
112  esp_err_t err;
113 #ifdef USE_ARDUINO
114  if (!btStart()) {
115  ESP_LOGE(TAG, "btStart failed: %d", esp_bt_controller_get_status());
116  return false;
117  }
118 #else
119  if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
120  // start bt controller
121  if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) {
122 #ifdef USE_ESP32_VARIANT_ESP32C6
123  esp_bt_controller_config_t cfg = BT_CONTROLLER_CONFIG;
124 #else
125  esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
126 #endif
127  err = esp_bt_controller_init(&cfg);
128  if (err != ESP_OK) {
129  ESP_LOGE(TAG, "esp_bt_controller_init failed: %s", esp_err_to_name(err));
130  return false;
131  }
132  while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE)
133  ;
134  }
135  if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) {
136  err = esp_bt_controller_enable(ESP_BT_MODE_BLE);
137  if (err != ESP_OK) {
138  ESP_LOGE(TAG, "esp_bt_controller_enable failed: %s", esp_err_to_name(err));
139  return false;
140  }
141  }
142  if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
143  ESP_LOGE(TAG, "esp bt controller enable failed");
144  return false;
145  }
146  }
147 #endif
148 
149  esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
150 
151  err = esp_bluedroid_init();
152  if (err != ESP_OK) {
153  ESP_LOGE(TAG, "esp_bluedroid_init failed: %d", err);
154  return false;
155  }
156  err = esp_bluedroid_enable();
157  if (err != ESP_OK) {
158  ESP_LOGE(TAG, "esp_bluedroid_enable failed: %d", err);
159  return false;
160  }
161 
162  if (!this->gap_event_handlers_.empty()) {
163  err = esp_ble_gap_register_callback(ESP32BLE::gap_event_handler);
164  if (err != ESP_OK) {
165  ESP_LOGE(TAG, "esp_ble_gap_register_callback failed: %d", err);
166  return false;
167  }
168  }
169 
170  if (!this->gatts_event_handlers_.empty()) {
171  err = esp_ble_gatts_register_callback(ESP32BLE::gatts_event_handler);
172  if (err != ESP_OK) {
173  ESP_LOGE(TAG, "esp_ble_gatts_register_callback failed: %d", err);
174  return false;
175  }
176  }
177 
178  if (!this->gattc_event_handlers_.empty()) {
179  err = esp_ble_gattc_register_callback(ESP32BLE::gattc_event_handler);
180  if (err != ESP_OK) {
181  ESP_LOGE(TAG, "esp_ble_gattc_register_callback failed: %d", err);
182  return false;
183  }
184  }
185 
186  std::string name = App.get_name();
187  if (name.length() > 20) {
189  name.erase(name.begin() + 13, name.end() - 7); // Remove characters between 13 and the mac address
190  } else {
191  name = name.substr(0, 20);
192  }
193  }
194 
195  err = esp_ble_gap_set_device_name(name.c_str());
196  if (err != ESP_OK) {
197  ESP_LOGE(TAG, "esp_ble_gap_set_device_name failed: %d", err);
198  return false;
199  }
200 
201  err = esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &(this->io_cap_), sizeof(uint8_t));
202  if (err != ESP_OK) {
203  ESP_LOGE(TAG, "esp_ble_gap_set_security_param failed: %d", err);
204  return false;
205  }
206 
207  // BLE takes some time to be fully set up, 200ms should be more than enough
208  delay(200); // NOLINT
209 
210  return true;
211 }
212 
214  esp_err_t err = esp_bluedroid_disable();
215  if (err != ESP_OK) {
216  ESP_LOGE(TAG, "esp_bluedroid_disable failed: %d", err);
217  return false;
218  }
219  err = esp_bluedroid_deinit();
220  if (err != ESP_OK) {
221  ESP_LOGE(TAG, "esp_bluedroid_deinit failed: %d", err);
222  return false;
223  }
224 
225 #ifdef USE_ARDUINO
226  if (!btStop()) {
227  ESP_LOGE(TAG, "btStop failed: %d", esp_bt_controller_get_status());
228  return false;
229  }
230 #else
231  if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
232  // stop bt controller
233  if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED) {
234  err = esp_bt_controller_disable();
235  if (err != ESP_OK) {
236  ESP_LOGE(TAG, "esp_bt_controller_disable failed: %s", esp_err_to_name(err));
237  return false;
238  }
239  while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED)
240  ;
241  }
242  if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) {
243  err = esp_bt_controller_deinit();
244  if (err != ESP_OK) {
245  ESP_LOGE(TAG, "esp_bt_controller_deinit failed: %s", esp_err_to_name(err));
246  return false;
247  }
248  }
249  if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
250  ESP_LOGE(TAG, "esp bt controller disable failed");
251  return false;
252  }
253  }
254 #endif
255  return true;
256 }
257 
259  switch (this->state_) {
262  return;
264  ESP_LOGD(TAG, "Disabling BLE...");
265 
266  for (auto *ble_event_handler : this->ble_status_event_handlers_) {
267  ble_event_handler->ble_before_disabled_event_handler();
268  }
269 
270  if (!ble_dismantle_()) {
271  ESP_LOGE(TAG, "BLE could not be dismantled");
272  this->mark_failed();
273  return;
274  }
276  return;
277  }
279  ESP_LOGD(TAG, "Enabling BLE...");
281 
282  if (!ble_setup_()) {
283  ESP_LOGE(TAG, "BLE could not be set up");
284  this->mark_failed();
285  return;
286  }
287 
289  return;
290  }
292  break;
293  }
294 
295  BLEEvent *ble_event = this->ble_events_.pop();
296  while (ble_event != nullptr) {
297  switch (ble_event->type_) {
298  case BLEEvent::GATTS:
299  this->real_gatts_event_handler_(ble_event->event_.gatts.gatts_event, ble_event->event_.gatts.gatts_if,
300  &ble_event->event_.gatts.gatts_param);
301  break;
302  case BLEEvent::GATTC:
303  this->real_gattc_event_handler_(ble_event->event_.gattc.gattc_event, ble_event->event_.gattc.gattc_if,
304  &ble_event->event_.gattc.gattc_param);
305  break;
306  case BLEEvent::GAP:
307  this->real_gap_event_handler_(ble_event->event_.gap.gap_event, &ble_event->event_.gap.gap_param);
308  break;
309  default:
310  break;
311  }
312  delete ble_event; // NOLINT(cppcoreguidelines-owning-memory)
313  ble_event = this->ble_events_.pop();
314  }
315 }
316 
317 void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
318  BLEEvent *new_event = new BLEEvent(event, param); // NOLINT(cppcoreguidelines-owning-memory)
319  global_ble->ble_events_.push(new_event);
320 } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
321 
322 void ESP32BLE::real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
323  ESP_LOGV(TAG, "(BLE) gap_event_handler - %d", event);
324  for (auto *gap_handler : this->gap_event_handlers_) {
325  gap_handler->gap_event_handler(event, param);
326  }
327 }
328 
329 void ESP32BLE::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
330  esp_ble_gatts_cb_param_t *param) {
331  BLEEvent *new_event = new BLEEvent(event, gatts_if, param); // NOLINT(cppcoreguidelines-owning-memory)
332  global_ble->ble_events_.push(new_event);
333 } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
334 
335 void ESP32BLE::real_gatts_event_handler_(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
336  esp_ble_gatts_cb_param_t *param) {
337  ESP_LOGV(TAG, "(BLE) gatts_event [esp_gatt_if: %d] - %d", gatts_if, event);
338  for (auto *gatts_handler : this->gatts_event_handlers_) {
339  gatts_handler->gatts_event_handler(event, gatts_if, param);
340  }
341 }
342 
343 void ESP32BLE::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
344  esp_ble_gattc_cb_param_t *param) {
345  BLEEvent *new_event = new BLEEvent(event, gattc_if, param); // NOLINT(cppcoreguidelines-owning-memory)
346  global_ble->ble_events_.push(new_event);
347 } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
348 
349 void ESP32BLE::real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
350  esp_ble_gattc_cb_param_t *param) {
351  ESP_LOGV(TAG, "(BLE) gattc_event [esp_gatt_if: %d] - %d", gattc_if, event);
352  for (auto *gattc_handler : this->gattc_event_handlers_) {
353  gattc_handler->gattc_event_handler(event, gattc_if, param);
354  }
355 }
356 
358 
360  const uint8_t *mac_address = esp_bt_dev_get_address();
361  if (mac_address) {
362  const char *io_capability_s;
363  switch (this->io_cap_) {
364  case ESP_IO_CAP_OUT:
365  io_capability_s = "display_only";
366  break;
367  case ESP_IO_CAP_IO:
368  io_capability_s = "display_yes_no";
369  break;
370  case ESP_IO_CAP_IN:
371  io_capability_s = "keyboard_only";
372  break;
373  case ESP_IO_CAP_NONE:
374  io_capability_s = "none";
375  break;
376  case ESP_IO_CAP_KBDISP:
377  io_capability_s = "keyboard_display";
378  break;
379  default:
380  io_capability_s = "invalid";
381  break;
382  }
383  ESP_LOGCONFIG(TAG, "ESP32 BLE:");
384  ESP_LOGCONFIG(TAG, " MAC address: %02X:%02X:%02X:%02X:%02X:%02X", mac_address[0], mac_address[1], mac_address[2],
385  mac_address[3], mac_address[4], mac_address[5]);
386  ESP_LOGCONFIG(TAG, " IO Capability: %s", io_capability_s);
387  } else {
388  ESP_LOGCONFIG(TAG, "ESP32 BLE: bluetooth stack is not enabled");
389  }
390 }
391 
392 uint64_t ble_addr_to_uint64(const esp_bd_addr_t address) {
393  uint64_t u = 0;
394  u |= uint64_t(address[0] & 0xFF) << 40;
395  u |= uint64_t(address[1] & 0xFF) << 32;
396  u |= uint64_t(address[2] & 0xFF) << 24;
397  u |= uint64_t(address[3] & 0xFF) << 16;
398  u |= uint64_t(address[4] & 0xFF) << 8;
399  u |= uint64_t(address[5] & 0xFF) << 0;
400  return u;
401 }
402 
403 ESP32BLE *global_ble = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
404 
405 } // namespace esp32_ble
406 } // namespace esphome
407 
408 #endif
const char * name
Definition: stm32flash.h:78
uint64_t ble_addr_to_uint64(const esp_bd_addr_t address)
Definition: ble.cpp:392
void set_min_preferred_interval(uint16_t interval)
ESP32BLE * global_ble
Definition: ble.cpp:403
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
Definition: ble.cpp:329
struct esphome::esp32_ble::BLEEvent::@76::gattc_event gattc
void set_service_data(const std::vector< uint8_t > &data)
void advertising_remove_service_uuid(ESPBTUUID uuid)
Definition: ble.cpp:87
std::vector< GAPEventHandler * > gap_event_handlers_
Definition: ble.h:115
std::vector< GATTcEventHandler * > gattc_event_handlers_
Definition: ble.h:116
Queue< BLEEvent > ble_events_
Definition: ble.h:121
void set_manufacturer_data(const std::vector< uint8_t > &data)
std::vector< GATTsEventHandler * > gatts_event_handlers_
Definition: ble.h:117
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
Definition: ble.cpp:317
static void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
Definition: ble.cpp:343
BLEComponentState state_
Definition: ble.h:119
void real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
Definition: ble.cpp:349
struct esphome::esp32_ble::BLEEvent::@76::gap_event gap
float get_setup_priority() const override
Definition: ble.cpp:357
Nothing has been initialized yet.
Definition: ble.h:42
void real_gatts_event_handler_(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
Definition: ble.cpp:335
void setup() override
Definition: ble.cpp:30
void advertising_set_service_data(const std::vector< uint8_t > &data)
Definition: ble.cpp:69
Application App
Global storage of Application pointer - only one Application can exist.
std::vector< BLEStatusEventHandler * > ble_status_event_handlers_
Definition: ble.h:118
enum esphome::esp32_ble::BLEEvent::ble_event_t type_
union esphome::esp32_ble::BLEEvent::@76 event_
const std::string & get_name() const
Get the name of this Application set by pre_setup().
Definition: application.h:202
void remove_service_uuid(ESPBTUUID uuid)
bool is_name_add_mac_suffix_enabled() const
Definition: application.h:213
void dump_config() override
Definition: ble.cpp:359
void loop() override
Definition: ble.cpp:258
void advertising_set_manufacturer_data(const std::vector< uint8_t > &data)
Definition: ble.cpp:75
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
esp_ble_io_cap_t io_cap_
Definition: ble.h:123
void real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
Definition: ble.cpp:322
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
BLE should be disabled on next loop.
Definition: ble.h:44
struct esphome::esp32_ble::BLEEvent::@76::gatts_event gatts
BLE should be enabled on next loop.
Definition: ble.h:48
void advertising_add_service_uuid(ESPBTUUID uuid)
Definition: ble.cpp:81
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:26
BLEAdvertising * advertising_
Definition: ble.h:122
void set_scan_response(bool scan_response)