def bleServiceScan(address, adapter, addressType, securityLevel):
    """
    Used by command line tool to initiate and print results for
    a scan of all services and
    characteristics present on a BTLE device.

    :param address: Address of target BTLE device
    :param adapter: Host adapter (Empty string to use host's default adapter)
    :param addressType: Type of address you want to connect to [public | random]
    :param securityLevel: Security level [low | medium | high]
    :type address: str
    :type adapter: str
    :type addressType: str
    :type securityLevel: str
    :return:
    """
    if address is None:
        raise Exception(
            "%s Bluetooth address is not valid. Please supply a valid Bluetooth address value."
            % address)

    connectionManager = bleConnectionManager.BLEConnectionManager(
        address, adapter, addressType, securityLevel)
    bleDevice = bleServiceManager.bleServiceDiscovery(address,
                                                      connectionManager)
    bleDevice.printDeviceStructure()
def bleRunSmartScan(address, adapter, addressType, securityLevel):
    """
    Used by command line tool to initiate and print results for
    a scan of all services,
    characteristics, and descriptors present on a BTLE device.

    :param address: Address of target BTLE device
    :param adapter: Host adapter (Empty string to use host's default adapter)
    :param addressType: Type of address you want to connect to [public | random]
    :param securityLevel: Security level [low | medium | high]
    :type address: str
    :type adapter: str
    :type addressType: str
    :type securityLevel: str
    :return:
    """
    if address is None:
        raise Exception(
            "%s Bluetooth address is not valid. Please supply a valid Bluetooth address value."
            % address)

    connectionManager = bleConnectionManager.BLEConnectionManager(
        address, adapter, addressType, securityLevel)
    bleDevice = bleSmartScan.bleSmartScan(address, connectionManager)

    print "**********************"
    print "Smart Scan Results"
    print "**********************"
    #print"BD_ADDR:", args.addr[0], "\n"

    #Print services and characteristics with data in between
    bleDevice.printDeviceStructure()

    print "**********************"
    print "Finished"
    print "**********************"
