Bluetooth LE (BLE)

BleUuid

Services and characteristics are typically identified by their UUID. There are two types:

  • 16-bit (short) UUIDs for well-known BLE services
  • 128-bit (long) UUIDs for everything else

The 16-bit service IDs are assigned by the Bluetooth SIG and are listed here.

The 16-bit characteristic IDs are listed here.

You can create a 16-bit UUID like this:

// PROTOTYPE
BleUuid(uint16_t uuid16);

// EXAMPLE
BleUuid healthThermometerService(0x1809);

The value 0x1809 is from the assigned list of service IDs.

The 128-bit UUIDs are used for your own custom services and characteristics. These are not assigned by any group. You can use any UUID generator, such as the online UUID generator or tools that you run on your computer. There is no central registry; they are statistically unlikely to ever conflict.

A 128-bit (16 byte) UUID is often written like this: 240d5183-819a-4627-9ca9-1aa24df29f18. It's a series of 32 hexadecimal digits (0-9, a-f) written in a 8-4-4-4-12 pattern.

// PROTOTYPE
BleUuid(const String& uuid);
BleUuid(const char* uuid);

// EXAMPLE
BleUuid myCustomService("240d5183-819a-4627-9ca9-1aa24df29f18");

You can also construct a UUID from an array of bytes (uint8_t):

// PROTOTYPE
BleUuid(const uint8_t* uuid128, BleUuidOrder order = BleUuidOrder::LSB);

// EXAMPLE
BleUuid myCustomService({0x24, 0x0d, 0x51, 0x83, 0x81, 0x9a, 0x46, 0x27, 0x9c, 0xa9, 0x1a, 0xa2, 0x4d, 0xf2, 0x9f, 0x18});

type()

// PROTOTYPE
BleUuidType type() const;

// EXAMPLE
BleUuidType uuidType = uuid.type();

Returns a constant:

  • BleUuidType::SHORT for 16-bit UUIDs
  • BleUuidType::LONG for 128-bit UUIDs

isValid()

// PROTOTYPE
bool isValid() const;
bool valid() const;

// EXAMPLE
bool isValid = uuid.isValid();

Return true if the UUID is valid or false if not.

Since 3.0.0:

In Device OS 3.0.0 and later,, valid() can be used as well. Before, the isValid() method was used.

equality

You can test two UUIDs for equality.

// PROTOTYPE
bool operator==(const BleUuid& uuid) const;
bool operator==(const char* uuid) const;
bool operator==(const String& uuid) const;
bool operator==(uint16_t uuid) const;
bool operator==(const uint8_t* uuid128) const;

// EXAMPLE 1
BleUuid rxUuid("6E400002-B5A3-F393-E0A9-E50E24DCCA9E");
BleUuid txUuid("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");

if (rxUuid == txUuid) {
    // This code won't be executed since they're not equal
}

// EXAMPLE 2
BleUuid foundServiceUUID;
size_t svcCount = scanResult->advertisingData().serviceUUID(&foundServiceUUID, 1);
if (svcCount > 0 && foundServiceUUID == serviceUuid) {
    // Device advertises our custom service "serviceUuid" so try to connect to it
}

rawBytes

Get the underlying bytes of the UUID.

// PROTOTYPE
void rawBytes(uint8_t uuid128[BLE_SIG_UUID_128BIT_LEN]) const;
    const uint8_t* rawBytes() const;
const uint8_t* rawBytes() const;    

operator[]

uint8_t operator[](uint8_t i) const;

Since 3.0.0:

In Device OS 3.0.0 and later, you can retrieve a raw bytes of the UUID using the [] operator.

Constructors

Other, less commonly used constructors include:

// PROTOTYPE
BleUuid(const hal_ble_uuid_t& uuid);
BleUuid(const BleUuid& uuid);
BleUuid(const uint8_t* uuid128, BleUuidOrder order = BleUuidOrder::LSB);
BleUuid(const uint8_t* uuid128, uint16_t uuid16, BleUuidOrder order = BleUuidOrder::LSB);
BleUuid(uint16_t uuid16);
BleUuid(const String& uuid);
BleUuid(const char* uuid);

Setters

You normally don't need to set the value of a BleUuid after construction, but the following methods are available:

// PROTOTYPE
BleUuid& operator=(const BleUuid& uuid);
BleUuid& operator=(const uint8_t* uuid128);
BleUuid& operator=(uint16_t uuid16);
BleUuid& operator=(const String& uuid);
BleUuid& operator=(const char* uuid);
BleUuid& operator=(const hal_ble_uuid_t& uuid);