1

Тема: Qt Bluetooth Low Energy

Нарешті знову взявся за це. І на самому ж початку спотикнувся.

Може я упускаю щось очевидне?

Чому оцей код із прикладу працює:

Прихований текст
Device::Device():
    connected(false), controller(0), m_deviceScanState(false), randomAddress(false)
{
    //! [les-devicediscovery-1]
    discoveryAgent = new QBluetoothDeviceDiscoveryAgent();
    connect(discoveryAgent, SIGNAL(deviceDiscovered(const QBluetoothDeviceInfo&)),
            this, SLOT(addDevice(const QBluetoothDeviceInfo&)));
    connect(discoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)),
            this, SLOT(deviceScanError(QBluetoothDeviceDiscoveryAgent::Error)));
    connect(discoveryAgent, SIGNAL(finished()), this, SLOT(deviceScanFinished()));
    //! [les-devicediscovery-1]

    setUpdate("Search");
}

void Device::startDeviceDiscovery()
{
    qDeleteAll(devices);
    devices.clear();
    emit devicesUpdated();

    setUpdate("Scanning for devices ...");
    //! [les-devicediscovery-2]
    discoveryAgent->start();
    //! [les-devicediscovery-2]

    if (discoveryAgent->isActive()) {
        m_deviceScanState = true;
        Q_EMIT stateChanged();
    }
}

Де Device це:

class Device: public QObject
{
    Q_OBJECT
    Q_PROPERTY(QVariant devicesList READ getDevices NOTIFY devicesUpdated)
    Q_PROPERTY(QVariant servicesList READ getServices NOTIFY servicesUpdated)
    Q_PROPERTY(QVariant characteristicList READ getCharacteristics NOTIFY characteristicsUpdated)
    Q_PROPERTY(QString update READ getUpdate WRITE setUpdate NOTIFY updateChanged)
    Q_PROPERTY(bool useRandomAddress READ isRandomAddress WRITE setRandomAddress NOTIFY randomAddressChanged)
    Q_PROPERTY(bool state READ state NOTIFY stateChanged)
    Q_PROPERTY(bool controllerError READ hasControllerError)
public:
    Device();
    ~Device();
    QVariant getDevices();
    QVariant getServices();
    QVariant getCharacteristics();
    QString getUpdate();
    bool state();
    bool hasControllerError() const;

    bool isRandomAddress() const;
    void setRandomAddress(bool newValue);

public slots:
    void startDeviceDiscovery();
    void scanServices(const QString &address);

    void connectToService(const QString &uuid);
    void disconnectFromDevice();

private slots:
    // QBluetoothDeviceDiscoveryAgent related
    void addDevice(const QBluetoothDeviceInfo&);
    void deviceScanFinished();
    void deviceScanError(QBluetoothDeviceDiscoveryAgent::Error);

    // QLowEnergyController realted
    void addLowEnergyService(const QBluetoothUuid &uuid);
    void deviceConnected();
    void errorReceived(QLowEnergyController::Error);
    void serviceScanDone();
    void deviceDisconnected();

    // QLowEnergyService related
    void serviceDetailsDiscovered(QLowEnergyService::ServiceState newState);

Q_SIGNALS:
    void devicesUpdated();
    void servicesUpdated();
    void characteristicsUpdated();
    void updateChanged();
    void stateChanged();
    void disconnected();
    void randomAddressChanged();

private:
    void setUpdate(QString message);
    QBluetoothDeviceDiscoveryAgent *discoveryAgent;
    DeviceInfo currentDevice;
    QList<QObject*> devices;
    QList<QObject*> m_services;
    QList<QObject*> m_characteristics;
    QString m_previousAddress;
    QString m_message;
    bool connected;
    QLowEnergyController *controller;
    bool m_deviceScanState;
    bool randomAddress;
};

А у цьому discoveryAgent->isActive() завжди True і список пристроїв завжди пустий:

Прихований текст
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent();
    discoveryAgent->start();

    QThread::sleep(10);
    while (discoveryAgent->isActive())
    {
        QThread::sleep(1);
        qDebug("wait...");
//        qDebug("Count: %d", discoveryAgent->discoveredDevices().count());
    }

    QList<QBluetoothDeviceInfo> deviceList = discoveryAgent->discoveredDevices();

    qDebug("Count: %d", deviceList.count());
}

