mirror of
https://github.com/esphome/aioesphomeapi.git
synced 2024-12-25 17:17:42 +01:00
Improve performance of converting raw BLE advertisements (#462)
This commit is contained in:
parent
b81fe760ba
commit
8ac62a321f
@ -134,7 +134,6 @@ from .model import (
|
|||||||
BluetoothGATTServices,
|
BluetoothGATTServices,
|
||||||
BluetoothLEAdvertisement,
|
BluetoothLEAdvertisement,
|
||||||
BluetoothLERawAdvertisement,
|
BluetoothLERawAdvertisement,
|
||||||
BluetoothLERawAdvertisements,
|
|
||||||
BluetoothProxyFeature,
|
BluetoothProxyFeature,
|
||||||
BluetoothProxySubscriptionFlag,
|
BluetoothProxySubscriptionFlag,
|
||||||
ButtonInfo,
|
ButtonInfo,
|
||||||
@ -183,6 +182,7 @@ from .model import (
|
|||||||
UserServiceArgType,
|
UserServiceArgType,
|
||||||
VoiceAssistantCommand,
|
VoiceAssistantCommand,
|
||||||
VoiceAssistantEventType,
|
VoiceAssistantEventType,
|
||||||
|
make_ble_raw_advertisement_processor,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -409,7 +409,7 @@ class APIClient:
|
|||||||
}
|
}
|
||||||
msg_types = (*response_types, CameraImageResponse)
|
msg_types = (*response_types, CameraImageResponse)
|
||||||
|
|
||||||
def on_msg(msg: message.Message) -> None:
|
def _on_state_msg(msg: message.Message) -> None:
|
||||||
msg_type = type(msg)
|
msg_type = type(msg)
|
||||||
cls = response_types.get(msg_type)
|
cls = response_types.get(msg_type)
|
||||||
if cls:
|
if cls:
|
||||||
@ -432,7 +432,7 @@ class APIClient:
|
|||||||
|
|
||||||
assert self._connection is not None
|
assert self._connection is not None
|
||||||
self._connection.send_message_callback_response(
|
self._connection.send_message_callback_response(
|
||||||
SubscribeStatesRequest(), on_msg, msg_types
|
SubscribeStatesRequest(), _on_state_msg, msg_types
|
||||||
)
|
)
|
||||||
|
|
||||||
async def subscribe_logs(
|
async def subscribe_logs(
|
||||||
@ -457,13 +457,15 @@ class APIClient:
|
|||||||
) -> None:
|
) -> None:
|
||||||
self._check_authenticated()
|
self._check_authenticated()
|
||||||
|
|
||||||
def on_msg(msg: HomeassistantServiceResponse) -> None:
|
def _on_home_assistant_service_response(
|
||||||
|
msg: HomeassistantServiceResponse,
|
||||||
|
) -> None:
|
||||||
on_service_call(HomeassistantServiceCall.from_pb(msg))
|
on_service_call(HomeassistantServiceCall.from_pb(msg))
|
||||||
|
|
||||||
assert self._connection is not None
|
assert self._connection is not None
|
||||||
self._connection.send_message_callback_response(
|
self._connection.send_message_callback_response(
|
||||||
SubscribeHomeassistantServicesRequest(),
|
SubscribeHomeassistantServicesRequest(),
|
||||||
on_msg,
|
_on_home_assistant_service_response,
|
||||||
(HomeassistantServiceResponse,),
|
(HomeassistantServiceResponse,),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -501,19 +503,23 @@ class APIClient:
|
|||||||
self._check_authenticated()
|
self._check_authenticated()
|
||||||
msg_types = (BluetoothLEAdvertisementResponse,)
|
msg_types = (BluetoothLEAdvertisementResponse,)
|
||||||
|
|
||||||
def on_msg(msg: BluetoothLEAdvertisementResponse) -> None:
|
def _on_bluetooth_le_advertising_response(
|
||||||
|
msg: BluetoothLEAdvertisementResponse,
|
||||||
|
) -> None:
|
||||||
on_bluetooth_le_advertisement(BluetoothLEAdvertisement.from_pb(msg)) # type: ignore[misc]
|
on_bluetooth_le_advertisement(BluetoothLEAdvertisement.from_pb(msg)) # type: ignore[misc]
|
||||||
|
|
||||||
assert self._connection is not None
|
assert self._connection is not None
|
||||||
self._connection.send_message_callback_response(
|
self._connection.send_message_callback_response(
|
||||||
SubscribeBluetoothLEAdvertisementsRequest(flags=0),
|
SubscribeBluetoothLEAdvertisementsRequest(flags=0),
|
||||||
on_msg,
|
_on_bluetooth_le_advertising_response,
|
||||||
msg_types,
|
msg_types,
|
||||||
)
|
)
|
||||||
|
|
||||||
def unsub() -> None:
|
def unsub() -> None:
|
||||||
if self._connection is not None:
|
if self._connection is not None:
|
||||||
self._connection.remove_message_callback(on_msg, msg_types)
|
self._connection.remove_message_callback(
|
||||||
|
_on_bluetooth_le_advertising_response, msg_types
|
||||||
|
)
|
||||||
self._connection.send_message(
|
self._connection.send_message(
|
||||||
UnsubscribeBluetoothLEAdvertisementsRequest()
|
UnsubscribeBluetoothLEAdvertisementsRequest()
|
||||||
)
|
)
|
||||||
@ -526,10 +532,8 @@ class APIClient:
|
|||||||
self._check_authenticated()
|
self._check_authenticated()
|
||||||
msg_types = (BluetoothLERawAdvertisementsResponse,)
|
msg_types = (BluetoothLERawAdvertisementsResponse,)
|
||||||
|
|
||||||
def on_msg(msg: BluetoothLERawAdvertisementsResponse) -> None:
|
|
||||||
on_advertisements(BluetoothLERawAdvertisements.from_pb(msg).advertisements) # type: ignore[misc]
|
|
||||||
|
|
||||||
assert self._connection is not None
|
assert self._connection is not None
|
||||||
|
on_msg = make_ble_raw_advertisement_processor(on_advertisements)
|
||||||
self._connection.send_message_callback_response(
|
self._connection.send_message_callback_response(
|
||||||
SubscribeBluetoothLEAdvertisementsRequest(
|
SubscribeBluetoothLEAdvertisementsRequest(
|
||||||
flags=BluetoothProxySubscriptionFlag.RAW_ADVERTISEMENTS
|
flags=BluetoothProxySubscriptionFlag.RAW_ADVERTISEMENTS
|
||||||
@ -553,18 +557,24 @@ class APIClient:
|
|||||||
self._check_authenticated()
|
self._check_authenticated()
|
||||||
msg_types = (BluetoothConnectionsFreeResponse,)
|
msg_types = (BluetoothConnectionsFreeResponse,)
|
||||||
|
|
||||||
def on_msg(msg: BluetoothConnectionsFreeResponse) -> None:
|
def _on_bluetooth_connections_free_response(
|
||||||
|
msg: BluetoothConnectionsFreeResponse,
|
||||||
|
) -> None:
|
||||||
resp = BluetoothConnectionsFree.from_pb(msg)
|
resp = BluetoothConnectionsFree.from_pb(msg)
|
||||||
on_bluetooth_connections_free_update(resp.free, resp.limit)
|
on_bluetooth_connections_free_update(resp.free, resp.limit)
|
||||||
|
|
||||||
assert self._connection is not None
|
assert self._connection is not None
|
||||||
self._connection.send_message_callback_response(
|
self._connection.send_message_callback_response(
|
||||||
SubscribeBluetoothConnectionsFreeRequest(), on_msg, msg_types
|
SubscribeBluetoothConnectionsFreeRequest(),
|
||||||
|
_on_bluetooth_connections_free_response,
|
||||||
|
msg_types,
|
||||||
)
|
)
|
||||||
|
|
||||||
def unsub() -> None:
|
def unsub() -> None:
|
||||||
if self._connection is not None:
|
if self._connection is not None:
|
||||||
self._connection.remove_message_callback(on_msg, msg_types)
|
self._connection.remove_message_callback(
|
||||||
|
_on_bluetooth_connections_free_response, msg_types
|
||||||
|
)
|
||||||
|
|
||||||
return unsub
|
return unsub
|
||||||
|
|
||||||
@ -583,7 +593,9 @@ class APIClient:
|
|||||||
|
|
||||||
event = asyncio.Event()
|
event = asyncio.Event()
|
||||||
|
|
||||||
def on_msg(msg: BluetoothDeviceConnectionResponse) -> None:
|
def _on_bluetooth_device_connection_response(
|
||||||
|
msg: BluetoothDeviceConnectionResponse,
|
||||||
|
) -> None:
|
||||||
resp = BluetoothDeviceConnection.from_pb(msg)
|
resp = BluetoothDeviceConnection.from_pb(msg)
|
||||||
if address == resp.address:
|
if address == resp.address:
|
||||||
on_bluetooth_connection_state(resp.connected, resp.mtu, resp.error)
|
on_bluetooth_connection_state(resp.connected, resp.mtu, resp.error)
|
||||||
@ -614,13 +626,15 @@ class APIClient:
|
|||||||
has_address_type=address_type is not None,
|
has_address_type=address_type is not None,
|
||||||
address_type=address_type or 0,
|
address_type=address_type or 0,
|
||||||
),
|
),
|
||||||
on_msg,
|
_on_bluetooth_device_connection_response,
|
||||||
msg_types,
|
msg_types,
|
||||||
)
|
)
|
||||||
|
|
||||||
def unsub() -> None:
|
def unsub() -> None:
|
||||||
if self._connection is not None:
|
if self._connection is not None:
|
||||||
self._connection.remove_message_callback(on_msg, msg_types)
|
self._connection.remove_message_callback(
|
||||||
|
_on_bluetooth_device_connection_response, msg_types
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
@ -930,14 +944,16 @@ class APIClient:
|
|||||||
BluetoothGATTNotifyResponse,
|
BluetoothGATTNotifyResponse,
|
||||||
)
|
)
|
||||||
|
|
||||||
def on_msg(msg: BluetoothGATTNotifyDataResponse) -> None:
|
def _on_bluetooth_gatt_notify_data_response(
|
||||||
|
msg: BluetoothGATTNotifyDataResponse,
|
||||||
|
) -> None:
|
||||||
notify = BluetoothGATTRead.from_pb(msg)
|
notify = BluetoothGATTRead.from_pb(msg)
|
||||||
if address == notify.address and handle == notify.handle:
|
if address == notify.address and handle == notify.handle:
|
||||||
on_bluetooth_gatt_notify(handle, bytearray(notify.data))
|
on_bluetooth_gatt_notify(handle, bytearray(notify.data))
|
||||||
|
|
||||||
assert self._connection is not None
|
assert self._connection is not None
|
||||||
remove_callback = self._connection.add_message_callback(
|
remove_callback = self._connection.add_message_callback(
|
||||||
on_msg, (BluetoothGATTNotifyDataResponse,)
|
_on_bluetooth_gatt_notify_data_response, (BluetoothGATTNotifyDataResponse,)
|
||||||
)
|
)
|
||||||
|
|
||||||
async def stop_notify() -> None:
|
async def stop_notify() -> None:
|
||||||
@ -959,13 +975,15 @@ class APIClient:
|
|||||||
) -> None:
|
) -> None:
|
||||||
self._check_authenticated()
|
self._check_authenticated()
|
||||||
|
|
||||||
def on_msg(msg: SubscribeHomeAssistantStateResponse) -> None:
|
def _on_subscribe_home_assistant_state_response(
|
||||||
|
msg: SubscribeHomeAssistantStateResponse,
|
||||||
|
) -> None:
|
||||||
on_state_sub(msg.entity_id, msg.attribute)
|
on_state_sub(msg.entity_id, msg.attribute)
|
||||||
|
|
||||||
assert self._connection is not None
|
assert self._connection is not None
|
||||||
self._connection.send_message_callback_response(
|
self._connection.send_message_callback_response(
|
||||||
SubscribeHomeAssistantStatesRequest(),
|
SubscribeHomeAssistantStatesRequest(),
|
||||||
on_msg,
|
_on_subscribe_home_assistant_state_response,
|
||||||
(SubscribeHomeAssistantStateResponse,),
|
(SubscribeHomeAssistantStateResponse,),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1349,7 +1367,7 @@ class APIClient:
|
|||||||
_LOGGER.error("Server could not be started")
|
_LOGGER.error("Server could not be started")
|
||||||
self._connection.send_message(VoiceAssistantResponse(error=True))
|
self._connection.send_message(VoiceAssistantResponse(error=True))
|
||||||
|
|
||||||
def on_msg(msg: VoiceAssistantRequest) -> None:
|
def _on_voice_assistant_request(msg: VoiceAssistantRequest) -> None:
|
||||||
command = VoiceAssistantCommand.from_pb(msg)
|
command = VoiceAssistantCommand.from_pb(msg)
|
||||||
if command.start:
|
if command.start:
|
||||||
start_task = asyncio.create_task(
|
start_task = asyncio.create_task(
|
||||||
@ -1368,7 +1386,7 @@ class APIClient:
|
|||||||
self._connection.send_message(SubscribeVoiceAssistantRequest(subscribe=True))
|
self._connection.send_message(SubscribeVoiceAssistantRequest(subscribe=True))
|
||||||
|
|
||||||
remove_callback = self._connection.add_message_callback(
|
remove_callback = self._connection.add_message_callback(
|
||||||
on_msg, (VoiceAssistantRequest,)
|
_on_voice_assistant_request, (VoiceAssistantRequest,)
|
||||||
)
|
)
|
||||||
|
|
||||||
def unsub() -> None:
|
def unsub() -> None:
|
||||||
|
@ -935,17 +935,16 @@ class BluetoothLERawAdvertisement:
|
|||||||
data: bytes = field(default_factory=bytes)
|
data: bytes = field(default_factory=bytes)
|
||||||
|
|
||||||
|
|
||||||
@_dataclass_decorator
|
def make_ble_raw_advertisement_processor(
|
||||||
class BluetoothLERawAdvertisements:
|
on_advertisements: Callable[[List[BluetoothLERawAdvertisement]], None]
|
||||||
advertisements: List[BluetoothLERawAdvertisement]
|
) -> Callable[["BluetoothLERawAdvertisementsResponse"], None]:
|
||||||
|
"""Make a processor for BluetoothLERawAdvertisementResponse."""
|
||||||
|
|
||||||
@classmethod
|
def _on_ble_raw_advertisement_response(
|
||||||
def from_pb( # type: ignore[misc]
|
|
||||||
cls: "BluetoothLERawAdvertisements",
|
|
||||||
data: "BluetoothLERawAdvertisementsResponse",
|
data: "BluetoothLERawAdvertisementsResponse",
|
||||||
) -> "BluetoothLERawAdvertisements":
|
) -> None:
|
||||||
return cls( # type: ignore[operator, no-any-return]
|
on_advertisements(
|
||||||
advertisements=[
|
[
|
||||||
BluetoothLERawAdvertisement( # type: ignore[call-arg]
|
BluetoothLERawAdvertisement( # type: ignore[call-arg]
|
||||||
adv.address, adv.rssi, adv.address_type, adv.data
|
adv.address, adv.rssi, adv.address_type, adv.data
|
||||||
)
|
)
|
||||||
@ -953,6 +952,8 @@ class BluetoothLERawAdvertisements:
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return _on_ble_raw_advertisement_response
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class BluetoothDeviceConnection(APIModelBase):
|
class BluetoothDeviceConnection(APIModelBase):
|
||||||
|
Loading…
Reference in New Issue
Block a user