- update example
- some fixes - added QBluetoothLeUartDeviceModel for use with QML
This commit is contained in:
parent
7f5ad16ba9
commit
60d10f056b
7 changed files with 191 additions and 20 deletions
|
@ -20,8 +20,10 @@ INCLUDEPATH += $$PWD/
|
|||
|
||||
SOURCES += \
|
||||
$$PWD/qbluetoothleuart.cpp \
|
||||
$$PWD/qbluetoothleuartdevice.cpp
|
||||
$$PWD/qbluetoothleuartdevice.cpp \
|
||||
$$PWD/qbluetoothleuartdevicemodel.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/qbluetoothleuart.h \
|
||||
$$PWD/qbluetoothleuartdevice.h
|
||||
$$PWD/qbluetoothleuartdevice.h \
|
||||
$$PWD/qbluetoothleuartdevicemodel.h
|
||||
|
|
|
@ -15,4 +15,4 @@ M_THEME_COLOR = #0094ff
|
|||
M_LINKS_NAVBAR1 =
|
||||
M_LINKS_NAVBAR2 = "<a href=\"index.html\">Introduction</a>" \
|
||||
annotated \
|
||||
"<a href=\"ScStwSharedLibraries.pdf\">Download</a>"
|
||||
"<a href=\"QBluetoothLeUart.pdf\">Download</a>"
|
||||
|
|
|
@ -17,6 +17,9 @@ QBluetoothLeUart::QBluetoothLeUart(QObject *parent) : QObject(parent)
|
|||
connect(bluetoothDeviceDiscoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)),
|
||||
this, SLOT(handleDeviceScanError(QBluetoothDeviceDiscoveryAgent::Error)));
|
||||
connect(this->bluetoothDeviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &QBluetoothLeUart::handleScanFinished);
|
||||
|
||||
// device model for QML
|
||||
this->availableDevicesModel = new QBluetoothLeUartDeviceModel(this->availableDevices, this);
|
||||
}
|
||||
|
||||
QBluetoothLeUart::~QBluetoothLeUart(){
|
||||
|
@ -28,9 +31,11 @@ QBluetoothLeUart::~QBluetoothLeUart(){
|
|||
// ------------------------------
|
||||
|
||||
bool QBluetoothLeUart::startScanningForDevices(){
|
||||
if(this->state != Idle)
|
||||
if(this->state != Idle && this->state != ScanFinished)
|
||||
return false;
|
||||
|
||||
this->availableDevicesModel->clear();
|
||||
|
||||
foreach(QBluetoothLeUartDevice* oldDevice, this->availableDevices)
|
||||
oldDevice->deleteLater();
|
||||
|
||||
|
@ -56,6 +61,7 @@ QList<QBluetoothLeUartDevice*> QBluetoothLeUart::getAvailableDevices() {
|
|||
}
|
||||
|
||||
QVariantList QBluetoothLeUart::getAvailableDevicesDetailList() {
|
||||
|
||||
QVariantList result;
|
||||
|
||||
for(int i=0; i < this->availableDevices.length(); i++) {
|
||||
|
@ -74,6 +80,11 @@ QVariantList QBluetoothLeUart::getAvailableDevicesDetailList() {
|
|||
return result;
|
||||
}
|
||||
|
||||
QBluetoothLeUartDeviceModel* QBluetoothLeUart::getAvailableDevicesModel() {
|
||||
return this->availableDevicesModel;
|
||||
}
|
||||
|
||||
|
||||
bool QBluetoothLeUart::connectToDevice(int deviceId) {
|
||||
if(deviceId < 0 || deviceId >= this->availableDevices.length())
|
||||
return false;
|
||||
|
@ -86,6 +97,9 @@ bool QBluetoothLeUart::connectToDevice(QBluetoothLeUartDevice *device){
|
|||
if(!this->availableDevices.contains(device))
|
||||
return false;
|
||||
|
||||
if(this->state == Scanning)
|
||||
this->stopScanningForDevices();
|
||||
|
||||
this->currentBluetoothDevice = device;
|
||||
|
||||
if (bluetoothController) {
|
||||
|
@ -113,22 +127,21 @@ bool QBluetoothLeUart::connectToDevice(QBluetoothLeUartDevice *device){
|
|||
}
|
||||
|
||||
bool QBluetoothLeUart::disconnectFromDevice() {
|
||||
if(this->state < ScanningForService)
|
||||
if(this->state < Connecting)
|
||||
return false;
|
||||
|
||||
this->bluetoothController->disconnectFromDevice();
|
||||
|
||||
disconnect(this->bluetoothController, &QLowEnergyController::serviceDiscovered, this, &QBluetoothLeUart::handleServiceDiscovered);
|
||||
disconnect(this->bluetoothController, &QLowEnergyController::discoveryFinished, this, &QBluetoothLeUart::handleServiceScanDone);
|
||||
disconnect(bluetoothController, SIGNAL(error(QLowEnergyController::Error)),
|
||||
this, SLOT(handleControllerError(QLowEnergyController::Error)));
|
||||
disconnect(this->bluetoothController, &QLowEnergyController::connected, this, &QBluetoothLeUart::handleDeviceConnected);
|
||||
disconnect(this->bluetoothController, &QLowEnergyController::disconnected, this, &QBluetoothLeUart::handleDeviceDisconnected);
|
||||
if(this->state >= Connected)
|
||||
this->bluetoothController->disconnectFromDevice();
|
||||
|
||||
this->bluetoothController->deleteLater();
|
||||
this->bluetoothController = nullptr;
|
||||
this->bluetoothService->deleteLater();
|
||||
this->bluetoothService = nullptr;
|
||||
|
||||
if(this->bluetoothService != nullptr) {
|
||||
this->bluetoothService->deleteLater();
|
||||
this->bluetoothService = nullptr;
|
||||
}
|
||||
|
||||
this->setState(Idle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -156,8 +169,13 @@ void QBluetoothLeUart::handleDeviceDiscovered(const QBluetoothDeviceInfo &device
|
|||
// Is it a BLE device?
|
||||
if (device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) {
|
||||
//qWarning() << "Discovered BLE Device: name: " << device.name() << " Address: " << device.address().toString();
|
||||
// ignore all devices that to not support our service
|
||||
if(!device.serviceUuids().contains(QBluetoothUuid(this->uartServiceUUID)))
|
||||
return;
|
||||
|
||||
QBluetoothLeUartDevice *dev = new QBluetoothLeUartDevice(device, this);
|
||||
availableDevices.append(dev);
|
||||
this->availableDevices.append(dev);
|
||||
this->availableDevicesModel->append(dev);
|
||||
emit this->foundNewDevice(dev);
|
||||
emit this->avaliableDevicesChanged(this->availableDevices);
|
||||
}
|
||||
|
@ -228,6 +246,7 @@ void QBluetoothLeUart::handleControllerError(QLowEnergyController::Error error)
|
|||
{
|
||||
qDebug() << "Cannot connect to remote device.";
|
||||
qWarning() << "Controller Error:" << error;
|
||||
this->disconnectFromDevice();
|
||||
}
|
||||
|
||||
void QBluetoothLeUart::handleDeviceConnected()
|
||||
|
@ -317,7 +336,8 @@ void QBluetoothLeUart::handleServiceDescriptorWritten(const QLowEnergyDescriptor
|
|||
|
||||
void QBluetoothLeUart::init() {
|
||||
#ifdef QBluetoothLeUart_QML
|
||||
qmlRegisterUncreatableType<QBluetoothLeUartDevice>("de.itsblue.bluetoothleuart", 1, 0, "QBluetoothLeUartDevice", "BluetoothDeviceInfo cannot be created");
|
||||
qmlRegisterUncreatableType<QBluetoothLeUartDevice>("de.itsblue.bluetoothleuart", 1, 0, "QBluetoothLeUartDevice", "QBluetoothLeUartDevice cannot be created");
|
||||
qmlRegisterUncreatableType<QBluetoothLeUartDeviceModel>("de.itsblue.bluetoothleuart", 1, 0, "QBluetoothLeUartDeviceModel", "QBluetoothLeUartDeviceModel cannot be created");
|
||||
qmlRegisterType<QBluetoothLeUart>("de.itsblue.bluetoothleuart", 1, 0, "QBluetoothLeUart");
|
||||
qRegisterMetaType<QBluetoothLeUart::BluetoothLeUartState>("QBluetoothLeUart::BluetoothLeUartState");
|
||||
qRegisterMetaType<QBluetoothLeUart::BluetoothScanError>("QBluetoothLeUart::BluetoothScanError");
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#endif
|
||||
|
||||
#include <qbluetoothleuartdevice.h>
|
||||
#include <qbluetoothleuartdevicemodel.h>
|
||||
|
||||
/*!
|
||||
* \mainpage Qt BluetoothLE UART library
|
||||
|
@ -80,11 +81,13 @@
|
|||
*
|
||||
* QML example:
|
||||
* \code{.qml}
|
||||
* import de.itsblue.bluetoothleuart 1.0
|
||||
*
|
||||
* QBluetoothLeUart {
|
||||
* id: ble
|
||||
* Component.onCompleted: {
|
||||
* ble.startScanningForDevices()
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* onFoundNewDevice: {
|
||||
* console.log("Found a device: name: " + device.name + " address: " + device.address)
|
||||
|
@ -107,7 +110,8 @@
|
|||
class QBluetoothLeUart : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QVariantList avaliableDevices READ getAvailableDevicesDetailList NOTIFY avaliableDevicesChanged)
|
||||
Q_PROPERTY(QVariantList availableDevices READ getAvailableDevicesDetailList NOTIFY avaliableDevicesChanged)
|
||||
Q_PROPERTY(QBluetoothLeUartDeviceModel* availableDevicesModel READ getAvailableDevicesModel NOTIFY avaliableDevicesModelChanged)
|
||||
Q_PROPERTY(BluetoothLeUartState state READ getState NOTIFY stateChanged)
|
||||
|
||||
public:
|
||||
|
@ -169,6 +173,9 @@ private:
|
|||
QLowEnergyDescriptor bluetoothTransmissionDescriptor;
|
||||
bool foundValidUARTService;
|
||||
|
||||
// for QML
|
||||
QBluetoothLeUartDeviceModel* availableDevicesModel;
|
||||
|
||||
public slots:
|
||||
|
||||
/*!
|
||||
|
@ -223,6 +230,15 @@ public slots:
|
|||
*/
|
||||
Q_INVOKABLE QVariantList getAvailableDevicesDetailList();
|
||||
|
||||
/*!
|
||||
* \brief Function to get a QBluetoothLeUartDeviceModel with all available devices
|
||||
*
|
||||
* \see QBluetoothLeUartDeviceModel
|
||||
*
|
||||
* \return A QBluetoothLeUartDeviceModel with all available devices
|
||||
*/
|
||||
Q_INVOKABLE QBluetoothLeUartDeviceModel* getAvailableDevicesModel();
|
||||
|
||||
/*!
|
||||
* \brief Function connect to a device using its internal id
|
||||
*
|
||||
|
@ -305,6 +321,7 @@ signals:
|
|||
|
||||
void foundNewDevice(QBluetoothLeUartDevice* device);
|
||||
void avaliableDevicesChanged(QList<QBluetoothLeUartDevice*> avaliableDevices);
|
||||
void avaliableDevicesModelChanged();
|
||||
void scanFinished(QList<QBluetoothLeUartDevice*> availableDevices);
|
||||
void scanningErrorOccured(QBluetoothLeUart::BluetoothScanError error);
|
||||
|
||||
|
|
|
@ -7,7 +7,10 @@ QBluetoothLeUartDevice::QBluetoothLeUartDevice(QBluetoothDeviceInfo info, QObjec
|
|||
|
||||
QString QBluetoothLeUartDevice::getName()
|
||||
{
|
||||
return bluetoothDeviceInfo.name();
|
||||
if(bluetoothDeviceInfo.isValid())
|
||||
return bluetoothDeviceInfo.name();
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
QBluetoothDeviceInfo QBluetoothLeUartDevice::getDevice()
|
||||
|
|
64
qbluetoothleuartdevicemodel.cpp
Normal file
64
qbluetoothleuartdevicemodel.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include "qbluetoothleuartdevicemodel.h"
|
||||
|
||||
QBluetoothLeUartDeviceModel::QBluetoothLeUartDeviceModel(QList<QBluetoothLeUartDevice*> availableDevices, QObject* parent) : QAbstractListModel(parent)
|
||||
{
|
||||
this->availableDevices = availableDevices;
|
||||
}
|
||||
|
||||
int QBluetoothLeUartDeviceModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return this->availableDevices.length();
|
||||
}
|
||||
|
||||
QVariant QBluetoothLeUartDeviceModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() < rowCount())
|
||||
switch (role) {
|
||||
case NameRole: return this->availableDevices[index.row()]->getName();
|
||||
case IdRole: return index.row();
|
||||
case AddressRole: return this->availableDevices[index.row()]->getAddress();
|
||||
case DeviceRole: return QVariant::fromValue(this->availableDevices[index.row()]);
|
||||
default: return QVariant();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> QBluetoothLeUartDeviceModel::roleNames() const
|
||||
{
|
||||
static const QHash<int, QByteArray> roles {
|
||||
{ NameRole, "name" },
|
||||
{ IdRole, "id" },
|
||||
{ AddressRole, "address"},
|
||||
{ DeviceRole, "device" }
|
||||
};
|
||||
return roles;
|
||||
}
|
||||
|
||||
void QBluetoothLeUartDeviceModel::append(QBluetoothLeUartDevice* device)
|
||||
{
|
||||
foreach(QBluetoothLeUartDevice* existingDevice, this->availableDevices){
|
||||
if(device == existingDevice)
|
||||
// dublicates aren't allowed
|
||||
return;
|
||||
}
|
||||
|
||||
int row = this->availableDevices.length();
|
||||
this->beginInsertRows(QModelIndex(), row, row);
|
||||
this->availableDevices.insert(row, device);
|
||||
this->endInsertRows();
|
||||
}
|
||||
|
||||
void QBluetoothLeUartDeviceModel::remove(int row)
|
||||
{
|
||||
if (row < 0 || row >= this->availableDevices.length())
|
||||
return;
|
||||
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
this->availableDevices.removeAt(row);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void QBluetoothLeUartDeviceModel::clear() {
|
||||
for(int i = 0; i < this->availableDevices.length(); i++)
|
||||
this->remove(i);
|
||||
}
|
65
qbluetoothleuartdevicemodel.h
Normal file
65
qbluetoothleuartdevicemodel.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
#ifndef QBLUETOOTHLEUARTDEVICEMODEL_H
|
||||
#define QBLUETOOTHLEUARTDEVICEMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QObject>
|
||||
#include <qbluetoothleuartdevice.h>
|
||||
|
||||
/*!
|
||||
* \brief The QBluetoothLeUartDeviceModel class can be used to display available devices in a QML ListView.
|
||||
*
|
||||
* Example implementation:
|
||||
* \code{.qml}
|
||||
* import de.itsblue.bluetoothleuart 1.0
|
||||
*
|
||||
* QBluetoothLeUart {
|
||||
* id: ble
|
||||
* Component.onCompleted: {
|
||||
* ble.startScanningForDevices()
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* ListView {
|
||||
* model: ble.availableDevicesModel
|
||||
*
|
||||
* delegate: ItemDelegate {
|
||||
* width: parent.width
|
||||
*
|
||||
* text: name
|
||||
*
|
||||
* onClicked: backend.bleController.connectToDevice(device)
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
class QBluetoothLeUartDeviceModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
friend class QBluetoothLeUart;
|
||||
|
||||
enum QBluetoothLeUartDeviceModelRole {
|
||||
NameRole = Qt::DisplayRole,
|
||||
IdRole,
|
||||
AddressRole,
|
||||
DeviceRole
|
||||
};
|
||||
Q_ENUM(QBluetoothLeUartDeviceModelRole)
|
||||
|
||||
int rowCount(const QModelIndex & = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QHash<int, QByteArray> roleNames() const;
|
||||
|
||||
protected:
|
||||
QBluetoothLeUartDeviceModel(QList<QBluetoothLeUartDevice*> availableDevices, QObject *parent = nullptr);
|
||||
|
||||
void append(QBluetoothLeUartDevice* device);
|
||||
void remove(int row);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
QList<QBluetoothLeUartDevice*> availableDevices;
|
||||
|
||||
};
|
||||
|
||||
#endif // QBLUETOOTHLEUARTDEVICEMODEL_H
|
Loading…
Reference in a new issue