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")
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"]