1
mirror of https://github.com/home-assistant/core synced 2024-10-07 10:13:38 +02:00
ha-core/homeassistant/components/esphome/bluetooth/characteristic.py
J. Nick Koston 7042d6d35b
Add ESPHome BleakClient (#78911)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2022-09-28 08:06:30 -10:00

96 lines
3.0 KiB
Python

"""BleakGATTCharacteristicESPHome."""
from __future__ import annotations
import contextlib
from uuid import UUID
from aioesphomeapi.model import BluetoothGATTCharacteristic
from bleak.backends.characteristic import BleakGATTCharacteristic
from bleak.backends.descriptor import BleakGATTDescriptor
PROPERTY_MASKS = {
2**n: prop
for n, prop in enumerate(
(
"broadcast",
"read",
"write-without-response",
"write",
"notify",
"indicate",
"authenticated-signed-writes",
"extended-properties",
"reliable-writes",
"writable-auxiliaries",
)
)
}
class BleakGATTCharacteristicESPHome(BleakGATTCharacteristic):
"""GATT Characteristic implementation for the ESPHome backend."""
obj: BluetoothGATTCharacteristic
def __init__(
self,
obj: BluetoothGATTCharacteristic,
max_write_without_response_size: int,
service_uuid: str,
service_handle: int,
) -> None:
"""Init a BleakGATTCharacteristicESPHome."""
super().__init__(obj, max_write_without_response_size)
self.__descriptors: list[BleakGATTDescriptor] = []
self.__service_uuid: str = service_uuid
self.__service_handle: int = service_handle
char_props = self.obj.properties
self.__props: list[str] = [
prop for mask, prop in PROPERTY_MASKS.items() if char_props & mask
]
@property
def service_uuid(self) -> str:
"""Uuid of the Service containing this characteristic."""
return self.__service_uuid
@property
def service_handle(self) -> int:
"""Integer handle of the Service containing this characteristic."""
return self.__service_handle
@property
def handle(self) -> int:
"""Integer handle for this characteristic."""
return self.obj.handle
@property
def uuid(self) -> str:
"""Uuid of this characteristic."""
return self.obj.uuid
@property
def properties(self) -> list[str]:
"""Properties of this characteristic."""
return self.__props
@property
def descriptors(self) -> list[BleakGATTDescriptor]:
"""List of descriptors for this service."""
return self.__descriptors
def get_descriptor(self, specifier: int | str | UUID) -> BleakGATTDescriptor | None:
"""Get a descriptor by handle (int) or UUID (str or uuid.UUID)."""
with contextlib.suppress(StopIteration):
if isinstance(specifier, int):
return next(filter(lambda x: x.handle == specifier, self.descriptors))
return next(filter(lambda x: x.uuid == str(specifier), self.descriptors))
return None
def add_descriptor(self, descriptor: BleakGATTDescriptor) -> None:
"""Add a :py:class:`~BleakGATTDescriptor` to the characteristic.
Should not be used by end user, but rather by `bleak` itself.
"""
self.__descriptors.append(descriptor)