ESPHome  2024.3.1
ble_server.cpp
Go to the documentation of this file.
1 #include "ble_server.h"
2 
4 #include "esphome/core/log.h"
6 #include "esphome/core/version.h"
7 
8 #ifdef USE_ESP32
9 
10 #include <nvs_flash.h>
11 #include <freertos/FreeRTOSConfig.h>
12 #include <esp_bt_main.h>
13 #include <esp_bt.h>
14 #include <freertos/task.h>
15 #include <esp_gap_ble_api.h>
16 
17 namespace esphome {
18 namespace esp32_ble_server {
19 
20 static const char *const TAG = "esp32_ble_server";
21 
22 static const uint16_t DEVICE_INFORMATION_SERVICE_UUID = 0x180A;
23 static const uint16_t MODEL_UUID = 0x2A24;
24 static const uint16_t VERSION_UUID = 0x2A26;
25 static const uint16_t MANUFACTURER_UUID = 0x2A29;
26 
28  if (this->parent_->is_failed()) {
29  this->mark_failed();
30  ESP_LOGE(TAG, "BLE Server was marked failed by ESP32BLE");
31  return;
32  }
33  global_ble_server = this;
34 }
35 
37  if (!this->parent_->is_active()) {
38  return;
39  }
40  switch (this->state_) {
41  case RUNNING:
42  return;
43 
44  case INIT: {
45  esp_err_t err = esp_ble_gatts_app_register(0);
46  if (err != ESP_OK) {
47  ESP_LOGE(TAG, "esp_ble_gatts_app_register failed: %d", err);
48  this->mark_failed();
49  return;
50  }
51  this->state_ = REGISTERING;
52  break;
53  }
54  case REGISTERING: {
55  if (this->registered_) {
56  // Create all services previously created
57  for (auto &pair : this->services_) {
58  pair.second->do_create(this);
59  }
60  if (this->device_information_service_ == nullptr) {
61  this->create_service(ESPBTUUID::from_uint16(DEVICE_INFORMATION_SERVICE_UUID));
63  this->get_service(ESPBTUUID::from_uint16(DEVICE_INFORMATION_SERVICE_UUID));
65  }
66  this->state_ = STARTING_SERVICE;
67  }
68  break;
69  }
70  case STARTING_SERVICE: {
72  break;
73  }
75  this->state_ = RUNNING;
76  this->restart_advertising_();
77  ESP_LOGD(TAG, "BLE server setup successfully");
78  } else if (!this->device_information_service_->is_starting()) {
80  }
81  break;
82  }
83  }
84 }
85 
86 bool BLEServer::is_running() { return this->parent_->is_active() && this->state_ == RUNNING; }
87 
88 bool BLEServer::can_proceed() { return this->is_running() || !this->parent_->is_active(); }
89 
91  if (this->is_running()) {
92  this->parent_->advertising_set_manufacturer_data(this->manufacturer_data_);
93  }
94 }
95 
97  if (this->model_.has_value()) {
98  BLECharacteristic *model =
100  model->set_value(this->model_.value());
101  } else {
102  BLECharacteristic *model =
104  model->set_value(ESPHOME_BOARD);
105  }
106 
109  version->set_value("ESPHome " ESPHOME_VERSION);
110 
111  BLECharacteristic *manufacturer =
113  manufacturer->set_value(this->manufacturer_);
114 
115  return true;
116 }
117 
118 void BLEServer::create_service(ESPBTUUID uuid, bool advertise, uint16_t num_handles, uint8_t inst_id) {
119  ESP_LOGV(TAG, "Creating BLE service - %s", uuid.to_string().c_str());
120  // If the service already exists, do nothing
121  BLEService *service = this->get_service(uuid);
122  if (service != nullptr) {
123  ESP_LOGW(TAG, "BLE service %s already exists", uuid.to_string().c_str());
124  return;
125  }
126  service = new BLEService(uuid, num_handles, inst_id, advertise); // NOLINT(cppcoreguidelines-owning-memory)
127  this->services_.emplace(uuid.to_string(), service);
128  service->do_create(this);
129 }
130 
132  ESP_LOGV(TAG, "Removing BLE service - %s", uuid.to_string().c_str());
133  BLEService *service = this->get_service(uuid);
134  if (service == nullptr) {
135  ESP_LOGW(TAG, "BLE service %s not found", uuid.to_string().c_str());
136  return;
137  }
138  service->do_delete();
139  delete service; // NOLINT(cppcoreguidelines-owning-memory)
140  this->services_.erase(uuid.to_string());
141 }
142 
144  BLEService *service = nullptr;
145  if (this->services_.count(uuid.to_string()) > 0) {
146  service = this->services_.at(uuid.to_string());
147  }
148  return service;
149 }
150 
151 void BLEServer::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
152  esp_ble_gatts_cb_param_t *param) {
153  switch (event) {
154  case ESP_GATTS_CONNECT_EVT: {
155  ESP_LOGD(TAG, "BLE Client connected");
156  this->add_client_(param->connect.conn_id, (void *) this);
157  this->connected_clients_++;
158  for (auto *component : this->service_components_) {
159  component->on_client_connect();
160  }
161  break;
162  }
163  case ESP_GATTS_DISCONNECT_EVT: {
164  ESP_LOGD(TAG, "BLE Client disconnected");
165  if (this->remove_client_(param->disconnect.conn_id))
166  this->connected_clients_--;
167  this->parent_->advertising_start();
168  for (auto *component : this->service_components_) {
169  component->on_client_disconnect();
170  }
171  break;
172  }
173  case ESP_GATTS_REG_EVT: {
174  this->gatts_if_ = gatts_if;
175  this->registered_ = true;
176  break;
177  }
178  default:
179  break;
180  }
181 
182  for (const auto &pair : this->services_) {
183  pair.second->gatts_event_handler(event, gatts_if, param);
184  }
185 }
186 
188  // Delete all clients
189  this->clients_.clear();
190  // Delete all services
191  for (auto &pair : this->services_) {
192  pair.second->do_delete();
193  }
194  this->registered_ = false;
195  this->state_ = INIT;
196 }
197 
199 
200 void BLEServer::dump_config() { ESP_LOGCONFIG(TAG, "ESP32 BLE Server:"); }
201 
202 BLEServer *global_ble_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
203 
204 } // namespace esp32_ble_server
205 } // namespace esphome
206 
207 #endif
value_type const & value() const
Definition: optional.h:89
bool remove_client_(uint16_t conn_id)
Definition: ble_server.h:74
float get_setup_priority() const override
Definition: ble_server.cpp:198
std::unordered_map< uint16_t, void * > clients_
Definition: ble_server.h:83
void create_service(ESPBTUUID uuid, bool advertise=false, uint16_t num_handles=15, uint8_t inst_id=0)
Definition: ble_server.cpp:118
void set_value(const uint8_t *data, size_t length)
bool has_value() const
Definition: optional.h:87
const float AFTER_BLUETOOTH
Definition: component.cpp:22
optional< std::string > model_
Definition: ble_server.h:77
void add_client_(uint16_t conn_id, void *client)
Definition: ble_server.h:73
std::unordered_map< std::string, BLEService * > services_
Definition: ble_server.h:84
std::vector< BLEServiceComponent * > service_components_
Definition: ble_server.h:87
enum esphome::esp32_ble_server::BLEServer::State INIT
static ESPBTUUID from_uint16(uint16_t uuid)
Definition: ble_uuid.cpp:16
BLEService * get_service(ESPBTUUID uuid)
Definition: ble_server.cpp:143
void ble_before_disabled_event_handler() override
Definition: ble_server.cpp:187
void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) override
Definition: ble_server.cpp:151
std::string to_string() const
Definition: ble_uuid.cpp:165
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:113
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
void remove_service(ESPBTUUID uuid)
Definition: ble_server.cpp:131
BLECharacteristic * create_characteristic(const std::string &uuid, esp_gatt_char_prop_t properties)
Definition: ble_service.cpp:34
std::vector< uint8_t > manufacturer_data_
Definition: ble_server.h:78