// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
    \example heartrate-server
    \title Bluetooth Low Energy Heart Rate Server
    \examplecategory {Connectivity}
    \brief An example demonstrating how to set up and advertise a GATT service. The example
    demonstrates the use of the Qt Bluetooth Low Energy classes related to peripheral (slave)
    functionality.

    The Bluetooth Low Energy Heart Rate Server is a command-line application that shows how to
    develop a Bluetooth GATT server using the Qt Bluetooth API.
    The application covers setting up a service, advertising it and notifying clients about changes
    to characteristic values.

    The example makes use of the following Qt classes:

    \list
        \li \l QLowEnergyAdvertisingData
        \li \l QLowEnergyAdvertisingParameters
        \li \l QLowEnergyServiceData
        \li \l QLowEnergyCharacteristicData
        \li \l QLowEnergyDescriptorData
        \li \l QLowEnergyController
        \li \l QLowEnergyService

    \endlist

    The example implements a server application, which means it has no graphical user interface.
    To visualize what it is doing, you can use the \l {heartrate-game}{Heart Rate Game}
    example, which is basically the client-side counterpart to this application.

    \note By default on Linux a kernel socket API is used for advertising, which
    means that a privileged access is required to start advertising. This can
    be achieved by running the example as root, for instance via \c sudo.
    Starting from Qt 6.5, an alternative approach is to use the BlueZ D-Bus
    backend for advertising, which does not require root access. To enable
    this backend, set \c QT_BLUETOOTH_USE_DBUS_PERIPHERAL environment variable.

    \section1 Setting up Advertising Data and Parameters

    Two classes are used to configure the advertising process:
    \list
        \li \l QLowEnergyAdvertisingData specifies which information is to be
            broadcasted
        \li \l QLowEnergyAdvertisingParameters is used for specific aspects such
            as setting the advertising interval or controlling which devices are
            allowed to connect.
    \endlist

    In our example, we simply use the default parameters.

    The information contained in the \l QLowEnergyAdvertisingData will be visible to other devices
    that are currently scanning. They can use it to decide whether they want to establish a connection
    or not. In our example, we include the type of service we offer, a name that adequately
    describes our device to humans, and the transmit power level of the device. The latter is
    often useful to potential clients, because they can tell how far away our device is by
    comparing the received signal strength to the advertised one.
    \note Space for the advertising data is very limited (only 31 bytes in total), so
          variable-length data such as the device name should be kept as short as possible.
    \snippet heartrate-server/main.cpp Advertising Data

    \section1 Setting up Service Data
    Next we configure the kind of service we want to offer. We use the
    \l {QBluetoothUuid::ServiceClassUuid}{Heart Rate} service as defined in the
    Bluetooth specification in its minimal form, that is, consisting only of the
    \l {QBluetoothUuid::CharacteristicType}{Heart Rate Measurement} characteristic.
    This characteristic must support the \l {QLowEnergyCharacteristic::}{Notify}
    property (and no others), and it needs to have a \l {QBluetoothUuid::DescriptorType}
    {Client Characteristic Configuration} descriptor, which enables clients to
    register to get notified about changes to characteristic values. We set the
    initial heart rate value to zero, as it cannot be read anyway (the only way
    the client can get the value is via notifications).
    \snippet heartrate-server/main.cpp Service Data

    \section1 Advertising and Listening for Incoming Connections
    Now that all the data has been set up, we can start advertising. First we create a
    \l QLowEnergyController object in the
    \l {QLowEnergyController::PeripheralRole} {peripheral role} and use it to create a (dynamic)
    \l QLowEnergyService object from our (static) \l QLowEnergyServiceData.
    Then we call \l QLowEnergyController::startAdvertising().
    Note that we hand in our \l QLowEnergyAdvertisingData twice: The first argument
    acts as the actual advertising data, the second one as the scan response data. They could
    transport different information, but here we don't have a need for that. We also pass
    a default-constructed instance of \l QLowEnergyAdvertisingParameters, because the default
    advertising parameters are fine for us. If a client is interested in the advertised service,
    it can now establish a connection to our device. When that happens, the device stops advertising
    and the \l QLowEnergyController::connected() signal is emitted.
    \note When a client disconnects, advertising does not resume automatically. If you want that
          to happen, you need to connect to the \l QLowEnergyController::disconnected() signal
          and call \l QLowEnergyController::startAdvertising() in the respective slot.
    \snippet heartrate-server/main.cpp Start Advertising

    \section1 Providing the Heartrate
    So far, so good. But how does a client actually get at the heart rate? This happens by
    regularly updating the value of the respective characteristic in the \l QLowEnergyService
    object that we received from the \l QLowEnergyController in the code snippet above.
    The source of the heart rate would normally be some kind of sensor, but in our example,
    we just make up values that we let oscillate between 60 and 100. The most important part in the
    following code snippet is the call to \l QLowEnergyService::writeCharacteristic. If
    a client is currently connected and has enabled notifications by writing to the aforementioned
    \c {Client Characteristic Configuration}, it will get notified about the new value.
    \snippet heartrate-server/main.cpp Provide Heartbeat
*/

