ESPHome 2025.5.0
Loading...
Searching...
No Matches
bluetooth_connection.cpp
Go to the documentation of this file.
2
5#include "esphome/core/log.h"
6
7#ifdef USE_ESP32
8
9#include "bluetooth_proxy.h"
10
11namespace esphome {
12namespace bluetooth_proxy {
13
14static const char *const TAG = "bluetooth_proxy.connection";
15
17 ESP_LOGCONFIG(TAG, "BLE Connection:");
19}
20
21bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
22 esp_ble_gattc_cb_param_t *param) {
23 if (!BLEClientBase::gattc_event_handler(event, gattc_if, param))
24 return false;
25
26 switch (event) {
27 case ESP_GATTC_DISCONNECT_EVT: {
28 this->proxy_->send_device_connection(this->address_, false, 0, param->disconnect.reason);
29 this->set_address(0);
31 break;
32 }
33 case ESP_GATTC_CLOSE_EVT: {
34 this->proxy_->send_device_connection(this->address_, false, 0, param->close.reason);
35 this->set_address(0);
37 break;
38 }
39 case ESP_GATTC_OPEN_EVT: {
40 if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
41 this->proxy_->send_device_connection(this->address_, false, 0, param->open.status);
42 this->set_address(0);
44 } else if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
45 this->proxy_->send_device_connection(this->address_, true, this->mtu_);
47 }
48 this->seen_mtu_or_services_ = false;
49 break;
50 }
51 case ESP_GATTC_CFG_MTU_EVT:
52 case ESP_GATTC_SEARCH_CMPL_EVT: {
53 if (!this->seen_mtu_or_services_) {
54 // We don't know if we will get the MTU or the services first, so
55 // only send the device connection true if we have already received
56 // the services.
57 this->seen_mtu_or_services_ = true;
58 break;
59 }
60 this->proxy_->send_device_connection(this->address_, true, this->mtu_);
62 break;
63 }
64 case ESP_GATTC_READ_DESCR_EVT:
65 case ESP_GATTC_READ_CHAR_EVT: {
66 if (param->read.status != ESP_GATT_OK) {
67 ESP_LOGW(TAG, "[%d] [%s] Error reading char/descriptor at handle 0x%2X, status=%d", this->connection_index_,
68 this->address_str_.c_str(), param->read.handle, param->read.status);
69 this->proxy_->send_gatt_error(this->address_, param->read.handle, param->read.status);
70 break;
71 }
73 resp.address = this->address_;
74 resp.handle = param->read.handle;
75 resp.data.reserve(param->read.value_len);
76 // Use bulk insert instead of individual push_backs
77 resp.data.insert(resp.data.end(), param->read.value, param->read.value + param->read.value_len);
79 break;
80 }
81 case ESP_GATTC_WRITE_CHAR_EVT:
82 case ESP_GATTC_WRITE_DESCR_EVT: {
83 if (param->write.status != ESP_GATT_OK) {
84 ESP_LOGW(TAG, "[%d] [%s] Error writing char/descriptor at handle 0x%2X, status=%d", this->connection_index_,
85 this->address_str_.c_str(), param->write.handle, param->write.status);
86 this->proxy_->send_gatt_error(this->address_, param->write.handle, param->write.status);
87 break;
88 }
90 resp.address = this->address_;
91 resp.handle = param->write.handle;
93 break;
94 }
95 case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
96 if (param->unreg_for_notify.status != ESP_GATT_OK) {
97 ESP_LOGW(TAG, "[%d] [%s] Error unregistering notifications for handle 0x%2X, status=%d",
98 this->connection_index_, this->address_str_.c_str(), param->unreg_for_notify.handle,
99 param->unreg_for_notify.status);
100 this->proxy_->send_gatt_error(this->address_, param->unreg_for_notify.handle, param->unreg_for_notify.status);
101 break;
102 }
104 resp.address = this->address_;
105 resp.handle = param->unreg_for_notify.handle;
107 break;
108 }
109 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
110 if (param->reg_for_notify.status != ESP_GATT_OK) {
111 ESP_LOGW(TAG, "[%d] [%s] Error registering notifications for handle 0x%2X, status=%d", this->connection_index_,
112 this->address_str_.c_str(), param->reg_for_notify.handle, param->reg_for_notify.status);
113 this->proxy_->send_gatt_error(this->address_, param->reg_for_notify.handle, param->reg_for_notify.status);
114 break;
115 }
117 resp.address = this->address_;
118 resp.handle = param->reg_for_notify.handle;
120 break;
121 }
122 case ESP_GATTC_NOTIFY_EVT: {
123 ESP_LOGV(TAG, "[%d] [%s] ESP_GATTC_NOTIFY_EVT: handle=0x%2X", this->connection_index_, this->address_str_.c_str(),
124 param->notify.handle);
126 resp.address = this->address_;
127 resp.handle = param->notify.handle;
128 resp.data.reserve(param->notify.value_len);
129 // Use bulk insert instead of individual push_backs
130 resp.data.insert(resp.data.end(), param->notify.value, param->notify.value + param->notify.value_len);
132 break;
133 }
134 default:
135 break;
136 }
137 return true;
138}
139
140void BluetoothConnection::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
142
143 switch (event) {
144 case ESP_GAP_BLE_AUTH_CMPL_EVT:
145 if (memcmp(param->ble_security.auth_cmpl.bd_addr, this->remote_bda_, 6) != 0)
146 break;
147 if (param->ble_security.auth_cmpl.success) {
148 this->proxy_->send_device_pairing(this->address_, true);
149 } else {
150 this->proxy_->send_device_pairing(this->address_, false, param->ble_security.auth_cmpl.fail_reason);
151 }
152 break;
153 default:
154 break;
155 }
156}
157
159 if (!this->connected()) {
160 ESP_LOGW(TAG, "[%d] [%s] Cannot read GATT characteristic, not connected.", this->connection_index_,
161 this->address_str_.c_str());
162 return ESP_GATT_NOT_CONNECTED;
163 }
164
165 ESP_LOGV(TAG, "[%d] [%s] Reading GATT characteristic handle %d", this->connection_index_, this->address_str_.c_str(),
166 handle);
167
168 esp_err_t err = esp_ble_gattc_read_char(this->gattc_if_, this->conn_id_, handle, ESP_GATT_AUTH_REQ_NONE);
169 if (err != ERR_OK) {
170 ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_read_char error, err=%d", this->connection_index_,
171 this->address_str_.c_str(), err);
172 return err;
173 }
174 return ESP_OK;
175}
176
177esp_err_t BluetoothConnection::write_characteristic(uint16_t handle, const std::string &data, bool response) {
178 if (!this->connected()) {
179 ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT characteristic, not connected.", this->connection_index_,
180 this->address_str_.c_str());
181 return ESP_GATT_NOT_CONNECTED;
182 }
183 ESP_LOGV(TAG, "[%d] [%s] Writing GATT characteristic handle %d", this->connection_index_, this->address_str_.c_str(),
184 handle);
185
186 esp_err_t err =
187 esp_ble_gattc_write_char(this->gattc_if_, this->conn_id_, handle, data.size(), (uint8_t *) data.data(),
188 response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
189 if (err != ERR_OK) {
190 ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char error, err=%d", this->connection_index_,
191 this->address_str_.c_str(), err);
192 return err;
193 }
194 return ESP_OK;
195}
196
197esp_err_t BluetoothConnection::read_descriptor(uint16_t handle) {
198 if (!this->connected()) {
199 ESP_LOGW(TAG, "[%d] [%s] Cannot read GATT descriptor, not connected.", this->connection_index_,
200 this->address_str_.c_str());
201 return ESP_GATT_NOT_CONNECTED;
202 }
203 ESP_LOGV(TAG, "[%d] [%s] Reading GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
204 handle);
205
206 esp_err_t err = esp_ble_gattc_read_char_descr(this->gattc_if_, this->conn_id_, handle, ESP_GATT_AUTH_REQ_NONE);
207 if (err != ERR_OK) {
208 ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_read_char_descr error, err=%d", this->connection_index_,
209 this->address_str_.c_str(), err);
210 return err;
211 }
212 return ESP_OK;
213}
214
215esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const std::string &data, bool response) {
216 if (!this->connected()) {
217 ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT descriptor, not connected.", this->connection_index_,
218 this->address_str_.c_str());
219 return ESP_GATT_NOT_CONNECTED;
220 }
221 ESP_LOGV(TAG, "[%d] [%s] Writing GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
222 handle);
223
224 esp_err_t err = esp_ble_gattc_write_char_descr(
225 this->gattc_if_, this->conn_id_, handle, data.size(), (uint8_t *) data.data(),
226 response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
227 if (err != ERR_OK) {
228 ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char_descr error, err=%d", this->connection_index_,
229 this->address_str_.c_str(), err);
230 return err;
231 }
232 return ESP_OK;
233}
234
235esp_err_t BluetoothConnection::notify_characteristic(uint16_t handle, bool enable) {
236 if (!this->connected()) {
237 ESP_LOGW(TAG, "[%d] [%s] Cannot notify GATT characteristic, not connected.", this->connection_index_,
238 this->address_str_.c_str());
239 return ESP_GATT_NOT_CONNECTED;
240 }
241
242 if (enable) {
243 ESP_LOGV(TAG, "[%d] [%s] Registering for GATT characteristic notifications handle %d", this->connection_index_,
244 this->address_str_.c_str(), handle);
245 esp_err_t err = esp_ble_gattc_register_for_notify(this->gattc_if_, this->remote_bda_, handle);
246 if (err != ESP_OK) {
247 ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_register_for_notify failed, err=%d", this->connection_index_,
248 this->address_str_.c_str(), err);
249 return err;
250 }
251 } else {
252 ESP_LOGV(TAG, "[%d] [%s] Unregistering for GATT characteristic notifications handle %d", this->connection_index_,
253 this->address_str_.c_str(), handle);
254 esp_err_t err = esp_ble_gattc_unregister_for_notify(this->gattc_if_, this->remote_bda_, handle);
255 if (err != ESP_OK) {
256 ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_unregister_for_notify failed, err=%d", this->connection_index_,
257 this->address_str_.c_str(), err);
258 return err;
259 }
260 }
261 return ESP_OK;
262}
263
267
268} // namespace bluetooth_proxy
269} // namespace esphome
270
271#endif // USE_ESP32
bool send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &msg)
bool send_bluetooth_gatt_notify_response(const BluetoothGATTNotifyResponse &msg)
bool send_bluetooth_gatt_write_response(const BluetoothGATTWriteResponse &msg)
bool send_bluetooth_gatt_notify_data_response(const BluetoothGATTNotifyDataResponse &msg)
esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override
esp_err_t write_descriptor(uint16_t handle, const std::string &data, bool response)
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override
bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
esp_err_t write_characteristic(uint16_t handle, const std::string &data, bool response)
esp_err_t notify_characteristic(uint16_t handle, bool enable)
esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override
void send_device_connection(uint64_t address, bool connected, uint16_t mtu=0, esp_err_t error=ESP_OK)
void send_device_pairing(uint64_t address, bool paired, esp_err_t error=ESP_OK)
void send_gatt_error(uint64_t address, uint16_t handle, esp_err_t error)
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override
bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7