Пример #1
0
def main(serial_port):
    # Open the BLE Device and suppress spammy log messages
    ble_device = BleDevice(serial_port)
    ble_device.event_logger.suppress(nrf_events.GapEvtAdvReport)
    # Configure the BLE device to support MTU sizes which allow the max data length extension PDU size
    # Note this isn't 100% necessary as the default configuration sets the max to this value also
    ble_device.configure(att_mtu_max_size=MTU_SIZE_FOR_MAX_DLE)
    ble_device.open()

    # Set scan duration for 4 seconds
    ble_device.scanner.set_default_scan_params(timeout_seconds=4)
    ble_device.set_default_peripheral_connection_params(10, 30, 4000)
    logger.info("Scanning for peripherals advertising UUID {}".format(
        nordic_uart.NORDIC_UART_SERVICE_UUID))

    target_address = None
    # Start scan and wait for it to complete
    scan_report = ble_device.scanner.start_scan().wait()
    # Search each peer's advertising data for the Nordic UART Service UUID to be advertised
    for report in scan_report.advertising_peers_found:
        if nordic_uart.NORDIC_UART_SERVICE_UUID in report.advertise_data.service_uuid128s and report.device_name == "Nordic UART Server":
            target_address = report.peer_address
            break

    if not target_address:
        logger.info("Did not find peripheral advertising Nordic UART service")
        return

    # Initiate connection and wait for it to finish
    logger.info("Found match: connecting to address {}".format(target_address))
    peer = ble_device.connect(target_address).wait()
    if not peer:
        logger.warning("Timed out connecting to device")
        return

    logger.info("Connected, conn_handle: {}".format(peer.conn_handle))

    logger.info("Exchanging MTU")
    peer.exchange_mtu(peer.max_mtu_size).wait(10)
    logger.info("MTU Exchange complete, discovering services")

    # Initiate service discovery and wait for it to complete
    _, event_args = peer.discover_services().wait(exception_on_timeout=False)
    logger.info("Service discovery complete! status: {}".format(
        event_args.status))

    uart_service = nordic_uart.find_nordic_uart_service(peer.database)
    if not uart_service:
        logger.info(
            "Failed to find Nordic UART service in peripheral database")
        peer.disconnect().wait()
        ble_device.close()
        return

    # Initialize the service
    uart_service.initialize().wait(5)
    uart_service.on_data_received.register(on_data_rx)

    while True:
        data = input("Enter data to send to peripheral (q to exit): ")
        if data == "q":
            break
        uart_service.write(data).wait(10)

    peer.disconnect().wait()
    ble_device.close()
Пример #2
0
def main(serial_port):
    # Set the target to the peripheral's advertised name
    target_device_name = constants.PERIPHERAL_NAME

    # Create and open the BLE device (and suppress spammy logs)
    ble_device = BleDevice(serial_port)
    ble_device.event_logger.suppress(nrf_events.GapEvtAdvReport)
    ble_device.open()

    # Set the scanner to scan for 4 seconds
    ble_device.scanner.set_default_scan_params(timeout_seconds=4)

    logger.info("Scanning for '{}'".format(target_device_name))
    target_address = example_utils.find_target_device(ble_device, target_device_name)

    if not target_address:
        logger.info("Did not find target peripheral")
        return

    # Initiate the connection and wait for it to finish
    logger.info("Found match: connecting to address {}".format(target_address))
    peer = ble_device.connect(target_address).wait()
    if not peer:
        logger.warning("Timed out connecting to device")
        return

    # Wait up to 10 seconds for service discovery to complete
    logger.info("Connected, conn_handle: {}".format(peer.conn_handle))
    _, event_args = peer.discover_services().wait(10, exception_on_timeout=False)
    logger.info("Service discovery complete! status: {}".format(event_args.status))

    # Log each service found
    for service in peer.database.services:
        logger.info(service)

    peer.set_connection_parameters(100, 120, 6000)  # Discovery complete, go to a longer connection interval

    # Pair with the peripheral
    def on_passkey_entry(peer, passkey_event_args):
        """
        Callback for when the user is requested to enter a passkey to resume the pairing process.
        Requests the user to enter the passkey and resolves the event with the passkey entered

        :param peer: the peer the passkey is for
        :param passkey_event_args:
        :type passkey_event_args: blatann.event_args.PasskeyEntryEventArgs
        """
        passkey = input("Enter peripheral passkey: ")
        passkey_event_args.resolve(passkey)

    # Setup the security parameters
    peer.security.set_security_params(passcode_pairing=True, io_capabilities=smp.IoCapabilities.KEYBOARD_DISPLAY,
                                      bond=False, out_of_band=False)
    # Register the callback for when a passkey needs to be entered by the user
    peer.security.on_passkey_required.register(on_passkey_entry)
    # Wait up to 60 seconds for the pairing process
    peer.security.pair().wait(60)

    # Find the counting characteristic
    counting_char = peer.database.find_characteristic(constants.COUNTING_CHAR_UUID)
    if counting_char:
        logger.info("Subscribing to the counting characteristic")
        counting_char.subscribe(on_counting_char_notification).wait(5)
    else:
        logger.warning("Failed to find counting characteristic")

    # Find the hex conversion characteristic. This characteristic takes in a bytestream and converts it to its
    # hex representation. e.g. '0123' -> '30313233'
    hex_convert_char = peer.database.find_characteristic(constants.HEX_CONVERT_CHAR_UUID)
    if hex_convert_char:
        # Generate some data ABCDEFG... Then, incrementally send increasing lengths of strings.
        # i.e. first send 'A', then 'AB', then 'ABC'...
        data_to_convert = bytes(ord('A') + i for i in range(12))
        for i in range(len(data_to_convert)):
            data_to_send = data_to_convert[:i+1]
            logger.info("Converting to hex data: '{}'".format(data_to_send))

            # Write the data, waiting up to 5 seconds for the write to complete
            if not hex_convert_char.write(data_to_send).wait(5, False):
                logger.error("Failed to write data, i={}".format(i))
                break

            # Write was successful, when we read the characteristic the peripheral should have converted the string
            # Once again, initiate a read and wait up to 5 seconds for the read to complete
            char, event_args = hex_convert_char.read().wait(5, False)
            logger.info("Hex: '{}'".format(event_args.value.decode("ascii")))
    else:
        logger.warning("Failed to find hex convert char")

    # Clean up
    logger.info("Disconnecting from peripheral")
    peer.disconnect().wait()
    ble_device.close()
Пример #3
0
def main(serial_port):
    # Open the BLE Device and suppress spammy log messages
    ble_device = BleDevice(serial_port)
    ble_device.event_logger.suppress(nrf_events.GapEvtAdvReport)
    ble_device.open()

    # Set scan duration for 4 seconds
    ble_device.scanner.set_default_scan_params(timeout_seconds=4)
    logger.info("Scanning for peripherals advertising UUID {}".format(
        battery.BATTERY_SERVICE_UUID))

    target_address = None
    # Start scan and wait for it to complete
    scan_report = ble_device.scanner.start_scan().wait()
    # Search each peer's advertising data for the Battery Service UUID to be advertised
    for report in scan_report.advertising_peers_found:
        if battery.BATTERY_SERVICE_UUID in report.advertise_data.service_uuid16s:
            target_address = report.peer_address
            break

    if not target_address:
        logger.info("Did not find peripheral advertising battery service")
        return

    # Initiate connection and wait for it to finish
    logger.info("Found match: connecting to address {}".format(target_address))
    peer = ble_device.connect(target_address).wait()
    if not peer:
        logger.warning("Timed out connecting to device")
        return

    logger.info("Connected, conn_handle: {}".format(peer.conn_handle))
    # Initiate service discovery and wait for it to complete
    _, event_args = peer.discover_services().wait(10,
                                                  exception_on_timeout=False)
    logger.info("Service discovery complete! status: {}".format(
        event_args.status))

    # Find the battery service within the peer's database
    battery_service = battery.find_battery_service(peer.database)
    if not battery_service:
        logger.info("Failed to find Battery Service in peripheral database")
        peer.disconnect().wait()
        return

    # Read out the battery level
    logger.info("Reading battery level...")
    _, event_args = battery_service.read().wait()
    battery_percent = event_args.value
    logger.info("Battery: {}%".format(battery_percent))

    if battery_service.can_enable_notifications:
        battery_service.on_battery_level_updated.register(
            on_battery_level_update)
        battery_service.enable_notifications().wait()

        wait_duration = 30
        logger.info("Waiting {} seconds for any battery notifications")
        time.sleep(wait_duration)

    # Clean up
    logger.info("Disconnecting from peripheral")
    peer.disconnect().wait()
    ble_device.close()
