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) {
48 ESP_LOGCONFIG(TAG,
" Address: %s", this->
address_str().c_str());
49 ESP_LOGCONFIG(TAG,
" Auto-Connect: %s", TRUEFALSE(this->
auto_connect_));
50 std::string state_name;
51 switch (this->
state()) {
55 case espbt::ClientState::DISCONNECTING:
56 state_name =
"DISCONNECTING";
61 case espbt::ClientState::SEARCHING:
62 state_name =
"SEARCHING";
64 case espbt::ClientState::DISCOVERED:
65 state_name =
"DISCOVERED";
67 case espbt::ClientState::READY_TO_CONNECT:
68 state_name =
"READY_TO_CONNECT";
70 case espbt::ClientState::CONNECTING:
71 state_name =
"CONNECTING";
74 state_name =
"CONNECTED";
76 case espbt::ClientState::ESTABLISHED:
77 state_name =
"ESTABLISHED";
80 state_name =
"UNKNOWN_STATE";
83 ESP_LOGCONFIG(TAG,
" State: %s", state_name.c_str());
84 if (this->
status_ == ESP_GATT_NO_RESOURCES) {
85 ESP_LOGE(TAG,
" Failed due to no resources. Try to reduce number of BLE clients in config.");
86 }
else if (this->
status_ != ESP_GATT_OK) {
87 ESP_LOGW(TAG,
" Failed due to error code %d", this->
status_);
100 if (ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG)
103 this->
set_state(espbt::ClientState::DISCOVERED);
119 this->
set_state(espbt::ClientState::CONNECTING);
135 if (this->
state_ == espbt::ClientState::SEARCHING || this->
state_ == espbt::ClientState::READY_TO_CONNECT ||
136 this->
state_ == espbt::ClientState::DISCOVERED) {
140 this->
set_state(espbt::ClientState::DISCONNECTING);
147 this->services_.clear();
148 #ifndef CONFIG_BT_GATTC_CACHE_NVS_FLASH 158 esp_ble_gattc_cb_param_t *param) {
159 if (event == ESP_GATTC_REG_EVT && this->
app_id != param->reg.app_id)
161 if (event != ESP_GATTC_REG_EVT && esp_gattc_if != ESP_GATT_IF_NONE && esp_gattc_if != this->
gattc_if_)
164 ESP_LOGV(TAG,
"[%d] [%s] gattc_event_handler: event=%d gattc_if=%d", this->
connection_index_,
168 case ESP_GATTC_REG_EVT: {
169 if (param->reg.status == ESP_GATT_OK) {
174 ESP_LOGE(TAG,
"[%d] [%s] gattc app registration failed id=%d code=%d", this->
connection_index_,
175 this->
address_str_.c_str(), param->reg.app_id, param->reg.status);
176 this->
status_ = param->reg.status;
181 case ESP_GATTC_OPEN_EVT: {
182 if (!this->
check_addr(param->open.remote_bda))
185 this->
conn_id_ = param->open.conn_id;
187 if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
193 auto ret = esp_ble_gattc_send_mtu_req(this->
gattc_if_, param->open.conn_id);
195 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_send_mtu_req failed, status=%x", this->
connection_index_,
202 this->
state_ = espbt::ClientState::ESTABLISHED;
205 esp_ble_gattc_search_service(esp_gattc_if, param->cfg_mtu.conn_id,
nullptr);
208 case ESP_GATTC_CONNECT_EVT: {
209 if (!this->
check_addr(param->connect.remote_bda))
214 case ESP_GATTC_DISCONNECT_EVT: {
215 if (!this->
check_addr(param->disconnect.remote_bda))
217 ESP_LOGD(TAG,
"[%d] [%s] ESP_GATTC_DISCONNECT_EVT, reason %d", this->
connection_index_,
224 case ESP_GATTC_CFG_MTU_EVT: {
225 if (this->
conn_id_ != param->cfg_mtu.conn_id)
227 if (param->cfg_mtu.status != ESP_GATT_OK) {
228 ESP_LOGW(TAG,
"[%d] [%s] cfg_mtu failed, mtu %d, status %d", this->
connection_index_,
229 this->
address_str_.c_str(), param->cfg_mtu.mtu, param->cfg_mtu.status);
234 param->cfg_mtu.status, param->cfg_mtu.mtu);
235 this->
mtu_ = param->cfg_mtu.mtu;
238 case ESP_GATTC_CLOSE_EVT: {
239 if (this->
conn_id_ != param->close.conn_id)
246 case ESP_GATTC_SEARCH_RES_EVT: {
247 if (this->
conn_id_ != param->search_res.conn_id)
257 ble_service->
start_handle = param->search_res.start_handle;
258 ble_service->
end_handle = param->search_res.end_handle;
259 ble_service->
client =
this;
263 case ESP_GATTC_SEARCH_CMPL_EVT: {
264 if (this->
conn_id_ != param->search_cmpl.conn_id)
266 this->
log_event_(
"ESP_GATTC_SEARCH_CMPL_EVT");
269 svc->uuid.to_string().c_str());
270 ESP_LOGV(TAG,
"[%d] [%s] start_handle: 0x%x end_handle: 0x%x", this->
connection_index_,
271 this->
address_str_.c_str(), svc->start_handle, svc->end_handle);
274 this->
state_ = espbt::ClientState::ESTABLISHED;
277 case ESP_GATTC_READ_DESCR_EVT: {
278 if (this->
conn_id_ != param->write.conn_id)
283 case ESP_GATTC_WRITE_DESCR_EVT: {
284 if (this->
conn_id_ != param->write.conn_id)
286 this->
log_event_(
"ESP_GATTC_WRITE_DESCR_EVT");
289 case ESP_GATTC_WRITE_CHAR_EVT: {
290 if (this->
conn_id_ != param->write.conn_id)
295 case ESP_GATTC_READ_CHAR_EVT: {
296 if (this->
conn_id_ != param->read.conn_id)
301 case ESP_GATTC_NOTIFY_EVT: {
302 if (this->
conn_id_ != param->notify.conn_id)
307 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
308 this->
log_event_(
"ESP_GATTC_REG_FOR_NOTIFY_EVT");
315 esp_gattc_descr_elem_t desc_result;
317 esp_gatt_status_t descr_status = esp_ble_gattc_get_descr_by_char_handle(
318 this->
gattc_if_, this->
conn_id_, param->reg_for_notify.handle, NOTIFY_DESC_UUID, &desc_result, &count);
319 if (descr_status != ESP_GATT_OK) {
320 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_get_descr_by_char_handle error, status=%d", this->
connection_index_,
324 esp_gattc_char_elem_t char_result;
325 esp_gatt_status_t char_status =
326 esp_ble_gattc_get_all_char(this->
gattc_if_, this->
conn_id_, param->reg_for_notify.handle,
327 param->reg_for_notify.handle, &char_result, &count, 0);
328 if (char_status != ESP_GATT_OK) {
329 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_get_all_char error, status=%d", this->
connection_index_,
338 uint16_t notify_en = char_result.properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY ? 1 : 2;
340 esp_ble_gattc_write_char_descr(this->
gattc_if_, this->
conn_id_, desc_result.handle,
sizeof(notify_en),
341 (uint8_t *) ¬ify_en, ESP_GATT_WRITE_TYPE_RSP, ESP_GATT_AUTH_REQ_NONE);
342 ESP_LOGD(TAG,
"Wrote notify descriptor %d, properties=%d", notify_en, char_result.properties);
344 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_write_char_descr error, status=%d", this->
connection_index_,
360 this->
defer(std::move(f));
366 case ESP_GAP_BLE_SEC_REQ_EVT:
367 if (!this->
check_addr(param->ble_security.auth_cmpl.bd_addr))
370 esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr,
true);
373 case ESP_GAP_BLE_AUTH_CMPL_EVT:
374 if (!this->
check_addr(param->ble_security.auth_cmpl.bd_addr))
376 esp_bd_addr_t bd_addr;
377 memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr,
sizeof(esp_bd_addr_t));
380 if (!param->ble_security.auth_cmpl.success) {
382 param->ble_security.auth_cmpl.fail_reason);
385 ESP_LOGD(TAG,
"[%d] [%s] auth success. address type = %d auth mode = %d", this->
connection_index_,
386 this->
address_str_.c_str(), param->ble_security.auth_cmpl.addr_type,
387 param->ble_security.auth_cmpl.auth_mode);
405 return (
float) ((uint8_t) value[0]);
412 return (
float) ((uint8_t) value[1]);
426 return (
float)
encode_uint32(value[1], value[2], value[3], value[4]);
430 return (
float) ((int8_t) value[1]);
434 return (
float) ((int16_t) (value[1] << 8) + (int16_t) value[2]);
439 return (
float) ((int32_t) (value[1] << 16) + (int32_t) (value[2] << 8) + (int32_t) (value[3]));
444 return (
float) ((int32_t) (value[1] << 24) + (int32_t) (value[2] << 16) + (int32_t) (value[3] << 8) +
445 (int32_t) (value[4]));
448 ESP_LOGW(TAG,
"[%d] [%s] Cannot parse characteristic value of type 0x%x length %d", this->
connection_index_,
455 if (svc->uuid == uuid)
467 return svc->get_characteristic(chr);
477 svc->parse_characteristics();
478 for (
auto *chr : svc->characteristics) {
479 if (chr->handle == handle)
488 if (chr !=
nullptr) {
490 chr->parse_descriptors();
491 for (
auto &desc : chr->descriptors) {
492 if (desc->uuid.get_uuid().uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG)
503 auto *ch = svc->get_characteristic(chr);
506 return ch->get_descriptor(descr);
517 svc->parse_characteristics();
518 for (
auto *chr : svc->characteristics) {
520 chr->parse_descriptors();
521 for (
auto *desc : chr->descriptors) {
522 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 dump_config() override
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
std::string address_str() const
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_
ClientState state() const
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.
esp_gatt_status_t status_
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)