QBluetoothSocketPrivate :: _ q_readNotify () 18 ошибка: -1 "Превышено время ожидания соединения" - PullRequest
2 голосов
/ 28 февраля 2020

Я использую qt на встроенной плате для связи с устройством IOS. Встроенная плата работает на qt 5.10 и находится в периферийном режиме. Иногда я получаю вышеупомянутую ошибку, и после этого возникает ошибка Bluetooth с сигналом ошибки следующим образом

Ошибка: QLowEnergyController :: Error (UnknownError)

Как могу я узнать источник этой проблемы? В документе ничего не говорится об этом.

Код основан на примере сервера сердечного ритма qt https://doc.qt.io/qt-5/qtbluetooth-heartrate-server-example.html

Мой класс для Bluetooth

#include "bluetooth.h"

#define log qDebug()<<"["<<__DATE__<<":"<<QTime::currentTime().toString()<<"]"<<"["<<__LINE__<<"]"<<"["<<__FILE__<<"] "

Bluetooth::Bluetooth(mainprocess *main,QObject *parent) :QObject(parent), mainObject(main)
{

   initializeBluetooth();
}

void Bluetooth::initializeBluetooth(){

   try{
       log<<"Initializing Bluetooth...\n";
       //! [Advertising Data]
       advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral);
       advertisingData.setLocalName("AtlasGo");
       advertisingData.setServices(QList<QBluetoothUuid>() <<QBluetoothUuid::Atlas);


       // For IOS its readonly and for Atlas its write only
       ReadCharacteristicData.setUuid(QBluetoothUuid::ReadCharacteristic);
       ReadCharacteristicData.setProperties(QLowEnergyCharacteristic::Notify);
       ReadCharacteristicDesc.setUuid(QBluetoothUuid::ClientCharacteristicConfiguration);
       ReadCharacteristicDesc.setValue(QByteArray(2,0));
       ReadCharacteristicData.addDescriptor(ReadCharacteristicDesc);



       // For IOS its write only characteristic and for Atlas its read only
       WriteCharactersiticData.setUuid(QBluetoothUuid::WriteCharacteristic);
       WriteCharactersiticData.setProperties(QLowEnergyCharacteristic::Write |QLowEnergyCharacteristic::Notify);
       WriteCharactersiticDesc.setUuid(QBluetoothUuid::AtlasDescriptor);
       WriteCharactersiticDesc.setValue(QByteArray::fromHex("Write").toHex());
       WriteCharactersiticData.addDescriptor(WriteCharactersiticDesc);

       // For IOS its readonly and for Atlas its write only
       ConnectivityData.setUuid(QBluetoothUuid::Connectivity);
       ConnectivityData.setProperties(QLowEnergyCharacteristic::Notify);
       ConnectivityDesc.setUuid(QBluetoothUuid::ClientCharacteristicConfiguration);
       ConnectivityDesc.setValue(QByteArray(2, 0));
       ConnectivityData.addDescriptor(ConnectivityDesc);


       // For IOS its write only characteristic and for Atlas its read only
       TrackerData_Data.setUuid(QBluetoothUuid::TrackingData);
       TrackerData_Data.setProperties(QLowEnergyCharacteristic::Notify);
       TrackerDesc.setUuid(QBluetoothUuid::ClientCharacteristicConfiguration);
       TrackerDesc.setValue(QByteArray(2, 0));
       TrackerData_Data.addDescriptor(TrackerDesc);



       serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
       serviceData.setUuid(QBluetoothUuid::Atlas);


       // Adding characteristic to our service
       serviceData.addCharacteristic(ReadCharacteristicData);
       serviceData.addCharacteristic(WriteCharactersiticData);
       serviceData.addCharacteristic(ConnectivityData);
       serviceData.addCharacteristic(TrackerData_Data);



       leController.reset(QLowEnergyController::createPeripheral()); // We are resetting only the pointer here (leController is a scoped pointer)
       service.reset(leController->addService(serviceData));         // Resetting  only the pointer here (service is a scoped pointer)


       while ( localdevice.hostMode()==QBluetoothLocalDevice::HostPoweredOff){

           log<<"Host is powered off";
           system("sudo rfkill unblock 3");
           system("sudo rfkill unblock 0");
           if(localdevice.hostMode()==QBluetoothLocalDevice::HostConnectable)
               break;


       }



       connect(&heartbeatTimer, &QTimer::timeout,mainObject, &mainprocess::TickProvider);
       connect(leController.data(), &QLowEnergyController::disconnected,mainObject,&mainprocess::reconnect);
       connect(leController.data(), &QLowEnergyController::connected,mainObject,&mainprocess::bleConnected);
       connect(service.data(),&QLowEnergyService::characteristicChanged,mainObject,&mainprocess::parseResponse);
       connect(leController.data(), static_cast<void (QLowEnergyController::*)(QLowEnergyController::Error)>(&QLowEnergyController::error),
               this,&Bluetooth::reconnectOnError);

       leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData,advertisingData);

       // We have to check if advertising succeeded ot not. If there was an advertising error we will
       // try to reinitialize our bluetooth service
       while (leController->state()!= QLowEnergyController::AdvertisingState){
           resetBluetoothService();
           leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData,advertisingData);

       }

       // Timer for periodically sending information to IOS
       // Tracking data
       // Connectivity information
       log<<"Starting the Tick Timer Timer";
       heartbeatTimer.start(66);
       //    heartbeatTimer.start(200); Just for testing
   }
   catch(std::exception e)
   {
       log<<"---------------------";
       log<<"Bluetooth Crashed";
       log<<"---------------------";
       log<<"Bluetooth Initialization failed";
       log<<e.what();
       emit recoverBluetooth();
   }


}

