def characteristics_properties(central, peripheral, characteristic_uuid,
                               set_property):
    # test all combinations except this illegal set
    if set_property == ["authSignedWrite"]:
        return

    peripheral.gattServer.declareService(0xFFFB)
    peripheral.gattServer.declareCharacteristic(characteristic_uuid)
    peripheral.gattServer.setCharacteristicProperties(*set_property)
    # if the characteristic is readable, the characteristic value can't be 0
    # TODO: investigate if it is a bug or not
    peripheral.gattServer.setCharacteristicValue("AA")
    declared_service = peripheral.gattServer.commitService().result

    # assert that properties set match expectations
    assert set_property.sort(
    ) == declared_service["characteristics"][0]["properties"].sort()

    connection_handle_central, connection_handle_peripheral = gap_connect(
        central, peripheral)
    discovered_services = discover_user_services(central,
                                                 connection_handle_central)
    assert set_property.sort(
    ) == discovered_services[0]["characteristics"][0]["properties"].sort()

    central.gap.disconnect(connection_handle_central, "USER_TERMINATION")
Beispiel #2
0
def test_cccd_not_shared_between_clients(central, peripheral, dual_role):
    """Client configuration descriptor values should not be shared across several clients"""
    cccd_uuid = 0x2902

    # CCCD is in the characteristic, there is no need to redeclare it, instantiate another random descriptor
    instantiate_descriptor(dual_role, 0xDEAD, "FEED")
    central_handle, dual_handle_as_peripheral = gap_connect(central, dual_role)
    dual_handle_as_central, peripheral_handle = gap_connect(dual_role, peripheral)

    services = discover_user_services(central, central_handle)
    characteristic = services[0]["characteristics"][0]
    # discover this descriptor
    descriptors = discover_descriptors(
        central,
        central_handle,
        characteristic["start_handle"],
        characteristic["end_handle"]
    )

    for descriptor in descriptors:
        if descriptor["UUID"] == cccd_uuid:
            descriptor_handle = descriptor["handle"]
            break

    def verify_cccds(expected_value_client_0, expected_value_client_1):
        verify_client_descriptor_value(central, central_handle, descriptor_handle, expected_value_client_0)
        assert expected_value_client_0 == dual_role.gattServer.read(descriptor_handle, dual_handle_as_peripheral).result

        verify_client_descriptor_value(peripheral, peripheral_handle, descriptor_handle, expected_value_client_1)
        assert expected_value_client_1 == dual_role.gattServer.read(descriptor_handle, dual_handle_as_central).result

    def write_value(client, handle, new_value):
        client.gattClient.writeCharacteristicDescriptor(handle, descriptor_handle, new_value)

    # at the beginning, CCCD should be equal to 0000
    verify_cccds("0000", "0000")

    # enable notifications for client 0 (note, send in little endian)
    write_value(central, central_handle, "0100")
    verify_cccds("0100", "0000")

    # enable indications for client 1 (note, send in little endian)
    write_value(peripheral, peripheral_handle, "0200")
    verify_cccds("0100", "0200")

    # disable notifications for client 0 (note, send in little endian)
    write_value(central, central_handle, "0000")
    verify_cccds("0000", "0200")

    # enable notification for client 1 (note, send in little endian)
    write_value(peripheral, peripheral_handle, "0100")
    verify_cccds("0000", "0100")
