4

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

}
Zain
  • 153
  • 7
  • Please show the relevant code and state the exact problem or error. A description alone is not enough. Also see [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – jww Nov 26 '19 at 01:08

2 Answers2

1

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.

JuanDeLosMuertos
  • 4,532
  • 15
  • 55
  • 87
  • 1
    Thanks alot for your response. I have updated my question. But Since I am in peripheral mode I am not scanning fro any device. I just offer service and wait for the central device (IOS app) to connect. – Zain Nov 27 '19 at 01:20
0

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.

Razorneck
  • 65
  • 6
  • Thanks for the input but I think above mentioned approach is using RFcomm as protocol whereas I am dealing with IOS which doesnt accept it. It only allows GATT. I am not expert in BLE services so I might be missing some information. – Zain Dec 03 '19 at 04:39