aioesphomeapi/aioesphomeapi/core.py

388 lines
11 KiB
Python
Raw Permalink Normal View History

2023-07-19 22:33:28 +02:00
from __future__ import annotations
import re
from aioesphomeapi.model import BluetoothGATTError
from .api_pb2 import ( # type: ignore
AlarmControlPanelCommandRequest,
AlarmControlPanelStateResponse,
BinarySensorStateResponse,
2022-09-28 18:50:37 +02:00
BluetoothConnectionsFreeResponse,
BluetoothDeviceClearCacheResponse,
2022-09-28 18:50:37 +02:00
BluetoothDeviceConnectionResponse,
2023-03-06 19:07:58 +01:00
BluetoothDevicePairingResponse,
2022-09-28 18:50:37 +02:00
BluetoothDeviceRequest,
2023-03-06 19:07:58 +01:00
BluetoothDeviceUnpairingResponse,
BluetoothGATTErrorResponse,
2022-09-28 18:50:37 +02:00
BluetoothGATTGetServicesDoneResponse,
BluetoothGATTGetServicesRequest,
BluetoothGATTGetServicesResponse,
BluetoothGATTNotifyDataResponse,
BluetoothGATTNotifyRequest,
BluetoothGATTNotifyResponse,
2022-09-28 18:50:37 +02:00
BluetoothGATTReadDescriptorRequest,
BluetoothGATTReadRequest,
BluetoothGATTReadResponse,
BluetoothGATTWriteDescriptorRequest,
BluetoothGATTWriteRequest,
BluetoothGATTWriteResponse,
BluetoothLEAdvertisementResponse,
BluetoothLERawAdvertisementsResponse,
2021-11-29 01:59:23 +01:00
ButtonCommandRequest,
CameraImageRequest,
CameraImageResponse,
ClimateCommandRequest,
ClimateStateResponse,
ConnectRequest,
ConnectResponse,
CoverCommandRequest,
CoverStateResponse,
DateCommandRequest,
DateStateResponse,
2024-04-22 05:58:16 +02:00
DateTimeCommandRequest,
DateTimeStateResponse,
DeviceInfoRequest,
DeviceInfoResponse,
DisconnectRequest,
DisconnectResponse,
EventResponse,
ExecuteServiceRequest,
FanCommandRequest,
FanStateResponse,
GetTimeRequest,
GetTimeResponse,
HelloRequest,
HelloResponse,
HomeassistantServiceResponse,
HomeAssistantStateResponse,
LightCommandRequest,
LightStateResponse,
ListEntitiesAlarmControlPanelResponse,
ListEntitiesBinarySensorResponse,
2021-11-29 01:59:23 +01:00
ListEntitiesButtonResponse,
ListEntitiesCameraResponse,
ListEntitiesClimateResponse,
ListEntitiesCoverResponse,
ListEntitiesDateResponse,
2024-04-22 05:58:16 +02:00
ListEntitiesDateTimeResponse,
ListEntitiesDoneResponse,
ListEntitiesEventResponse,
ListEntitiesFanResponse,
ListEntitiesLightResponse,
2022-01-11 02:29:19 +01:00
ListEntitiesLockResponse,
2022-05-18 03:28:40 +02:00
ListEntitiesMediaPlayerResponse,
2021-06-29 12:42:38 +02:00
ListEntitiesNumberResponse,
ListEntitiesRequest,
2021-07-26 20:51:12 +02:00
ListEntitiesSelectResponse,
ListEntitiesSensorResponse,
ListEntitiesServicesResponse,
2021-09-09 03:11:51 +02:00
ListEntitiesSirenResponse,
ListEntitiesSwitchResponse,
ListEntitiesTextResponse,
ListEntitiesTextSensorResponse,
2024-03-20 02:31:00 +01:00
ListEntitiesTimeResponse,
ListEntitiesValveResponse,
2022-01-11 02:29:19 +01:00
LockCommandRequest,
LockStateResponse,
2022-05-18 03:28:40 +02:00
MediaPlayerCommandRequest,
MediaPlayerStateResponse,
2021-06-29 12:42:38 +02:00
NumberCommandRequest,
NumberStateResponse,
PingRequest,
PingResponse,
2021-07-26 20:51:12 +02:00
SelectCommandRequest,
SelectStateResponse,
SensorStateResponse,
2021-09-09 03:11:51 +02:00
SirenCommandRequest,
SirenStateResponse,
2022-09-28 18:50:37 +02:00
SubscribeBluetoothConnectionsFreeRequest,
SubscribeBluetoothLEAdvertisementsRequest,
SubscribeHomeassistantServicesRequest,
SubscribeHomeAssistantStateResponse,
SubscribeHomeAssistantStatesRequest,
SubscribeLogsRequest,
SubscribeLogsResponse,
SubscribeStatesRequest,
SubscribeVoiceAssistantRequest,
SwitchCommandRequest,
SwitchStateResponse,
TextCommandRequest,
TextSensorStateResponse,
TextStateResponse,
2024-03-20 02:31:00 +01:00
TimeCommandRequest,
TimeStateResponse,
UnsubscribeBluetoothLEAdvertisementsRequest,
ValveCommandRequest,
ValveStateResponse,
VoiceAssistantAudio,
VoiceAssistantEventResponse,
VoiceAssistantRequest,
VoiceAssistantResponse,
)
2019-04-07 19:03:26 +02:00
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",
}
2019-04-07 19:03:26 +02:00
class APIConnectionError(Exception):
pass
class APIConnectionCancelledError(APIConnectionError):
pass
class InvalidAuthAPIError(APIConnectionError):
pass
class ResolveAPIError(APIConnectionError):
pass
class ProtocolAPIError(APIConnectionError):
pass
class RequiresEncryptionAPIError(ProtocolAPIError):
pass
class SocketAPIError(APIConnectionError):
pass
class SocketClosedAPIError(SocketAPIError):
pass
class HandshakeAPIError(APIConnectionError):
pass
class ConnectionNotEstablishedAPIError(APIConnectionError):
pass
class BadNameAPIError(APIConnectionError):
"""Raised when a name received from the remote but does not much the expected name."""
def __init__(self, msg: str, received_name: str) -> None:
super().__init__(f"{msg}: received_name={received_name}")
self.received_name = received_name
class InvalidEncryptionKeyAPIError(HandshakeAPIError):
def __init__(
2023-07-19 22:33:28 +02:00
self, msg: str | None = None, received_name: str | None = None
) -> None:
super().__init__(f"{msg}: received_name={received_name}")
self.received_name = received_name
class PingFailedAPIError(APIConnectionError):
pass
class TimeoutAPIError(APIConnectionError):
pass
class ReadFailedAPIError(APIConnectionError):
pass
class UnhandledAPIConnectionError(APIConnectionError):
pass
class BluetoothConnectionDroppedError(APIConnectionError):
"""Raised when a Bluetooth connection is dropped."""
def to_human_readable_address(address: int) -> str:
"""Convert a MAC address to a human readable format."""
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 "
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
2019-04-07 19:03:26 +02:00
MESSAGE_TYPE_TO_PROTO = {
1: HelloRequest,
2: HelloResponse,
3: ConnectRequest,
4: ConnectResponse,
5: DisconnectRequest,
6: DisconnectResponse,
7: PingRequest,
8: PingResponse,
9: DeviceInfoRequest,
10: DeviceInfoResponse,
11: ListEntitiesRequest,
12: ListEntitiesBinarySensorResponse,
13: ListEntitiesCoverResponse,
14: ListEntitiesFanResponse,
15: ListEntitiesLightResponse,
16: ListEntitiesSensorResponse,
17: ListEntitiesSwitchResponse,
18: ListEntitiesTextSensorResponse,
19: ListEntitiesDoneResponse,
20: SubscribeStatesRequest,
21: BinarySensorStateResponse,
22: CoverStateResponse,
23: FanStateResponse,
24: LightStateResponse,
25: SensorStateResponse,
26: SwitchStateResponse,
27: TextSensorStateResponse,
28: SubscribeLogsRequest,
29: SubscribeLogsResponse,
30: CoverCommandRequest,
31: FanCommandRequest,
32: LightCommandRequest,
33: SwitchCommandRequest,
34: SubscribeHomeassistantServicesRequest,
35: HomeassistantServiceResponse,
36: GetTimeRequest,
37: GetTimeResponse,
38: SubscribeHomeAssistantStatesRequest,
39: SubscribeHomeAssistantStateResponse,
40: HomeAssistantStateResponse,
41: ListEntitiesServicesResponse,
42: ExecuteServiceRequest,
43: ListEntitiesCameraResponse,
44: CameraImageResponse,
45: CameraImageRequest,
46: ListEntitiesClimateResponse,
47: ClimateStateResponse,
48: ClimateCommandRequest,
2021-06-29 12:42:38 +02:00
49: ListEntitiesNumberResponse,
50: NumberStateResponse,
51: NumberCommandRequest,
2021-07-26 20:51:12 +02:00
52: ListEntitiesSelectResponse,
53: SelectStateResponse,
54: SelectCommandRequest,
2021-09-09 03:11:51 +02:00
55: ListEntitiesSirenResponse,
56: SirenStateResponse,
57: SirenCommandRequest,
2022-01-11 02:29:19 +01:00
58: ListEntitiesLockResponse,
59: LockStateResponse,
60: LockCommandRequest,
2021-11-29 01:59:23 +01:00
61: ListEntitiesButtonResponse,
62: ButtonCommandRequest,
2022-05-18 03:28:40 +02:00
63: ListEntitiesMediaPlayerResponse,
64: MediaPlayerStateResponse,
65: MediaPlayerCommandRequest,
66: SubscribeBluetoothLEAdvertisementsRequest,
67: BluetoothLEAdvertisementResponse,
2022-09-28 18:50:37 +02:00
68: BluetoothDeviceRequest,
69: BluetoothDeviceConnectionResponse,
70: BluetoothGATTGetServicesRequest,
71: BluetoothGATTGetServicesResponse,
72: BluetoothGATTGetServicesDoneResponse,
73: BluetoothGATTReadRequest,
74: BluetoothGATTReadResponse,
75: BluetoothGATTWriteRequest,
76: BluetoothGATTReadDescriptorRequest,
77: BluetoothGATTWriteDescriptorRequest,
78: BluetoothGATTNotifyRequest,
79: BluetoothGATTNotifyDataResponse,
80: SubscribeBluetoothConnectionsFreeRequest,
81: BluetoothConnectionsFreeResponse,
82: BluetoothGATTErrorResponse,
83: BluetoothGATTWriteResponse,
84: BluetoothGATTNotifyResponse,
2023-03-06 19:07:58 +01:00
85: BluetoothDevicePairingResponse,
86: BluetoothDeviceUnpairingResponse,
87: UnsubscribeBluetoothLEAdvertisementsRequest,
88: BluetoothDeviceClearCacheResponse,
89: SubscribeVoiceAssistantRequest,
90: VoiceAssistantRequest,
91: VoiceAssistantResponse,
92: VoiceAssistantEventResponse,
93: BluetoothLERawAdvertisementsResponse,
94: ListEntitiesAlarmControlPanelResponse,
95: AlarmControlPanelStateResponse,
96: AlarmControlPanelCommandRequest,
97: ListEntitiesTextResponse,
98: TextStateResponse,
99: TextCommandRequest,
100: ListEntitiesDateResponse,
101: DateStateResponse,
102: DateCommandRequest,
2024-03-20 02:31:00 +01:00
103: ListEntitiesTimeResponse,
104: TimeStateResponse,
105: TimeCommandRequest,
106: VoiceAssistantAudio,
107: ListEntitiesEventResponse,
108: EventResponse,
109: ListEntitiesValveResponse,
110: ValveStateResponse,
111: ValveCommandRequest,
2024-04-22 05:58:16 +02:00
112: ListEntitiesDateTimeResponse,
113: DateTimeStateResponse,
114: DateTimeCommandRequest,
2019-04-07 19:03:26 +02:00
}