def test_characteristic_has_cccd(central, peripheral, char_property,
                                 descriptor):
    log.info(
        'Testing characteristic with a property {} and {} has a CCCD available'
        .format(char_property[0], descriptor[0]))
    properties = char_property[1]
    descriptors = descriptor[1]

    services_uuids = [0xBEAF, make_uuid()]

    characteristics = [0xDEAD, make_uuid()]

    declared_services = []

    # declare services and commit them
    for uuid in services_uuids:
        peripheral.gattServer.declareService(uuid)
        for characteristic in characteristics:
            peripheral.gattServer.declareCharacteristic(characteristic)
            peripheral.gattServer.setCharacteristicProperties(*properties)
            for descriptor in descriptors:
                peripheral.gattServer.declareDescriptor(descriptor)
        declared_service = peripheral.gattServer.commitService().result

        # assert that characteristics UUID match and that services UUID match
        assert_uuid_equals(uuid, declared_service["UUID"])
        assert len(characteristics) == len(declared_service["characteristics"])
        for i in range(len(characteristics)):
            characteristic = characteristics[i]
            declared_characteristic = declared_service["characteristics"][i]
            assert_uuid_equals(characteristic, declared_characteristic["UUID"])
            declared_descriptors = declared_characteristic["descriptors"]
            for j in range(len(descriptors)):
                assert_uuid_equals(descriptors[j],
                                   declared_descriptors[j]["UUID"])

        declared_services.append(declared_service)

    # connect central and peripheral and discover user services
    central_connection_handle, _ = gap_connect(central, peripheral)
    discovered_services = discover_user_services(central,
                                                 central_connection_handle)

    # the number of services discovered should be equal to the number of services registered
    assert len(services_uuids) == len(discovered_services)

    # services discovery should return services in declaration order
    for i in range(len(services_uuids)):
        declared_service = declared_services[i]
        discovered_service = discovered_services[i]

        assert_uuid_equals(declared_service["UUID"],
                           discovered_service["UUID"])
        assert declared_service["handle"] == discovered_service["start_handle"]

        # discovery process should report the same characteristics as the ones registered
        assert len(declared_service["characteristics"]) == len(
            discovered_service["characteristics"])

        for j in range(len(declared_service["characteristics"])):
            declared_characteristic = declared_service["characteristics"][j]
            discovered_characteristic = discovered_service["characteristics"][
                j]

            assert declared_characteristic[
                "value_handle"] == discovered_characteristic["value_handle"]
            assert_uuid_equals(declared_characteristic["UUID"],
                               discovered_characteristic["UUID"])

            # discover descriptors and compare against what has been registered
            discovered_descriptors = discover_descriptors(
                central, central_connection_handle,
                discovered_characteristic["start_handle"],
                discovered_characteristic["end_handle"])

            # find the CCCD
            cccd = [x for x in discovered_descriptors if x["UUID"] == 0x2902]
            assert 1 == len(cccd)
            discovered_descriptors.remove(cccd[0])

            # notify/indicate descriptor is implicit
            assert len(declared_characteristic["descriptors"]) == len(
                discovered_descriptors)
            for k in range(len(declared_characteristic["descriptors"])):
                declared_descriptor = declared_characteristic["descriptors"][k]
                discovered_descriptor = discovered_descriptors[k]
                assert_uuid_equals(declared_descriptor["UUID"],
                                   discovered_descriptor["UUID"])
                assert declared_descriptor["handle"] == discovered_descriptor[
                    "handle"]
def test_allow_characteristic(central, peripheral, characteristic, descriptor):
    log.info('Testing {} with {} is allowed'.format(characteristic[0],
                                                    descriptor[0]))

    characteristics = [{
        "uuid": characteristic[1],
        "descriptors_uuid": descriptor[1]
    }]

    services_uuids = [0xBEAF, make_uuid()]

    declared_services = []

    # declare services and commit them
    for uuid in services_uuids:
        peripheral.gattServer.declareService(uuid)
        for characteristic in characteristics:
            peripheral.gattServer.declareCharacteristic(characteristic["uuid"])
            for descriptor_uuid in characteristic["descriptors_uuid"]:
                peripheral.gattServer.declareDescriptor(descriptor_uuid)
        declared_service = peripheral.gattServer.commitService().result

        # assert that characteristics UUID match and that services UUID match
        assert_uuid_equals(uuid, declared_service["UUID"])
        assert len(characteristics) == len(declared_service["characteristics"])
        for i in range(len(characteristics)):
            characteristic = characteristics[i]
            declared_characteristic = declared_service["characteristics"][i]
            assert_uuid_equals(characteristic["uuid"],
                               declared_characteristic["UUID"])
            descriptors_uuid = characteristic["descriptors_uuid"]
            declared_descriptors = declared_characteristic["descriptors"]
            for j in range(len(descriptors_uuid)):
                assert_uuid_equals(descriptors_uuid[j],
                                   declared_descriptors[j]["UUID"])

        declared_services.append(declared_service)

    # connect central and peripheral and discover user services
    central_connection_handle, _ = gap_connect(central, peripheral)
    discovered_services = discover_user_services(central,
                                                 central_connection_handle)

    # the number of services discovered should be equal to the number of services registered
    assert len(services_uuids) == len(discovered_services)

    # services discovery should return services in declaration order
    for i in range(len(services_uuids)):
        declared_service = declared_services[i]
        discovered_service = discovered_services[i]

        assert_uuid_equals(declared_service["UUID"],
                           discovered_service["UUID"])
        assert declared_service["handle"] == discovered_service["start_handle"]

        # discovery process should report the same characteristics as the ones registered
        assert len(declared_service["characteristics"]) == len(
            discovered_service["characteristics"])

        for j in range(len(declared_service["characteristics"])):
            declared_characteristic = declared_service["characteristics"][j]
            discovered_characteristic = discovered_service["characteristics"][
                j]

            assert declared_characteristic[
                "value_handle"] == discovered_characteristic["value_handle"]
            assert_uuid_equals(declared_characteristic["UUID"],
                               discovered_characteristic["UUID"])

            # discover descriptors and compare against what has been registered
            discovered_descriptors = discover_descriptors(
                central, central_connection_handle,
                discovered_characteristic["start_handle"],
                discovered_characteristic["end_handle"])

            assert len(declared_characteristic["descriptors"]) == len(
                discovered_descriptors)
            for k in range(len(declared_characteristic["descriptors"])):
                declared_descriptor = declared_characteristic["descriptors"][k]
                discovered_descriptor = discovered_descriptors[k]
                assert_uuid_equals(declared_descriptor["UUID"],
                                   discovered_descriptor["UUID"])
                assert declared_descriptor["handle"] == discovered_descriptor[
                    "handle"]