Central role

Bluetooth Low Energy central role is used to connect to a BLE peripheral and interact with it. WHAD provides a specific connector, whad.ble.connector.Central, that implements this role.

It also provides a specific wrapper for connected devices in order to mask the underlying GATT stack and allow easy access to device services and charactersitics, whad.ble.profile.device.PeripheralDevice.

Bluetooth Low Energy Central connector

class whad.ble.connector.Central(device, existing_connection=None, from_json=None, stack=<class 'whad.ble.stack.BleStack'>, client=<class 'whad.ble.stack.gatt.GattClient'>, security_database=None)[source]

This connector provides a BLE Central role.

To initiate a connection to a device, just call Central.connect() with the target BD address and it should return an instance of whad.ble.profile.device.PeripheralDevice in return.

connect(bd_address, random=False, timeout=30, access_address=None, channel_map=None, crc_init=None, hop_interval=None, hop_increment=None) PeripheralDevice[source]

Connect to a target device

Parameters:
  • bd_address (str) – Bluetooth device address (in format ‘xx:xx:xx:xx:xx:xx’)

  • timeout (float) – Connection timeout

  • access_address (int) – Access address to use (optional)

  • channel_map (int) – Channel map to use (optional)

  • crc_init (int) – CRC Initialization value to use (optional)

  • hop_interval (int) – Hop interval to use (optional)

  • hop_increment (int) – Hop increment to use (optional)

Returns:

An instance of PeripheralDevice on success, None on failure.

Return type:

whad.ble.profile.device.PeripheralDevice

export_profile()[source]

Export GATT profile of the existing connection.

Returns:

Profile as a JSON string

Return type:

str

is_connected() bool[source]

Determine if the central device is connected to a peripheral.

Returns:

True if central is connected to a peripheral device, False otherwise.

Return type:

bool

property local_peer: BDAddress

Local peer BD address.

on_connected(connection_data)[source]

Callback method to handle connection event.

Parameters:

connection_data (dict) – Connection data

on_ctl_pdu(pdu)[source]

This callback method is called whenever a control PDU is received. This PDU is then forwarded to the BLE stack to handle it.

Central devices act as master, so we only forward slave to master messages to the stack.

Parameters:

pdu (scapy.layers.bluetooth4LE.BTLE) – BLE Control PDU

on_data_pdu(pdu)[source]

This callback method is called whenever a data PDU is received. This PDU is then forwarded to the BLE stack to handle it.

Central devices act as master, so we only forward slave to master messages to the stack.

Parameters:

pdu (scapy.layers.bluetooth4LE.BTLE_DATA) – BLE Data PDU

on_disconnected(disconnection_data)[source]

Callback method to handle disconnection event.

Parameters:

disconnection_data (whad.protocol.ble_pb2.Disconnected) – Disconnection data

on_new_connection(connection)[source]

On new connection, discover primary services.

Parameters:

connection (whad.protocol.ble_pb2.Connected) – New connection Protobuf message

peripheral() PeripheralDevice[source]

Connected BLE peripheral.

send_pdu(pdu, conn_handle=0, direction=1, access_address=2391391958, encrypt=None) bool[source]

Send a PDU to the connected peripheral device or to the central device.

Parameters:
  • pdu (scapy.layers.bluetooth4LE.BTLE) – BLE PDU to send.

  • conn_handle (int) – Connection handle

  • direction (whad.protocol.ble.ble_pb2.BleDirection) – Direction (central to peripheral, peripheral to central)

  • access_address (int) – Access address to use while sending PDU.

  • encrypt (bool) – Enable PDU encryption if set to True.

Returns:

PDU transmission result.

Return type:

bool

property stack

Return the current stack instance

property target_peer: BDAddress

Remote peer BD address.

version(synchronous=True)[source]

Query BLE version of remote peer.

Bluetooth Low Energy Peripheral abstraction

This module provides the PeripheralDevice class used to wrap all GATT operations for a given connected device. This class wraps all the following operations:

  • service and characteristics discovery

  • ATT MTU exchange

  • characteristic and descriptor read

  • characteristic and descriptor write

For instance, a Central object can be used to initiate a BLE connection to a target, and will return a PeripheralDevice object, as shown below:

central = Central(...)
target = central.connect('00:11:22:33:44:55')

One can then use this object to discover all the services and characteristics:

target.discover()

And look for a specific characteristic and read it:

device_name = target.get_characteristic(UUID('1800'), UUID('2A00'))
if device_name is not None:
    print('Device name is {}'.format(device_name.read()))

It is also possible to write to a characteristic (if writeable):

device_name.value = b'MyNewDeviceName'
class whad.ble.profile.device.PeripheralDevice(central, gatt_client, conn_handle, from_json=None)[source]

GATT client wrapper representing a remote device.

