Planned maintenance: From Sunday 8th December 10:00 CET there will be changes to try and solve the caching issues that have been experienced. If anyone has a problem connecting after this period then please PM @AndyS or any of the moderators.

Cannot change QtBluetooth advertising service



  • I have been experimenting with the BLE Heart Rate Server and BLE Scanner examples, and was successful in getting a Qualcomm DragonBoard 410C and an Android phone to work together and detect the Heart Rate service. The problem is, now that I have modified the original BLE Heart Rate Server example so that QBluetoothUuid::HeartRate is now QBluetoothUuid::BatteryService, and QBluetoothUuid::HeartRateMeasurement is now QBluetoothUuid::BatteryLevel, the BLE Scanner app on Android still says the "HeartRateServer" has a HeartRate service instead of a BatteryService. I have power cycled both devices and cannot figure out why this is happening. Below is my BLE Heart Rate Server modified main.cpp. I am checking all of the serviceUuid values of the advertisingData and serviceData in the std::cout << "service: " statements, they all output 6159 which is expected, the BatteryService uuid. I also changed the localName to "HeartRateServ" to make sure the Android phone is actually reading the new device, and it does, so that is not the issue.

    int main(int argc, char *argv[])
    {
        QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
        QCoreApplication app(argc, argv);
    
        //! [Advertising Data]
        QLowEnergyAdvertisingData advertisingData;
        advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral);
        advertisingData.setIncludePowerLevel(true);
        advertisingData.setLocalName("HeartRateServ");
        advertisingData.setServices(QList<QBluetoothUuid>() << QBluetoothUuid(QBluetoothUuid::BatteryService));
        std::cout << "service: " << advertisingData.services()[0].data1 << std::endl;
        //! [Advertising Data]
    
        //! [Service Data]
        QLowEnergyCharacteristicData charData;
        charData.setUuid(QBluetoothUuid::BatteryLevel);
        charData.setValue(QByteArray(1, 50));
        charData.setProperties(QLowEnergyCharacteristic::Notify);
        const QLowEnergyDescriptorData clientConfig(QBluetoothUuid::ClientCharacteristicConfiguration,
                                                    QByteArray(2, 0));
        charData.addDescriptor(clientConfig);
    
        QLowEnergyServiceData serviceData;
        serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
        serviceData.setUuid(QBluetoothUuid(QBluetoothUuid::BatteryService));
        serviceData.addCharacteristic(charData);
        //! [Service Data]
    
        //! [Start Advertising]
        const QScopedPointer<QLowEnergyController> leController(QLowEnergyController::createPeripheral());
        const QScopedPointer<QLowEnergyService> service(leController->addService(serviceData));
        std::cout << "service: " << advertisingData.services()[0].data1 << std::endl;
        std::cout << "service2: " << serviceData.uuid().data1 << std::endl;
        leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData, advertisingData);
        std::cout << "service3: " << advertisingData.services()[0].data1 << std::endl;
        std::cout << "service4: " << serviceData.uuid().data1 << std::endl;
        //! [Start Advertising]
    
        //! [Provide Heartbeat]
    //    QTimer heartbeatTimer;
    //    quint8 currentHeartRate = 60;
    //    enum ValueChange { ValueUp, ValueDown } valueChange = ValueUp;
    //    const auto heartbeatProvider = [&service, &currentHeartRate, &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::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]
        QByteArray value;
        value.append(char(51));
        service->writeCharacteristic(service->characteristic(QBluetoothUuid::BatteryLevel), value);
        auto reconnect = [&leController, advertisingData]() {
            leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData,
                                           advertisingData);
        };
        QObject::connect(leController.data(), &QLowEnergyController::disconnected, reconnect);
    
        return app.exec();
    }
    


  • Hi, did you find a way to solve this issue? I have the same problem, I modified the Heart Rate Server example to advertise a custom uuid but my iPhone app is still discovering Heart Rate service. I have also tried advertising Battery Service as you did in your question but the problem persists.



  • @Scarlet I solved the problem, iPhone was caching bluetooth data for the peripheral which is why it was always discovering the same service and characteristic. Turning bluetooth off and on again on iPhone fixed the problem. Hopefully this might help someone who runs into the same issue.


Log in to reply