Exemplo n.º 1
0
Arquivo: client.py Projeto: h4/bleak
    async def connect(self) -> bool:
        """Connect to the specified GATT server.

        Returns:
            Boolean representing connection status.

        """

        # A Discover must have been run before connecting to any devices. Do a quick one here
        # to ensure that it has been done.
        await discover(timeout=0.1, loop=self.loop)

        # Create system bus
        self._bus = await txdbus_connect(
            reactor, busAddress="system").asFuture(self.loop)
        # TODO: Handle path errors from txdbus/dbus
        self._device_path = get_device_object_path(self.device, self.address)

        def _services_resolved_callback(message):
            iface, changed, invalidated = message.body
            is_resolved = defs.DEVICE_INTERFACE and changed.get(
                "ServicesResolved", False)
            if iface == is_resolved:
                logger.info("Services resolved.")
                self.services_resolved = True

        rule_id = await signals.listen_properties_changed(
            self._bus, self.loop, _services_resolved_callback)

        logger.debug("Connecting to BLE device @ {0} with {1}".format(
            self.address, self.device))
        try:
            await self._bus.callRemote(
                self._device_path,
                "Connect",
                interface="org.bluez.Device1",
                destination="org.bluez",
            ).asFuture(self.loop)
        except RemoteError as e:
            raise BleakError(str(e))

        if await self.is_connected():
            logger.debug("Connection successful.")
        else:
            raise BleakError("Connection to {0} was not successful!".format(
                self.address))

        # Get all services. This means making the actual connection.
        await self.get_services()
        properties = await self._get_device_properties()
        if not properties.get("Connected"):
            raise BleakError("Connection failed!")

        await self._bus.delMatch(rule_id).asFuture(self.loop)
        self._rules["PropChanged"] = await signals.listen_properties_changed(
            self._bus, self.loop, self._properties_changed_callback)
        return True
Exemplo n.º 2
0
    async def connect(self, **kwargs) -> bool:
        """Connect to the specified GATT server.

        Keyword Args:
            timeout (float): Timeout for required ``discover`` call. Defaults to 2.0.

        Returns:
            Boolean representing connection status.

        """
        # A Discover must have been run before connecting to any devices. Do a quick one here
        # to ensure that it has been done.
        timeout = kwargs.get("timeout", self._timeout)
        discovered = await discover(timeout=timeout,
                                    device=self.device,
                                    loop=self.loop)

        # Issue 150 hints at the device path not being possible to create as
        # is done in the `get_device_object_path` method. Try to get it from
        # BlueZ instead.
        # Otherwise, use the old fallback and hope for the best.
        bluez_devices = list(
            filter(lambda d: d.address.lower() == self.address.lower(),
                   discovered))
        if bluez_devices:
            self._device_path = bluez_devices[0].details["path"]
        else:
            # TODO: Better to always get path from BlueZ backend...
            self._device_path = get_device_object_path(self.device,
                                                       self.address)

        self._reactor = get_reactor(self.loop)

        # Create system bus
        self._bus = await txdbus_connect(
            self._reactor, busAddress="system").asFuture(self.loop)

        def _services_resolved_callback(message):
            iface, changed, invalidated = message.body
            is_resolved = defs.DEVICE_INTERFACE and changed.get(
                "ServicesResolved", False)
            if iface == is_resolved:
                logger.info("Services resolved.")
                self.services_resolved = True

        rule_id = await signals.listen_properties_changed(
            self._bus, self.loop, _services_resolved_callback)

        logger.debug("Connecting to BLE device @ {0} with {1}".format(
            self.address, self.device))
        try:
            await self._bus.callRemote(
                self._device_path,
                "Connect",
                interface="org.bluez.Device1",
                destination="org.bluez",
            ).asFuture(self.loop)
        except RemoteError as e:
            await self._cleanup_all()
            if 'Method "Connect" with signature "" on interface' in str(e):
                raise BleakError(
                    "Device with address {0} could not be found. "
                    "Try increasing `timeout` value or moving the device closer."
                    .format(self.address))
            else:
                raise BleakError(str(e))

        if await self.is_connected():
            logger.debug("Connection successful.")
        else:
            await self._cleanup_all()
            raise BleakError("Connection to {0} was not successful!".format(
                self.address))

        # Get all services. This means making the actual connection.
        await self.get_services()
        properties = await self._get_device_properties()
        if not properties.get("Connected"):
            await self._cleanup_all()
            raise BleakError("Connection failed!")

        await self._bus.delMatch(rule_id).asFuture(self.loop)
        self._rules["PropChanged"] = await signals.listen_properties_changed(
            self._bus, self.loop, self._properties_changed_callback)
        return True