mirror of
https://github.com/esphome/esphome.git
synced 2025-10-23 04:03:52 +01:00
Send GATT error events to HA (#3884)
This commit is contained in:
@@ -4,21 +4,24 @@
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#ifdef USE_API
|
||||
#include "esphome/components/api/api_server.h"
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace bluetooth_proxy {
|
||||
|
||||
static const char *const TAG = "bluetooth_proxy";
|
||||
|
||||
static const esp_err_t ESP_GATT_NOT_CONNECTED = -1;
|
||||
static const esp_err_t ESP_GATT_WRONG_ADDRESS = -2;
|
||||
|
||||
BluetoothProxy::BluetoothProxy() {
|
||||
global_bluetooth_proxy = this;
|
||||
this->address_ = 0;
|
||||
}
|
||||
|
||||
bool BluetoothProxy::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
|
||||
if (!api::global_api_server->is_connected())
|
||||
return false;
|
||||
ESP_LOGV(TAG, "Proxying packet from %s - %s. RSSI: %d dB", device.get_name().c_str(), device.address_str().c_str(),
|
||||
device.get_rssi());
|
||||
this->send_api_packet_(device);
|
||||
@@ -38,9 +41,6 @@ bool BluetoothProxy::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
||||
}
|
||||
|
||||
void BluetoothProxy::send_api_packet_(const esp32_ble_tracker::ESPBTDevice &device) {
|
||||
#ifndef USE_API
|
||||
return;
|
||||
#else
|
||||
api::BluetoothLEAdvertisementResponse resp;
|
||||
resp.address = device.address_uint64();
|
||||
if (!device.get_name().empty())
|
||||
@@ -62,7 +62,6 @@ void BluetoothProxy::send_api_packet_(const esp32_ble_tracker::ESPBTDevice &devi
|
||||
resp.manufacturer_data.push_back(std::move(manufacturer_data));
|
||||
}
|
||||
api::global_api_server->send_bluetooth_le_advertisement(resp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void BluetoothProxy::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
||||
@@ -70,30 +69,23 @@ void BluetoothProxy::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if
|
||||
BLEClientBase::gattc_event_handler(event, gattc_if, param);
|
||||
switch (event) {
|
||||
case ESP_GATTC_DISCONNECT_EVT: {
|
||||
#ifdef USE_API
|
||||
api::global_api_server->send_bluetooth_device_connection(this->address_, false, this->mtu_,
|
||||
param->disconnect.reason);
|
||||
api::global_api_server->send_bluetooth_connections_free(this->get_bluetooth_connections_free(),
|
||||
this->get_bluetooth_connections_limit());
|
||||
#endif
|
||||
this->address_ = 0;
|
||||
}
|
||||
case ESP_GATTC_OPEN_EVT: {
|
||||
if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
|
||||
#ifdef USE_API
|
||||
api::global_api_server->send_bluetooth_device_connection(this->address_, false, this->mtu_, param->open.status);
|
||||
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_SEARCH_CMPL_EVT: {
|
||||
#ifdef USE_API
|
||||
api::global_api_server->send_bluetooth_device_connection(this->address_, true, this->mtu_);
|
||||
api::global_api_server->send_bluetooth_connections_free(this->get_bluetooth_connections_free(),
|
||||
this->get_bluetooth_connections_limit());
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_READ_DESCR_EVT:
|
||||
@@ -101,10 +93,11 @@ void BluetoothProxy::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if
|
||||
if (param->read.conn_id != this->conn_id_)
|
||||
break;
|
||||
if (param->read.status != ESP_GATT_OK) {
|
||||
ESP_LOGW(TAG, "Error reading char/descriptor at handle %d, status=%d", param->read.handle, param->read.status);
|
||||
ESP_LOGW(TAG, "Error reading char/descriptor at handle 0x%2X, status=%d", param->read.handle,
|
||||
param->read.status);
|
||||
api::global_api_server->send_bluetooth_gatt_error(this->address_, param->read.handle, param->read.status);
|
||||
break;
|
||||
}
|
||||
#ifdef USE_API
|
||||
api::BluetoothGATTReadResponse resp;
|
||||
resp.address = this->address_;
|
||||
resp.handle = param->read.handle;
|
||||
@@ -113,14 +106,56 @@ void BluetoothProxy::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if
|
||||
resp.data.push_back(param->read.value[i]);
|
||||
}
|
||||
api::global_api_server->send_bluetooth_gatt_read_response(resp);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_WRITE_CHAR_EVT:
|
||||
case ESP_GATTC_WRITE_DESCR_EVT: {
|
||||
if (param->write.conn_id != this->conn_id_)
|
||||
break;
|
||||
if (param->write.status != ESP_GATT_OK) {
|
||||
ESP_LOGW(TAG, "Error writing char/descriptor at handle 0x%2X, status=%d", param->write.handle,
|
||||
param->write.status);
|
||||
api::global_api_server->send_bluetooth_gatt_error(this->address_, param->write.handle, param->write.status);
|
||||
break;
|
||||
}
|
||||
api::BluetoothGATTWriteResponse resp;
|
||||
resp.address = this->address_;
|
||||
resp.handle = param->write.handle;
|
||||
api::global_api_server->send_bluetooth_gatt_write_response(resp);
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
|
||||
if (param->unreg_for_notify.status != ESP_GATT_OK) {
|
||||
ESP_LOGW(TAG, "Error unregistering notifications for handle 0x%2X, status=%d", param->unreg_for_notify.handle,
|
||||
param->unreg_for_notify.status);
|
||||
api::global_api_server->send_bluetooth_gatt_error(this->address_, param->unreg_for_notify.handle,
|
||||
param->unreg_for_notify.status);
|
||||
break;
|
||||
}
|
||||
api::BluetoothGATTNotifyResponse resp;
|
||||
resp.address = this->address_;
|
||||
resp.handle = param->unreg_for_notify.handle;
|
||||
api::global_api_server->send_bluetooth_gatt_notify_response(resp);
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
|
||||
if (param->reg_for_notify.status != ESP_GATT_OK) {
|
||||
ESP_LOGW(TAG, "Error registering notifications for handle 0x%2X, status=%d", param->reg_for_notify.handle,
|
||||
param->reg_for_notify.status);
|
||||
api::global_api_server->send_bluetooth_gatt_error(this->address_, param->reg_for_notify.handle,
|
||||
param->reg_for_notify.status);
|
||||
break;
|
||||
}
|
||||
api::BluetoothGATTNotifyResponse resp;
|
||||
resp.address = this->address_;
|
||||
resp.handle = param->reg_for_notify.handle;
|
||||
api::global_api_server->send_bluetooth_gatt_notify_response(resp);
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_NOTIFY_EVT: {
|
||||
if (param->notify.conn_id != this->conn_id_)
|
||||
break;
|
||||
ESP_LOGV(TAG, "ESP_GATTC_NOTIFY_EVT: handle=0x%x", param->notify.handle);
|
||||
#ifdef USE_API
|
||||
ESP_LOGV(TAG, "ESP_GATTC_NOTIFY_EVT: handle=0x%2X", param->notify.handle);
|
||||
api::BluetoothGATTNotifyDataResponse resp;
|
||||
resp.address = this->address_;
|
||||
resp.handle = param->notify.handle;
|
||||
@@ -129,7 +164,6 @@ void BluetoothProxy::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if
|
||||
resp.data.push_back(param->notify.value[i]);
|
||||
}
|
||||
api::global_api_server->send_bluetooth_gatt_notify_data_response(resp);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -141,7 +175,6 @@ void BluetoothProxy::dump_config() { ESP_LOGCONFIG(TAG, "Bluetooth Proxy:"); }
|
||||
|
||||
void BluetoothProxy::loop() {
|
||||
BLEClientBase::loop();
|
||||
#ifdef USE_API
|
||||
if (this->state_ != espbt::ClientState::IDLE && !api::global_api_server->is_connected()) {
|
||||
ESP_LOGI(TAG, "[%s] Disconnecting.", this->address_str().c_str());
|
||||
auto err = esp_ble_gattc_close(this->gattc_if_, this->conn_id_);
|
||||
@@ -177,10 +210,8 @@ void BluetoothProxy::loop() {
|
||||
api::global_api_server->send_bluetooth_gatt_services(resp);
|
||||
this->send_service_++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_API
|
||||
void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest &msg) {
|
||||
switch (msg.request_type) {
|
||||
case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT: {
|
||||
@@ -220,16 +251,19 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest
|
||||
void BluetoothProxy::bluetooth_gatt_read(const api::BluetoothGATTReadRequest &msg) {
|
||||
if (this->state_ != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "Cannot read GATT characteristic, not connected.");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_NOT_CONNECTED);
|
||||
return;
|
||||
}
|
||||
if (this->address_ != msg.address) {
|
||||
ESP_LOGW(TAG, "Address mismatch for read GATT characteristic request");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_WRONG_ADDRESS);
|
||||
return;
|
||||
}
|
||||
|
||||
auto *characteristic = this->get_characteristic(msg.handle);
|
||||
if (characteristic == nullptr) {
|
||||
ESP_LOGW(TAG, "Cannot read GATT characteristic, not found.");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_INVALID_HANDLE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -239,43 +273,53 @@ void BluetoothProxy::bluetooth_gatt_read(const api::BluetoothGATTReadRequest &ms
|
||||
esp_ble_gattc_read_char(this->gattc_if_, this->conn_id_, characteristic->handle, ESP_GATT_AUTH_REQ_NONE);
|
||||
if (err != ERR_OK) {
|
||||
ESP_LOGW(TAG, "esp_ble_gattc_read_char error, err=%d", err);
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, err);
|
||||
}
|
||||
}
|
||||
|
||||
void BluetoothProxy::bluetooth_gatt_write(const api::BluetoothGATTWriteRequest &msg) {
|
||||
if (this->state_ != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "Cannot write GATT characteristic, not connected.");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_NOT_CONNECTED);
|
||||
return;
|
||||
}
|
||||
if (this->address_ != msg.address) {
|
||||
ESP_LOGW(TAG, "Address mismatch for write GATT characteristic request");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_WRONG_ADDRESS);
|
||||
return;
|
||||
}
|
||||
|
||||
auto *characteristic = this->get_characteristic(msg.handle);
|
||||
if (characteristic == nullptr) {
|
||||
ESP_LOGW(TAG, "Cannot write GATT characteristic, not found.");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_INVALID_HANDLE);
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Writing GATT characteristic %s", characteristic->uuid.to_string().c_str());
|
||||
characteristic->write_value((uint8_t *) msg.data.data(), msg.data.size(),
|
||||
msg.response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP);
|
||||
auto err = characteristic->write_value((uint8_t *) msg.data.data(), msg.data.size(),
|
||||
msg.response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP);
|
||||
if (err != ERR_OK) {
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, err);
|
||||
}
|
||||
}
|
||||
|
||||
void BluetoothProxy::bluetooth_gatt_read_descriptor(const api::BluetoothGATTReadDescriptorRequest &msg) {
|
||||
if (this->state_ != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "Cannot read GATT characteristic descriptor, not connected.");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_NOT_CONNECTED);
|
||||
return;
|
||||
}
|
||||
if (this->address_ != msg.address) {
|
||||
ESP_LOGW(TAG, "Address mismatch for read GATT characteristic descriptor request");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_WRONG_ADDRESS);
|
||||
return;
|
||||
}
|
||||
|
||||
auto *descriptor = this->get_descriptor(msg.handle);
|
||||
if (descriptor == nullptr) {
|
||||
ESP_LOGW(TAG, "Cannot read GATT characteristic descriptor, not found.");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_INVALID_HANDLE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -286,22 +330,26 @@ void BluetoothProxy::bluetooth_gatt_read_descriptor(const api::BluetoothGATTRead
|
||||
esp_ble_gattc_read_char_descr(this->gattc_if_, this->conn_id_, descriptor->handle, ESP_GATT_AUTH_REQ_NONE);
|
||||
if (err != ERR_OK) {
|
||||
ESP_LOGW(TAG, "esp_ble_gattc_read_char error, err=%d", err);
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, err);
|
||||
}
|
||||
}
|
||||
|
||||
void BluetoothProxy::bluetooth_gatt_write_descriptor(const api::BluetoothGATTWriteDescriptorRequest &msg) {
|
||||
if (this->state_ != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "Cannot write GATT characteristic descriptor, not connected.");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_NOT_CONNECTED);
|
||||
return;
|
||||
}
|
||||
if (this->address_ != msg.address) {
|
||||
ESP_LOGW(TAG, "Address mismatch for write GATT characteristic descriptor request");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_WRONG_ADDRESS);
|
||||
return;
|
||||
}
|
||||
|
||||
auto *descriptor = this->get_descriptor(msg.handle);
|
||||
if (descriptor == nullptr) {
|
||||
ESP_LOGW(TAG, "Cannot write GATT characteristic descriptor, not found.");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_INVALID_HANDLE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -313,20 +361,34 @@ void BluetoothProxy::bluetooth_gatt_write_descriptor(const api::BluetoothGATTWri
|
||||
(uint8_t *) msg.data.data(), ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
if (err != ERR_OK) {
|
||||
ESP_LOGW(TAG, "esp_ble_gattc_write_char_descr error, err=%d", err);
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, err);
|
||||
}
|
||||
}
|
||||
|
||||
void BluetoothProxy::bluetooth_gatt_send_services(const api::BluetoothGATTGetServicesRequest &msg) {
|
||||
if (this->state_ != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "Cannot get GATT services, not connected.");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, 0, ESP_GATT_NOT_CONNECTED);
|
||||
return;
|
||||
}
|
||||
if (this->address_ != msg.address) {
|
||||
ESP_LOGW(TAG, "Address mismatch for service list request");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, 0, ESP_GATT_WRONG_ADDRESS);
|
||||
return;
|
||||
}
|
||||
this->send_service_ = 0;
|
||||
}
|
||||
|
||||
void BluetoothProxy::bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest &msg) {
|
||||
if (this->state_ != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "Cannot configure notify, not connected.");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_NOT_CONNECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->address_ != msg.address) {
|
||||
ESP_LOGW(TAG, "Address mismatch for notify");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_WRONG_ADDRESS);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -334,6 +396,7 @@ void BluetoothProxy::bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest
|
||||
|
||||
if (characteristic == nullptr) {
|
||||
ESP_LOGW(TAG, "Cannot notify GATT characteristic, not found.");
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, ESP_GATT_INVALID_HANDLE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -342,17 +405,17 @@ void BluetoothProxy::bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest
|
||||
err = esp_ble_gattc_register_for_notify(this->gattc_if_, this->remote_bda_, characteristic->handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "esp_ble_gattc_register_for_notify failed, err=%d", err);
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, err);
|
||||
}
|
||||
} else {
|
||||
err = esp_ble_gattc_unregister_for_notify(this->gattc_if_, this->remote_bda_, characteristic->handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "esp_ble_gattc_unregister_for_notify failed, err=%d", err);
|
||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BluetoothProxy *global_bluetooth_proxy = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
} // namespace bluetooth_proxy
|
||||
|
Reference in New Issue
Block a user