Device Model

WHAD uses a specific device model to create BLE peripherals. This device model is implemented in Profile and allows dynamic modification of services and characteristics but also provides a convenient way to define a device’s services, characteristics and descriptors.

Creating a device model of a BLE peripheral

Here is an example of a BLE peripheral implemented with WHAD:

from whad.ble import UUID, Profile, PrimaryService, Characteristic

class MyPeripheral(Profile):

    generic_access = PrimaryService(
        UUID(0x1800),

        device_name = Characteristic(
            UUID(0x2A00),
            permissions=['read', 'notify'],
            value=b'My device name'
        )
    )

Profile performs an introspection on its properties to find every instance of PrimaryService, finds every instance of Characteristic declared into each service and populates its attribute database based on the discovered information.

But this mechanism also allows dynamic modification of any characteristic, for instance the device name characteristic:

periph_inst = MyPeripheral()
periph_inst.generic_access.device_name = b'Another name'

Of course, this can also be done when the peripheral is running and will cause the BLE stack to send notifications or indications based on the characteristics properties.

Defining and using a standard service

WHAD provides a StandardService class used to define standard services in a custom profile. This class is a wrapper around the generic PrimaryService that automatically retrieves the service’s UUID from a special class property and equip the service class with additional methods allowing to provide an abstraction level from its characteristics.

A standard service shall be defined as follows:

from struct import pack, unpack
from whad.ble import UUID, Characteristic
from whad.ble.service import StandardService

class CustomService(StandardService):
    """An example of a standard service.

    This service exposes a single read-only characteristic
    that contains some version number stored on 3 bytes.

    It defines a property named `version` that parses
    the characteristic's value and return a tuple with
    the version's major, minor and revision numbers.

    When this property is set, the provided version numbers
    are packed into a byte array and written into the
    corresponding characteristic's value.
    """

    # Service UUID is expected in `_uuid`:
    _uuid = UUID(0x1337)

    # Characteristics are defined as class properties
    version = Characteristic(
        UUID(0x1338),
        properties=Characteristic.READ,
        value=b'\x01\x00\x00',
        required=True, # Characteristic MUST be present
    )

    @property
    def version(self) -> (int, int, int):
        return unpack("<BBB", self.version.value)

    @version.setter
    def version(self, version: (int, int, int)):
        major, minor, rev = version
        self.version.value = pack('<BBB', major, minor, rev)

The same class will be used to define a peripheral’s profile and access the service from a central device. The following code defines a peripheral profile using the above standard service:

from whad.ble import Profile, Peripheral
from .service import CustomService

class CutomProfile(Profile):
    """My custom profile"""
    custom_service = CustomService()

# Create an instance of our profile and set its version
profile = CustomProfile()
profile.custom_service.version = (1,2,3)

# Create a peripheral using this profile
periph = Peripheral(Device.create('hci0'), profile=profile)

And to access the same service from a GATT client:

from whad.ble import Profile, Central
from .service import CustomService

class CutomProfile(Profile):
    """My custom profile"""
    custom_service = CustomService()

# Create a central device
central = Central(Device.create('hci0'))

# Connect to a device that exposes our custom service
target = central.connect('11:22:33:44:55:66')
if target is not None:
    # Once connected, query the service and read the version
    if target.has(CustomService):
        custom_service = target.query(CustomService)
        major, minor, rev = custom_service.version
        print(f"Device custom version: {major}.{minor}.{rev}")
    else:
        print("Device does not expose our custom service.")

    # Disconnect
    target.disconnect()

Supported standard services

The following standard Bluetooth Low Energy services are supported:

Hooking GATT events on characteristics

WHAD BLE device model provides a set of method decorators that must be used to attach a method to a specific event and a specific characteristic:

  • read declares a characteristic read event handler

  • write declares a characteristic before-write event handler

  • written declares a characteristic after-write event handler

  • subscribed declares a characteristic subscribe event handler

  • unsubscribed declares a characteristic unsubscribe event handler

