Пример #1
0
 def _connect(self,
              addr,
              addrType=btle.ADDR_TYPE_PUBLIC,
              iface=None,
              timeout=None):
     if len(addr.split(":")) != 6:
         raise ValueError("Expected MAC address, got %s" % repr(addr))
     if addrType not in (btle.ADDR_TYPE_PUBLIC, btle.ADDR_TYPE_RANDOM):
         raise ValueError(
             "Expected address type public or random, got {}".format(
                 addrType))
     self._startHelper(iface)
     self.addr = addr
     self.addrType = addrType
     self.iface = iface
     if iface is not None:
         self._writeCmd("conn %s %s %s\n" %
                        (addr, addrType, "hci" + str(iface)))
     else:
         self._writeCmd("conn %s %s\n" % (addr, addrType))
     rsp = self._getResp('stat', timeout)
     if rsp is None:
         raise btle.BTLEDisconnectError(
             "Timed out while trying to connect to peripheral %s, addr type: %s"
             % (addr, addrType), rsp)
     while rsp['state'][0] == 'tryconn':
         rsp = self._getResp('stat', timeout)
     if rsp['state'][0] != 'conn':
         self._stopHelper()
         raise btle.BTLEDisconnectError(
             "Failed to connect to peripheral %s, addr type: %s" %
             (addr, addrType), rsp)
Пример #2
0
    def _connect(self, addr, addrType=btle.ADDR_TYPE_PUBLIC, iface=None, timeout=5):
        """
        Temporary manual patch see https://github.com/IanHarvey/bluepy/pull/434
        also added a default `timeout` as this is not part yet of the release bluepy package
        """
        if len(addr.split(":")) != 6:
            raise ValueError("Expected MAC address, got %s" % repr(addr))
        if addrType not in (btle.ADDR_TYPE_PUBLIC, btle.ADDR_TYPE_RANDOM):
            raise ValueError("Expected address type public or random, got {}".format(addrType))
        self._startHelper(iface)
        self.addr = addr
        self.addrType = addrType
        self.iface = iface
        if iface is not None:
            self._writeCmd("conn %s %s %s\n" % (addr, addrType, "hci"+str(iface)))
        else:
            self._writeCmd("conn %s %s\n" % (addr, addrType))
        rsp = self._getResp('stat', timeout)
        if rsp is None:
            self._stopHelper()
            raise btle.BTLEDisconnectError("Timed out while trying to connect to peripheral %s, addr type: %s" %
                                      (addr, addrType), rsp)
        while rsp and rsp['state'][0] == 'tryconn':
            rsp = self._getResp('stat', timeout)

        if rsp is None:
            self._stopHelper()
            raise btle.BTLEDisconnectError("Timed out while trying to connect to peripheral %s, addr type: %s" %
                                      (addr, addrType), rsp)

        if rsp['state'][0] != 'conn':
            self._stopHelper()
            raise btle.BTLEDisconnectError("Failed to connect to peripheral %s, addr type: %s [%s]" % (addr, addrType, rsp), rsp)
Пример #3
0
    def btle_connection(self):
        """Contextmanager to handle a bluetooth connection to Comet Blue device.
        Any problem that arises when using the connection, will be handled,
        the connection closed and any resources aquired released.
        Debug logging for analysis is integrated, the errors are raised to be
        handled by the user.

        The following aspects are managed:
        * Connect handles setup, preparations for read/write and authentication.
        * Read/Write error handling.
        * Disconnect handles proper releasing of any aquired resources.
        """
        conn = self._connect()
        self.available = True
        try:
            yield conn
        except btle.BTLEException as ex:
            _LOGGER.debug(
                "Couldn't read/write cometblue data for device %s:\n%s",
                self._address, ex)
            self.available = False
            raise
        except BrokenPipeError as ex:
            _LOGGER.debug("Device %s BrokenPipeError: %s", self._address, ex)
            self.available = False
            raise btle.BTLEDisconnectError() from ex
        finally:
            self._disconnect(conn)
Пример #4
0
 def _disconnect(self, connection):
     """Disconnect from thermostat"""
     try:
         connection.disconnect()
     except (btle.BTLEException, BrokenPipeError) as ex:
         _LOGGER.debug("Couldn't disconnect from device %s:\n%s",
                       self._address, ex)
         raise btle.BTLEDisconnectError() from ex
     else:
         _LOGGER.debug("Disconnected from device %s", self._address)
Пример #5
0
    def _waitResp(self, wantType, timeout=None):
        while True:
            if self._helper.poll() is not None:
                raise btle.BTLEInternalError("Helper exited")

            if timeout:
                logger.debug("_waitResp - set timeout to %d", timeout)
                fds = self._poller.poll(timeout * 1000)
                if len(fds) == 0:
                    logger.debug("Select timeout")
                    return None

            rv = self._helper.stdout.readline()
            if rv.startswith('#') or rv == '\n' or len(rv) == 0:
                continue

            resp = btle.BluepyHelper.parseResp(rv)
            if 'rsp' not in resp:
                raise btle.BTLEInternalError("No response type indicator",
                                             resp)

            respType = resp['rsp'][0]
            if respType in wantType:
                logger.debug("_waitResp - resp [%s]", resp)
                return resp
            elif respType == 'stat':
                if 'state' in resp and len(
                        resp['state']) > 0 and resp['state'][0] == 'disc':
                    self._stopHelper()
                    raise btle.BTLEDisconnectError("Device disconnected", resp)
            elif respType == 'err':
                errcode = resp['code'][0]
                if errcode == 'nomgmt':
                    raise btle.BTLEManagementError(
                        "Management not available (permissions problem?)",
                        resp)
                elif errcode == 'atterr':
                    raise btle.BTLEGattError("Bluetooth command failed", resp)
                else:
                    raise btle.BTLEException(
                        "Error from bluepy-helper (%s)" % errcode, resp)
            elif respType == 'scan':
                # Scan response when we weren't interested. Ignore it
                continue
            else:
                raise btle.BTLEInternalError(
                    "Unexpected response (%s)" % respType, resp)
Пример #6
0
    def _disconnect(self):
        """Disconnect from the weather station.  If we are not already
        connected, raise a btle.BTLEDisconnectError exception.

        This method is called by most other methods if an exception is
        caught, whilst they're doing anything, to avoid jamming the
        Bluetooth stack on the weather station.
        """

        if not self._station:
            raise btle.BTLEDisconnectError(
                "already disconnected from weather station")

        self._station.disconnect()
        self._station = None

        logging.debug("disconnected from weather station: %s", self._mac)
Пример #7
0
    def _connect(self):
        """This method connects to the weather station.

        If the weather station is already connected, it will be
        disconnected (to avoid jamming up a station's Bluetooth stack)
        and a btle.BTLEDisconnectError exception raised.
        """

        # if the station is already connected, disconnect and raise exception

        if self._station:
            self._disconnect()

            raise btle.BTLEDisconnectError(
                "already connected to weather station: %s" % self._mac)

        # connect to the station

        logging.debug("connecting to weather station: %s", self._mac)

        try:
            self._station = btle.Peripheral(self._mac, btle.ADDR_TYPE_RANDOM)

        except btle.BTLEDisconnectError:
            logging.debug("error connecting to weather station")
            raise

        # set up the notification delegate

        try:
            self._station.withDelegate(_WeatherStationDelegate())

        except btle.BTLEDisconnectError:
            self._disconnect()

            logging.debug("error setting notification delegate for station")
            raise

        logging.debug("connected to weather station: %s", self._mac)