void Bluetooth::reconnectOnDisconnect(){


   try{

       log<<"Bluetooth Device Disconnected";
       log<<"Resetting Bluetooth bt.service";


        //resetBluetoothService();
       if(leController->state()!= QLowEnergyController::ConnectedState){
           //leController->disconnectFromDevice();
           leController.reset(QLowEnergyController::createPeripheral());
           service.reset(leController->addService(serviceData));
       }

       if (!service.isNull()){

           if(leController->state()!=QLowEnergyController::AdvertisingState && leController->state()!=QLowEnergyController::ConnectedState){
               leController->startAdvertising(QLowEnergyAdvertisingParameters(),advertisingData,advertisingData);   //, advertisingData);
           }

           // We have to check if advertising succeeded ot not. If there was an advertising error we will
           // try to reinitialize our bluetooth service
           while (leController->state()!= QLowEnergyController::AdvertisingState && leController->state()!= QLowEnergyController::ConnectedState ){
               resetBluetoothService();
               leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData,advertisingData);

           }

           connect(service.data(),&QLowEnergyService::characteristicChanged,mainObject,&mainprocess::parseResponse);
           connect(leController.data(), &QLowEnergyController::disconnected,mainObject,&mainprocess::reconnect);
           connect(leController.data(), &QLowEnergyController::disconnected,mainObject,&mainprocess::stopTracker);
           connect(leController.data(), &QLowEnergyController::connected,mainObject,&mainprocess::bleConnected);
           connect(leController.data(), static_cast<void (QLowEnergyController::*)(QLowEnergyController::Error)>(&QLowEnergyController::error),
                   this,&Bluetooth::reconnectOnError);


       }
   }
   catch(std::exception e){

       log<<"---------------------";
       log<<"Bluetooth Crashed";
       log<<"---------------------";
       log<<"Error while handling bluetooth Disconnect";
       log<<e.what();
       emit recoverBluetooth();
   }


}

void Bluetooth::reconnectOnError(QLowEnergyController::Error error){


   try{

       // Have to check this error because of Qt's bug. It throws error when remote device disconnects
       if(error!=QLowEnergyController::RemoteHostClosedError){

           log<<"Bluetooth Error !!";
           log<<"Resetting Bluetooth bt.service";
           log<<"Error: "<<error;

          // resetBluetoothService();

           if(leController->state()!= QLowEnergyController::ConnectedState){
               //leController->disconnectFromDevice();
               leController.reset(QLowEnergyController::createPeripheral());
               service.reset(leController->addService(serviceData));
           }


           if (service!=nullptr){

               if(leController->state()!=QLowEnergyController::AdvertisingState && leController->state()!=QLowEnergyController::ConnectedState){
                   leController->startAdvertising(QLowEnergyAdvertisingParameters(),advertisingData,advertisingData);   //, advertisingData);
               }

               // We have to check if advertising succeeded or not. If there was an advertising error we will
               // try to reinitialize our bluetooth service
               while (leController->state()!= QLowEnergyController::AdvertisingState && leController->state()!= QLowEnergyController::ConnectedState ){
                   //resetBluetoothService();
                   leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData,advertisingData);

               }

               // Connections
               connect(service.data(),&QLowEnergyService::characteristicChanged,mainObject,&mainprocess::parseResponse);
               connect(service.data(), QOverload<QLowEnergyService::ServiceError>::of(&QLowEnergyService::error),[=](QLowEnergyService::ServiceError newError){
                   log<<"---------------------";
                   log<<"Bluetooth Service Error:"<<newError;
                   log<<"---------------------";
               });
               connect(leController.data(), &QLowEnergyController::disconnected,mainObject,&mainprocess::reconnect);
               connect(leController.data(), &QLowEnergyController::connected,mainObject,&mainprocess::bleConnected);
               connect(leController.data(), &QLowEnergyController::disconnected,mainObject,&mainprocess::stopTracker);
               connect(leController.data(), static_cast<void (QLowEnergyController::*)(QLowEnergyController::Error)>(&QLowEnergyController::error),
                       this,&Bluetooth::reconnectOnError);


           }
       }
   }

   catch(std::exception e){

       log<<"---------------------";
       log<<"Bluetooth Crashed";
       log<<"---------------------";
       log<<"Error while reconnecting after remote device disconnection";
       log<<e.what();
       emit recoverBluetooth();
   }


}



void Bluetooth::resetBluetoothService(){

   try{

       log<<"Trying to reset bluetooth";
       if(leController->state()==QLowEnergyController::AdvertisingState)
           leController->stopAdvertising();


       // Todo: Use timer
       system("sudo service bluetooth stop");
       QThread::sleep(1);
       system("sudo service bluetooth start");
       QThread::sleep(1);

       log<<"Bluetooth Reset complete";
   }

   catch(std::exception e){
       log<<"---------------------";
       log<<"Bluetooth Crashed";
       log<<"---------------------";
       log<<"Error while resetting bluetooth";
       log<<e.what();
       emit recoverBluetooth();
   }
}

...