def bleServiceReadAsync(address,
                        adapter,
                        addressType,
                        securityLevel,
                        handles,
                        UUIDS,
                        maxTries=5,
                        timeout=5):
    """
    Used by command line tool to read data from device by handle using the async
    method. As of now, errors are not returned when reading asynchronously, so a
    timeout must be specified to determine when we should stop looking for a response
    from a device. (Note: This call is blocking until responses are received or a timeout
    is reached).

    :param address: Address of target BTLE device
    :param adapter: Host adapter (Empty string to use host's default adapter)
    :param addressType: Type of address you want to connect to [public | random]
    :param securityLevel: Security level [low | medium | high]
    :param handles: List of handles to read from
    :param UUIDS: List of UUIDs to read from
    :param maxTries: Maximum number of times to attempt each write operation. Default: 5
    :param timeout: Time (in seconds) until each read times out if there's an issue. Default: 5
    :type address: str
    :type adapter: str
    :type addressType: str
    :type securityLevel: str
    :type handles: list of base 10 ints
    :type UUIDS: list of strings
    :type maxTries: int
    :type timeout: int
    :return: uuidData, handleData
    :rtype: list of (UUID, data) tuples and list of (handle, data) tuples
    """
    import time

    def asyncHandleCallback(data):
        #print "\nHandle:", "0x" + handle
        #"".join("{:02x}".format(ord(c)) for c in handle)
        logger.debug("Raw callback data: %s" % data)
        utils.printHelper.printDataAndHex([data], False)

    logger.debug("Creating connection manager")
    connectionManager = bleConnectionManager.BLEConnectionManager(
        address, adapter, addressType, securityLevel)
    #connectionManager.createResponse(responseFunction=asyncHandleCallback)
    #connectionManager.createResponse()
    connectionManager.connect()
    logger.debug("Connected")
    uuidResponses = []
    handleResponses = []

    handleResponseQueue = []
    uuidResponseQueue = []
    for handle in handles:
        if handle is not None:
            tries = 0
            while True:
                try:
                    if not connectionManager.isConnected():
                        connectionManager.connect()
                    resp = bleServiceManager.bleServiceReadByHandleAsync(
                        connectionManager, int(handle, 16), None)
                    handleResponseQueue.append((handle, resp, time.time()))
                    break
                except RuntimeError as e:
                    if "Invalid handle" in str(e):
                        handleResponses.append((handle, ["Invalid handle"]))
                        break
                    elif "Attribute can't" in str(e):
                        handleResponses.append(
                            (handle, ["Attribute can't be read"]))
                        break
                    else:
                        if tries >= maxTries:
                            logger.debug(
                                "%s Tries exceeded, throwing Runtime error and aborting write"
                                % maxTries)
                            raise RuntimeError(e)
                        else:
                            logger.debug("Error: %s Trying Again" % e)
                            tries += 1
    for UUID in UUIDS:
        if UUID is not None:
            tries = 0
            while True:
                try:
                    if not connectionManager.isConnected():
                        connectionManager.connect()
                    resp = bleServiceManager.bleServiceReadByUUIDAsync(
                        connectionManager, UUID)
                    uuidResponseQueue.append((UUID, resp, time.time()))
                    break
                except RuntimeError as e:
                    if "Invalid handle" in str(e):
                        uuidResponses.append((UUID, ["Invalid UUID"]))
                        break
                    elif "Attribute can't" in str(e):
                        uuidResponses.append(
                            (UUID, ["Attribute can't be read"]))
                        break
                    else:
                        if tries >= maxTries:
                            logger.debug(
                                "%s Tries exceeded, throwing Runtime error and aborting write"
                                % maxTries)
                            raise RuntimeError(e)
                        else:
                            logger.debug("Error: %s Trying Again" % e)
                            tries += 1
    #returns list of tuples (handle, data)
    while True:
        for i in handleResponseQueue:
            if i[1][1].received():
                data = i[1][1].received()
                logger.debug("Handle: %s Received data: %s" % (i[0], data))
                handleResponses.append((i[0], i[1]))
                handleResponseQueue.remove(i)
            elif time.time() - i[2] >= timeout:
                handleResponses.append(
                    (i[0], ["Error: Timeout reached for action"]))
                handleResponseQueue.remove(i)
            logger.debug("Response creation time: %s current time: %s" %
                         (i[2], time.time()))
            #utils.printHelper.printDataAndHex()
            #handleResponses.remove(i)
            #connectionManager.responses.remove(i[1])
            #if not i.is_alive():
            #    handleThreads.remove(i)
        for i in uuidResponseQueue:
            if i[1][1].received():
                data = i[1][1].received()
                handle = data[:2][::-1]
                data = data[2:]
                logger.debug("UUID: %s HANDLE: %s Received data: %s" %
                             (i[0], handle, data))
                uuidResponses.append((i[0], i[1], handle))
                uuidResponseQueue.remove(i)
            elif time.time() - i[2] >= timeout:
                uuidResponses.append(
                    (i[0], ["Error: Timeout reached for action"]))
                uuidResponseQueue.remove(i)
            logger.debug("Response creation time: %s current time: %s" %
                         (i[2], time.time()))
        if len(handleResponseQueue) <= 0 and len(uuidResponseQueue) <= 0:
            logger.debug("Out of responses")
            break
        logger.debug("Number of responses that haven't received: %s" %
                     (len(handleResponseQueue) + len(uuidResponseQueue)))
        time.sleep(0.1)

    return uuidResponses, handleResponses
