summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp')
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp189
1 files changed, 175 insertions, 14 deletions
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
index 1d86fed7..06b8b59a 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
@@ -41,10 +41,13 @@
#include "qbluetoothservicediscoveryagent.h"
#include "qbluetoothservicediscoveryagent_p.h"
+#include "qlowenergycharacteristicinfo_p.h"
+#include "qlowenergyserviceinfo_p.h"
#include "bluez/manager_p.h"
#include "bluez/adapter_p.h"
#include "bluez/device_p.h"
+#include "bluez/characteristic_p.h"
#include <QtDBus/QDBusPendingCallWatcher>
@@ -73,7 +76,7 @@ QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate(
void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address)
{
- Q_Q(QBluetoothServiceDiscoveryAgent);
+ Q_Q(QBluetoothServiceDiscoveryAgent);
#ifdef QT_SERVICEDISCOVERY_DEBUG
qDebug() << "Full discovery on: " << address.toString();
@@ -174,20 +177,54 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_createdDevice(QDBusPendingCallWa
#endif
return;
}
- QVariantMap v = deviceReply.value();
- QStringList device_uuids = v.value(QLatin1String("UUIDs")).toStringList();
-
- QString pattern;
- foreach (const QBluetoothUuid &uuid, uuidFilter)
- pattern += uuid.toString().remove(QLatin1Char('{')).remove(QLatin1Char('}')) + QLatin1Char(' ');
+ QVariantMap deviceProperties = deviceReply.value();
+ QString classType = deviceProperties.value(QStringLiteral("Class")).toString();
+ /*
+ * Low Energy services in bluez are represented as the list of the paths that can be
+ * accessed with org.bluez.Characteristic
+ */
+ //QDBusArgument services = v.value(QLatin1String("Services")).value<QDBusArgument>();
+ const QStringList deviceUuids = deviceProperties.value(QStringLiteral("UUIDs")).toStringList();
+
+ for (int i = 0; i < deviceUuids.size(); i++) {
+ QString b = deviceUuids.at(i);
+ b = b.remove(QLatin1Char('{')).remove(QLatin1Char('}'));
+ QString leServiceCheck = QString(b.at(4)) + QString(b.at(5));
+ /*
+ * In this part we want to emit only Bluetooth Low Energy service. BLE services
+ * have 18xx UUID. Some LE Services contain zeros in last part of UUID.
+ * In the end in case there is an uuidFilter we need to prevent emitting LE services
+ */
+ if ((leServiceCheck == QStringLiteral("18") || b.contains(QStringLiteral("000000000000"))) && uuidFilter.size() == 0) {
+ QBluetoothUuid uuid(b);
+ QLowEnergyServiceInfo lowEnergyService(uuid);
+ lowEnergyService.d_ptr->adapterAddress = m_deviceAdapterAddress;
+ lowEnergyService.setDevice(discoveredDevices.at(0));
+ q_ptr->serviceDiscovered(lowEnergyService);
+ }
-#ifdef QT_SERVICEDISCOVERY_DEBUG
- qDebug() << Q_FUNC_INFO << "Discover: " << pattern.trimmed();
-#endif
- QDBusPendingReply<ServiceMap> discoverReply = device->DiscoverServices(pattern.trimmed());
- watcher = new QDBusPendingCallWatcher(discoverReply, q);
- QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
- q, SLOT(_q_discoveredServices(QDBusPendingCallWatcher*)));
+ }
+ /*
+ * Bluez v4.1 does not have extra bit which gives information if device is Bluetooth
+ * Low Energy device and the way to discover it is with Class property of the Bluetooth device.
+ * Low Energy devices do not have property Class.
+ * In case we have have LE device finish service discovery; otherwise search for regular services.
+ */
+ if (classType.isEmpty())
+ q_ptr->finished();
+ else {
+ QString pattern;
+ foreach (const QBluetoothUuid &uuid, uuidFilter)
+ pattern += uuid.toString().remove(QLatin1Char('{')).remove(QLatin1Char('}')) + QLatin1Char(' ');
+
+ #ifdef QT_SERVICEDISCOVERY_DEBUG
+ qDebug() << Q_FUNC_INFO << "Discover: " << pattern.trimmed();
+ #endif
+ QDBusPendingReply<ServiceMap> discoverReply = device->DiscoverServices(pattern.trimmed());
+ watcher = new QDBusPendingCallWatcher(discoverReply, q);
+ QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ q, SLOT(_q_discoveredServices(QDBusPendingCallWatcher*)));
+ }
}
@@ -269,6 +306,130 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_discoveredServices(QDBusPendingC
_q_serviceDiscoveryFinished();
}
+/*
+ * Following three methods are implemented in this way to avoid blocking the main thread.
+ * We first go through list of services path and then through services characteristics paths.
+ *
+ * Bluez v4.x does not have support for LE devices through org.bluez interfaces. Because of that
+ * these functions will not be used now. I propose to leave them commented because in Bluez v5.x
+ * we have support for LE devices and we can use these functions.
+ */
+/*
+void QBluetoothServiceDiscoveryAgentPrivate::_g_discoveredGattService()
+{
+
+ if (!gattServices.empty()) {
+ qDebug() << gattServices.at(0) << gattServices.size();
+ gattService = QLowEnergyServiceInfo(gattServices.at(0));
+ gattService.getProperties();
+ QObject::connect(gattService.d_ptr.data(), SIGNAL(finished()), this, SLOT(_g_discoveredGattService()));
+ characteristic = new OrgBluezCharacteristicInterface(QLatin1String("org.bluez"), gattServices.at(0), QDBusConnection::systemBus());
+ QDBusPendingReply<QList<QDBusObjectPath> > characterictisReply = characteristic->DiscoverCharacteristics();
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(characterictisReply, this);
+ QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(_q_discoverGattCharacteristics(QDBusPendingCallWatcher*)));
+
+ gattServices.removeFirst();
+ q_ptr->lowEnergyServiceDiscovered(gattService);
+ emit gattService.d_ptr->finished();
+ }
+ else
+ q_ptr->finished();
+
+}
+
+void QBluetoothServiceDiscoveryAgentPrivate::_q_discoverGattCharacteristics(QDBusPendingCallWatcher *watcher)
+{
+
+ QDBusPendingReply<QList<QDBusObjectPath> > characterictisReply = *watcher;
+ if (characterictisReply.isError()){
+ qDebug()<< "Discovering service characteristic error" << characterictisReply.error().message();
+ Q_Q(QBluetoothServiceDiscoveryAgent);
+ error = QBluetoothServiceDiscoveryAgent::UnknownError;
+ errorString = characterictisReply.error().message();
+ emit q->error(error);
+ _q_serviceDiscoveryFinished();
+ return;
+ }
+
+ foreach (const QDBusObjectPath &characteristicPath, characterictisReply.value())
+ gattCharacteristics.append(characteristicPath.path());
+ characteristic = new OrgBluezCharacteristicInterface(QLatin1String("org.bluez"), gattCharacteristics.at(0), QDBusConnection::systemBus());
+ QDBusPendingReply<QVariantMap> characteristicProperty = characteristic->GetProperties();
+ watcher = new QDBusPendingCallWatcher(characteristicProperty, this);
+ _q_discoveredGattCharacteristic(watcher);
+
+}
+
+void QBluetoothServiceDiscoveryAgentPrivate::_q_discoveredGattCharacteristic(QDBusPendingCallWatcher *watcher)
+{
+
+ QDBusPendingReply<QVariantMap> characteristicProperty = *watcher;
+ //qDebug()<<characteristicProperty.value();
+ if (characteristicProperty.isError()){
+ qDebug() << "Characteristic properties error" << characteristicProperty.error().message();
+ Q_Q(QBluetoothServiceDiscoveryAgent);
+ error = QBluetoothServiceDiscoveryAgent::UnknownError;
+ errorString = characteristicProperty.error().message();
+ emit q->error(error);
+ _q_serviceDiscoveryFinished();
+ return;
+ }
+ QStringList serviceName;
+
+ if (characteristicProperty.isError())
+ qDebug()<<characteristicProperty.error().message();
+
+ QVariantMap properties = characteristicProperty.value();
+ QString name = properties.value(QLatin1String("Name")).toString();
+ QString description = properties.value(QLatin1String("Description")).toString();
+ serviceName = description.split(QStringLiteral(" "));
+ QString charUuid = properties.value(QLatin1String("UUID")).toString();
+ QBluetoothUuid characteristicUuid(charUuid);
+
+ QVariant value = properties.value(QLatin1String("Value"));
+ QByteArray byteValue = QByteArray();
+ if (value.type() == QVariant::ByteArray)
+ byteValue = value.toByteArray();
+
+ //qDebug() << name << description << characteristicUuid.toString()<< byteValue.size();
+ gattCharacteristic = QLowEnergyCharacteristicInfo(name, description, characteristicUuid, byteValue);
+ gattCharacteristic.setPath(gattCharacteristics.at(0));
+ qDebug() << gattCharacteristics.at(0);
+ gattService.addCharacteristic(gattCharacteristic);
+
+
+ //Testing part for setting the property
+ QString b = "f000aa02-0451-4000-b000-000000000000";
+ QBluetoothUuid u(b);
+ if (gattCharacteristic.uuid() == u){
+ for (int j = 0; j< byteValue.size(); j++){
+ qDebug() << (int) byteValue.at(j);
+ byteValue[j]=1;
+ qDebug() << (int) byteValue.at(j);
+ }
+ bool s = gattCharacteristic.setPropertyValue(QStringLiteral("Value"), byteValue);
+ qDebug() <<s;
+ }
+
+ QString serName = serviceName.at(0) + " Service";
+
+ gattCharacteristics.removeFirst();
+ if (gattCharacteristics.isEmpty()){
+ q_ptr->lowEnergyServiceDiscovered(gattService);
+ emit gattService.d_ptr->finished();
+ }
+ else{
+ OrgBluezCharacteristicInterface *characteristicProperties = new OrgBluezCharacteristicInterface(QLatin1String("org.bluez"), gattCharacteristics.at(0), QDBusConnection::systemBus());
+ QDBusPendingReply<QVariantMap> characteristicProperty = characteristicProperties->GetProperties();
+ watcher = new QDBusPendingCallWatcher(characteristicProperty, this);
+ QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(_q_discoveredGattCharacteristic(QDBusPendingCallWatcher*)));
+ }
+
+}
+*/
+
QVariant QBluetoothServiceDiscoveryAgentPrivate::readAttributeValue(QXmlStreamReader &xml)
{
if (xml.name() == QLatin1String("boolean")) {