9 namespace esp32_ble_client {
11 static const char *
const TAG =
"esp32_ble_client";
12 static const esp_bt_uuid_t NOTIFY_DESC_UUID = {
13 .len = ESP_UUID_LEN_16,
16 .uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG,
21 static uint8_t connection_index = 0;
31 auto ret = esp_ble_gattc_app_register(this->
app_id);
33 ESP_LOGE(TAG,
"gattc app register failed. app_id=%d code=%d", this->
app_id, ret);
40 if (this->
state_ == espbt::ClientState::READY_TO_CONNECT) {
56 if (ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG)
59 this->
set_state(espbt::ClientState::DISCOVERED);
75 this->
set_state(espbt::ClientState::CONNECTING);
91 if (this->
state_ == espbt::ClientState::SEARCHING || this->
state_ == espbt::ClientState::READY_TO_CONNECT ||
92 this->
state_ == espbt::ClientState::DISCOVERED) {
96 this->
set_state(espbt::ClientState::DISCONNECTING);
103 this->services_.clear();
104 #ifndef CONFIG_BT_GATTC_CACHE_NVS_FLASH 114 esp_ble_gattc_cb_param_t *param) {
115 if (event == ESP_GATTC_REG_EVT && this->
app_id != param->reg.app_id)
117 if (event != ESP_GATTC_REG_EVT && esp_gattc_if != ESP_GATT_IF_NONE && esp_gattc_if != this->
gattc_if_)
120 ESP_LOGV(TAG,
"[%d] [%s] gattc_event_handler: event=%d gattc_if=%d", this->
connection_index_,
124 case ESP_GATTC_REG_EVT: {
125 if (param->reg.status == ESP_GATT_OK) {
130 ESP_LOGE(TAG,
"[%d] [%s] gattc app registration failed id=%d code=%d", this->
connection_index_,
131 this->
address_str_.c_str(), param->reg.app_id, param->reg.status);
135 case ESP_GATTC_OPEN_EVT: {
136 if (!this->
check_addr(param->open.remote_bda))
139 this->
conn_id_ = param->open.conn_id;
141 if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
147 auto ret = esp_ble_gattc_send_mtu_req(this->
gattc_if_, param->open.conn_id);
149 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_send_mtu_req failed, status=%x", this->
connection_index_,
156 this->
state_ = espbt::ClientState::ESTABLISHED;
159 esp_ble_gattc_search_service(esp_gattc_if, param->cfg_mtu.conn_id,
nullptr);
162 case ESP_GATTC_CONNECT_EVT: {
163 if (!this->
check_addr(param->connect.remote_bda))
168 case ESP_GATTC_DISCONNECT_EVT: {
169 if (!this->
check_addr(param->disconnect.remote_bda))
171 ESP_LOGD(TAG,
"[%d] [%s] ESP_GATTC_DISCONNECT_EVT, reason %d", this->
connection_index_,
178 case ESP_GATTC_CFG_MTU_EVT: {
179 if (this->
conn_id_ != param->cfg_mtu.conn_id)
181 if (param->cfg_mtu.status != ESP_GATT_OK) {
182 ESP_LOGW(TAG,
"[%d] [%s] cfg_mtu failed, mtu %d, status %d", this->
connection_index_,
183 this->
address_str_.c_str(), param->cfg_mtu.mtu, param->cfg_mtu.status);
188 param->cfg_mtu.status, param->cfg_mtu.mtu);
189 this->
mtu_ = param->cfg_mtu.mtu;
192 case ESP_GATTC_CLOSE_EVT: {
193 if (this->
conn_id_ != param->close.conn_id)
200 case ESP_GATTC_SEARCH_RES_EVT: {
201 if (this->
conn_id_ != param->search_res.conn_id)
211 ble_service->
start_handle = param->search_res.start_handle;
212 ble_service->
end_handle = param->search_res.end_handle;
213 ble_service->
client =
this;
217 case ESP_GATTC_SEARCH_CMPL_EVT: {
218 if (this->
conn_id_ != param->search_cmpl.conn_id)
220 this->
log_event_(
"ESP_GATTC_SEARCH_CMPL_EVT");
223 svc->uuid.to_string().c_str());
224 ESP_LOGV(TAG,
"[%d] [%s] start_handle: 0x%x end_handle: 0x%x", this->
connection_index_,
225 this->
address_str_.c_str(), svc->start_handle, svc->end_handle);
228 this->
state_ = espbt::ClientState::ESTABLISHED;
231 case ESP_GATTC_READ_DESCR_EVT: {
232 if (this->
conn_id_ != param->write.conn_id)
237 case ESP_GATTC_WRITE_DESCR_EVT: {
238 if (this->
conn_id_ != param->write.conn_id)
240 this->
log_event_(
"ESP_GATTC_WRITE_DESCR_EVT");
243 case ESP_GATTC_WRITE_CHAR_EVT: {
244 if (this->
conn_id_ != param->write.conn_id)
249 case ESP_GATTC_READ_CHAR_EVT: {
250 if (this->
conn_id_ != param->read.conn_id)
255 case ESP_GATTC_NOTIFY_EVT: {
256 if (this->
conn_id_ != param->notify.conn_id)
261 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
262 this->
log_event_(
"ESP_GATTC_REG_FOR_NOTIFY_EVT");
269 esp_gattc_descr_elem_t desc_result;
271 esp_gatt_status_t descr_status = esp_ble_gattc_get_descr_by_char_handle(
272 this->
gattc_if_, this->
conn_id_, param->reg_for_notify.handle, NOTIFY_DESC_UUID, &desc_result, &count);
273 if (descr_status != ESP_GATT_OK) {
274 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_get_descr_by_char_handle error, status=%d", this->
connection_index_,
278 esp_gattc_char_elem_t char_result;
279 esp_gatt_status_t char_status =
280 esp_ble_gattc_get_all_char(this->
gattc_if_, this->
conn_id_, param->reg_for_notify.handle,
281 param->reg_for_notify.handle, &char_result, &count, 0);
282 if (char_status != ESP_GATT_OK) {
283 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_get_all_char error, status=%d", this->
connection_index_,
292 uint16_t notify_en = char_result.properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY ? 1 : 2;
294 esp_ble_gattc_write_char_descr(this->
gattc_if_, this->
conn_id_, desc_result.handle,
sizeof(notify_en),
295 (uint8_t *) ¬ify_en, ESP_GATT_WRITE_TYPE_RSP, ESP_GATT_AUTH_REQ_NONE);
296 ESP_LOGD(TAG,
"Wrote notify descriptor %d, properties=%d", notify_en, char_result.properties);
298 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_write_char_descr error, status=%d", this->
connection_index_,
314 this->
defer(std::move(f));
320 case ESP_GAP_BLE_SEC_REQ_EVT:
321 if (!this->
check_addr(param->ble_security.auth_cmpl.bd_addr))
324 esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr,
true);
327 case ESP_GAP_BLE_AUTH_CMPL_EVT:
328 if (!this->
check_addr(param->ble_security.auth_cmpl.bd_addr))
330 esp_bd_addr_t bd_addr;
331 memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr,
sizeof(esp_bd_addr_t));
334 if (!param->ble_security.auth_cmpl.success) {
336 param->ble_security.auth_cmpl.fail_reason);
339 ESP_LOGD(TAG,
"[%d] [%s] auth success. address type = %d auth mode = %d", this->
connection_index_,
340 this->
address_str_.c_str(), param->ble_security.auth_cmpl.addr_type,
341 param->ble_security.auth_cmpl.auth_mode);
359 return (
float) ((uint8_t) value[0]);
366 return (
float) ((uint8_t) value[1]);
380 return (
float)
encode_uint32(value[1], value[2], value[3], value[4]);
384 return (
float) ((int8_t) value[1]);
388 return (
float) ((int16_t) (value[1] << 8) + (int16_t) value[2]);
393 return (
float) ((int32_t) (value[1] << 16) + (int32_t) (value[2] << 8) + (int32_t) (value[3]));
398 return (
float) ((int32_t) (value[1] << 24) + (int32_t) (value[2] << 16) + (int32_t) (value[3] << 8) +
399 (int32_t) (value[4]));
402 ESP_LOGW(TAG,
"[%d] [%s] Cannot parse characteristic value of type 0x%x length %d", this->
connection_index_,
409 if (svc->uuid == uuid)
421 return svc->get_characteristic(chr);
431 svc->parse_characteristics();
432 for (
auto *chr : svc->characteristics) {
433 if (chr->handle == handle)
442 if (chr !=
nullptr) {
444 chr->parse_descriptors();
445 for (
auto &desc : chr->descriptors) {
446 if (desc->uuid.get_uuid().uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG)
457 auto *ch = svc->get_characteristic(chr);
460 return ch->get_descriptor(descr);
471 svc->parse_characteristics();
472 for (
auto *chr : svc->characteristics) {
474 chr->parse_descriptors();
475 for (
auto *desc : chr->descriptors) {
476 if (desc->handle == handle)
BLEDescriptor * get_descriptor(espbt::ESPBTUUID service, espbt::ESPBTUUID chr, espbt::ESPBTUUID descr)
BLEService * get_service(espbt::ESPBTUUID uuid)
void log_event_(const char *name)
std::string format_hex(const uint8_t *data, size_t length)
Format the byte array data of length len in lowercased hex.
std::vector< BLEService * > services_
void defer(const std::string &name, std::function< void()> &&f)
Defer a callback to the next loop() call.
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
float get_setup_priority() const override
bool check_addr(esp_bd_addr_t &addr)
void run_later(std::function< void()> &&f)
const float AFTER_BLUETOOTH
BLEDescriptor * get_config_descriptor(uint16_t handle)
esp_bd_addr_t remote_bda_
void disconnect() override
static ESPBTUUID from_uuid(esp_bt_uuid_t uuid)
ESP32BLETracker * global_esp32_ble_tracker
virtual void set_state(ClientState st)
uint8_t connection_index_
espbt::ConnectionType connection_type_
static ESPBTUUID from_uint16(uint16_t uuid)
constexpr uint32_t encode_uint24(uint8_t byte1, uint8_t byte2, uint8_t byte3)
Encode a 24-bit value given three bytes in most to least significant byte order.
esp_ble_addr_type_t remote_addr_type_
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
esp_ble_addr_type_t get_address_type() const
uint64_t address_uint64() const
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override
BLECharacteristic * get_characteristic(espbt::ESPBTUUID service, espbt::ESPBTUUID chr)
void set_address(uint64_t address)
virtual void mark_failed()
Mark this component as failed.
Implementation of SPI Controller mode.
bool parse_device(const espbt::ESPBTDevice &device) 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
void print_bt_device_info(const ESPBTDevice &device)
float parse_char_value(uint8_t *value, uint16_t length)