// Copyright (C) 2017 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include #include #include #include #include #include #include #include #include #ifndef Q_OS_ANDROID #include #else #include #endif #include #include #include #include int main(int argc, char *argv[]) { // QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); #ifndef Q_OS_ANDROID QCoreApplication app(argc, argv); #else QGuiApplication app(argc, argv); #endif //! [Advertising Data] QLowEnergyAdvertisingData advertisingData; advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral); advertisingData.setIncludePowerLevel(true); advertisingData.setLocalName("HeartRateServer"); advertisingData.setServices(QList() << QBluetoothUuid::ServiceClassUuid::HeartRate); //! [Advertising Data] //! [Service Data] QLowEnergyCharacteristicData charData; charData.setUuid(QBluetoothUuid::CharacteristicType::HeartRateMeasurement); charData.setValue(QByteArray(2, 0)); charData.setProperties(QLowEnergyCharacteristic::Notify); const QLowEnergyDescriptorData clientConfig(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration, QByteArray(2, 0)); charData.addDescriptor(clientConfig); QLowEnergyServiceData serviceData; serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary); serviceData.setUuid(QBluetoothUuid::ServiceClassUuid::HeartRate); serviceData.addCharacteristic(charData); //! [Service Data] //! [Start Advertising] const QScopedPointer leController(QLowEnergyController::createPeripheral()); QScopedPointer service(leController->addService(serviceData)); leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData, advertisingData); //! [Start Advertising] //! [Provide Heartbeat] QTimer heartbeatTimer; quint8 currentHeartRate = 60; enum ValueChange { ValueUp, ValueDown } valueChange = ValueUp; const auto heartbeatProvider = [&service, ¤tHeartRate, &valueChange]() { QByteArray value; value.append(char(0)); // Flags that specify the format of the value. value.append(char(currentHeartRate)); // Actual value. QLowEnergyCharacteristic characteristic = service->characteristic(QBluetoothUuid::CharacteristicType::HeartRateMeasurement); Q_ASSERT(characteristic.isValid()); service->writeCharacteristic(characteristic, value); // Potentially causes notification. if (currentHeartRate == 60) valueChange = ValueUp; else if (currentHeartRate == 100) valueChange = ValueDown; if (valueChange == ValueUp) ++currentHeartRate; else --currentHeartRate; }; QObject::connect(&heartbeatTimer, &QTimer::timeout, heartbeatProvider); heartbeatTimer.start(1000); //! [Provide Heartbeat] auto reconnect = [&leController, advertisingData, &service, serviceData]() { service.reset(leController->addService(serviceData)); if (!service.isNull()) leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData, advertisingData); }; QObject::connect(leController.data(), &QLowEnergyController::disconnected, reconnect); return app.exec(); }