mirror of
https://github.com/esphome/esphome.git
synced 2024-12-23 05:54:56 +01:00
Add ability to clear the gatt cache (#4621)
* Add ability to clear the gatt cache
With BlueZ we can fully clear the cache when something goes wrong with the services, however since this is also a cache on the ESP32 we need to be able to clear the on device cache as well for the proxies since if something goes wrong with the service resolution it can cache the bad resolution on NVS forever.
Our current client implementation is limited to clearing the memory cache in Home Assistant 89355e0879/homeassistant/components/esphome/bluetooth/client.py (L512)
related issue https://github.com/esphome/issues/issues/4156
https://github.com/esphome/aioesphomeapi/pull/410
* naming
* lint
* lint
* naming
* naming
* naming
* 88 now that 87 is taken
* make const
* Update esphome/components/api/api_frame_helper.cpp
This commit is contained in:
parent
36c0e2416d
commit
9ee661c1e4
10 changed files with 111 additions and 1 deletions
|
@ -1156,6 +1156,7 @@ enum BluetoothDeviceRequestType {
|
||||||
BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3;
|
BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3;
|
||||||
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE = 4;
|
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE = 4;
|
||||||
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE = 5;
|
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE = 5;
|
||||||
|
BLUETOOTH_DEVICE_REQUEST_TYPE_CLEAR_CACHE = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BluetoothDeviceRequest {
|
message BluetoothDeviceRequest {
|
||||||
|
@ -1359,3 +1360,13 @@ message BluetoothDeviceUnpairingResponse {
|
||||||
bool success = 2;
|
bool success = 2;
|
||||||
int32 error = 3;
|
int32 error = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message BluetoothDeviceClearCacheResponse {
|
||||||
|
option (id) = 88;
|
||||||
|
option (source) = SOURCE_SERVER;
|
||||||
|
option (ifdef) = "USE_BLUETOOTH_PROXY";
|
||||||
|
|
||||||
|
uint64 address = 1;
|
||||||
|
bool success = 2;
|
||||||
|
int32 error = 3;
|
||||||
|
}
|
||||||
|
|
|
@ -953,7 +953,9 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
|
||||||
resp.webserver_port = USE_WEBSERVER_PORT;
|
resp.webserver_port = USE_WEBSERVER_PORT;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
resp.bluetooth_proxy_version = bluetooth_proxy::global_bluetooth_proxy->has_active() ? 4 : 1;
|
resp.bluetooth_proxy_version = bluetooth_proxy::global_bluetooth_proxy->has_active()
|
||||||
|
? bluetooth_proxy::ACTIVE_CONNECTIONS_VERSION
|
||||||
|
: bluetooth_proxy::PASSIVE_ONLY_VERSION;
|
||||||
#endif
|
#endif
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -400,6 +400,8 @@ const char *proto_enum_to_string<enums::BluetoothDeviceRequestType>(enums::Bluet
|
||||||
return "BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE";
|
return "BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE";
|
||||||
case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE:
|
case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE:
|
||||||
return "BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE";
|
return "BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE";
|
||||||
|
case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CLEAR_CACHE:
|
||||||
|
return "BLUETOOTH_DEVICE_REQUEST_TYPE_CLEAR_CACHE";
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
@ -6060,6 +6062,49 @@ void BluetoothDeviceUnpairingResponse::dump_to(std::string &out) const {
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
bool BluetoothDeviceClearCacheResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||||
|
switch (field_id) {
|
||||||
|
case 1: {
|
||||||
|
this->address = value.as_uint64();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
this->success = value.as_bool();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
this->error = value.as_int32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void BluetoothDeviceClearCacheResponse::encode(ProtoWriteBuffer buffer) const {
|
||||||
|
buffer.encode_uint64(1, this->address);
|
||||||
|
buffer.encode_bool(2, this->success);
|
||||||
|
buffer.encode_int32(3, this->error);
|
||||||
|
}
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
|
void BluetoothDeviceClearCacheResponse::dump_to(std::string &out) const {
|
||||||
|
__attribute__((unused)) char buffer[64];
|
||||||
|
out.append("BluetoothDeviceClearCacheResponse {\n");
|
||||||
|
out.append(" address: ");
|
||||||
|
sprintf(buffer, "%llu", this->address);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" success: ");
|
||||||
|
out.append(YESNO(this->success));
|
||||||
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" error: ");
|
||||||
|
sprintf(buffer, "%d", this->error);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
|
out.append("}");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace api
|
} // namespace api
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -163,6 +163,7 @@ enum BluetoothDeviceRequestType : uint32_t {
|
||||||
BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3,
|
BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3,
|
||||||
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE = 4,
|
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE = 4,
|
||||||
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE = 5,
|
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE = 5,
|
||||||
|
BLUETOOTH_DEVICE_REQUEST_TYPE_CLEAR_CACHE = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace enums
|
} // namespace enums
|
||||||
|
@ -1554,6 +1555,19 @@ class BluetoothDeviceUnpairingResponse : public ProtoMessage {
|
||||||
protected:
|
protected:
|
||||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||||
};
|
};
|
||||||
|
class BluetoothDeviceClearCacheResponse : public ProtoMessage {
|
||||||
|
public:
|
||||||
|
uint64_t address{0};
|
||||||
|
bool success{false};
|
||||||
|
int32_t error{0};
|
||||||
|
void encode(ProtoWriteBuffer buffer) const override;
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
|
void dump_to(std::string &out) const override;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace api
|
} // namespace api
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -441,6 +441,14 @@ bool APIServerConnectionBase::send_bluetooth_device_unpairing_response(const Blu
|
||||||
return this->send_message_<BluetoothDeviceUnpairingResponse>(msg, 86);
|
return this->send_message_<BluetoothDeviceUnpairingResponse>(msg, 86);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
|
bool APIServerConnectionBase::send_bluetooth_device_clear_cache_response(const BluetoothDeviceClearCacheResponse &msg) {
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
|
ESP_LOGVV(TAG, "send_bluetooth_device_clear_cache_response: %s", msg.dump().c_str());
|
||||||
|
#endif
|
||||||
|
return this->send_message_<BluetoothDeviceClearCacheResponse>(msg, 88);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
|
bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
|
||||||
switch (msg_type) {
|
switch (msg_type) {
|
||||||
case 1: {
|
case 1: {
|
||||||
|
|
|
@ -215,6 +215,9 @@ class APIServerConnectionBase : public ProtoService {
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
bool send_bluetooth_device_unpairing_response(const BluetoothDeviceUnpairingResponse &msg);
|
bool send_bluetooth_device_unpairing_response(const BluetoothDeviceUnpairingResponse &msg);
|
||||||
|
#endif
|
||||||
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
|
bool send_bluetooth_device_clear_cache_response(const BluetoothDeviceClearCacheResponse &msg);
|
||||||
#endif
|
#endif
|
||||||
protected:
|
protected:
|
||||||
bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;
|
bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;
|
||||||
|
|
|
@ -331,6 +331,17 @@ void APIServer::send_bluetooth_device_unpairing(uint64_t address, bool success,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void APIServer::send_bluetooth_device_clear_cache(uint64_t address, bool success, esp_err_t error) {
|
||||||
|
BluetoothDeviceClearCacheResponse call;
|
||||||
|
call.address = address;
|
||||||
|
call.success = success;
|
||||||
|
call.error = error;
|
||||||
|
|
||||||
|
for (auto &client : this->clients_) {
|
||||||
|
client->send_bluetooth_device_clear_cache_response(call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void APIServer::send_bluetooth_connections_free(uint8_t free, uint8_t limit) {
|
void APIServer::send_bluetooth_connections_free(uint8_t free, uint8_t limit) {
|
||||||
BluetoothConnectionsFreeResponse call;
|
BluetoothConnectionsFreeResponse call;
|
||||||
call.free = free;
|
call.free = free;
|
||||||
|
|
|
@ -80,6 +80,7 @@ class APIServer : public Component, public Controller {
|
||||||
void send_bluetooth_device_connection(uint64_t address, bool connected, uint16_t mtu = 0, esp_err_t error = ESP_OK);
|
void send_bluetooth_device_connection(uint64_t address, bool connected, uint16_t mtu = 0, esp_err_t error = ESP_OK);
|
||||||
void send_bluetooth_device_pairing(uint64_t address, bool paired, esp_err_t error = ESP_OK);
|
void send_bluetooth_device_pairing(uint64_t address, bool paired, esp_err_t error = ESP_OK);
|
||||||
void send_bluetooth_device_unpairing(uint64_t address, bool success, esp_err_t error = ESP_OK);
|
void send_bluetooth_device_unpairing(uint64_t address, bool success, esp_err_t error = ESP_OK);
|
||||||
|
void send_bluetooth_device_clear_cache(uint64_t address, bool success, esp_err_t error = ESP_OK);
|
||||||
void send_bluetooth_connections_free(uint8_t free, uint8_t limit);
|
void send_bluetooth_connections_free(uint8_t free, uint8_t limit);
|
||||||
void send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &call);
|
void send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &call);
|
||||||
void send_bluetooth_gatt_write_response(const BluetoothGATTWriteResponse &call);
|
void send_bluetooth_gatt_write_response(const BluetoothGATTWriteResponse &call);
|
||||||
|
|
|
@ -306,6 +306,13 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest
|
||||||
api::global_api_server->send_bluetooth_device_unpairing(msg.address, ret == ESP_OK, ret);
|
api::global_api_server->send_bluetooth_device_unpairing(msg.address, ret == ESP_OK, ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CLEAR_CACHE: {
|
||||||
|
esp_bd_addr_t address;
|
||||||
|
uint64_to_bd_addr(msg.address, address);
|
||||||
|
esp_err_t ret = esp_ble_gattc_cache_clean(address);
|
||||||
|
api::global_api_server->send_bluetooth_device_clear_cache(msg.address, ret == ESP_OK, ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,14 @@ class BluetoothProxy : public esp32_ble_tracker::ESPBTDeviceListener, public Com
|
||||||
|
|
||||||
extern BluetoothProxy *global_bluetooth_proxy; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
extern BluetoothProxy *global_bluetooth_proxy; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
|
|
||||||
|
// Version 1: Initial version without active connections
|
||||||
|
// Version 2: Support for active connections
|
||||||
|
// Version 3: New connection API
|
||||||
|
// Version 4: Pairing support
|
||||||
|
// Version 5: Cache clear support
|
||||||
|
static const uint32_t ACTIVE_CONNECTIONS_VERSION = 5;
|
||||||
|
static const uint32_t PASSIVE_ONLY_VERSION = 1;
|
||||||
|
|
||||||
} // namespace bluetooth_proxy
|
} // namespace bluetooth_proxy
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue