Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions bless/backends/bluezdbus/dbus/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ def __init__(self, name: str, destination: str, bus: MessageBus):
self.Write: Optional[
Callable[[BlueZGattCharacteristic, bytes, Dict[str, Any]], None]
] = None
self.StartNotify: Optional[Callable[[None], None]] = None
self.StopNotify: Optional[Callable[[None], None]] = None
self.StartNotify: Optional[
Callable[[BlueZGattCharacteristic, Dict[str, Any]], None]
] = None
self.StopNotify: Optional[
Callable[[BlueZGattCharacteristic, Dict[str, Any]], None]
] = None

self.subscribed_characteristics: List[str] = []

Expand Down
23 changes: 7 additions & 16 deletions bless/backends/bluezdbus/dbus/characteristic.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

if TYPE_CHECKING:
from bless.backends.bluezdbus.dbus.service import ( # type: ignore # noqa: F401
BlueZGattService
BlueZGattService,
)


Expand Down Expand Up @@ -68,10 +68,7 @@ def __init__(
self._service: "BlueZGattService" = service # noqa: F821

self._value: bytes = b""
self._notifying: bool = (
"notify" in self._flags
or "indicate" in self._flags
)
self._notifying: bool = "notify" in self._flags or "indicate" in self._flags
self.descriptors: List["BlueZGattDescriptor"] = [] # noqa: F821

super(BlueZGattCharacteristic, self).__init__(self.interface_name)
Expand All @@ -91,9 +88,7 @@ def Value(self) -> "ay": # type: ignore # noqa: F821 N802
@Value.setter # type: ignore
def Value(self, value: "ay"): # type: ignore # noqa: F821 N802
self._value = value
self.emit_properties_changed(
changed_properties={"Value": self._value}
)
self.emit_properties_changed(changed_properties={"Value": self._value})

@dbus_property(access=PropertyAccess.READ)
def Notifying(self) -> "b": # type: ignore # noqa: F821 N802
Expand Down Expand Up @@ -150,7 +145,7 @@ def StartNotify(self): # noqa: N802
f = self._service.app.StartNotify
if f is None:
raise NotImplementedError()
f(None)
f(self, {})
self._service.app.subscribed_characteristics.append(self._uuid)

@method()
Expand All @@ -161,7 +156,7 @@ def StopNotify(self): # noqa: N802
f = self._service.app.StopNotify
if f is None:
raise NotImplementedError()
f(None)
f(self, {})
self._service.app.subscribed_characteristics.remove(self._uuid)

async def add_descriptor(
Expand All @@ -180,9 +175,7 @@ async def add_descriptor(
The descriptor's value
"""
index: int = len(self.descriptors) + 1
descriptor: BlueZGattDescriptor = BlueZGattDescriptor(
uuid, flags, index, self
)
descriptor: BlueZGattDescriptor = BlueZGattDescriptor(uuid, flags, index, self)
descriptor._value = value # type: ignore
self.descriptors.append(descriptor)
await self._service.app._register_object(descriptor)
Expand All @@ -198,6 +191,4 @@ async def get_obj(self) -> Dict:
Dict
The dictionary that describes the characteristic
"""
return {
"UUID": Variant('s', self._uuid)
}
return {"UUID": Variant("s", self._uuid)}
38 changes: 32 additions & 6 deletions bless/backends/bluezdbus/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,8 @@ async def setup(self: "BlessServerBlueZDBus"):

self.app.Read = self.read
self.app.Write = self.write

# We don't need to define these
self.app.StartNotify = lambda x: None
self.app.StopNotify = lambda x: None
self.app.StartNotify = self.subscribe
self.app.StopNotify = self.unsubscribe

potential_adapter: Optional[ProxyObject] = await get_adapter(
self.bus, self._adapter
Expand Down Expand Up @@ -248,8 +246,8 @@ async def add_new_descriptor(
service.get_characteristic(std_char_uuid),
)
std_desc_uuid = normalize_uuid_str(desc_uuid)
descriptor: BlessGATTDescriptorBlueZDBus = (
BlessGATTDescriptorBlueZDBus(std_desc_uuid, properties, permissions, value)
descriptor: BlessGATTDescriptorBlueZDBus = BlessGATTDescriptorBlueZDBus(
std_desc_uuid, properties, permissions, value
)

await descriptor.init(characteristic)
Expand Down Expand Up @@ -333,3 +331,31 @@ def write(
The value being requested to set
"""
return self.write_request(char.UUID, bytearray(value), options)

def subscribe(self, char: BlueZGattCharacteristic, options: Dict[str, Any]):
"""
Subscribe request.
This function re-routes the subscribe request sent from the
BlueZGattApplication to the server function for re-route to the user
defined handler

Parameters
----------
char : BlueZGattCharacteristic
The characteristic object involved in the request
"""
return self.subscribe_request(char.UUID, options)

def unsubscribe(self, char: BlueZGattCharacteristic, options: Dict[str, Any]):
"""
Unsubscribe request.
This function re-routes the unsubscribe request sent from the
BlueZGattApplication to the server function for re-route to the user
defined handler

Parameters
----------
char : BlueZGattCharacteristic
The characteristic object involved in the request
"""
return self.unsubscribe_request(char.UUID, options)
84 changes: 55 additions & 29 deletions bless/backends/corebluetooth/peripheral_manager_delegate.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import os
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional
from warnings import warn


if TYPE_CHECKING:

class PeripheralManagerDelegate: # type: ignore # noqa: F811
event_loop: Optional["asyncio.AbstractEventLoop"]
peripheral_manager: Any
Expand All @@ -14,39 +17,43 @@ class PeripheralManagerDelegate: # type: ignore # noqa: F811
pyobjc_classMethods: Any

@classmethod
def alloc(cls) -> "PeripheralManagerDelegate":
...
def alloc(cls) -> "PeripheralManagerDelegate": ...

def init(self: "PeripheralManagerDelegate"):
...
def init(
self: "PeripheralManagerDelegate",
server: Optional[Any] = None,
callbacks: Optional[Dict[str, Callable[..., Any]]] = None,
) -> "PeripheralManagerDelegate": ...

async def start_advertising(
self, advertisement_data: Dict[str, Any], timeout: float = 2.0
) -> None:
...
) -> None: ...

async def stop_advertising(self) -> None:
...
async def stop_advertising(self) -> None: ...

def is_connected(self) -> bool:
...
def is_connected(self) -> bool: ...

def is_advertising(self) -> bool:
...
def is_advertising(self) -> bool: ...

async def add_service(self, service: Any) -> None:
...
async def add_service(self, service: Any) -> None: ...

def compliant(self) -> bool: ...

def compliant(self) -> bool:
...

if os.environ.get("BLESS_DOCS_BUILD"):

class PeripheralManagerDelegate: # type: ignore # noqa: F811
"""
Stub for documentation builds where CoreBluetooth is unavailable.
"""

def init(self: "PeripheralManagerDelegate"):
def init(
self: "PeripheralManagerDelegate",
server: Optional[Any] = None,
callbacks: Optional[Dict[str, Callable[..., Any]]] = None,
):
self.server = server
self._callbacks = callbacks or {}
return self

async def start_advertising(self, advertisement_data, timeout: float = 2.0):
Expand All @@ -60,6 +67,7 @@ def is_connected(self) -> bool:

def is_advertising(self) -> bool:
return False

else:
import objc # type: ignore
import asyncio
Expand Down Expand Up @@ -92,22 +100,25 @@ def is_advertising(self) -> bool:
CBPeripheralManagerDelegate = objc.protocolNamed("CBPeripheralManagerDelegate")

class PeripheralManagerDelegate( # type: ignore # noqa: F811
NSObject,
protocols=[CBPeripheralManagerDelegate]
):
def init(self: "PeripheralManagerDelegate"):
NSObject, protocols=[CBPeripheralManagerDelegate]
):
def init(
self: "PeripheralManagerDelegate",
server: Optional[Any] = None,
callbacks: Optional[Dict[str, Callable]] = None,
):
self = objc.super(PeripheralManagerDelegate, self).init()

self.event_loop: Optional[asyncio.AbstractEventLoop] = None
self.server: Optional[Any] = None
self.server: Optional[Any] = server

self.peripheral_manager: CBPeripheralManager = (
CBPeripheralManager.alloc().initWithDelegate_queue_(
self, dispatch_queue_create(b"BLE", DISPATCH_QUEUE_SERIAL)
)
self.peripheral_manager: (
CBPeripheralManager
) = CBPeripheralManager.alloc().initWithDelegate_queue_(
self, dispatch_queue_create(b"BLE", DISPATCH_QUEUE_SERIAL)
)

self._callbacks: Dict[str, Callable] = {}
self._callbacks: Dict[str, Callable] = callbacks or {}

# Events
self._powered_on_event: threading.Event = threading.Event()
Expand Down Expand Up @@ -365,6 +376,10 @@ def peripheralManager_central_didSubscribeToCharacteristic_( # noqa: N802
)
else:
self._central_subscriptions[central_uuid] = [char_uuid]
self._callbacks.get("subscribe", lambda x: None)(
characteristic.UUID().UUIDString()
)
self.get_callback("subscribe")(characteristic.UUID().UUIDString())

def peripheralManager_central_didUnsubscribeFromCharacteristic_( # noqa: N802 E501
self,
Expand All @@ -383,6 +398,8 @@ def peripheralManager_central_didUnsubscribeFromCharacteristic_( # noqa: N802 E
if len(self._central_subscriptions[central_uuid]) < 1:
del self._central_subscriptions[central_uuid]

self.get_callback("unsubscribe")(characteristic.UUID().UUIDString())

def peripheralManagerIsReadyToUpdateSubscribers_( # noqa: N802
self, peripheral_manager: CBPeripheralManager
):
Expand All @@ -400,7 +417,7 @@ def peripheralManager_didReceiveReadRequest_( # noqa: N802
)
)
request.setValue_(
self.read_request_func(request.characteristic().UUID().UUIDString())
self.get_callback("read")(request.characteristic().UUID().UUIDString())
)
peripheral_manager.respondToRequest_withResult_(request, CBATTErrorSuccess)

Expand All @@ -420,8 +437,17 @@ def peripheralManager_didReceiveWriteRequests_( # noqa: N802
value,
)
)
self.write_request_func(char.UUID().UUIDString(), value)
self.get_callback("write")(char.UUID().UUIDString(), value)

peripheral_manager.respondToRequest_withResult_(
requests[0], CBATTErrorSuccess
)

def get_callback(self, callback_name: str) -> Callable:
if callback_name not in self._callbacks:
warn(
"Callback {} does not exist".format(callback_name),
UserWarning,
)
return lambda x: None
return self._callbacks[callback_name]
15 changes: 10 additions & 5 deletions bless/backends/corebluetooth/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,17 @@ def __init__(self, name: str, loop: Optional[AbstractEventLoop] = None, **kwargs

self.name: str = name

self.peripheral_manager_delegate: PeripheralManagerDelegate = (
PeripheralManagerDelegate.alloc().init()
self.peripheral_manager_delegate: (
PeripheralManagerDelegate
) = PeripheralManagerDelegate.alloc().init(
self,
{
"read": self.read_request,
"write": self.write_request,
"subscribe": self.subscribe_request,
"unsubscribe": self.unsubscribe_request,
},
)
self.peripheral_manager_delegate.server = self
self.peripheral_manager_delegate.read_request_func = self.read_request
self.peripheral_manager_delegate.write_request_func = self.write_request

async def start(
self,
Expand Down
Loading