Qt Bluetooth - no devices discovered.
-
Based on an example I do
#include "bluetooth/device.h" static Device bt_device; void BLE_Scan() { bt_device.startDeviceDiscovery(); QVariant devices_list = bt_device.getDevices(); }I see no device in devices_list . So I check it from a command line
sudo hcitool lescanand I see the list
sudo hcitool lescan LE Scan ... 14:3A:B7:53:DF:27 (unknown) 58:80:3C:47:1F:DA (unknown) 58:80:3C:47:1F:DA Amazfit-765D 6B:CA:29:3A:63:03 (unknown) 20:FB:2D:0F:D6:DA (unknown) EF:A6:D6:17:CB:8D (unknown) 7E:F1:45:DF:D3:A4 (unknown) 5A:79:C1:65:91:D6 (unknown) 5A:79:C1:65:91:D6 (unknown)Something I miss?
I've modified the code
void BLE_Scan() { bt_device.startDeviceDiscovery(); while (bt_device.state()) ; //here we get a scan state QVariant devices_list = bt_device.getDevices(); }Now it stays in a while loop.
-
Based on an example I do
#include "bluetooth/device.h" static Device bt_device; void BLE_Scan() { bt_device.startDeviceDiscovery(); QVariant devices_list = bt_device.getDevices(); }I see no device in devices_list . So I check it from a command line
sudo hcitool lescanand I see the list
sudo hcitool lescan LE Scan ... 14:3A:B7:53:DF:27 (unknown) 58:80:3C:47:1F:DA (unknown) 58:80:3C:47:1F:DA Amazfit-765D 6B:CA:29:3A:63:03 (unknown) 20:FB:2D:0F:D6:DA (unknown) EF:A6:D6:17:CB:8D (unknown) 7E:F1:45:DF:D3:A4 (unknown) 5A:79:C1:65:91:D6 (unknown) 5A:79:C1:65:91:D6 (unknown)Something I miss?
I've modified the code
void BLE_Scan() { bt_device.startDeviceDiscovery(); while (bt_device.state()) ; //here we get a scan state QVariant devices_list = bt_device.getDevices(); }Now it stays in a while loop.
@jenya7 macOS (possibly Monterey) ?
possible this situation:
https://bugreports.qt.io/browse/QTCREATORBUG-25252 -
@jenya7 macOS (possibly Monterey) ?
possible this situation:
https://bugreports.qt.io/browse/QTCREATORBUG-25252@J-Hilk
I added qDebug() and I seeLast device added: "14-7D-DA-B5-DA-DE" Last device added: "43-8F-37-BA-48-86" Last device added: "42-E5-CA-7D-CB-90" Last device added: "13-82-BE-60-4F-B8" Last device added: "62-7C-68-B4-D6-7F" Last device added: "JBL Pulse 3" Last device added: "67-FB-3F-F2-97-4A" Last device added: "64-C5-8A-03-6E-58" Last device added: "54-1C-9E-74-DB-3C" Last device added: "3F-9D-0D-CB-1C-B8" Last device added: "75-88-C7-2C-7B-E1" Last device added: "1A-AF-D3-12-C3-57" Last device added: "25-30-77-C8-E9-43" Last device added: "Amazfit-765D"Obviously I miss the end of the scan. I see
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::deviceScanFinished);but discoveryAgent is a private member. How can get ScanFinished event?
-
@J-Hilk
I added qDebug() and I seeLast device added: "14-7D-DA-B5-DA-DE" Last device added: "43-8F-37-BA-48-86" Last device added: "42-E5-CA-7D-CB-90" Last device added: "13-82-BE-60-4F-B8" Last device added: "62-7C-68-B4-D6-7F" Last device added: "JBL Pulse 3" Last device added: "67-FB-3F-F2-97-4A" Last device added: "64-C5-8A-03-6E-58" Last device added: "54-1C-9E-74-DB-3C" Last device added: "3F-9D-0D-CB-1C-B8" Last device added: "75-88-C7-2C-7B-E1" Last device added: "1A-AF-D3-12-C3-57" Last device added: "25-30-77-C8-E9-43" Last device added: "Amazfit-765D"Obviously I miss the end of the scan. I see
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::deviceScanFinished);but discoveryAgent is a private member. How can get ScanFinished event?
@jenya7 said in Qt Bluetooth - no devices discovered.:
but discoveryAgent is a private member
Private member of what?
-
@jenya7 said in Qt Bluetooth - no devices discovered.:
but discoveryAgent is a private member
Private member of what?
@jsulm said in Qt Bluetooth - no devices discovered.:
@jenya7 said in Qt Bluetooth - no devices discovered.:
but discoveryAgent is a private member
Private member of what?
I use this class from the example (lowenergyscanner). 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(const 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 = false; QLowEnergyController *controller = nullptr; bool m_deviceScanState = false; bool randomAddress = false; }; -
@jsulm said in Qt Bluetooth - no devices discovered.:
@jenya7 said in Qt Bluetooth - no devices discovered.:
but discoveryAgent is a private member
Private member of what?
I use this class from the example (lowenergyscanner). 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(const 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 = false; QLowEnergyController *controller = nullptr; bool m_deviceScanState = false; bool randomAddress = false; }; -
@jenya7 So, if this is your own class simply add a signal to it and connect it to &QBluetoothDeviceDiscoveryAgent::finished
@jsulm said in Qt Bluetooth - no devices discovered.:
@jenya7 So, if this is your own class simply add a signal to it and connect it to &QBluetoothDeviceDiscoveryAgent::finished
I use this class from the example (lowenergyscanner).
I get an error - finished is a private member. -
@jsulm said in Qt Bluetooth - no devices discovered.:
@jenya7 So, if this is your own class simply add a signal to it and connect it to &QBluetoothDeviceDiscoveryAgent::finished
I use this class from the example (lowenergyscanner).
I get an error - finished is a private member.@jenya7 https://doc.qt.io/qt-5/qbluetoothdevicediscoveryagent.html#finished - does not look like private to me.
Please post whole error message and code. -
@jenya7 https://doc.qt.io/qt-5/qbluetoothdevicediscoveryagent.html#finished - does not look like private to me.
Please post whole error message and code.@jsulm said in Qt Bluetooth - no devices discovered.:
@jenya7 https://doc.qt.io/qt-5/qbluetoothdevicediscoveryagent.html#finished - does not look like private to me.
Please post whole error message and code.QBluetoothDeviceDiscoveryAgent - it is global.
but in the class
private: QBluetoothDeviceDiscoveryAgent *discoveryAgent;and in constructor
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::deviceScanFinished);Actually it's a pointer ( *discoveryAgent). How do I pass my object (QBluetoothDeviceDiscoveryAgent ) to the class?
-
@jsulm said in Qt Bluetooth - no devices discovered.:
@jenya7 https://doc.qt.io/qt-5/qbluetoothdevicediscoveryagent.html#finished - does not look like private to me.
Please post whole error message and code.QBluetoothDeviceDiscoveryAgent - it is global.
but in the class
private: QBluetoothDeviceDiscoveryAgent *discoveryAgent;and in constructor
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::deviceScanFinished);Actually it's a pointer ( *discoveryAgent). How do I pass my object (QBluetoothDeviceDiscoveryAgent ) to the class?
@jenya7 said in Qt Bluetooth - no devices discovered.:
Actually it's a pointer ( *discoveryAgent). How do I pass my object (QBluetoothDeviceDiscoveryAgent ) to the class?
You don't.
What I suggested is:- Add a signal to Device class
- Connect discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished to this new signal
- Other classes can now connect to this new signal
No need to pass anything to anybody...
-
@jenya7 said in Qt Bluetooth - no devices discovered.:
Actually it's a pointer ( *discoveryAgent). How do I pass my object (QBluetoothDeviceDiscoveryAgent ) to the class?
You don't.
What I suggested is:- Add a signal to Device class
- Connect discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished to this new signal
- Other classes can now connect to this new signal
No need to pass anything to anybody...
@jsulm said in Qt Bluetooth - no devices discovered.:
@jenya7 said in Qt Bluetooth - no devices discovered.:
Actually it's a pointer ( *discoveryAgent). How do I pass my object (QBluetoothDeviceDiscoveryAgent ) to the class?
You don't.
What I suggested is:- Add a signal to Device class
- Connect discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished to this new signal
- Other classes can now connect to this new signal
No need to pass anything to anybody...
OK.
Device::Device() { //! [les-devicediscovery-1] discoveryAgent = new QBluetoothDeviceDiscoveryAgent(); discoveryAgent->setLowEnergyDiscoveryTimeout(5000); connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &Device::addDevice); connect(discoveryAgent, QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error), this, &Device::deviceScanError); connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::deviceScanFinished); //! [les-devicediscovery-1] setUpdate("Search"); } a private finished connected to a private deviceScanFinished. What's the point in it? -
@jsulm said in Qt Bluetooth - no devices discovered.:
@jenya7 said in Qt Bluetooth - no devices discovered.:
Actually it's a pointer ( *discoveryAgent). How do I pass my object (QBluetoothDeviceDiscoveryAgent ) to the class?
You don't.
What I suggested is:- Add a signal to Device class
- Connect discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished to this new signal
- Other classes can now connect to this new signal
No need to pass anything to anybody...
OK.
Device::Device() { //! [les-devicediscovery-1] discoveryAgent = new QBluetoothDeviceDiscoveryAgent(); discoveryAgent->setLowEnergyDiscoveryTimeout(5000); connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &Device::addDevice); connect(discoveryAgent, QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error), this, &Device::deviceScanError); connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::deviceScanFinished); //! [les-devicediscovery-1] setUpdate("Search"); } a private finished connected to a private deviceScanFinished. What's the point in it?This post is deleted! -
@jsulm said in Qt Bluetooth - no devices discovered.:
@jenya7 said in Qt Bluetooth - no devices discovered.:
Actually it's a pointer ( *discoveryAgent). How do I pass my object (QBluetoothDeviceDiscoveryAgent ) to the class?
You don't.
What I suggested is:- Add a signal to Device class
- Connect discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished to this new signal
- Other classes can now connect to this new signal
No need to pass anything to anybody...
OK.
Device::Device() { //! [les-devicediscovery-1] discoveryAgent = new QBluetoothDeviceDiscoveryAgent(); discoveryAgent->setLowEnergyDiscoveryTimeout(5000); connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &Device::addDevice); connect(discoveryAgent, QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error), this, &Device::deviceScanError); connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::deviceScanFinished); //! [les-devicediscovery-1] setUpdate("Search"); } a private finished connected to a private deviceScanFinished. What's the point in it?@jenya7 Did you actually read what I wrote?!
For the third time: you add a new SIGNAL to Device class...connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::scanFinished); // scanFinished is the new signal -
@jsulm said in Qt Bluetooth - no devices discovered.:
@jenya7 And why is deviceScanFinished private?
It is actually apparent that it should be public...it's an official example in the examples folder (C:\Qt\Examples\Qt-5.12.0\bluetooth\lowenergyscanner).
I wouldn't dare to change it, only if you say so. -
@jsulm said in Qt Bluetooth - no devices discovered.:
@jenya7 And why is deviceScanFinished private?
It is actually apparent that it should be public...it's an official example in the examples folder (C:\Qt\Examples\Qt-5.12.0\bluetooth\lowenergyscanner).
I wouldn't dare to change it, only if you say so. -
@jsulm
What if I do deviceScanFinished public?OK. I see what's going on. Just a strong encapsulation.
The signal already set
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::deviceScanFinished);and it sets m_deviceScanState
void Device::deviceScanFinished() { emit devicesUpdated(); m_deviceScanState = false; emit stateChanged(); if (devices.isEmpty()) setUpdate("No Low Energy devices found..."); else setUpdate("Done! Scan Again!"); }so my
while (bt_device.state()) ;actually tests the memeber
bool Device::state() { return m_deviceScanState; }so deviceScanFinished never occurs.
-
@jsulm
What if I do deviceScanFinished public?OK. I see what's going on. Just a strong encapsulation.
The signal already set
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::deviceScanFinished);and it sets m_deviceScanState
void Device::deviceScanFinished() { emit devicesUpdated(); m_deviceScanState = false; emit stateChanged(); if (devices.isEmpty()) setUpdate("No Low Energy devices found..."); else setUpdate("Done! Scan Again!"); }so my
while (bt_device.state()) ;actually tests the memeber
bool Device::state() { return m_deviceScanState; }so deviceScanFinished never occurs.
@jenya7 said in Qt Bluetooth - no devices discovered.:
What if I do deviceScanFinished public?
To achieve what exactly? deviceScanFinished is a slot not signal in Device - how will making it public help other classes?
"The signal already set" - the signal from private member is "set", this does not help other classes as you already discovered.
Why don't you try my approach? Signals/slots are one of the most important features in Qt and it is really not much work:
class Device... { signals: void scanFinished(); } // In Device constructor: connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::deviceScanFinished); connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::scanFinished); // Now in some other class you simply do: connect(&bt_device, &Device::scanFinished, this, &SomeOtherClass::someSlot);Isn't this easy and clear? And you do not expose any private members from Device to outer world (which would be bad design).
-
@jenya7 said in Qt Bluetooth - no devices discovered.:
What if I do deviceScanFinished public?
To achieve what exactly? deviceScanFinished is a slot not signal in Device - how will making it public help other classes?
"The signal already set" - the signal from private member is "set", this does not help other classes as you already discovered.
Why don't you try my approach? Signals/slots are one of the most important features in Qt and it is really not much work:
class Device... { signals: void scanFinished(); } // In Device constructor: connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::deviceScanFinished); connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Device::scanFinished); // Now in some other class you simply do: connect(&bt_device, &Device::scanFinished, this, &SomeOtherClass::someSlot);Isn't this easy and clear? And you do not expose any private members from Device to outer world (which would be bad design).
@jsulm
It seems OK. But here in the constructorBT_DEVICE::BT_DEVICE(QObject *parent) : QObject(parent) { connect(&bt_device, &Device::scanFinished, this, &BT_DEVICE::ScanFinished); }I get - "undefined reference to `vtable for BT_DEVICE' ". And I don't have any virtual function.
-
@jsulm
It seems OK. But here in the constructorBT_DEVICE::BT_DEVICE(QObject *parent) : QObject(parent) { connect(&bt_device, &Device::scanFinished, this, &BT_DEVICE::ScanFinished); }I get - "undefined reference to `vtable for BT_DEVICE' ". And I don't have any virtual function.
@jenya7 Please read https://doc.qt.io/qt-5/signalsandslots.html
If you want to have signals and/or slots in a class you have to derive this class from QObject and add Q_OBJECT macro right at the beginning of your class.#include <QObject> class BT_DEVICE : public QObject { Q_OBJECT signals: void scanFinished(); ...Do a complete rebuild of your project after these changes.
-
@jenya7 Please read https://doc.qt.io/qt-5/signalsandslots.html
If you want to have signals and/or slots in a class you have to derive this class from QObject and add Q_OBJECT macro right at the beginning of your class.#include <QObject> class BT_DEVICE : public QObject { Q_OBJECT signals: void scanFinished(); ...Do a complete rebuild of your project after these changes.
@jsulm
this is h fileclass BT_DEVICE : public QObject { Q_OBJECT public: BT_DEVICE(QObject *parent = nullptr); void BLE_Scan(); signals: void ScanFinished(); };and cpp file
BT_DEVICE::BT_DEVICE(QObject *parent) : QObject(parent) { connect(&bt_device, &Device::scanFinished, this, &BT_DEVICE::ScanFinished); } void BT_DEVICE::BLE_Scan() { scanning = 1; bt_device.startDeviceDiscovery(); while (scanning) ; QVariant devices = bt_device.getDevices(); } void BT_DEVICE::ScanFinished() { scanning = 0; }