def bleHandleSubscribe(address, handles, adapter, addressType, securityLevel,
                       mode):
    """
    Used by command line tool to enable specified handles' notify mode
    and listen until user interrupts.

    :param address: Address of target BTLE device
    :param handles: List of handle descriptors to write 0100 (enable notification) to
    :param adapter: Host adapter (Empty string to use host's default adapter)
    :param addressType: Type of address you want to connect to [public | random]
    :param securityLevel: Security level [low | medium | high]
    :param mode: Mode to set for characteristic configuration (0=off,1=notifications,2=indications,
    3=notifications and inidications)
    :type address: str
    :type handles: list of base 10 ints
    :type adapter: str
    :type addressType: str
    :type securityLevel: str
    :type mode: int
    :return:
    """
    logger.debug("Beginning Subscribe Function")
    if address is None:
        raise Exception(
            "%s Bluetooth address is not valid. Please supply a valid Bluetooth address value."
            % address)

    if mode == 0:
        configVal = str(bytearray([00, 00]))
    elif mode == 1:
        configVal = str(bytearray([01, 00]))
    elif mode == 2:
        configVal = str(bytearray([02, 00]))
    elif mode == 3:
        configVal = str(bytearray([03, 00]))
    else:
        raise Exception(
            "%s is not a valid mode. Please supply a value between 0 and 3 (inclusive)"
            % mode)

    class Requester(GATTRequester):
        def __init__(self, *args):
            GATTRequester.__init__(self, *args)

        def on_notification(self, originHandle, data):
            print "\nNotification on Handle"
            print "======================="
            print format(originHandle, "#8x")
            utils.printHelper.printDataAndHex([data], False)
            #self.wakeup.set()

        def on_indication(self, originHandle, data):
            print "\nIndication on Handle"
            print "======================="
            print format(originHandle, "#8x")
            utils.printHelper.printDataAndHex([data], False)
            #self.wakeup.set()

    class ReceiveNotification(object):
        def __init__(self, connectionManager, handles, configVal):
            logger.debug("Initializing receiver")
            self.connectionManager = connectionManager
            self.configVal = configVal
            self.handles = handles
            self.wait_notification()

        def connect(self):
            logger.debug("Connecting...")
            sys.stdout.flush()

            self.connectionManager.connect()
            #self.requester.connect(True)
            logger.debug("OK!")

        def wait_notification(self):
            print "Listening for communications"
            logger.debug("Listening for communications")
            #self.received.wait()
            while True:
                if self.connectionManager.isConnected():
                    continue
                logger.debug("Connection Lost, re-connecting subscribe")
                self.connectionManager.connect()
                for i in self.handles:
                    bleServiceManager.bleServiceWriteToHandle(
                        connectionManager, int(i, 16), self.configVal)

    #print "About to try to receive"

    connectionManager = bleConnectionManager.BLEConnectionManager(
        address, adapter, addressType, securityLevel, createRequester=False)
    #Special requester that has an overridden on_notification handler
    requester = Requester(address, False)
    connectionManager.setRequester(requester)
    connectionManager.connect()
    for handle in handles:
        logger.debug("Writing %s to handle %s" % (configVal, handle))
        try:
            bleServiceManager.bleServiceWriteToHandle(connectionManager,
                                                      int(handle, 16),
                                                      configVal)
        except RuntimeError as e:
            if "Invalid handle" in str(e):
                data = -1
            elif "Attribute can't be read" in str(e):
                data = -2
            else:
                raise RuntimeError(e)

    ReceiveNotification(connectionManager, handles, configVal)