A characteristic event handler may raise one of the following exception to cause the GATT stack to react accordingly:

  • HookReturnValue: force a characteristic value to be returned to a GATT client on a read event

  • HookReturnGattError: generates a GATT error that will be sent back to the connected GATT client

  • HookReturnNotFound: tells a GATT client the characteristic does not exist

  • HookReturnAccesDenied: tells a GATT client that authentication is required to access this characteristic

If no exception is raised in the event handler, the GATT operation continues as expected. As an example, here follows a peripheral model declaration that uses a characteristic event handler:

class MyPeripheral(Profile):

    generic_access = PrimaryService(
        UUID(0x1800),

        device_name = Characteristic(
            UUID(0x2A00),
            permissions=['read', 'write', 'notify'],
            value=b'My device name'
        )
    )

    @read(generic_access.device_name)
    def on_device_name_read(self, offset, mtu):
        """Return the content of the device name characteristic prefixed with 'FOO'
        """
        raise HookReturnValue(b'FOO'+ self.generic_access.device_name.value)

    @written(generic_access.device_name)
    def on_device_name_changed(self, value, without_response):
        """Called every time the device name characteristic has been changed by client.
        """
        print(f"Device name has been changed to: {value}")

GATT Profile API

class whad.ble.UUID(uuid)[source]

UUID class borrowed from pyBT (c) Mike Ryan

__init__(uuid)[source]
classmethod from_name(name)[source]

Get UUID from standard name.

to_bytes()[source]

Convert UUID to bytes

value()[source]

Retrieve UUID value (16-bit)

class whad.ble.read(*args)[source]

Read hook decorator

This decorator is used to declare a callback method for read operations on a specific characteristic.

class whad.ble.write(*args)[source]

Write hook decorator

This decorator is used to declare a callback method for write operations on a specific characteristic. This callback will be called before the write operation happens.

class whad.ble.written(*args)[source]

Written hook decorator

This decorator is used to declare a callback method for write operations on a specific characteristic. This callback will be called after the write operation happens.

class whad.ble.subscribed(*args)[source]

Subscribe hook decorator

This decorator is used to declare a callback method for subscribe operations on a specific characteristic.

class whad.ble.unsubscribed(*args)[source]

Unsubscribe hook decorator

This decorator is used to declare a callback method for unsubscribe operations on a specific characteristic.

class whad.ble.Profile(start_handle: int = 1, from_json: str | None = None)[source]

This class implements a GATT profile, i.e. a set of services and characteristics exposed by a Bluetooth Low Energy GATT server.

__init__(start_handle: int = 1, from_json: str | None = None)[source]

Parse the device model, instantiate all the services, characteristics and descriptors, compute all handle values and registers everything inside this instance for further use.

Parameters:
  • start_handle (int) – Start handle value to use (default: 0)

  • from_json (str) – JSON data describing a GATT profile

add_service(service: Service, handles_only: bool = False)[source]

Add a service to the current device

Parameters:
  • service (Service) – Service to add to the device

  • handles_only (bool) – Add only service handles if set to True

attr_by_type_uuid(uuid, start: int = 1, end: int = 65535) Iterator[Attribute][source]

Enumerate attributes that have a specific type UUID.

Parameters:
  • uuid (UUID) – Type UUID

  • start (int) – Start handle

  • end (int) – End handle

char(uuid: str | UUID) Characteristic | None[source]

Get characteristic by its UUID.

Parameters:

uuid (str) – Characteristic UUID to look for

Returns:

Characteristic if found, None otherwise

Return type:

whad.ble.profile.characteristic.Characteristic, optional

export_json() str[source]

Export profile as JSON data, including services, characteristics and descriptors definition.

Returns:

JSON data corresponding to this profile

Return type:

str

find_characteristic_by_value_handle(value_handle: int) Characteristic | None[source]

