2

I'm using QtBluetooth under Win10. Works fine.

However, as my app is deployed both on laptops (that may or may not have a BT adapter) and desktops (that are likely not to have an adapter), I'd like to programmatically check if the adapter is available or not (present and enabled).

Considering the documentation, I tested 4 functions:

bool isBluetoothAvailable1()
{
    return !QBluetoothLocalDevice::allDevices().empty();
}

bool isBluetoothAvailable2()
{
    QBluetoothLocalDevice localDevice;
    return localDevice.isValid();
}

bool isBluetoothAvailable3()
{
    std::shared_ptr<QLowEnergyController> created( QLowEnergyController::createPeripheral() );
    if ( created )
    {
        if ( !created->localAddress().isNull() )
            return true;
    }
    return false;
}

bool isBluetoothAvailable4()
{
    std::shared_ptr<QLowEnergyController> created( QLowEnergyController::createCentral( QBluetoothDeviceInfo() ) );
    if ( created )
    {
        if ( !created->localAddress().isNull() )
            return true;
    }
    return false;
}

But when I run my code on a Win10 laptop, they all return false! Even if I can search an connect a remote device using the QBluetooth API.

What's the right method to know if a BLE adapter is available?

jpo38
  • 20,821
  • 10
  • 70
  • 151

1 Answers1

0

The correct solution would be to use isBluetoothAvailable1() because the call to allDevices() lists all connected Bluetooth adapters. However, this does not works on Windows.

I do not fully understand their reasoning, but there are 2 Windows implementations of this function in Qt.

https://code.qt.io/cgit/qt/qtconnectivity.git/tree/src/bluetooth/qbluetoothlocaldevice_win.cpp?h=5.15.2

https://code.qt.io/cgit/qt/qtconnectivity.git/tree/src/bluetooth/qbluetoothlocaldevice_winrt.cpp?h=5.15.2

And by default it uses the one that always returns empty list (qbluetoothlocaldevice_win.cpp).

QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices()
{
    QList<QBluetoothHostInfo> localDevices;
    return localDevices;
}

The simplest solution is to use the code from the other Windows implementation that works (qbluetoothlocaldevice_winrt.cpp)

#include <Windows.h>
#include <BluetoothAPIs.h>

QList<QBluetoothHostInfo> allDevices()
{
    BLUETOOTH_FIND_RADIO_PARAMS params;
    ::ZeroMemory(&params, sizeof(params));
    params.dwSize = sizeof(params);

    QList<QBluetoothHostInfo> foundAdapters;

    HANDLE hRadio = nullptr;
    if (const HBLUETOOTH_RADIO_FIND hSearch = ::BluetoothFindFirstRadio(&params, &hRadio)) {
        for (;;) {
            BLUETOOTH_RADIO_INFO radio;
            ::ZeroMemory(&radio, sizeof(radio));
            radio.dwSize = sizeof(radio);

            const DWORD retval = ::BluetoothGetRadioInfo(hRadio, &radio);
            ::CloseHandle(hRadio);

            if (retval != ERROR_SUCCESS)
                break;

            QBluetoothHostInfo adapterInfo;
            adapterInfo.setAddress(QBluetoothAddress(radio.address.ullLong));
            adapterInfo.setName(QString::fromWCharArray(radio.szName));

            foundAdapters << adapterInfo;

            if (!::BluetoothFindNextRadio(hSearch, &hRadio))
                break;
        }

        ::BluetoothFindRadioClose(hSearch);
    }

    return foundAdapters;
}

Also you will need to link the necessary libraries Bthprops and ws2_32.