65 lines
2.2 KiB
Python
65 lines
2.2 KiB
Python
from concurrent.futures import ProcessPoolExecutor
|
|
from logging import getLogger
|
|
from typing import Dict, List, Optional
|
|
|
|
import bluetooth
|
|
|
|
from platypush.entities.bluetooth import BluetoothService
|
|
|
|
from .._model import BluetoothServicesBuilder
|
|
|
|
|
|
# pylint: disable=too-few-public-methods
|
|
class ServiceDiscoverer:
|
|
"""
|
|
Runs the service discovery processes in a pool.
|
|
"""
|
|
|
|
def __init__(self, max_workers: int = 4, timeout: float = 30):
|
|
self._max_workers = max_workers
|
|
self._timeout = timeout
|
|
self.logger = getLogger(__name__)
|
|
|
|
def _discover(self, address: str) -> List[BluetoothService]:
|
|
"""
|
|
Inner implementation of the service discovery for a specific device.
|
|
"""
|
|
self.logger.info("Discovering services for %s...", address)
|
|
try:
|
|
return BluetoothServicesBuilder.build(
|
|
bluetooth.find_service(address=address)
|
|
)
|
|
except Exception as e:
|
|
self.logger.warning(
|
|
"Failed to discover services for the device %s: %s", address, e
|
|
)
|
|
return []
|
|
finally:
|
|
self.logger.info("Service discovery for %s completed", address)
|
|
|
|
def discover(
|
|
self, *addresses: str, timeout: Optional[float] = None
|
|
) -> Dict[str, List[BluetoothService]]:
|
|
"""
|
|
Discover the services for the given addresses. Discovery will happen in
|
|
parallel through a process pool.
|
|
|
|
:param addresses: The addresses to scan.
|
|
:param timeout: The timeout in seconds.
|
|
:return: An ``{address: [services]}`` dictionary with the discovered
|
|
services per device.
|
|
"""
|
|
discovered_services: Dict[str, List[BluetoothService]] = {}
|
|
with ProcessPoolExecutor(max_workers=self._max_workers) as executor:
|
|
try:
|
|
for i, services in enumerate(
|
|
executor.map(
|
|
self._discover, addresses, timeout=timeout or self._timeout
|
|
)
|
|
):
|
|
discovered_services[addresses[i]] = services
|
|
except TimeoutError:
|
|
self.logger.warning("Service discovery timed out.")
|
|
|
|
return discovered_services
|