Find characteristic object by its value handle.

Parameters:

value_handle (int) – Characteristic value handle

Returns:

Corresponding characteristic object or None if not found.

Return type:

Characteristic

find_characteristic_end_handle(handle: int) int | None[source]

Find characteristic end handle based on its handle.

Parameters:

handle (int) – Characteristic handle

Return type:

int

Returns:

Characteristic value handle

Raises:

InvalidHandleValueException

find_hook(service: Service, characteristic: Characteristic, operation: str) Callable[[...], Any] | None[source]

Find a registered hook for a specific service, characteristic and operation.

Parameters:
  • service (Service) – Service object

  • characteristic (Characteristic) – Characteristic object

  • operation (str) – GATT operation

Returns:

Hook callback

Return type:

callable

find_object_by_handle(handle: int) Attribute[source]

Find an object by its handle value

Parameters:

handle (int) – Object handle

Returns:

Object if handle is valid, or raise an IndexError exception otherwise

Return type:

Attribute

Raises:

IndexError

find_objects_by_range(start: int, end: int) List[Attribute][source]

Find attributes with handles belonging in the [start, end+1] interval.

Parameters:
  • start (int) – Start handle value

  • end (int) – End handle value

Returns:

List of objects with handles between start and end values

Return type:

list

Raises:

IndexError

find_service_by_characteristic_handle(handle: int) Service[source]

Find a service object given a characteristic handle that belongs to this service.

Parameters:

handle (int) – Characteristic handle belonging to the searched service

Return type:

Service

Returns:

Service object containing the specified characteristic

Raises:

InvalidHandleValueException

get_characteristic_by_uuid(uuid: str | UUID)[source]

Get characteristic by its UUID.

Parameters:

uuid (str) – Characteristic UUID to look for

Returns:

Characteristic if found, None otherwise

Return type:

whad.ble.profile.characteristic.Characteristic

Raises:

InvalidUUIDException – Specified UUID is invalid

get_service_by_uuid(uuid: str | UUID) Service | None[source]

Retrieve a Service object given its UUID.

Parameters:

uuid (str) – Service UUID

Returns:

Corresponding Service object if found, None otherwise.

Return type:

Service, optional

Raises:

InvalidUUIDException – Specified UUID is invalid

Deprecated since version 1.3.0: Use the service() method to find a service based on its UUID (simpler syntax).

included_services() Iterator[IncludeService][source]

Enumerate included services.

on_characteristic_read(service: Service, characteristic: Characteristic, offset: int = 0, length: int = 0)[source]

Characteristic read hook.

This hook is called whenever a characteristic is about to be read by a GATT client. If this method returns a byte array, this byte array will be sent back to the GATT client. If this method returns None, then the read operation will return an error (not allowed to read characteristic value).

Parameters:
  • service (Service) – Service owning the characteristic

  • characteristic (Characteristic) – Characteristic object

  • offset (int) – Read offset (default: 0)

  • length (int) – Max read length

Returns:

Value to return to the GATT client

Return type:

bytes

on_characteristic_subscribed(service: Service, characteristic: Characteristic, notification: bool = False, indication: bool = False)[source]

Characteristic subscribed hook

This hook is called whenever a characteristic has been subscribed to.

Parameters:
  • service (Service) – Service owning the characteristic

  • characteristic (Characteristic) – Characteristic object

  • notification (bool) – Set to True if subscribed to notification

  • indication (bool) – Set to True if subscribed to notification

on_characteristic_unsubscribed(service: Service, characteristic: Characteristic)[source]

Characteristic unsubscribed hook

This hook is called whenever a characteristic has been unsubscribed.

Parameters:
  • service (Service) – Service owning the characteristic

  • characteristic (Characteristic) – Characteristic object

on_characteristic_write(service: Service, characteristic: Characteristic, offset: int = 0, value: bytes = b'', without_response: bool = False)[source]

Characteristic write hook

