0

I try to develope a windows 10 software on Qt creator(C++) who need the heart frequency. I buy the sensor below who transfer it's data by bluetooth(BLE:bluetooth low energy):

https://www.decathlon.fr/p/ceinture-cardiofrequencemetre-course-a-pied-dual-ant-bluetooth-smart/_/R-p-128085

but when i try to read the value, i have a empty buffer.

the sensor work correcly on a android appli (on play store)

my code :

initialisation:OK

TWindowsStatistique::TWindowsStatistique(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::TWindowsStatistique)
{
      QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
      connect(discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),this, SLOT(deviceDiscovered(QBluetoothDeviceInfo)));
      discoveryAgent->start();
}

get the list of bluetooth device:OK

void TWindowsStatistique::deviceDiscovered(const QBluetoothDeviceInfo &device)
{
    if(device.name()=="Decathlon Dual HR")
    {
        m_device=device;
        if (!controller) 
        {
            controller = QLowEnergyController::createCentral(device);
            connect(controller, &QLowEnergyController::connected,this, &TWindowsStatistique::deviceConnected);
            connect(controller, QOverload<QLowEnergyController::Error>::of(&QLowEnergyController::error),this, &TWindowsStatistique::errorReceived);
            connect(controller, &QLowEnergyController::disconnected,this, &TWindowsStatistique::deviceDisconnected);
        }
        controller->connectToDevice();
    }
}

get service list:OK

void TWindowsStatistique::deviceConnected()
{
    connect(controller, &QLowEnergyController::serviceDiscovered,this, &TWindowsStatistique::addLowEnergyService);
    connect(controller, &QLowEnergyController::discoveryFinished,this, &TWindowsStatistique::serviceScanDone);
    controller->discoverServices();
}


void TWindowsStatistique::addLowEnergyService(const QBluetoothUuid &newService)
{
    QLowEnergyService *service = controller->createServiceObject(newService);
    if (!service) return;

    if(service->serviceName()=="Heart Rate")
    {
        heart_rate_service=service;
    }
}


void TWindowsStatistique::serviceScanDone()
{
    if(heart_rate_service!=NULL)
    {
        connect(heart_rate_service, &QLowEnergyService::stateChanged, this, &TWindowsStatistique::serviceDetailsDiscovered);
        heart_rate_service->discoverDetails();
    }
}

get caracteristic list :OK with heart rate data : NOK


void TWindowsStatistique::serviceDetailsDiscovered(QLowEnergyService::ServiceState newState)
{
    const QList<QLowEnergyCharacteristic> chars = heart_rate_service->characteristics();
    for (int i=0;i<chars.size();i++)
    {
        QLowEnergyCharacteristic tmp_char=chars.at(i);
        if(tmp_char.name()=="Heart Rate Measurement")//the code go in : **OK**
        {
            qDebug() << "carac value" << chars.at(i).value().toHex();//return a empty buffer : **NOK**

            //test by using a class with notify requerement : **NOK**
            // in THeartRateCharacteristic.h: Q_PROPERTY(QString characteristicValue READ getValue NOTIFY characteristicChanged)
            heart_rate_characteristic = new THeartRateCharacteristic(tmp_char);
            
            //test by using characteristicChanged : slot isn't call : **NOK**
            connect(heart_rate_characteristic, SIGNAL(characteristicChanged()), this, SLOT(heart_rate_update()));

            //try tu use readCharacteristic : the sensor doesn't answer **NOK**
            heart_rate_service->readCharacteristic(tmp_char);

            //Test to put notification flag to 1 : **heart rate data stay empty**
            for(int j=0;j<chars.at(i).descriptors().size();j++)
            {
                if(chars.at(i).descriptors().at(j).name()=="Client Characteristic Configuration")
                {
                    QByteArray tmp=chars.at(i).descriptors().at(j).value();
                    tmp[1]=0;
                    tmp[0]=1;
                    if(chars.at(i).descriptors().at(j).value().compare(tmp)!=0)
                    {
                        connect(heart_rate_service, &QLowEnergyService::descriptorWritten,this, &TWindowsStatistique::descriptorWritten_slot);
                        connect(heart_rate_service, SIGNAL(error(QLowEnergyService::ServiceError)),this, SLOT(service_error_slot(QLowEnergyService::ServiceError)));
                        heart_rate_service->writeDescriptor(chars.at(i).descriptors().at(j),tmp);
                    }
                }
            }

        }
    }
}



void TWindowsStatistique::timer_1s_timeout()
{
    if(heart_rate_characteristic)
    {
            qDebug() << "timer: data value:" << heart_rate_characteristic->getValue();//return a empty buffer : **NOK**
    }
}
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
ppac
  • 1
  • 2
  • **NEW:** I tester the other data and I can read them. the difference with heart rate is that it's type is 'NOTIFY' and not 'Read'. I seen that there had been a problem with BLE notification : [https://forum.qt.io/topic/122098/qt-bluetooth-low-energy-notification-bug-downgrade-qt] I try to had "BLUETOOTH_FORCE_DBUS_LE_VERSION=5.41 /path" in .pro with path of exe but it do nothing. – ppac Aug 16 '21 at 00:40
  • What do you mean by "Test to put notification flag to 1 : **heart rate data stay empty**"? After you set the CCCD to 1, considering your code, `heart_rate_update()` should be executed whenever a new HRM value is being notified. Isn't that what happens? – jpo38 Aug 16 '21 at 08:16

2 Answers2

0

connect(heart_rate_characteristic, SIGNAL(characteristicChanged()), this, SLOT(heart_rate_update())); won't work as the signal characteristicChanged is declared in QLowEnergyService service class, not in QLowEnergyCharacteristic characteristic class, so you must use the service to connection this signal to your slot.

By the way, I recommende that you try Qt sample project "Bluetooth Low Energy Heart Rate Game", this provides full code doing exactly what you want. Just compile and run it. Then, if it works smartly with your device, compare code to yours and possibly use a debugger to understand why your code fails while this one works.

jpo38
  • 20,821
  • 10
  • 70
  • 151
  • as say in the code : the slot "heart_rate_update()" is never call, even with CCCD to 1. – ppac Aug 16 '21 at 13:26
  • I try the "Bluetooth Low Energy Heart Rate Game", I can't compile it directly, because I with MSVC 2017 5.12.11 ans the project was developed in 6.2. after the regression modif done(signal(errorOccured) -> signal(error) // rename QLowEnergyService::ServiceState flag) the function stay in first screen(waiting screen). I will try to download MSVC 2019 – ppac Aug 16 '21 at 13:32
  • See my edited answer, you are not using the good object when establishing connection from `characteristicChanged` signal to your slot. – jpo38 Aug 16 '21 at 13:41
0

I tested Qt sample project "Bluetooth Low Energy Heart Rate Game" with QT5.12 (MSVC 2017) => I stay in the waiting screem. I tested Qt sample project "Bluetooth Low Energy Heart Rate Game" with QT6.02 (MSVC 2019) => It's work.

so I will continue my sowftware in 6.2 with MSVC 2019.

@jpo38 : thank for you help

ppac
  • 1
  • 2