Zain
Zain

Reputation: 153

QT Low energy controller peripheral mode crashes with error "Resource not available"

Updated:

Qt Version : 5.11

Platform : Raspberry pi 3

Operating System : Rasbpian

I am connecting my linux Qt BLE app to IOS central device. It works fine for the most part but sometimes it crashes with following error

qt.bluetooth.bluez: void QBluetoothSocketPrivate::_q_readNotify() 29 error: -1 "Resource temporarily unavailable"

Here is the code and underlying scenario.

I have a raspberrypi that is running Qt 5.11 and I have created a BLE low energy peripheral device that connects to IOS app and sends and receives data.

Declarations :

QLowEnergyCharacteristicData ReadCharacteristicData,
                             WriteCharactersiticData,       
                             ConnectivityData,
                             TrackerData_Data; 

QLowEnergyCharacteristic charas;

QLowEnergyDescriptorData  ReadCharacteristicDesc,
                          WriteCharactersiticDesc,
                          ConnectivityDesc,
                          TrackerDesc;

QLowEnergyServiceData serviceData;

QScopedPointer<QLowEnergyController> leController; 
QScopedPointer<QLowEnergyService> service;


Service Initialization :`


Here I am initializing bluetooth service
    //! [Advertising Data]

advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral);
advertisingData.setLocalName("Atlas360Dev");
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);

    serviceData.addCharacteristic(ReadCharacteristicData);
    serviceData.addCharacteristic(WriteCharactersiticData);
    serviceData.addCharacteristic(ConnectivityData);
    serviceData.addCharacteristic(TrackerData_Data);


    leController.reset(QLowEnergyController::createPeripheral());




    // leController->addService(serviceData) will return a pointer to service object
    service.reset(leController->addService(serviceData));

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



    connect(&heartbeatTimer, &QTimer::timeout,this, &mainprocess::TickProvider);
    connect(leController.data(), &QLowEnergyController::disconnected,this,&mainprocess::reconnect);
    connect(service.data(),&QLowEnergyService::characteristicChanged,this,&mainprocess::printvalue);

    heartbeatTimer.start(30);


///////////////////////////////////////
This sends data to IOS app every 30ms
///////////////////////////////////////

void mainprocess::TickProvider ()
{

    if(Tracker.isRunning())

    {
        // sending Tracker Data
        I have ommitted the code


        QLowEnergyCharacteristic Charac_1 = service->characteristic(QBluetoothUuid::TrackingData);
        service->writeCharacteristic(Charac_1,trackingdata);

    }


    // Sending Connectivity Status
    QByteArray connectivity;

    QLowEnergyCharacteristic Charac_2 = service->characteristic(QBluetoothUuid::Connectivity);
    service->writeCharacteristic(Charac_2,connectivity);

}

//////////////////////////////////////////////////////////
Here I receive commands from IOS and respond accordingly
/////////////////////////////////////////////////////////

void mainprocess::printvalue(const QLowEnergyCharacteristic &info, const QByteArray &ba){


    if (info.uuid()== QBluetoothUuid(QBluetoothUuid::WriteCharacteristic)){


        // Username
        if(ba.at(0)==0xA1){

        }

        // Password
        if(ba.at(0)==0xA2){

        }

        // Tour Title
        if(ba.at(0)==0xA3){

        }

        // Section Title
        if(ba.at(0)==0xA4){

        }

        // Distance Interval
        if(ba.at(0)==0xA7){

        }

        // Countdown
        if(ba.at(0)==0xA8){

        }

        // Address
        if(ba.at(0)==0xA9){

        }

        // Address Upload Later
        if(ba.at(0)==0xA5){

        }

        // Mode
        if(ba.at(0)==0xAA){

        }

    }
}

/////////////////////
Reconnect Function
////////////////////

void mainprocess::reconnect()
{
    qDebug()<<"Reconnect Called";
//initializeBluetooth();

   // connect(leController.data(), &QLowEnergyController::disconnected,this,&mainprocess::reconnect);

   service.reset(leController->addService(serviceData));
 connect(service.data(),&QLowEnergyService::characteristicChanged,this,&mainprocess::printvalue);
    if (service!=nullptr)
        leController->startAdvertising(QLowEnergyAdvertisingParameters(),
                                       advertisingData,advertisingData);//, advertisingData);

}

Upvotes: 4

Views: 944

Answers (2)

Razorneck
Razorneck

Reputation: 65

This is most likely the same issue as described here: QBluetoothSocketPrivate::_q_readNotify() 14 error According to SteffenH you have to use an individual port for each socket connection to a service. I believe currently you are using only port 1.

Upvotes: 0

JuanDeLosMuertos
JuanDeLosMuertos

Reputation: 4620

The same happens to me, during a BLE scan. It seems that the device is down for some reason (can be investigated through hcitool command - on Linux platform)

You should connect a slot to the following signal:

QBluetoothDeviceDiscoveryAgent::error(QBluetoothDeviceDiscoveryAgent::Error)

and you probably discover that your device is OFF.

In that case, check the following:

QBluetoothLocalDevice::hostMode()

if it returns QBluetoothLocalDevice::HostPoweredOff, just do :

your_bluetooth_local_device->powerOn();

Anyway: please add a complete example of what you are actually doing, the Qt version used, the platform.

Upvotes: 1

Related Questions