This hook is called whenever a charactertistic is about to be written by a GATT client.

Parameters:
  • service (Service) – Service owning the characteristic

  • characteristic (Characteristic) – Characteristic object

  • offset (int) – Read offset (default: 0)

  • value (bytes) – Value about to be written into the characteristic

  • without_response (bool) – Set to True if no response is required

on_characteristic_written(service: Service, characteristic: Characteristic, offset: int = 0, value: bytes = b'', without_response: bool = False)[source]

Characteristic written hook

This hook is called whenever a charactertistic has been written by a GATT client.

Parameters:
  • service (Service) – Service owning the characteristic

  • characteristic (Characteristic) – Characteristic object

  • offset (int) – Read offset (default: 0)

  • value (bytes) – Value about to be written into the characteristic

  • without_response (bool) – Set to True if no response is required

on_connect(conn_handle: int)[source]

Connection hook.

This hook is only used to notify the connection of a device.

Parameters:

conn_handle (int) – Connection handle

on_disconnect(conn_handle: int)[source]

Disconnection hook.

This hook is only used to notify the disconnection of a device.

Parameters:

conn_handle (int) – Connection handle

on_indication(service: Service, characteristic: Characteristic, value: bytes)[source]

Characteristic indication hook.

This hook is called when a indication is sent to a characteristic.

Parameters:
  • service (Service) – Service owning the characteristic

  • characteristic (Characteristic) – Characteristic object

  • value (bytes) – Characteristic value

on_mtu_changed(mtu: int)[source]

MTU change callback

Parameters:

mtu (int) – New MTU value

on_notification(service: Service, characteristic: Characteristic, value: bytes)[source]

Characteristic notification hook.

This hook is called when a notification is sent to a characteristic.

Parameters:
  • service (Service) – Service owning the characteristic

  • characteristic (Characteristic) – Characteristic object

  • value (bytes) – Characteristic value

register_attribute(attribute: Attribute)[source]

Register a GATT attribute

Parameters:

attribute (Attribute) – Attribute to register

remove_service(service: Service, handles_only: bool = False)[source]

Remove service

Parameters:
  • service (Service) – Service object or UUID

  • handles_only (bool) – Remove only handles if set to True

service(uuid: str | UUID) Service | None[source]

Retrieve a Service object given its UUID.

Parameters:

uuid (UUID, str) – Service UUID

Returns:

Corresponding Service object if found, None otherwise.

Return type:

Service

Raise:

InvalidUUIDException

services() Iterator[Service][source]

Enumerate service objects.

This method is a generator and will yield service objects registered into the profile.

update_service(service: Service) bool[source]

Update service in profile.

Keep service in place in the service list, but update all the services declared after this one.

Parameters:

service (Service) – Service object to update.

Returns:

True if service has been updated, False otherwise.

Return type:

bool

class whad.ble.Service(type_uuid: UUID, uuid: UUID, handle: int = 0, end_handle: int = 0, **children)[source]

GATT service attribute

__init__(type_uuid: UUID, uuid: UUID, handle: int = 0, end_handle: int = 0, **children)[source]

Instantiate a new service attribute with the specified handle.

Parameters:
  • type_uuid (UUID) – Attribute type UUID

  • uuid (UUID) – Service UUID

  • handle (int) – Service handle

  • end_handle (int) – Handle of last attribute in the service

  • children (dict, optional) – List of children attributes to add into this service

add_characteristic(characteristic: Characteristic)[source]

Add characteristic into this service.

Parameters:

characteristic (Characteristic) – Characteristic object to add into this service.

add_included_service(included_service: IncludeService)[source]

Add include service definition.

Parameters:

included_service (IncludeService) – Include service definition

build()[source]

Build a new service based on current template class.

char(uuid: str | UUID) Characteristic | None[source]

Get characteristic by UUID.

Parameters:

uuid (UUID) – Searched characteristic’s UUID

Returns:

Characteristic object if found, None otherwise

Return type:

Characteristic, optional

Raises:

InvalidUUIDException – Invalid UUID

characteristics() Iterator[Characteristic][source]

Enumerate characteristics.

Returns:

Iterator over this service’s characteristics.

property end_handle: int

End handle

get_characteristic(uuid: str | UUID) Characteristic | None[source]

Get characteristic by UUID.

Deprecated since version 1.3.0: Use char() instead of get_characteristic().

Parameters:

uuid (UUID, str) – Searched characteristic’s UUID

Returns:

Characteristic object if found, None otherwise

Return type:

Characteristic, optional

Raises:

InvalidUUIDException – Invalid UUID

property handle: int

Attribute handle

included_services() Iterator[IncludeService][source]

Enumerate included services

property name: str

Readable service name

Returns:

Service name as readable text, if either defined in the Bluetooth specification or known from DarkMentorLLC’s CLUES database.

Return type:

str

payload()[source]

Return service attribute’s value.

Returns:

Service attribute value

Return type:

bytes

remove_characteristic(characteristic: UUID | Type[Characteristic])[source]

Remove a specific characteristic

Parameters:

characteristic (Characteristic, UUID) – Characteristic object to remove from service’s characteristics.

remove_include_service(included_service: UUID | Type[IncludeService])[source]

Remove a specific include service definition.

Parameters:

included_service (IncludeService, UUID) – Include service definition or its UUID

property uuid: UUID

Service UUID

class whad.ble.PrimaryService(uuid: UUID, handle: int = 0, end_handle: int = 0, **characteristics)[source]

Primary service attribute.

This attribute has a type UUID of 0x2800.

__init__(uuid: UUID, handle: int = 0, end_handle: int = 0, **characteristics)[source]

Initialize a primary service of UUID uuid and declare the requested characteristics.

Parameters:
  • uuid (UUID) – Service UUID

  • handle (int, optional) – Service handle

  • end_handle (int, optional) – Handle of service’s last attribute

  • characteristics (dict) – Additional characteristics’s definitions to add into this service

class whad.ble.SecondaryService(uuid, handle: int = 0)[source]

Secondary service attribute.

This attribute has a type UUID of 0x2801.

__init__(uuid, handle: int = 0)[source]

Initialize a secondary service identified by UUID uuid,

class whad.ble.IncludeService(uuid, handle=0, start_handle=0, end_handle=0)[source]

IncludeService Attribute class

This class stores the information related to an included service:

  • the included service UUID (16-bit or 128-bit UUID)

  • the start and end handles of the said included service

__init__(uuid, handle=0, start_handle=0, end_handle=0)[source]

Initialize an included service

Parameters:
  • uuid (UUID) – Included service UUID

  • handle (int) – Included service start handle

  • end_handle (int) – Included service end handle

property end_handle

Return this attribute end handle

This attribute does not belong to a group so its end handle is the same than its handle.

property name: str

Generate the description of the included service definition attribute.

payload() bytes[source]

Return service UUID as bytes

property service_end_handle: int

Return the included service end handle

property service_start_handle: int

Return the included service start handle

property service_uuid: UUID

Return the included service UUID

property uuid: UUID

Return the attribute type UUID.

class whad.ble.Characteristic(uuid: UUID, handle: int = 0, end_handle: int = 0, value: bytes = b'', properties: int = 0, permissions: List[str] | None = None, notify: bool = False, indicate: bool = False, required: bool = False, description: str | None = None, security: SecurityAccess | None = None, descriptors: List[Descriptor] = [])[source]

BLE Characteristic

__init__(uuid: UUID, handle: int = 0, end_handle: int = 0, value: bytes = b'', properties: int = 0, permissions: List[str] | None = None, notify: bool = False, indicate: bool = False, required: bool = False, description: str | None = None, security: SecurityAccess | None = None, descriptors: List[Descriptor] = [])[source]

