def ble_service_read(address, adapter, addressType, handles, UUIDS, timeout):
    """
    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
    """
    with connection_manager.BLEConnectionManager(
            adapter, 'central') as connectionManager:
        connection = connectionManager.init_connection(address, addressType)
        success = connectionManager.connect(connection)
        if not success:
            print("Failed to connected to target device")
            return

        uuidData = []
        handleData = []
        for handle in handles:
            if handle is not None:
                tries = 0
                if not connectionManager.is_connected(connection):
                    connectionManager.connect(connection)
                req = connectionManager.gatt_read_handle(connection,
                                                         int(handle, 16),
                                                         timeout=timeout)

                if req.has_error():
                    handleData.append((handle, req.get_error_message()))
                else:
                    handleData.append((handle, req.response.data))
        for UUID in UUIDS:
            if UUID is not None:
                tries = 0
                if not connectionManager.is_connected(connection):
                    connectionManager.connect(connection)
                req = connectionManager.gatt_read_uuid(connection,
                                                       UUID,
                                                       timeout=timeout)

                if req.has_error():
                    uuidData.append((UUID, req.get_error_message()))
                else:
                    uuidData.append((UUID, req.response.data))

    # returns list of tuples (handle, data)
    return uuidData, handleData
def ble_service_scan(address, adapter, addressType):
    """
    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)
    with connection_manager.BLEConnectionManager(
            adapter, 'central') as connectionManager:
        connection = connectionManager.init_connection(address, addressType)
        success = connectionManager.connect(connection)
        if not success:
            print("Failed to connected to target device")
            return

        device = connectionManager.gatt_discover_primary_services(connection)
        device = connectionManager.gatt_discover_characteristics(connection,
                                                                 device=device)
        device = connectionManager.gatt_discover_descriptors(connection,
                                                             device=device)

    device.print_device_structure()
Exemple #3
0
def ble_run_smart_scan(address, adapter, addressType, skip_device_info_query=False, attempt_read=True,
                       timeout=None):
    """
    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:/usr/lib/python2.7/json/decoder.py
    """
    if address is None:
        raise Exception("%s Bluetooth address is not valid. Please supply a valid Bluetooth address value." % address)

    with connection_manager.BLEConnectionManager(adapter, 'central') as connectionManager:
        logger.debug("ConnectionManager available")
        connection = connectionManager.init_connection(address, addressType)
        success = connectionManager.connect(connection)
        if not success:
            print "Failed to connected to target device"
            return None
        logger.debug("Connected!")
        device = connectionManager.smart_scan(connection, device=None,
                                              look_for_device_info=(not skip_device_info_query),
                                              attempt_desc_read=attempt_read, timeout=timeout)
    return device
Exemple #4
0
def general_scan(adapter=0, timeout=50):
    """
    Scan for BTLE Devices and print out results
    :param timeout: Scan timeout (seconds)
    :param adapter: Host adapter to use for scanning (Use empty string to use host's default adapter)
    :type timeout: int
    :type adapter: str
    :return: Discovered devices ({<address>:(<addressType>, <data>)})
    :rtype: dict
    """
    if timeout < 0:
        raise Exception(
            "%s is an invalid scan timeout value. The timeout must be a positive integer"
            % timeout)

    with connection_manager.BLEConnectionManager(
            adapter, "central") as connectionManager:
        connectionManager.start_scan()
        start = time.time() * 1000
        logger.debug("Starting sleep loop")
        while ((time.time() * 1000) - start) < (timeout * 1000):
            logger.debug("Scanning...")
            gevent.sleep(1)
            connectionManager.stop_scan()
        logger.debug("Done scanning!")
        discovered_devices = connectionManager.get_discovered_devices()

    return discovered_devices
def ble_service_write(address, adapter, addressType, handles, inputs, timeout):
    """
    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)
    """
    with connection_manager.BLEConnectionManager(
            adapter, 'central') as connectionManager:
        connection = connectionManager.init_connection(address, addressType)
        success = connectionManager.connect(connection)
        if not success:
            print("Failed to connected to target device")
            return
        handleData = []
        for inputVal in inputs:
            for handle in handles:
                if handle is not None:
                    tries = 0

                    if not connectionManager.is_connected(connection):
                        connectionManager.connect(connection)
                    req = connectionManager.gatt_write_handle(connection,
                                                              int(handle, 16),
                                                              inputVal,
                                                              timeout=timeout)
                    if req.has_error():
                        handleData.append(
                            (handle, req.get_error_message(), inputVal))
                    else:
                        handleData.append(
                            (handle, req.response.data, inputVal))
    return handleData
Exemple #6
0
def scan_device(adapter,
                address,
                address_type="random",
                skip_device_info_query=False,
                attempt_read=False,
                timeout=None):
    with connection_manager.BLEConnectionManager(
            adapter, 'central') as connectionManager:
        print "Smart scanning for clone"
        connection = connectionManager.init_connection(address, address_type)
        success = connectionManager.connect(connection)
        if not success:
            print "Failed to connected to target device"
            return None
        target_device = connectionManager.smart_scan(
            connection,
            device=None,
            look_for_device_info=(not skip_device_info_query),
            attempt_desc_read=attempt_read,
            timeout=timeout)
        return target_device
def ble_service_read_async(address,
                           adapter,
                           addressType,
                           handles,
                           UUIDS,
                           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
    import gevent

    with connection_manager.BLEConnectionManager(
            adapter, 'central') as connectionManager:
        connection = connectionManager.init_connection(address, addressType)
        success = connectionManager.connect(connection)
        if not success:
            print("Failed to connected to target device")
            return

        uuidRequests = []
        handleRequests = []

        handleRequestQueue = []
        uuidRequestQueue = []
        for handle in handles:
            if handle is not None:
                tries = 0
                if not connectionManager.is_connected(connection):
                    connectionManager.connect(connection)
                logger.debug("Attempting to read from handle: %s" % handle)
                req = connectionManager.gatt_read_handle_async(connection,
                                                               int(handle, 16),
                                                               timeout=timeout)
                handleRequestQueue.append((handle, req, req.creation_time))

        for UUID in UUIDS:
            if UUID is not None:
                tries = 0
                if not connectionManager.is_connected(connection):
                    connectionManager.connect(connection)
                logger.debug("Attempting to read from UUID: %s" % UUID)
                req = connectionManager.gatt_read_uuid_async(connection,
                                                             UUID,
                                                             timeout=timeout)
                uuidRequestQueue.append((UUID, req, req.creation_time))

        #returns list of tuples (handle, data)
        while True:
            for i in handleRequestQueue:
                req = i[1]
                if req.has_response():
                    data = req.response.data
                    logger.debug("Handle: %s Received data: %s" % (i[0], data))
                    handleRequests.append((i[0], data))
                    handleRequestQueue.remove(i)
                elif req.has_error():
                    error = req.get_error_message()
                    logger.debug("Handle: %s Error message: %s" %
                                 (i[0], error))
                    handleRequests.append((i[0], error))
                    handleRequestQueue.remove(i)
                logger.debug("Response creation time: %s current time: %s" %
                             (i[2], time.time()))
            for i in uuidRequestQueue:
                req = i[1]
                if req.has_response():
                    data = req.response.data
                    logger.debug("UUID: %s Received data: %s" % (i[0], data))
                    uuidRequests.append((i[0], data))
                    uuidRequestQueue.remove(i)
                elif req.has_error():
                    error = req.get_error_message()
                    uuidRequests.append((i[0], error))
                    uuidRequestQueue.remove(i)
                logger.debug("Response creation time: %s current time: %s" %
                             (i[2], time.time()))
            if len(handleRequestQueue) <= 0 and len(uuidRequestQueue) <= 0:
                logger.debug("Out of responses")
                break
            logger.debug("Number of responses that haven't received: %s" %
                         (len(handleRequestQueue) + len(uuidRequestQueue)))
            gevent.sleep(0.1)

    return uuidRequests, handleRequests
def ble_handle_subscribe(address,
                         handles,
                         adapter,
                         addressType,
                         mode,
                         listenTime=None):
    """
    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:
    """
    import time
    import gevent
    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([0o1, 00]))
    elif mode == 2:
        configVal = str(bytearray([0o2, 00]))
    elif mode == 3:
        configVal = str(bytearray([0o3, 00]))
    else:
        raise Exception(
            "%s is not a valid mode. Please supply a value between 0 and 3 (inclusive)"
            % mode)

    class EventHandler(event_handler.BTEventHandler):
        def __init__(self, connection_manager):
            event_handler.BTEventHandler.__init__(self, connection_manager)
            self.connectionManager = connection_manager

        def on_att_event(self, connection_handle, data):
            from blesuite.pybt.att import ATT_PDU_OPCODE_BY_NAME
            if data.opcode == 0x1b:  #notification
                print("\nNotification on Handle %s" % hex(data.gatt_handle))
                print("=======================")
                #print format(originHandle, "#8x")
                print_helper.print_data_and_hex([data.value], False)
            elif data.opcode == 0x1d:  #indication
                print("\nIndication on Handle %s" % hex(data.gatt_handle))
                print("=======================")
                print_helper.print_data_and_hex([data.value], False)

    with connection_manager.BLEConnectionManager(
            adapter, 'central') as connectionManager:
        connection = connectionManager.init_connection(address, addressType)
        success = connectionManager.connect(connection)
        if not success:
            print("Failed to connected to target device")
            return
        connectionManager.set_event_handler(EventHandler(connectionManager))

        for handle in handles:
            connectionManager.gatt_write_handle(connection, int(handle, 16),
                                                configVal)
        start = time.time() * 1000
        while True:
            if connectionManager.is_connected(connection):
                if listenTime is not None:
                    if ((time.time() * 1000) - start) >= listenTime:
                        break
                gevent.sleep(.1)
                continue
            logger.debug("Connection Lost, re-connecting subscribe")
            connectionManager.connect(connection)
            for i in handles:
                connectionManager.gatt_write_handle(connection, int(i, 16),
                                                    configVal)

            if listenTime is not None:
                if ((time.time() * 1000) - start) >= listenTime:
                    break
            gevent.sleep(.1)
Exemple #9
0
def advertise(adapter, peripheral, data):
    with connection_manager.BLEConnectionManager(
            adapter, 'peripheral') as connectionManager:
        #peripheral, advertising_data_list = load_device(address)
        #ret = bdaddr.bdaddr(("hci"+str(adapter)), peripheral.address)
        #if ret == -1:
        #    raise ValueError("Spoofing failed.")
        #else:
        #    print "Address Spoofed."

        #local_name = "Name"
        #complete_local_name = "Name2"
        # Generate integer representation of advertisement data flags using helper function
        #flag_int = gap_utils.generate_ad_flag_value(le_general_discoverable=True, bredr_not_supported=True)
        # Generate advertisement data entry using helper function
        #flag_entry = gap_utils.advertisement_data_entry_builder("Flags", chr(flag_int))
        # Generate advertisement data entry for shortened local name using helper function
        #short_local_name_entry = gap_utils.advertisement_data_entry_builder("Shortened Local Name", complete_local_name)
        # Generate advertisement data entry for complete local name using helper function
        #complete_local_name_entry = gap_utils.advertisement_data_entry_builder("Complete Local Name", local_name)
        # Build advertisement data list
        #ad_entries_list = [flag_entry, short_local_name_entry,complete_local_name_entry]
        # Build finalized advertisement data from list
        #ad_entries = gap_utils.advertisement_data_complete_builder(ad_entries_list)
        # Set advertising data sent in advertising packet
        #connectionManager.set_advertising_data(ad_entries)
        # Set data sent in response to an inquiry packet
        #connectionManager.set_scan_response_data(ad_entries)
        #connectionManager.set_local_name("MyFitnessTracker")
        # Set advertising parameters - advertising type, channel map, interval_min, interval_max,
        # destination address (only used if using directed advertising, just set to 00:00:00:00:00:00),
        # destination address type (only used if using directed advertising, set to 0x00 otherwise which is public)
        #connectionManager.set_advertising_parameters(gap_utils.gap.GAP_ADV_TYPES['ADV_IND'], 7, 0x0020, 0x00a0,
        #                                            "00:00:00:00:00:00", 0x00)

        # Generate BLEDevice
        ble_device = BLEDevice()

        # Add Services and Characteristics to BLEDevice
        service1 = ble_device.add_service(0x01, 0x06, "2124")
        characteristic1 = service1.add_characteristic(
            0x03,
            0x02,
            "2124",
            Permissions.READ | Permissions.WRITE,
            "testValue1",
            characteristic_value_attribute_read_permission=att_utils.
            ATT_SECURITY_MODE_ENCRYPTION_NO_AUTHENTICATION,
            characteristic_value_attribute_write_permission=att_utils.
            ATT_SECURITY_MODE_ENCRYPTION_NO_AUTHENTICATION)
        characteristic1.add_user_description_descriptor(
            0x04, "Characteristic 1")
        services = peripheral.get_services()
        connectionManager.initialize_gatt_server_from_ble_device(
            ble_device, True)
        gatt_server = connectionManager.get_gatt_server()
        gatt_server.debug_print_db()
        #connectionManager.start_advertising()

        result, ble_connection = connectionManager.advertise_and_wait_for_connection(
        )

    if result:
        print "We are connected!"
        connectionManager.smart_scan(ble_connection,
                                     look_for_device_info=False,
                                     timeout=5)
        #data = "41542b424f4e443a4f4b0d0a".decode("hex")
        #handle = "0x0e"
        #connectionManager.gatt_write_handle_async(ble_connection,int(handle,0),data)
        gevent.sleep(50)
    else:
        print "Timeout reached. No one connected."
Exemple #10
0
def advanced_peripheral(address, adapter, role):
    with connection_manager.BLEConnectionManager(adapter,
                                                 role) as connectionManager:
        '''
        Generate a GATT server for interaction by a Central device
        '''
        # Generate BLEDevice
        # ble_device = BLEDevice()
        #
        # # Add Services and Characteristics to BLEDevice
        # service1 = ble_device.add_service(0x01, 0x06, "2124")
        # characteristic1 = service1.add_characteristic(0x03, 0x02, "2124",
        #                                               Permissions.READ | Permissions.WRITE,
        #                                               "testValue1",
        #                                               characteristic_value_attribute_read_permission=att_utils.ATT_SECURITY_MODE_ENCRYPTION_NO_AUTHENTICATION,
        #                                               characteristic_value_attribute_write_permission=att_utils.ATT_SECURITY_MODE_ENCRYPTION_NO_AUTHENTICATION
        #                                               )
        # characteristic1.add_user_description_descriptor(0x04,
        #                                                 "Characteristic 1")
        #

        per, data = load_device(address)
        # Generate GATT server on host using BLEDevice information.
        # 2nd param (True) tells the GATT import process to use attribute handles specified in the BLEDevice rather
        # than sequentially assigning them as attributes are added to the server
        connectionManager.initialize_gatt_server_from_ble_device(per, True)

        # Retrieve GATT server
        gatt_server = connectionManager.get_gatt_server()

        # Print GATT server for demonstration purposes
        gatt_server.debug_print_db()

        # Begin advertising and block until we are connected to a Central device (or until timeout is reached)
        result, ble_connection = connectionManager.advertise_and_wait_for_connection(
        )

        if result:
            print "We are connected!"

            # After peer connects, quickly scan their gatt server and see what info is there
            ble_device = connectionManager.smart_scan(
                ble_connection, look_for_device_info=False, timeout=5)

            ble_device.print_device_structure()

            #Notification
            data1 = 0x41542b424f4e443a4f4b0d0a
            notify = connectionManager.gatt_write_handle(
                ble_connection, data1, "000b")
            #data2 = 0x

            # assuming we know a handle by this point, we can then start reading data
            # read from handle 0x0a
            read_request = connectionManager.gatt_read_handle(
                ble_connection, 0x3e)

            if read_request.has_error():
                print "Got error:", read_request.get_error_message()
            elif read_request.has_response():
                print "Got response:", read_request.response.data, "from handle", hex(
                    read_request.handle)