SimpleBLE

Advertise

Host a local BLE peripheral and advertise a GATT service so nearby centrals can connect.

Advertising is how this host is found. A local peripheral serves GATT, sends advertisements, and waits for a central to connect.

SimpleBLE::Peripheral is a remote device. SimpleBLE::Local::Peripheral is this host. Create the local peripheral from an Adapter, the same object used to scan.

Available on all supported platforms

The C++ API can host a local peripheral on every supported platform. Native Android applications must provide their application context with SimpleBLE::Advanced::Android::set_context() before creating the local peripheral. SimpleDroidBLE exposes the same flow directly in Kotlin.

Flow

  1. Get an adapter.
  2. Create a local peripheral.
  3. Select the advertised service UUIDs, if needed.
  4. Add services and characteristics.
  5. Register client or write callbacks if you need them.
  6. Call start(), keep the process alive, then stop().
auto adapters = SimpleBLE::Adapter::get_adapters();
auto adapter = adapters.front();
auto peripheral = adapter.create_local_peripheral();

peripheral.add_advertised_service("12345678-1234-5678-1234-56789abcdef0");

auto service = peripheral.add_service("12345678-1234-5678-1234-56789abcdef0");
auto characteristic = service.add_characteristic(
    "12345678-1234-5678-1234-56789abcdef1",
    {SimpleBLE::Local::CharacteristicCapability::READ,
     SimpleBLE::Local::CharacteristicCapability::WRITE_REQUEST,
     SimpleBLE::Local::CharacteristicCapability::NOTIFY});
characteristic.set_value(SimpleBLE::ByteArray("ready"));

characteristic.set_callback_on_write([&characteristic](SimpleBLE::ByteArray value) {
    // Echo the written value to subscribed clients.
    characteristic.set_value(std::move(value));
});

peripheral.set_callback_on_client_connected(
    [](SimpleBLE::BluetoothAddress address) {
        std::cout << "Client connected: " << address << std::endl;
    });

peripheral.start();

Configure services, characteristics, and advertising before start(). While started, update data with set_value() rather than rebuilding the GATT table. set_value() also publishes the latest value to subscribed clients when the characteristic has NOTIFY or INDICATE capability.

SimpleBLE permits the same adapter to scan while the local peripheral is started when the platform Bluetooth stack and controller support concurrent scanning and advertising. On Linux, BlueZ and the controller must support both operations at the same time.

Practical notes

  • Keep the process alive after start(). Advertising stops when the object is destroyed or stop() is called.
  • Pass capabilities as a std::set (an initializer list is enough). Each characteristic needs at least one capability.
  • On Linux, BlueZ must be running and the process must have D-Bus access, as with scanning.
  • On macOS, CoreBluetooth reports client connection and disconnection callbacks when the client first subscribes and finally unsubscribes.
  • On Windows, the adapter and driver must support the peripheral role. Applications distributed as AppX/MSIX packages should declare <DeviceCapability Name="bluetooth" /> in Package.appxmanifest; ordinary unpackaged executables do not need this manifest declaration. Windows controls the advertised Bluetooth name.
  • On Android, SimpleBLE includes the adapter's system Bluetooth name. Android's public advertising API cannot set an arbitrary per-advertisement name.
  • Linux, macOS, and iOS callers that need a platform-specific advertised name can use set_advertisement_local_name() from the corresponding SimpleBLE::Advanced platform namespace before start().

For the full C++ walkthrough, see Advertise, Serve, Publish. For scanning from the other side of the link, see Scan.

On this page