2 Востаннє редагувалося ADR (18.04.2016 16:09:34)

Re: Qt Bluetooth Low Energy

Ура. До мене дойшло. QBluetoothDeviceDiscoveryAgent використовує сигнали у своїх потребах, а я їх блокую.
Виправив:

#include <QCoreApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent();
    discoveryAgent->start();

    while (discoveryAgent->isActive())
    {
        QThread::sleep(1);
        qDebug("wait...");
        QCoreApplication::processEvents();  // <--
    }

    QList<QBluetoothDeviceInfo> deviceList = discoveryAgent->discoveredDevices();

    qDebug("Count: %d", deviceList.count());
}

3 Востаннє редагувалося ADR (19.04.2016 01:00:27)

Re: Qt Bluetooth Low Energy

Офігенно... пофіксили один баг і схоже що тепер вперся в інший...
service->discoverDetails(); — ніколи не завершується.

програма для перевірки
#include <QApplication>
#include <QQmlApplicationEngine>
#include <qbluetoothglobal.h>
#include <qbluetoothlocaldevice.h>
#include <QObject>
#include <QVariant>
#include <QList>
#include <QBluetoothServiceDiscoveryAgent>
#include <QBluetoothDeviceDiscoveryAgent>
#include <QLowEnergyController>
#include <QBluetoothServiceInfo>
#include <QThread>
#include <QCoreApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent();
    discoveryAgent->start();

    while (discoveryAgent->isActive())
    {
        QCoreApplication::processEvents();
        qDebug("wait for search...");
        QThread::sleep(1);
    }
    qDebug("searching end.");

    qDebug("Count: %d", discoveryAgent->discoveredDevices().count());
    foreach (QBluetoothDeviceInfo device, discoveryAgent->discoveredDevices()) {
        qDebug() << "Name: " << device.name() << "; Adress: " << device.address().toString();
        if(device.address().toString() == "00:A0:50:00:00:0B")
        {
            QLowEnergyController *controller = new QLowEnergyController(device);
            controller->connectToDevice();
            while (controller->state() == QLowEnergyController::ConnectingState)
            {
                QCoreApplication::processEvents();
                qDebug("wait for connecting...");
                QThread::msleep(200);
            }
            if (controller->state() == QLowEnergyController::ConnectedState)
            {
                qDebug("connected.");
            }
            else
            {
                qDebug("connect error: %d", controller->error());
                return -1;
            }


            controller->discoverServices();
            while (controller->state() == QLowEnergyController::DiscoveringState)
            {
                QCoreApplication::processEvents();
                qDebug("wait for discovering service...");
                QThread::msleep(200);
            }
            if (controller->state() == QLowEnergyController::DiscoveredState)
            {
                qDebug("discovered. count: %d", controller->services().count());
            }
            else
            {
                qDebug("discovering error: %d", controller->error());
                return -1;
            }

            foreach (QBluetoothUuid serviceUuid, controller->services())
            {
                qDebug("Service UUID: %s", qPrintable(serviceUuid.toString()));

                if (serviceUuid.data1 == 0x00001809)
                {
                    QLowEnergyService *service = controller->createServiceObject(serviceUuid);
                    qDebug("Service State: %d", service->state());
                    if(service->state() == QLowEnergyService::DiscoveryRequired)
                    {
                        service->discoverDetails();
                        QCoreApplication::processEvents();
                        while(service->state() == QLowEnergyService::DiscoveringServices)
                        {
                            QCoreApplication::processEvents();
                            qDebug("wait for discovering service details...");
                            QThread::msleep(200);
                        }
                    }
                    foreach (const QLowEnergyCharacteristic characteristic, service->characteristics())
                    {
                         qDebug("Characteristic UUID: %s",
                                qPrintable(characteristic.uuid().toString()));
                    }

                }
            }

        }
    }





//    QQmlApplicationEngine engine;
//    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

//    return app.exec();
}

https://bugreports.qt.io/browse/QTBUG-44736

Надіюсь я ще нікого не замахав своїм мініблогом)