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
11 changes: 8 additions & 3 deletions bless/backends/bluezdbus/dbus/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ def _ensure_bluez_available() -> None:
LOGGER.warning(message)
raise RuntimeError("BlueZ is not available on this system")

async def add_service(self, uuid: str) -> BlueZGattService: # noqa: F821
async def add_service(
self, uuid: str, primary: Optional[bool] = None
) -> BlueZGattService: # noqa: F821
"""
Add a service to the application
The first service to be added will be the primary service
Expand All @@ -99,15 +101,18 @@ async def add_service(self, uuid: str) -> BlueZGattService: # noqa: F821
----------
uuid : str
The string representation of the uuid for the service to create
primary : Optional[bool]
True if this is a primary service, False otherwise. If None,
the first service added will be primary, all others will be secondary
Returns
-------
BlueZGattService
Returns and instance of the service object
"""
index: int = len(self.services) + 1
primary: bool = index == 1
service: BlueZGattService = BlueZGattService(uuid, primary, index, self)
is_primary: bool = primary if primary is not None else index == 1
service: BlueZGattService = BlueZGattService(uuid, is_primary, index, self)
self.services.append(service)
self.bus.export(service.path, service)
return service
Expand Down
8 changes: 6 additions & 2 deletions bless/backends/bluezdbus/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,21 @@ async def is_advertising(self) -> bool:
await self.setup_task
return await self.app.is_advertising(self.adapter)

async def add_new_service(self, uuid: str):
async def add_new_service(self, uuid: str, primary: Optional[bool] = None):
"""
Add a new GATT service to be hosted by the server
Parameters
----------
uuid : str
The UUID for the service to add
primary : Optional[bool]
True if this is a primary service, False otherwise. If None,
default behavior of the backend is used which is only the first
service added is primary.
"""
await self.setup_task
service: BlessGATTServiceBlueZDBus = BlessGATTServiceBlueZDBus(uuid)
service: BlessGATTServiceBlueZDBus = BlessGATTServiceBlueZDBus(uuid, primary)
await service.init(self)
self.services[service.uuid] = service

Expand Down
14 changes: 10 additions & 4 deletions bless/backends/bluezdbus/service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from uuid import UUID
from typing import Mapping, Union, cast, TYPE_CHECKING
from typing import Mapping, Optional, Union, cast, TYPE_CHECKING

from bleak.backends.service import BleakGATTService # type: ignore
from bless.backends.bluezdbus.dbus.service import BlueZGattService
Expand All @@ -17,16 +17,20 @@ class BlessGATTServiceBlueZDBus(BaseBlessGATTService, BleakGATTService):
GATT service implementation for the BlueZ backend
"""

def __init__(self, uuid: Union[str, UUID]):
def __init__(self, uuid: Union[str, UUID], primary: Optional[bool] = None):
"""
Initialize the Bless GATT Service

Parameters
----------
uuid : Union[str, UUID]
The UUID to assign to the service
primary : Optional[bool]
True if this is a primary service, False otherwise. If None,
default behavior of the backend is used which is only the first
service added is primary.
"""
BaseBlessGATTService.__init__(self, uuid)
BaseBlessGATTService.__init__(self, uuid, primary)
self._characteristics: Mapping[int, BlessGATTCharacteristic] = (
{} # type: ignore[assignment]
)
Expand All @@ -43,7 +47,9 @@ async def init(self, server: "BaseBlessServer"):
The server to assign the service to
"""
bluez_server: "BlessServerBlueZDBus" = cast("BlessServerBlueZDBus", server)
gatt_service: BlueZGattService = await bluez_server.app.add_service(self._uuid)
gatt_service: BlueZGattService = await bluez_server.app.add_service(
self._uuid, primary=self._primary
)

# Store the BlueZ GATT service
self.gatt = gatt_service
Expand Down
9 changes: 7 additions & 2 deletions bless/backends/corebluetooth/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,17 +171,22 @@ async def is_advertising(self) -> bool:
"""
return self.peripheral_manager_delegate.is_advertising() == 1

async def add_new_service(self, uuid: str):
async def add_new_service(self, uuid: str, primary: Optional[bool] = None):
"""
Add a service and all it's characteristics to be advertised
Parameters
----------
uuid : str
The string representation of the UUID of the service to be added
primary : Optional[bool]
True if this is a primary service, False otherwise. If None, default
behavior of the backend is used which is that all services are primary.
"""
logger.debug("Creating a new service with uuid: {}".format(uuid))
service: BlessGATTServiceCoreBluetooth = BlessGATTServiceCoreBluetooth(uuid)
service: BlessGATTServiceCoreBluetooth = BlessGATTServiceCoreBluetooth(
uuid, primary
)
await service.init(self)
self.services[service.uuid] = service

Expand Down
11 changes: 7 additions & 4 deletions bless/backends/corebluetooth/service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from uuid import UUID
from typing import Union, Dict
from typing import Optional, Union, Dict

from CoreBluetooth import CBMutableService, CBUUID # type: ignore

Expand All @@ -16,16 +16,19 @@ class BlessGATTServiceCoreBluetooth(BaseBlessGATTService, BleakGATTService):
GATT Characteristic implementation for the CoreBluetooth backend
"""