Instantiate a BLE characteristic object

Parameters:
  • uuid – 16-bit or 128-bit UUID

  • handle (int) – Handle value

  • value (bytes) – Characteristic value

  • perms (int) – Permissions

add_descriptor(descriptor: Descriptor) Characteristic[source]

Add a descriptor

Parameters:

descriptor (whad.ble.profile.characteristic.Descriptor) – Descriptor instance to add to this characteristic.

property alias: str | None

Characteristic alias.

attach(service)[source]

Attach this characteristic to a service.

Parameters:

service (Service) – Service referenced

build()[source]

Build a new characteristic from current object.

can_indicate() bool[source]

Determine if characteristic sends indications.

Returns:

True if characteristic sends indication, False otherwise.

Return type:

bool

can_notify() bool[source]

Determine if characteristic sends notifications.

Returns:

True if characteristic sends notification, False otherwise.

Return type:

bool

check_security_property(access_type, prop)[source]

Returns a boolean indicating if a property is required for a given access type.

Parameters:
  • access_type (SecurityAccess) – access type to check

  • property (SecurityProperty) – security property to check

descriptors() Iterator[Descriptor][source]

Iterate over the registered descriptors (generator)

property end_handle

Characteristic end handle

get_client_config()[source]

Find characteristic client configuration descriptor

get_descriptor(desc_type: UUID | Type[Descriptor]) Descriptor | None[source]

Retrieve a decriptor based on its type UUID or class.

Parameters:

desc_type (UUID, whad.ble.profile.characteristic.Descriptor) – Descriptor type

Returns:

First matching descriptor belonging to this characteristic

Return type:

whad.ble.profile.Descriptor, optional

get_security_access(access_type)[source]

Returns the security access properties linked to an access type.

Parameters:

access_type (SecurityAccess) – access type to check

property handle: int

Attribute handle

must_indicate()[source]

Determine if an indication must be sent for this characteristic.

Indication must be sent when a characteristic has the indication property and its ClientCharacteristicConfiguration descriptor has indications enabled.

must_notify()[source]

Determine if a notification must be sent for this characteristic.

Notification must be sent when a characteristic has the notification property and its ClientCharacteristicConfiguration descriptor has notifications enabled.

property name

Characteristic standard name (if any)

payload()[source]

Return characteristic payload

property properties

Characteristic properties

readable()[source]

Determine if characteristic can be read

property security: SecurityAccess

Returns security access property

property service

Service this characteristic belongs to.

set_indication_callback(callback)[source]

Save the provided callback as indication callback

set_notification_callback(callback)[source]

Save the provided callback as notification callback

property uuid: UUID

Characteristic UUID

property value

Attribute value

property value_attr

Associated value attribute

property value_handle

Characteristic value handle

writeable()[source]

Determine if characteristic can be written to

class whad.ble.Descriptor(uuid: UUID, handle: int = 0, value: bytes = b'', characteristic: Characteristic | None = None)[source]

BLE Characteristic descriptor

__init__(uuid: UUID, handle: int = 0, value: bytes = b'', characteristic: Characteristic | None = None)[source]

Instantiate a GATT Attribute

property characteristic: Characteristic | None

Parent characteristic

static from_uuid(characteristic, handle: int, uuid: UUID, value: bytes)[source]

Create an instance of a descriptor based on the provided UUID and descriptor value.

Parameters:
  • uuid (UUID) – Descriptor UUID

  • value (bytes) – Descriptor value

Returns:

Instance of the corresponding descriptor

Return type:

Descriptor

static get_type_uuid(desc_cls) UUID | None[source]

Find the type UUID corresponding to a given registered descriptor’s class.

Returns:

Descriptor’s type UUID if found, None otherwise.

Return type:

UUID

property name

Descriptor name

static register_type(uuid: UUID, cls)[source]

