从 BLE 传感器获取心脏频率

get heart frequency frome a BLE sensor

我尝试在需要心脏频率的Qt creator(C++) 上开发一个windows 10 软件。我买了下面的传感器,它通过蓝牙传输数据(BLE:蓝牙低能量):

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

但是当我尝试读取值时,我有一个空缓冲区。

传感器在 android 应用程序(Play 商店)上正常工作

我的代码:

初始化: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();
}

获取蓝牙设备列表:确定

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();
    }
}

获取服务列表:确定

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();
    }
}

获取特征列表:确定 有心率数据: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**
    }
}

connect(heart_rate_characteristic, SIGNAL(characteristicChanged()), this, SLOT(heart_rate_update())); 将不起作用,因为信号 characteristicChangedQLowEnergyService 服务 class 中声明,而不是在 QLowEnergyCharacteristic 特征 class 中声明, 因此您必须使用该服务将此信号连接到您的插槽。

顺便说一句,我建议您尝试 Qt 示例项目“蓝牙低功耗心率游戏”,它提供了完全符合您要求的完整代码。只需编译并 运行 它。然后,如果它在您的设备上运行良好,请将代码与您的代码进行比较,并可能使用调试器来了解为什么您的代码在该设备运行时失败。

我用 QT5.12 (MSVC 2017) 测试了 Qt 示例项目“蓝牙低功耗心率游戏”=> 我一直在等待屏幕。 我用 QT6.02 (MSVC 2019) 测试了 Qt 示例项目“蓝牙低功耗心率游戏”=> 成功了。

所以我将在 6.2 中使用 MSVC 2019 继续我的软件。

@jpo38 : 谢谢你的帮助