def bleServiceWrite(address,
                    adapter,
                    addressType,
                    securityLevel,
                    handles,
                    inputs,
                    maxTries=5):
    """
    Used by command line tool to wrtie data to a device handle

    :param address: Address of target BTLE device
    :param adapter: Host adapter (Empty string to use host's default adapter)
    :param addressType: Type of address you want to connect to [public | random]
    :param securityLevel: Security level [low | medium | high]
    :param handles: List of handles to write to
    :param inputs: List of strings to write to handles
    :param maxTries: Maximum number of times to attempt each write operation. Default: 5
    :type address: str
    :type adapter: str
    :type addressType: str
    :type securityLevel: str
    :type handles: list of base 10 ints
    :type inputs: list of strings
    :type maxTries: int
    :return: list of (handle, data, input)
    :rtype: list of tuples (int, str, str)
    """
    connectionManager = bleConnectionManager.BLEConnectionManager(
        address, adapter, addressType, securityLevel)
    connectionManager.connect()
    #print "Input:",input
    handleData = []
    for inputVal in inputs:
        for handle in handles:
            if handle is not None:
                tries = 0
                while True:
                    try:
                        if not connectionManager.isConnected():
                            connectionManager.connect()
                        data = bleServiceManager.bleServiceWriteToHandle(
                            connectionManager, int(handle, 16), inputVal)
                        break
                    except RuntimeError as e:
                        if "Invalid handle" in str(e):
                            data = -1
                            break
                        elif "Attribute can't" in str(e):
                            data = -2
                            break
                        else:
                            if tries >= maxTries:
                                logger.debug(
                                    "%s Tries exceeded, throwing Runtime error and aborting write"
                                    % maxTries)
                                raise RuntimeError(e)
                            else:
                                logger.debug("Error: %s Trying Again" % e)
                                tries += 1
                handleData.append((handle, data, inputVal))
    return handleData
def bleServiceRead(address,
                   adapter,
                   addressType,
                   securityLevel,
                   handles,
                   UUIDS,
                   maxTries=5):
    """
    Used by command line tool to read data from device by handle

    :param address: Address of target BTLE device
    :param adapter: Host adapter (Empty string to use host's default adapter)
    :param addressType: Type of address you want to connect to [public | random]
    :param securityLevel: Security level [low | medium | high]
    :param handles: List of handles to read from
    :param UUIDS: List of UUIDs to read from
    :param maxTries: Maximum number of times to attempt each write operation. Default: 5
    :type address: str
    :type adapter: str
    :type addressType: str
    :type securityLevel: str
    :type handles: list of base 10 ints
    :type UUIDS: list of strings
    :type maxTries: int
    :return: uuidData, handleData
    :rtype: list of (UUID, data) tuples and list of (handle, data) tuples
    """
    connectionManager = bleConnectionManager.BLEConnectionManager(
        address, adapter, addressType, securityLevel)
    connectionManager.connect()
    uuidData = []
    handleData = []
    for handle in handles:
        if handle is not None:
            tries = 0
            while True:
                try:
                    if not connectionManager.isConnected():
                        connectionManager.connect()
                    data = bleServiceManager.bleServiceReadByHandle(
                        connectionManager, int(handle, 16))
                    break
                except RuntimeError as e:
                    if "Invalid handle" in str(e):
                        data = -1
                        break
                    elif "Attribute can't be read" in str(e):
                        data = -2
                        break
                    else:
                        if tries >= maxTries:
                            raise RuntimeError(e)
                        else:
                            tries += 1
                #print "\nHandle:", format(ord(binascii.unhexlify(handle)), "#8x")
                #printDataAndHex(data, 10)
            handleData.append((handle, data))
    for UUID in UUIDS:
        if UUID is not None:
            tries = 0
            while True:
                try:
                    if not connectionManager.isConnected():
                        connectionManager.connect()
                    data, handle = bleServiceManager.bleServiceReadByUUID(
                        connectionManager, UUID)
                    break
                except RuntimeError as e:
                    if "Invalid handle" in str(e):
                        data = -1
                        break
                    elif "Attribute can't be read" in str(e):
                        data = -2
                        break
                    else:
                        if tries >= maxTries:
                            raise RuntimeError(e)
                        else:
                            tries += 1
            #print "\nUUID:", UUID
            #printDataAndHex(data, 10)
            uuidData.append((UUID, handle, data))
    #returns list of tuples (handle, data)
    return uuidData, handleData
Exemple #7
0
 def __init__(self, address, adapter, addressType, securityLevel, createRequester, psm=0, mtu=0):
     """ Create an instance of BLE Manager """
     self.address = address
     self.cm = bleConnectionManager.BLEConnectionManager(address, adapter, addressType, securityLevel)
     self.sm = BLEServiceManager(self.cm, self.address)