This class is used to wrap a device model used in a gatt client in order to provide easy-to-use methods to access its services, characteristics and descriptors.

property conn_handle: int

Current connection handle.

disconnect()[source]

Terminate the connection to this device

discover()[source]

Discovers services, characteristics and descriptors.

This method must be called before accessing any service or characteristic, as it is required to retrieve the corresponding GATT handles.

find_characteristic_by_uuid(uuid: UUID)[source]

Find characteristic by its UUID

Parameters:

uuid (whad.ble.profile.attribute.UUID) – Characteristic UUID

Returns:

PeripheralCharacteristic: An instance of PeripheralCharacteristic if characteristic has been found, None otherwise.

Return type:

whad.ble.profile.device.PeripheralCharacteristic

find_object_by_handle(handle)[source]

Find an existing object (service, attribute, descriptor) based on its handle, it known from the underlying GenericProfile.

Parameters:

handle (int) – Object handle

Returns:

Characteristic, characteristic value or service

Return type:

whad.ble.profile.device.PeripheralCharacteristic, whad.ble.profile.device.PeripheralCharacteristicValue, whad.ble.profile.device.PeripheralService

find_service_by_uuid(uuid: UUID) PeripheralService[source]

Find service by its UUID

Parameters:

uuid (whad.ble.profile.attribute.UUID) – Characteristic UUID

Returns:

PeripheralService: An instance of PeripheralService if service has been found, None otherwise.

Return type:

whad.ble.profile.device.PeripheralService

get_characteristic(service_uuid: UUID, charac_uuid: UUID)[source]

Get a PeripheralCharacteristic object representing a characteristic defined by the given service UUID and characteristic UUID.

Parameters:
  • service_uuid (whad.ble.profile.attribute.UUID) – Service UUID

  • charac_uuid (whad.ble.profile.attribute.UUID) – Characteristic UUID

Returns:

PeripheralCharacteristic object on success, None if not found.

Return type:

whad.ble.profile.device.PeripheralCharacteristic

get_service(uuid)[source]

Retrieve a PeripheralService object given its UUID.

Parameters:

uuid (whad.ble.profile.attribute.UUID) – Service UUID

Returns:

Corresponding PeripheralService object if found, None otherwise.

Return type:

whad.ble.profile.device.PeripheralService

on_disconnect(conn_handle)[source]

Disconnection callback

Parameters:

conn_handle (int) – Connection handle

pairing(pairing=None)[source]

Trigger a pairing according to provided parameters. Default parameters will be used if pairing parameter is None.

read(handle, offset=None, long=False)[source]

Perform a read operation on an attribute based on its handle.

This method allows to interact with characteristics and descriptors without having performing a GATT services and characteristics discovery. One just need to specify the handle corresponding to a characteristic value or descriptor and our GATT stack will handle it.

Note that there is absolutely no check on corresponding characteristic permissions (meaning you can try to read from a write-only characteristic value) and that this method may raise exceptions due to potential GATT errors the remote device may return.

Parameters:
  • handle (int) – Characteristic or descriptor handle.

  • offset (int, optional) – Offset applied when reading data from characteristic or descriptor (default: 0).

  • long (bool, optional) – use GATT long read procedure if set to True (default: False)

Returns:

Content of the characteristic or descriptor.

Return type:

bytes

set_disconnect_cb(callback)[source]

Set disconnection callback.

Parameters:

callback (callable) – Callback function to call on disconnection.

set_mtu(mtu: int)[source]

Update connection MTU.

Parameters:

mtu (int) – ATT MTU to use for this connection.

Returns:

Remote device MTU.

Return type:

int

write(handle, value)[source]

Perform a write operation on an attribute based on its handle.

This method allows to interact with characteristics and descriptors without having performing a GATT services and characteristics discovery. One just need to specify the handle corresponding to a characteristic value or descriptor and the value to write to it, and our GATT stack will handle it.

Note that there is absolutely no check on corresponding characteristic permissions (meaning you can try to write on a read-only characteristic value) and that this method may raise exceptions due to potential GATT errors the remote device may return.

Parameters:
  • handle (int) – Characteristic or descriptor handle to write.

  • value (bytes) – Bytes to write into this characteristic.

write_command(handle, value, without_response=False)[source]

Perform a write command operation (no write response will be sent) on an attribute based on its handle.

This method allows to interact with characteristics and descriptors without having performing a GATT services and characteristics discovery. One just need to specify the handle corresponding to a characteristic value or descriptor and the value to write to it, and our GATT stack will handle it.

Note that there is absolutely no check on corresponding characteristic permissions (meaning you can try to write on a read-only characteristic value) and that this method may raise exceptions due to potential GATT errors the remote device may return.

Parameters:
  • handle (int) – Characteristic or descriptor handle to write.

  • value (bytes) – Bytes to write into this characteristic.