Пример #4
0
def main(serial_port):
    # Open the BLE Device and suppress spammy log messages
    ble_device = BleDevice(serial_port)
    ble_device.event_logger.suppress(nrf_events.GapEvtAdvReport)
    ble_device.open()

    # Set scan duration to 4 seconds
    ble_device.scanner.set_default_scan_params(timeout_seconds=4)
    logger.info("Scanning for peripherals advertising UUID {}".format(
        device_info.DIS_SERVICE_UUID))

    target_address = None
    # Start scan and wait for it to complete
    scan_report = ble_device.scanner.start_scan().wait()
    # Search each peer's advertising data for the DIS Service UUID to be advertised
    for report in scan_report.advertising_peers_found:
        if device_info.DIS_SERVICE_UUID in report.advertise_data.service_uuid16s:
            target_address = report.peer_address
            break

    if not target_address:
        logger.info("Did not find peripheral advertising DIS service")
        return

    # Initiate connection and wait for it to finish
    logger.info("Found match: connecting to address {}".format(target_address))
    peer = ble_device.connect(target_address).wait()
    if not peer:
        logger.warning("Timed out connecting to device")
        return

    logger.info("Connected, conn_handle: {}".format(peer.conn_handle))
    # Initiate service discovery and wait for it to complete
    _, event_args = peer.discover_services().wait(10,
                                                  exception_on_timeout=False)
    logger.info("Service discovery complete! status: {}".format(
        event_args.status))

    # Find the device info service in the peer's database
    dis = device_info.find_device_info_service(peer.database)
    if not dis:
        logger.info(
            "Failed to find Device Info Service in peripheral database")
        peer.disconnect().wait()
        return

    # Example 1:
    # Iterate through all possible device info characteristics, read the value if present in service
    for char in device_info.CHARACTERISTICS:
        if dis.has(char):
            logger.info("Reading characteristic: {}...".format(char))
            char, event_args = dis.get(char).wait()
            if isinstance(event_args.value, bytes):
                value = event_args.value.decode("utf8")
            else:
                value = event_args.value
            logger.info("Value: {}".format(value))

    # Example 2:
    # Read specific characteristics, if present in the service
    if dis.has_software_revision:
        char, event_args = dis.get_software_revision().wait()
        sw_version = event_args.value
        logger.info("Software Version: {}".format(sw_version.decode("utf8")))
    if dis.has_pnp_id:
        char, event_args = dis.get_pnp_id().wait()
        pnp_id = event_args.value  # type: device_info.PnpId
        logger.info("Vendor ID: {}".format(pnp_id.vendor_id))
    if dis.has_system_id:
        char, event_args = dis.get_system_id().wait()
        system_id = event_args.value  # type: device_info.SystemId
        logger.info("System ID: {}".format(system_id))

    # Disconnect and close device
    peer.disconnect().wait()
    ble_device.close()
Пример #5
0
def main(serial_port):
    # Create and open the device
    ble_device = BleDevice(serial_port)
    ble_device.configure()
    ble_device.open()

    ble_device.scanner.set_default_scan_params(timeout_seconds=4)

    # Set the target to the peripheral's advertised name
    target_device_name = constants.PERIPHERAL_NAME

    logger.info("Scanning for '{}'".format(target_device_name))
    target_address = example_utils.find_target_device(ble_device, target_device_name)

    if not target_address:
        logger.info("Did not find target peripheral")
        return

    # Initiate the connection and wait for it to finish
    logger.info("Found match: connecting to address {}".format(target_address))
    peer = ble_device.connect(target_address).wait()
    if not peer:
        logger.warning("Timed out connecting to device")
        return
    logger.info("Connected, conn_handle: {}".format(peer.conn_handle))

    # Wait up to 10 seconds for service discovery to complete
    _, event_args = peer.discover_services().wait(10, exception_on_timeout=False)
    logger.info("Service discovery complete! status: {}".format(event_args.status))

    # Find the Time characteristic
    time_char = peer.database.find_characteristic(constants.DESC_EXAMPLE_CHAR_UUID)
    if not time_char:
        logger.info("Did not find the time characteristic")
    else:
        logger.info("Reading all characteristic attributes")
        for attr in time_char.attributes:
            logger.info(f"Reading UUID {attr.uuid} - {attr.uuid.description or '[unknown]'}")
            _, event_args = attr.read().wait(5)
            if event_args.status == GattStatusCode.success:
                # Show as hex unless it's the user descriptor UUID which should be a string
                if attr.uuid == DescriptorUuid.user_description:
                    value = event_args.value.decode("utf8")
                else:
                    value = binascii.hexlify(event_args.value)
                logger.info(f"    Value: {value}")
            else:
                logger.warning(f"    Failed to read attribute, status: {event_args.status}")

        # Read the characteristic's Presentation Format descriptor directly and decode the value
        presentation_fmt_desc = time_char.find_descriptor(DescriptorUuid.presentation_format)
        if presentation_fmt_desc:
            # Read, then decode the value using the PresentationFormat type
            logger.info("Reading the presentation format descriptor directly")
            _, event_args = presentation_fmt_desc.read().wait(5)
            if event_args.status == GattStatusCode.success:
                try:
                    fmt = PresentationFormat.decode(event_args.value)
                    logger.info(f"Presentation Format: {str(fmt.format)}, Exponent: {fmt.exponent}, Unit: {str(fmt.unit)}")
                except Exception as e:
                    logger.error("Failed to decode the presentation format descriptor")
                    logger.exception(e)
        else:
            logger.info("Failed to find the presentation format descriptor")

    # Clean up
    logger.info("Disconnecting from peripheral")
    peer.disconnect().wait()
    ble_device.close()