mirror of
https://github.com/esphome/aioesphomeapi.git
synced 2025-01-22 21:41:26 +01:00
Improve bluetooth error reporting (#297)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
4f751f3740
commit
c6e824e778
@ -3,6 +3,7 @@ from .ble_defs import ESP_CONNECTION_ERROR_DESCRIPTION, BLEConnectionError
|
||||
from .client import APIClient
|
||||
from .connection import APIConnection, ConnectionParams
|
||||
from .core import (
|
||||
ESPHOME_GATT_ERRORS,
|
||||
MESSAGE_TYPE_TO_PROTO,
|
||||
APIConnectionError,
|
||||
BadNameAPIError,
|
||||
|
@ -96,7 +96,12 @@ from .api_pb2 import ( # type: ignore
|
||||
TextSensorStateResponse,
|
||||
)
|
||||
from .connection import APIConnection, ConnectionParams
|
||||
from .core import APIConnectionError, BluetoothGATTAPIError, TimeoutAPIError
|
||||
from .core import (
|
||||
APIConnectionError,
|
||||
BluetoothGATTAPIError,
|
||||
TimeoutAPIError,
|
||||
to_human_readable_address,
|
||||
)
|
||||
from .host_resolver import ZeroconfInstanceType
|
||||
from .model import (
|
||||
APIVersion,
|
||||
@ -514,12 +519,20 @@ class APIClient:
|
||||
async with async_timeout.timeout(timeout):
|
||||
await event.wait()
|
||||
except asyncio.TimeoutError as err:
|
||||
unsub()
|
||||
try:
|
||||
unsub()
|
||||
except ValueError:
|
||||
_LOGGER.warning(
|
||||
"%s: Bluetooth device connection timed out but already unsubscribed",
|
||||
to_human_readable_address(address),
|
||||
)
|
||||
# Disconnect before raising the exception to ensure
|
||||
# the slot is recovered before the timeout is raised
|
||||
# to avoid race were we run out even though we have a slot.
|
||||
await self.bluetooth_device_disconnect(address)
|
||||
raise TimeoutAPIError("Timeout waiting for connect response") from err
|
||||
raise TimeoutAPIError(
|
||||
f"Timeout waiting for connect response while connecting to {to_human_readable_address(address)}"
|
||||
) from err
|
||||
|
||||
return unsub
|
||||
|
||||
|
@ -91,6 +91,53 @@ from .api_pb2 import ( # type: ignore
|
||||
|
||||
TWO_CHAR = re.compile(r".{2}")
|
||||
|
||||
# Taken from esp_gatt_status_t in esp_gatt_defs.h
|
||||
ESPHOME_GATT_ERRORS = {
|
||||
-1: "Not connected", # Custom ESPHome error
|
||||
1: "Invalid handle",
|
||||
2: "Read not permitted",
|
||||
3: "Write not permitted",
|
||||
4: "Invalid PDU",
|
||||
5: "Insufficient authentication",
|
||||
6: "Request not supported",
|
||||
7: "Invalid offset",
|
||||
8: "Insufficient authorization",
|
||||
9: "Prepare queue full",
|
||||
10: "Attribute not found",
|
||||
11: "Attribute not long",
|
||||
12: "Insufficient key size",
|
||||
13: "Invalid attribute length",
|
||||
14: "Unlikely error",
|
||||
15: "Insufficient encryption",
|
||||
16: "Unsupported group type",
|
||||
17: "Insufficient resources",
|
||||
128: "Application error",
|
||||
129: "Internal error",
|
||||
130: "Wrong state",
|
||||
131: "Database full",
|
||||
132: "Busy",
|
||||
133: "Error",
|
||||
134: "Command started",
|
||||
135: "Illegal parameter",
|
||||
136: "Pending",
|
||||
137: "Auth fail",
|
||||
138: "More",
|
||||
139: "Invalid configuration",
|
||||
140: "Service started",
|
||||
141: "Encrypted no mitm",
|
||||
142: "Not encrypted",
|
||||
143: "Congested",
|
||||
144: "Duplicate registration",
|
||||
145: "Already open",
|
||||
146: "Cancel",
|
||||
224: "Stack RSP",
|
||||
225: "App RSP",
|
||||
239: "Unknown error",
|
||||
253: "CCC config error",
|
||||
254: "Procedure already in progress",
|
||||
255: "Out of range",
|
||||
}
|
||||
|
||||
|
||||
class APIConnectionError(Exception):
|
||||
pass
|
||||
@ -153,10 +200,19 @@ def to_human_readable_address(address: int) -> str:
|
||||
return ":".join(TWO_CHAR.findall(f"{address:012X}"))
|
||||
|
||||
|
||||
def to_human_readable_gatt_error(error: int) -> str:
|
||||
"""Convert a GATT error to a human readable format."""
|
||||
return ESPHOME_GATT_ERRORS.get(error, "Unknown error")
|
||||
|
||||
|
||||
class BluetoothGATTAPIError(APIConnectionError):
|
||||
def __init__(self, error: BluetoothGATTError) -> None:
|
||||
super().__init__(
|
||||
f"Bluetooth GATT Error address={to_human_readable_address(error.address)} handle={error.handle} error={error.error}"
|
||||
f"Bluetooth GATT Error "
|
||||
f"address={to_human_readable_address(error.address)} "
|
||||
f"handle={error.handle} "
|
||||
f"error={error.error} "
|
||||
f"description={to_human_readable_gatt_error(error.error)}"
|
||||
)
|
||||
self.error = error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user