Register descriptor type (associate a descriptor UUID with the corresponding Python class (must inherit from Descriptor)

property uuid

Descriptor UUID

class whad.ble.ClientCharacteristicConfig(handle: int = 0, notify: bool = False, indicate: bool = False, characteristic: Characteristic | None = None)[source]

Client Characteristic Configuration Descriptor

__init__(handle: int = 0, notify: bool = False, indicate: bool = False, characteristic: Characteristic | None = None)[source]

Instantiate a Client Characteristic Configuration Descriptor

Parameters:
  • notify (bool) – Set to True to get the corresponding characteristic notified on change

  • indicate (bool) – Set to True to get the corresponding characteristic indicated on change

property config

CCCD configuration

static from_value(characteristic, handle, value)[source]

Create a ClientCharacteristicConfig instance from the provided handle and value, and tie it to a specific characteristic.

class whad.ble.UserDescription(handle: int = 0, description: str = '', characteristic: Characteristic | None = None)[source]

Characteristic user description descriptor.

This descriptor specifies a textual description of the characteristic it is attached to. This description is exposed by the GATT server and can be read by a GATT client.

__init__(handle: int = 0, description: str = '', characteristic: Characteristic | None = None)[source]

Instantiate a Characteristic User Description descriptor

Parameters:
  • description (str) – Set characteristic text description

  • characteristic (Characteristic, optional) – Characteristic this descriptor is attached to, not required when defining a GATT model.

static from_value(characteristic, handle, value)[source]

Create CUD descriptor from value

property name

Descriptor name

Clean description as it may contain null chars.

property text: str

User description

class whad.ble.DeviceInformationService(handle: int = 0, end_handle: int = 0, **children)[source]

Device Information Service version 1.2 as defined in specification.

class whad.ble.BatteryService(handle: int = 0, end_handle: int = 0)[source]

Battery Service Profile

This service implements the BLE Battery Service as described in the spec.

property percentage: int

Battery level as percentage.

class whad.ble.HeartRateService(handle: int = 0, end_handle: int = 0)[source]

Heart Rate service version 1.0 as defined in specification.

class UpdateEvent(rate: int, energy_expended: int | None, skin_contact: bool | None)[source]

Heart Rate service update event.

property energy_expended: int | None

Energy expended, if available.

property heart_rate: int

Heart Rate value

property skin_contact: bool | None

Skin contact detected, if sensor is present.

property contact_sensor: bool

Contact sensor present

enable_contact(contact: bool)[source]

Enable/disable contact support.

property energy_expended: int | None

Energy expended in kJ

on_update(_: Characteristic, value: bytes, __: bool = False)[source]

Process incoming notifications.

property rate: int

Heart rate in BPM.

set_location(location: str)[source]

Update body sensor location’s characteristic value.

Parameters:

location (str) – Sensor location

property skin_contact: bool

Skin contact status

update(rate: int, energy: int | None = None, skin: bool | None = None)[source]

Update the measurement characteristic with the corresponding values.

Parameters:
  • rate (int) – Current heart rate in BPM

  • energy (int, optional) – Energy expended in kJ

  • skin (bool, optional) – Skin contact

Deprecated

class whad.ble.GenericProfile(start_handle: int = 1, from_json: str | None = None)[source]

Old name of the Profile class, kept for backward compatibility.

Changed in version 1.3.0: GenericProfile has been renamed to Profile to simplify code and due to a change in the way standard services are now declared within a GATT profile class.

In previous versions, including a Battery Service into a custom profile required to inherit from both GenericProfile and BatteryService. A generic profile was then considered as an empty GATT profile that could be used to create default profiles, an idea now put aside because it does not fit in our vision of GATT profiles anymore.

__init__(start_handle: int = 1, from_json: str | None = None)

Parse the device model, instantiate all the services, characteristics and descriptors, compute all handle values and registers everything inside this instance for further use.

Parameters:
  • start_handle (int) – Start handle value to use (default: 0)

  • from_json (str) – JSON data describing a GATT profile