ESPHome 2025.5.0
Loading...
Searching...
No Matches
ble_server.cpp
Go to the documentation of this file.
1#include "ble_server.h"
2
4#include "esphome/core/log.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
17namespace esphome {
18namespace esp32_ble_server {
19
20static const char *const TAG = "esp32_ble_server";
21
23 if (this->parent_->is_failed()) {
24 this->mark_failed();
25 ESP_LOGE(TAG, "BLE Server was marked failed by ESP32BLE");
26 return;
27 }
28 global_ble_server = this;
29}
30
32 if (!this->parent_->is_active()) {
33 return;
34 }
35 switch (this->state_) {
36 case RUNNING: {
37 // Start all services that are pending to start
38 if (!this->services_to_start_.empty()) {
39 uint16_t index_to_remove = 0;
40 // Iterate over the services to start
41 for (unsigned i = 0; i < this->services_to_start_.size(); i++) {
42 BLEService *service = this->services_to_start_[i];
43 if (service->is_created()) {
44 service->start(); // Needs to be called once per characteristic in the service
45 } else {
46 index_to_remove = i + 1;
47 }
48 }
49 // Remove the services that have been started
50 if (index_to_remove > 0) {
51 this->services_to_start_.erase(this->services_to_start_.begin(),
52 this->services_to_start_.begin() + index_to_remove - 1);
53 }
54 }
55 break;
56 }
57 case INIT: {
58 esp_err_t err = esp_ble_gatts_app_register(0);
59 if (err != ESP_OK) {
60 ESP_LOGE(TAG, "esp_ble_gatts_app_register failed: %d", err);
61 this->mark_failed();
62 return;
63 }
64 this->state_ = REGISTERING;
65 break;
66 }
67 case REGISTERING: {
68 if (this->registered_) {
69 // Create the device information service first so
70 // it is at the top of the GATT table
72 // Create all services previously created
73 for (auto &pair : this->services_) {
74 if (pair.second == this->device_information_service_) {
75 continue;
76 }
77 pair.second->do_create(this);
78 }
79 this->state_ = STARTING_SERVICE;
80 }
81 break;
82 }
83 case STARTING_SERVICE: {
85 this->state_ = RUNNING;
87 ESP_LOGD(TAG, "BLE server setup successfully");
88 } else if (this->device_information_service_->is_created()) {
90 }
91 break;
92 }
93 }
94}
95
96bool BLEServer::is_running() { return this->parent_->is_active() && this->state_ == RUNNING; }
97
98bool BLEServer::can_proceed() { return this->is_running() || !this->parent_->is_active(); }
99
101 if (this->is_running()) {
102 this->parent_->advertising_set_manufacturer_data(this->manufacturer_data_);
103 }
104}
105
106BLEService *BLEServer::create_service(ESPBTUUID uuid, bool advertise, uint16_t num_handles) {
107 ESP_LOGV(TAG, "Creating BLE service - %s", uuid.to_string().c_str());
108 // Calculate the inst_id for the service
109 uint8_t inst_id = 0;
110 for (; inst_id < 0xFF; inst_id++) {
111 if (this->get_service(uuid, inst_id) == nullptr) {
112 break;
113 }
114 }
115 if (inst_id == 0xFF) {
116 ESP_LOGW(TAG, "Could not create BLE service %s, too many instances", uuid.to_string().c_str());
117 return nullptr;
118 }
119 BLEService *service = // NOLINT(cppcoreguidelines-owning-memory)
120 new BLEService(uuid, num_handles, inst_id, advertise);
121 this->services_.emplace(BLEServer::get_service_key(uuid, inst_id), service);
122 if (this->parent_->is_active() && this->registered_) {
123 service->do_create(this);
124 }
125 return service;
126}
127
128void BLEServer::remove_service(ESPBTUUID uuid, uint8_t inst_id) {
129 ESP_LOGV(TAG, "Removing BLE service - %s %d", uuid.to_string().c_str(), inst_id);
130 BLEService *service = this->get_service(uuid, inst_id);
131 if (service == nullptr) {
132 ESP_LOGW(TAG, "BLE service %s %d does not exist", uuid.to_string().c_str(), inst_id);
133 return;
134 }
135 service->do_delete();
136 delete service; // NOLINT(cppcoreguidelines-owning-memory)
137 this->services_.erase(BLEServer::get_service_key(uuid, inst_id));
138}
139
141 BLEService *service = nullptr;
142 if (this->services_.count(BLEServer::get_service_key(uuid, inst_id)) > 0) {
143 service = this->services_.at(BLEServer::get_service_key(uuid, inst_id));
144 }
145 return service;
146}
147
148std::string BLEServer::get_service_key(ESPBTUUID uuid, uint8_t inst_id) {
149 return uuid.to_string() + std::to_string(inst_id);
150}
151
152void BLEServer::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
153 esp_ble_gatts_cb_param_t *param) {
154 switch (event) {
155 case ESP_GATTS_CONNECT_EVT: {
156 ESP_LOGD(TAG, "BLE Client connected");
157 this->add_client_(param->connect.conn_id);
158 this->emit_(BLEServerEvt::EmptyEvt::ON_CONNECT, param->connect.conn_id);
159 break;
160 }
161 case ESP_GATTS_DISCONNECT_EVT: {
162 ESP_LOGD(TAG, "BLE Client disconnected");
163 this->remove_client_(param->disconnect.conn_id);
164 this->parent_->advertising_start();
165 this->emit_(BLEServerEvt::EmptyEvt::ON_DISCONNECT, param->disconnect.conn_id);
166 break;
167 }
168 case ESP_GATTS_REG_EVT: {
169 this->gatts_if_ = gatts_if;
170 this->registered_ = true;
171 break;
172 }
173 default:
174 break;
175 }
176
177 for (const auto &pair : this->services_) {
178 pair.second->gatts_event_handler(event, gatts_if, param);
179 }
180}
181
183 // Delete all clients
184 this->clients_.clear();
185 // Delete all services
186 for (auto &pair : this->services_) {
187 pair.second->do_delete();
188 }
189 this->registered_ = false;
190 this->state_ = INIT;
191}
192
194
195void BLEServer::dump_config() { ESP_LOGCONFIG(TAG, "ESP32 BLE Server:"); }
196
197BLEServer *global_ble_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
198
199} // namespace esp32_ble_server
200} // namespace esphome
201
202#endif
virtual void mark_failed()
Mark this component as failed.
std::string to_string() const
Definition ble_uuid.cpp:171
void ble_before_disabled_event_handler() override
std::vector< uint8_t > manufacturer_data_
Definition ble_server.h:76
static std::string get_service_key(ESPBTUUID uuid, uint8_t inst_id)
void remove_client_(uint16_t conn_id)
Definition ble_server.h:74
float get_setup_priority() const override
enum esphome::esp32_ble_server::BLEServer::State INIT
BLEService * get_service(ESPBTUUID uuid, uint8_t inst_id=0)
std::vector< BLEService * > services_to_start_
Definition ble_server.h:82
BLEService * create_service(ESPBTUUID uuid, bool advertise=false, uint16_t num_handles=15)
void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) override
void remove_service(ESPBTUUID uuid, uint8_t inst_id=0)
void add_client_(uint16_t conn_id)
Definition ble_server.h:73
std::unordered_map< std::string, BLEService * > services_
Definition ble_server.h:81
std::unordered_set< uint16_t > clients_
Definition ble_server.h:80
void do_create(BLEServer *server)
void emit_(BLEServerEvt::EmptyEvt event, Args... args)
const float AFTER_BLUETOOTH
Definition component.cpp:22
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7