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