Add bluetooth connections free

Add callbacks to remove message subscriptions

Move stop notify to callback of start notify
This commit is contained in:
Jesse Hills 2022-09-28 10:54:35 +13:00
parent a43518c5ed
commit 51e364cdb7
No known key found for this signature in database
GPG Key ID: BEAAE804EFD8E83A
6 changed files with 208 additions and 57 deletions

View File

@ -1291,3 +1291,18 @@ message BluetoothGATTNotifyDataResponse {
repeated uint32 data = 3 [packed=true]; repeated uint32 data = 3 [packed=true];
} }
message SubscribeBluetoothConnectionsFreeRequest {
option (id) = 79;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_BLUETOOTH_PROXY";
}
message BluetoothConnectionsFreeResponse {
option (id) = 80;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint32 free = 1;
uint32 limit = 2;
}

File diff suppressed because one or more lines are too long

View File

@ -18,16 +18,17 @@ from google.protobuf import message
from .api_pb2 import ( # type: ignore from .api_pb2 import ( # type: ignore
BinarySensorStateResponse, BinarySensorStateResponse,
BluetoothConnectionsFreeResponse,
BluetoothDeviceConnectionResponse, BluetoothDeviceConnectionResponse,
BluetoothDeviceRequest, BluetoothDeviceRequest,
BluetoothGATTReadDescriptorRequest,
BluetoothGATTWriteDescriptorRequest,
BluetoothGATTGetServicesRequest, BluetoothGATTGetServicesRequest,
BluetoothGATTGetServicesResponse, BluetoothGATTGetServicesResponse,
BluetoothGATTNotifyRequest,
BluetoothGATTNotifyDataResponse, BluetoothGATTNotifyDataResponse,
BluetoothGATTNotifyRequest,
BluetoothGATTReadDescriptorRequest,
BluetoothGATTReadRequest, BluetoothGATTReadRequest,
BluetoothGATTReadResponse, BluetoothGATTReadResponse,
BluetoothGATTWriteDescriptorRequest,
BluetoothGATTWriteRequest, BluetoothGATTWriteRequest,
BluetoothLEAdvertisementResponse, BluetoothLEAdvertisementResponse,
ButtonCommandRequest, ButtonCommandRequest,
@ -76,6 +77,7 @@ from .api_pb2 import ( # type: ignore
SensorStateResponse, SensorStateResponse,
SirenCommandRequest, SirenCommandRequest,
SirenStateResponse, SirenStateResponse,
SubscribeBluetoothConnectionsFreeRequest,
SubscribeBluetoothLEAdvertisementsRequest, SubscribeBluetoothLEAdvertisementsRequest,
SubscribeHomeassistantServicesRequest, SubscribeHomeassistantServicesRequest,
SubscribeHomeAssistantStateResponse, SubscribeHomeAssistantStateResponse,
@ -94,6 +96,7 @@ from .model import (
APIVersion, APIVersion,
BinarySensorInfo, BinarySensorInfo,
BinarySensorState, BinarySensorState,
BluetoothConnectionsFree,
BluetoothDeviceConnection, BluetoothDeviceConnection,
BluetoothDeviceRequestType, BluetoothDeviceRequestType,
BluetoothGATTRead, BluetoothGATTRead,
@ -401,7 +404,7 @@ class APIClient:
async def subscribe_bluetooth_le_advertisements( async def subscribe_bluetooth_le_advertisements(
self, on_bluetooth_le_advertisement: Callable[[BluetoothLEAdvertisement], None] self, on_bluetooth_le_advertisement: Callable[[BluetoothLEAdvertisement], None]
) -> None: ) -> Callable([], None):
self._check_authenticated() self._check_authenticated()
def on_msg(msg: message.Message) -> None: def on_msg(msg: message.Message) -> None:
@ -413,12 +416,39 @@ class APIClient:
SubscribeBluetoothLEAdvertisementsRequest(), on_msg SubscribeBluetoothLEAdvertisementsRequest(), on_msg
) )
def unsub() -> None:
assert self._connection is not None
self._connection.remove_message_callback(on_msg)
return unsub
async def subscribe_bluetooth_connections_free(
self, on_bluetooth_connections_free_update: Callable[[int, int], None]
) -> Callable[[], None]:
self._check_authenticated()
def on_msg(msg: message.Message) -> None:
if isinstance(msg, BluetoothConnectionsFreeResponse):
resp = BluetoothConnectionsFree.from_pb(msg)
on_bluetooth_connections_free_update(resp.free, resp.limit)
assert self._connection is not None
await self._connection.send_message_callback_response(
SubscribeBluetoothConnectionsFreeRequest(), on_msg
)
def unsub() -> None:
assert self._connection is not None
self._connection.remove_message_callback(on_msg)
return unsub
async def bluetooth_device_connect( async def bluetooth_device_connect(
self, self,
address: int, address: int,
on_bluetooth_connection_state: Callable[[bool, int], None], on_bluetooth_connection_state: Callable[[bool, int], None],
timeout: float = 10.0, timeout: float = 10.0,
) -> None: ) -> Callable([], None):
self._check_authenticated() self._check_authenticated()
fut = asyncio.get_event_loop().create_future() fut = asyncio.get_event_loop().create_future()
@ -444,6 +474,12 @@ class APIClient:
except asyncio.TimeoutError as err: except asyncio.TimeoutError as err:
raise TimeoutAPIError("Timeout waiting for connect response") from err raise TimeoutAPIError("Timeout waiting for connect response") from err
def unsub() -> None:
assert self._connection is not None
self._connection.remove_message_callback(on_msg)
return unsub
async def bluetooth_device_disconnect(self, address: int) -> None: async def bluetooth_device_disconnect(self, address: int) -> None:
self._check_authenticated() self._check_authenticated()
@ -565,7 +601,7 @@ class APIClient:
address: int, address: int,
handle: int, handle: int,
on_bluetooth_gatt_notify: Callable[[int, bytearray], None], on_bluetooth_gatt_notify: Callable[[int, bytearray], None],
) -> None: ) -> Callable([], None):
self._check_authenticated() self._check_authenticated()
def on_msg(msg: message.Message) -> None: def on_msg(msg: message.Message) -> None:
@ -580,13 +616,17 @@ class APIClient:
on_msg, on_msg,
) )
async def bluetooth_gatt_stop_notify(self, address: int, handle: int) -> None: async def stop_notify() -> None:
self._check_authenticated() assert self._connection is not None
self._connection.remove_message_callback(on_msg)
assert self._connection is not None self._check_authenticated()
await self._connection.send_message(
BluetoothGATTNotifyRequest(address=address, handle=handle, enable=False) await self._connection.send_message(
) BluetoothGATTNotifyRequest(address=address, handle=handle, enable=False)
)
return stop_notify
async def subscribe_home_assistant_states( async def subscribe_home_assistant_states(
self, on_state_sub: Callable[[str, Optional[str]], None] self, on_state_sub: Callable[[str, Optional[str]], None]

View File

@ -362,6 +362,10 @@ class APIConnection:
await self._report_fatal_error(err) await self._report_fatal_error(err)
raise raise
def remove_message_callback(self, on_message: Callable[[Any], None]) -> None:
"""Remove a message callback."""
self._message_handlers.remove(on_message)
async def send_message_callback_response( async def send_message_callback_response(
self, send_msg: message.Message, on_message: Callable[[Any], None] self, send_msg: message.Message, on_message: Callable[[Any], None]
) -> None: ) -> None:

View File

@ -1,5 +1,6 @@
from .api_pb2 import ( # type: ignore from .api_pb2 import ( # type: ignore
BinarySensorStateResponse, BinarySensorStateResponse,
BluetoothConnectionsFreeResponse,
BluetoothDeviceConnectionResponse, BluetoothDeviceConnectionResponse,
BluetoothDeviceRequest, BluetoothDeviceRequest,
BluetoothGATTGetServicesRequest, BluetoothGATTGetServicesRequest,
@ -67,6 +68,7 @@ from .api_pb2 import ( # type: ignore
SensorStateResponse, SensorStateResponse,
SirenCommandRequest, SirenCommandRequest,
SirenStateResponse, SirenStateResponse,
SubscribeBluetoothConnectionsFreeRequest,
SubscribeBluetoothLEAdvertisementsRequest, SubscribeBluetoothLEAdvertisementsRequest,
SubscribeHomeassistantServicesRequest, SubscribeHomeassistantServicesRequest,
SubscribeHomeAssistantStateResponse, SubscribeHomeAssistantStateResponse,
@ -215,4 +217,6 @@ MESSAGE_TYPE_TO_PROTO = {
76: BluetoothGATTWriteDescriptorRequest, 76: BluetoothGATTWriteDescriptorRequest,
77: BluetoothGATTNotifyRequest, 77: BluetoothGATTNotifyRequest,
78: BluetoothGATTNotifyDataResponse, 78: BluetoothGATTNotifyDataResponse,
79: SubscribeBluetoothConnectionsFreeRequest,
80: BluetoothConnectionsFreeResponse,
} }

View File

@ -879,6 +879,12 @@ class BluetoothGATTServices(APIModelBase):
) )
@dataclass(frozen=True)
class BluetoothConnectionsFree(APIModelBase):
free: int = 0
limit: int = 0
class BluetoothDeviceRequestType(APIIntEnum): class BluetoothDeviceRequestType(APIIntEnum):
CONNECT = 0 CONNECT = 0
DISCONNECT = 1 DISCONNECT = 1