def __init__(self, uuid: Union[str, UUID]):
def __init__(self, uuid: Union[str, UUID], primary: Optional[bool] = None):
"""
New Bless Service for macOS
Parameters
----------
uuid: Union[str, UUID]
The uuid to assign to the service
primary : Optional[bool]
True if this is a primary service, False otherwise. If None, default
behavior of the backend is used which is that all services are primary.
"""
BaseBlessGATTService.__init__(self, uuid)
BaseBlessGATTService.__init__(self, uuid, primary)
self.__handle = 0
self._characteristics: Dict[int, BlessGATTCharacteristic] = {} # type: ignore
self._cb_service = None
Expand All @@ -36,7 +39,7 @@ async def init(self, server: "BaseBlessServer"):
"""
service_uuid: CBUUID = CBUUID.alloc().initWithString_(self._uuid)
cb_service: CBMutableService = CBMutableService.alloc().initWithType_primary_(
service_uuid, True
service_uuid, True if self._primary is None else self._primary
)

# Store the CoreBluetooth service
Expand Down
5 changes: 4 additions & 1 deletion bless/backends/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,17 @@ async def is_advertising(self) -> bool:
raise NotImplementedError()

@abc.abstractmethod
async def add_new_service(self, uuid: str):
async def add_new_service(self, uuid: str, primary: Optional[bool] = None):
"""
Add a new GATT service to be hosted by the server
Parameters
----------
uuid : str
The UUID for the service to add
primary : Optional[bool]
True if this is a primary service, False otherwise. If None,
default behavior of the backend is used.
"""
raise NotImplementedError()

Expand Down
8 changes: 6 additions & 2 deletions bless/backends/service.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import abc

from uuid import UUID
from typing import List, Union, cast, TYPE_CHECKING
from typing import Optional, List, Union, cast, TYPE_CHECKING
from bleak.backends.service import BleakGATTService # type: ignore

if TYPE_CHECKING:
Expand All @@ -14,7 +14,7 @@ class BlessGATTService(BleakGATTService):
GATT Service object for Bless
"""

def __init__(self, uuid: Union[str, UUID]):
def __init__(self, uuid: Union[str, UUID], primary: Optional[bool] = None):
"""
Instantiates a new GATT Service but is not yet assigned to any
application
Expand All @@ -23,11 +23,15 @@ def __init__(self, uuid: Union[str, UUID]):
----------
uuid : Union[str, UUID]
The uuid of the service
primary : Optional[bool]
True if this is a primary service, False otherwise. If None, default
behavior of the backend is used.
"""
if type(uuid) is str:
uuid_str: str = cast(str, uuid)
uuid = UUID(uuid_str)
self._uuid: str = str(uuid)
self._primary = primary
self._characteristics: dict[int, BlessGATTCharacteristic] = {} # type: ignore

@abc.abstractmethod
Expand Down
9 changes: 7 additions & 2 deletions bless/backends/winrt/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,18 +232,23 @@ def _status_update(
if args is not None and args.status == 2:
self._advertising_started.set()

async def add_new_service(self, uuid: str):
async def add_new_service(self, uuid: str, primary: Optional[bool] = None):
"""
Generate a new service to be associated with the server
Parameters
----------
uuid : str
The string representation of the UUID of the service to be added
primary : Optional[bool]
True if this is a primary service, False otherwise. If None,
default behavior of the backend is used.
For WinRT, it seems to only allow primary services to be added so
this is currently unused.
"""
logger.debug("Creating a new service with uuid: {}".format(uuid))
logger.debug("Adding service to server with uuid {}".format(uuid))
service: BlessGATTServiceWinRT = BlessGATTServiceWinRT(uuid)
service: BlessGATTServiceWinRT = BlessGATTServiceWinRT(uuid, primary)
await service.init(self)
self.services[service.uuid] = service

Expand Down
9 changes: 7 additions & 2 deletions bless/backends/winrt/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,21 @@ class BlessGATTServiceWinRT(BaseBlessGATTService, BleakGATTService):
GATT Characteristic implementation for the WinRT backend
"""

def __init__(self, uuid: Union[str, UUID]):
def __init__(self, uuid: Union[str, UUID], primary: Optional[bool] = None):
"""
Initialize the Bless GATT Service object
Parameters
----------
uuid: Union[str, UUID]
The UUID to assign to the service
primary : Optional[bool]
True if this is a primary service, False otherwise. If None, default
behavior of the backend is used.
For WinRT, it seems to only allow primary services to be added so this
is currently unused.
"""
BaseBlessGATTService.__init__(self, uuid)
BaseBlessGATTService.__init__(self, uuid, primary)
self.service_provider: Optional[GattServiceProvider] = None
self._local_service: Optional[GattLocalService] = None
self._characteristics: Dict[int, BlessGATTCharacteristic] = {} # type: ignore
Expand Down