summaryrefslogtreecommitdiffstats
path: root/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp')
-rw-r--r--tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp834
1 files changed, 714 insertions, 120 deletions
diff --git a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
index 3cb57e3f..5faf5fee 100644
--- a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
+++ b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -53,6 +53,19 @@
QT_USE_NAMESPACE
+// This define must be set if the platform provides access to GATT handles
+// otherwise it must not be defined. As of now the two supported platforms
+// (Android and Bluez/Linux) provide access or some notion of it.
+#ifndef Q_OS_MAC
+#define HANDLES_PROVIDED_BY_PLATFORM
+#endif
+
+#ifdef HANDLES_PROVIDED_BY_PLATFORM
+#define HANDLE_COMPARE(actual,expected) QCOMPARE(actual,expected)
+#else
+#define HANDLE_COMPARE(actual,expected)
+#endif
+
class tst_QLowEnergyController : public QObject
{
Q_OBJECT
@@ -63,6 +76,7 @@ public:
private slots:
void initTestCase();
+ void init();
void cleanupTestCase();
void tst_emptyCtor();
void tst_connect();
@@ -70,19 +84,20 @@ private slots:
void tst_defaultBehavior();
void tst_writeCharacteristic();
void tst_writeCharacteristicNoResponse();
- void tst_writeDescriptor();
- void tst_encryption();
+ void tst_readWriteDescriptor();
+ void tst_customProgrammableDevice();
+ void tst_errorCases();
private:
void verifyServiceProperties(const QLowEnergyService *info);
QBluetoothDeviceDiscoveryAgent *devAgent;
QBluetoothAddress remoteDevice;
+ QBluetoothDeviceInfo remoteDeviceInfo;
QList<QBluetoothUuid> foundServices;
};
Q_DECLARE_METATYPE(QLowEnergyCharacteristic)
Q_DECLARE_METATYPE(QLowEnergyDescriptor)
-Q_DECLARE_METATYPE(QLowEnergyService::ServiceError)
tst_QLowEnergyController::tst_QLowEnergyController()
{
@@ -90,6 +105,9 @@ tst_QLowEnergyController::tst_QLowEnergyController()
qRegisterMetaType<QLowEnergyDescriptor>();
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+#ifndef Q_OS_MAC
+ // Core Bluetooth (OS X and iOS) does not work with addresses,
+ // making the code below useless.
const QString remote = qgetenv("BT_TEST_DEVICE");
if (!remote.isEmpty()) {
remoteDevice = QBluetoothAddress(remote);
@@ -97,6 +115,7 @@ tst_QLowEnergyController::tst_QLowEnergyController()
} else {
qWarning() << "Not using any remote device for testing. Set BT_TEST_DEVICE env to run manual tests involving a remote device";
}
+#endif
}
tst_QLowEnergyController::~tst_QLowEnergyController()
@@ -106,12 +125,19 @@ tst_QLowEnergyController::~tst_QLowEnergyController()
void tst_QLowEnergyController::initTestCase()
{
+#ifndef Q_OS_MAC
if (remoteDevice.isNull()
|| QBluetoothLocalDevice::allDevices().isEmpty()) {
qWarning("No remote device or local adapter found.");
return;
}
-
+#elif defined(Q_OS_OSX)
+ // allDevices is always empty on iOS:
+ if (QBluetoothLocalDevice::allDevices().isEmpty()) {
+ qWarning("No local adapter found.");
+ return;
+ }
+#endif
devAgent = new QBluetoothDeviceDiscoveryAgent(this);
@@ -124,7 +150,14 @@ void tst_QLowEnergyController::initTestCase()
devAgent->start();
QTRY_VERIFY_WITH_TIMEOUT(finishedSpy.count() > 0, 30000);
foreach (const QBluetoothDeviceInfo &info, devAgent->discoveredDevices()) {
+#ifndef Q_OS_MAC
if (info.address() == remoteDevice) {
+#else
+ // On OS X/iOS the only way to find the device we are
+ // interested in - is to use device's name.
+ if (info.name().contains("Sensor") && info.name().contains("Tag")) {
+ remoteDeviceInfo = info;
+#endif
deviceFound = true;
break;
}
@@ -133,8 +166,11 @@ void tst_QLowEnergyController::initTestCase()
QVERIFY2(deviceFound, "Cannot find remote device.");
// These are the services exported by the TI SensorTag
+#ifndef Q_OS_MAC
+ // Core Bluetooth somehow ignores/hides/fails to discover these services.
foundServices << QBluetoothUuid(QString("00001800-0000-1000-8000-00805f9b34fb"));
foundServices << QBluetoothUuid(QString("00001801-0000-1000-8000-00805f9b34fb"));
+#endif
foundServices << QBluetoothUuid(QString("0000180a-0000-1000-8000-00805f9b34fb"));
foundServices << QBluetoothUuid(QString("0000ffe0-0000-1000-8000-00805f9b34fb"));
foundServices << QBluetoothUuid(QString("f000aa00-0451-4000-b000-000000000000"));
@@ -148,6 +184,20 @@ void tst_QLowEnergyController::initTestCase()
foundServices << QBluetoothUuid(QString("f000ffc0-0451-4000-b000-000000000000"));
}
+/*
+ * Executed in between each test function call.
+ */
+void tst_QLowEnergyController::init()
+{
+#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
+ /*
+ * Add a delay to give Android/iOS stack time to catch up in between
+ * the multiple connect/disconnects within each test function.
+ */
+ QTest::qWait(2000);
+#endif
+}
+
void tst_QLowEnergyController::cleanupTestCase()
{
@@ -198,17 +248,38 @@ void tst_QLowEnergyController::tst_emptyCtor()
void tst_QLowEnergyController::tst_connect()
{
QList<QBluetoothHostInfo> localAdapters = QBluetoothLocalDevice::allDevices();
+
+#ifndef Q_OS_MAC
if (localAdapters.isEmpty() || remoteDevice.isNull())
+#elif defined(Q_OS_OSX)
+ if (localAdapters.isEmpty() || remoteDeviceInfo.deviceUuid().isNull())
+#elif defined (Q_OS_IOS)
+ if (remoteDeviceInfo.deviceUuid().isNull())
+#endif
QSKIP("No local Bluetooth or remote BTLE device found. Skipping test.");
+#ifndef Q_OS_IOS
const QBluetoothAddress localAdapter = localAdapters.at(0).address();
+#endif
+
+#ifndef Q_OS_MAC
QLowEnergyController control(remoteDevice);
+#else
+ // Create a low energy controller using Apple's
+ // uuid (NSUUID).
+ QLowEnergyController control(remoteDeviceInfo);
+#endif
+
QSignalSpy connectedSpy(&control, SIGNAL(connected()));
QSignalSpy disconnectedSpy(&control, SIGNAL(disconnected()));
+#ifndef Q_OS_IOS
QCOMPARE(control.localAddress(), localAdapter);
QVERIFY(!control.localAddress().isNull());
+#endif
+#ifndef Q_OS_MAC
QCOMPARE(control.remoteAddress(), remoteDevice);
+#endif
QCOMPARE(control.state(), QLowEnergyController::UnconnectedState);
QCOMPARE(control.error(), QLowEnergyController::NoError);
QVERIFY(control.errorString().isEmpty());
@@ -251,7 +322,7 @@ void tst_QLowEnergyController::tst_connect()
QSignalSpy serviceFoundSpy(&control, SIGNAL(serviceDiscovered(QBluetoothUuid)));
QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState)));
control.discoverServices();
- QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000);
+ QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000);
QCOMPARE(stateSpy.count(), 2);
QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(),
QLowEnergyController::DiscoveringState);
@@ -344,12 +415,19 @@ void tst_QLowEnergyController::tst_connect()
void tst_QLowEnergyController::tst_concurrentDiscovery()
{
+#ifndef Q_OS_MAC
QList<QBluetoothHostInfo> localAdapters = QBluetoothLocalDevice::allDevices();
if (localAdapters.isEmpty() || remoteDevice.isNull())
QSKIP("No local Bluetooth or remote BTLE device found. Skipping test.");
// quick setup - more elaborate test is done by connectNew()
QLowEnergyController control(remoteDevice);
+#else
+ if (remoteDeviceInfo.deviceUuid().isNull())
+ QSKIP("No local Bluetooth or remote BTLE device found. Skipping test.");
+ QLowEnergyController control(remoteDeviceInfo);
+#endif
+
QCOMPARE(control.state(), QLowEnergyController::UnconnectedState);
QCOMPARE(control.error(), QLowEnergyController::NoError);
@@ -376,7 +454,18 @@ void tst_QLowEnergyController::tst_concurrentDiscovery()
30000);
}
+#ifdef Q_OS_ANDROID
+ QCOMPARE(control.state(), QLowEnergyController::ConnectedState);
+ QCOMPARE(control2.state(), QLowEnergyController::ConnectedState);
+ control2.disconnectFromDevice();
+ QTest::qWait(3000);
+ QCOMPARE(control.state(), QLowEnergyController::ConnectedState);
+ QCOMPARE(control2.state(), QLowEnergyController::UnconnectedState);
+#else
+ // see QTBUG-42519
+ // Linux cannot maintain two controller connections at the same time
QVERIFY(control2.error() != QLowEnergyController::NoError);
+#endif
}
/* We are testing that we can run service discovery on the same device
@@ -386,7 +475,7 @@ void tst_QLowEnergyController::tst_concurrentDiscovery()
QSignalSpy discoveryFinishedSpy(&control, SIGNAL(discoveryFinished()));
QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState)));
control.discoverServices();
- QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000);
+ QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000);
QCOMPARE(stateSpy.count(), 2);
QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(),
QLowEnergyController::DiscoveringState);
@@ -444,7 +533,7 @@ void tst_QLowEnergyController::tst_concurrentDiscovery()
QCOMPARE(control.state(), QLowEnergyController::ConnectedState);
stateSpy.clear();
control.discoverServices();
- QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000);
+ QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000);
QCOMPARE(stateSpy.count(), 2);
QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(),
QLowEnergyController::DiscoveringState);
@@ -515,7 +604,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Device Name
QString temp("00002a00-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x3));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x3));
QCOMPARE(chars[0].properties(), QLowEnergyCharacteristic::Read);
QCOMPARE(chars[0].value(), QByteArray::fromHex("544920424c452053656e736f7220546167"));
QVERIFY(chars[0].isValid());
@@ -525,7 +614,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Appearance
temp = QString("00002a01-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x5));
+ HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x5));
QCOMPARE(chars[1].properties(), QLowEnergyCharacteristic::Read);
QCOMPARE(chars[1].value(), QByteArray::fromHex("0000"));
QVERIFY(chars[1].isValid());
@@ -535,7 +624,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Peripheral Privacy Flag
temp = QString("00002a02-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x7));
+ HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x7));
QCOMPARE(chars[2].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[2].value(), QByteArray::fromHex("00"));
@@ -546,7 +635,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Reconnection Address
temp = QString("00002a03-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[3].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[3].handle(), QLowEnergyHandle(0x9));
+ HANDLE_COMPARE(chars[3].handle(), QLowEnergyHandle(0x9));
//Early firmware version had this characteristic as Read|Write and may fail
QCOMPARE(chars[3].properties(), QLowEnergyCharacteristic::Write);
if (chars[3].properties() & QLowEnergyCharacteristic::Read)
@@ -560,7 +649,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Peripheral Preferred Connection Parameters
temp = QString("00002a04-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[4].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[4].handle(), QLowEnergyHandle(0xb));
+ HANDLE_COMPARE(chars[4].handle(), QLowEnergyHandle(0xb));
QCOMPARE(chars[4].properties(), QLowEnergyCharacteristic::Read);
QCOMPARE(chars[4].value(), QByteArray::fromHex("5000a0000000e803"));
QVERIFY(chars[4].isValid());
@@ -576,7 +665,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QString temp("00002a05-0000-1000-8000-00805f9b34fb");
//this should really be readable according to GATT Service spec
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0xe));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0xe));
QCOMPARE(chars[0].properties(), QLowEnergyCharacteristic::Indicate);
QCOMPARE(chars[0].value(), QByteArray());
QVERIFY(chars[0].isValid());
@@ -584,7 +673,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().count(), 1);
QCOMPARE(chars[0].descriptors().at(0).isValid(), true);
- QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0xf));
+ HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0xf));
QCOMPARE(chars[0].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration));
QCOMPARE(chars[0].descriptors().at(0).type(),
@@ -601,9 +690,11 @@ void tst_QLowEnergyController::verifyServiceProperties(
QString temp("00002a23-0000-1000-8000-00805f9b34fb");
//this should really be readable according to GATT Service spec
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x12));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x12));
QCOMPARE(chars[0].properties(), QLowEnergyCharacteristic::Read);
- QCOMPARE(chars[0].value(), QByteArray::fromHex("6e41ab0000296abc"));
+// Do not read the System ID as it is different for every device
+// QEXPECT_FAIL("", "The value is different on different devices", Continue);
+// QCOMPARE(chars[0].value(), QByteArray::fromHex("6e41ab0000296abc"));
QVERIFY(chars[0].isValid());
QVERIFY(info->contains(chars[0]));
QCOMPARE(chars[0].descriptors().count(), 0);
@@ -611,7 +702,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Model Number
temp = QString("00002a24-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x14));
+ HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x14));
QCOMPARE(chars[1].properties(), QLowEnergyCharacteristic::Read);
QCOMPARE(chars[1].value(), QByteArray::fromHex("4e2e412e00"));
QVERIFY(chars[1].isValid());
@@ -621,7 +712,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Serial Number
temp = QString("00002a25-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x16));
+ HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x16));
QCOMPARE(chars[2].properties(),
(QLowEnergyCharacteristic::Read));
QCOMPARE(chars[2].value(), QByteArray::fromHex("4e2e412e00"));
@@ -632,7 +723,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Firmware Revision
temp = QString("00002a26-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[3].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[3].handle(), QLowEnergyHandle(0x18));
+ HANDLE_COMPARE(chars[3].handle(), QLowEnergyHandle(0x18));
QCOMPARE(chars[3].properties(),
(QLowEnergyCharacteristic::Read));
//FW rev. : 1.5 (Oct 23 2013)
@@ -645,7 +736,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Hardware Revision
temp = QString("00002a27-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[4].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[4].handle(), QLowEnergyHandle(0x1a));
+ HANDLE_COMPARE(chars[4].handle(), QLowEnergyHandle(0x1a));
QCOMPARE(chars[4].properties(),
(QLowEnergyCharacteristic::Read));
QCOMPARE(chars[4].value(), QByteArray::fromHex("4e2e412e00"));
@@ -656,7 +747,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Software Revision
temp = QString("00002a28-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[5].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[5].handle(), QLowEnergyHandle(0x1c));
+ HANDLE_COMPARE(chars[5].handle(), QLowEnergyHandle(0x1c));
QCOMPARE(chars[5].properties(),
(QLowEnergyCharacteristic::Read));
QCOMPARE(chars[5].value(), QByteArray::fromHex("4e2e412e00"));
@@ -667,7 +758,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Manufacturer Name
temp = QString("00002a29-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[6].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[6].handle(), QLowEnergyHandle(0x1e));
+ HANDLE_COMPARE(chars[6].handle(), QLowEnergyHandle(0x1e));
QCOMPARE(chars[6].properties(),
(QLowEnergyCharacteristic::Read));
QCOMPARE(chars[6].value(), QByteArray::fromHex("546578617320496e737472756d656e747300"));
@@ -678,7 +769,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// IEEE
temp = QString("00002a2a-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[7].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[7].handle(), QLowEnergyHandle(0x20));
+ HANDLE_COMPARE(chars[7].handle(), QLowEnergyHandle(0x20));
QCOMPARE(chars[7].properties(),
(QLowEnergyCharacteristic::Read));
QCOMPARE(chars[7].value(), QByteArray::fromHex("fe006578706572696d656e74616c"));
@@ -689,7 +780,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// PnP ID
temp = QString("00002a50-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[8].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[8].handle(), QLowEnergyHandle(0x22));
+ HANDLE_COMPARE(chars[8].handle(), QLowEnergyHandle(0x22));
QCOMPARE(chars[8].properties(),
(QLowEnergyCharacteristic::Read));
QCOMPARE(chars[8].value(), QByteArray::fromHex("010d0000001001"));
@@ -705,7 +796,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Temp Data
QString temp("f000aa01-0451-4000-b000-000000000000");
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x25));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x25));
QCOMPARE(chars[0].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify));
QCOMPARE(chars[0].value(), QByteArray::fromHex("00000000"));
@@ -715,7 +806,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().count(), 2);
//descriptor checks
QCOMPARE(chars[0].descriptors().at(0).isValid(), true);
- QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x26));
+ HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x26));
QCOMPARE(chars[0].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration));
QCOMPARE(chars[0].descriptors().at(0).type(),
@@ -724,7 +815,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QVERIFY(info->contains(chars[0].descriptors().at(0)));
QCOMPARE(chars[0].descriptors().at(1).isValid(), true);
- QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x27));
+ HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x27));
QCOMPARE(chars[0].descriptors().at(1).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[0].descriptors().at(1).type(),
@@ -737,7 +828,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Temp Config
temp = QString("f000aa02-0451-4000-b000-000000000000");
QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x29));
+ HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x29));
QCOMPARE(chars[1].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[1].value(), QByteArray::fromHex("00"));
@@ -747,7 +838,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[1].descriptors().count(), 1);
//descriptor checks
QCOMPARE(chars[1].descriptors().at(0).isValid(), true);
- QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x2a));
+ HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x2a));
QCOMPARE(chars[1].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[1].descriptors().at(0).type(),
@@ -762,7 +853,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
if (chars.count() > 2) {
temp = QString("f000aa03-0451-4000-b000-000000000000");
QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x2c));
+ HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x2c));
QCOMPARE(chars[2].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[2].value(), QByteArray::fromHex("64"));
@@ -772,7 +863,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[2].descriptors().count(), 1);
//descriptor checks
QCOMPARE(chars[2].descriptors().at(0).isValid(), true);
- QCOMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x2d));
+ HANDLE_COMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x2d));
QCOMPARE(chars[2].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[2].descriptors().at(0).type(),
@@ -791,7 +882,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QString temp("0000ffe1-0000-1000-8000-00805f9b34fb");
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x6b));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x6b));
QCOMPARE(chars[0].properties(),
(QLowEnergyCharacteristic::Notify));
QCOMPARE(chars[0].value(), QByteArray());
@@ -802,7 +893,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//descriptor checks
QCOMPARE(chars[0].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x6c));
+ HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x6c));
QCOMPARE(chars[0].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration));
QCOMPARE(chars[0].descriptors().at(0).type(),
@@ -812,7 +903,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().at(1).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x6d));
+ HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x6d));
QCOMPARE(chars[0].descriptors().at(1).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[0].descriptors().at(1).type(),
@@ -831,7 +922,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QString temp("f000aa11-0451-4000-b000-000000000000");
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x30));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x30));
QCOMPARE(chars[0].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify));
QCOMPARE(chars[0].value(), QByteArray::fromHex("000000"));
@@ -842,7 +933,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x31));
+ HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x31));
QCOMPARE(chars[0].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration));
QCOMPARE(chars[0].descriptors().at(0).type(),
@@ -852,7 +943,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().at(1).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x32));
+ HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x32));
QCOMPARE(chars[0].descriptors().at(1).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[0].descriptors().at(1).type(),
@@ -865,7 +956,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
temp = QString("f000aa12-0451-4000-b000-000000000000");
QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x34));
+ HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x34));
QCOMPARE(chars[1].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[1].value(), QByteArray::fromHex("00"));
@@ -875,7 +966,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[1].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x35));
+ HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x35));
QCOMPARE(chars[1].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[1].descriptors().at(0).type(),
@@ -888,7 +979,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
temp = QString("f000aa13-0451-4000-b000-000000000000");
QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x37));
+ HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x37));
QCOMPARE(chars[2].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[2].value(), QByteArray::fromHex("64")); // don't change it or set it to 0x64
@@ -899,7 +990,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//descriptor checks
QCOMPARE(chars[2].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x38));
+ HANDLE_COMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x38));
QCOMPARE(chars[2].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[2].descriptors().at(0).type(),
@@ -918,7 +1009,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QString temp("f000aa21-0451-4000-b000-000000000000");
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x3b));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x3b));
QCOMPARE(chars[0].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify));
QCOMPARE(chars[0].value(), QByteArray::fromHex("00000000"));
@@ -929,7 +1020,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//descriptor checks
QCOMPARE(chars[0].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x3c));
+ HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x3c));
QCOMPARE(chars[0].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration));
QCOMPARE(chars[0].descriptors().at(0).type(),
@@ -939,7 +1030,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().at(1).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x3d));
+ HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x3d));
QCOMPARE(chars[0].descriptors().at(1).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[0].descriptors().at(1).type(),
@@ -952,7 +1043,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
temp = QString("f000aa22-0451-4000-b000-000000000000");
QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x3f));
+ HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x3f));
QCOMPARE(chars[1].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[1].value(), QByteArray::fromHex("00"));
@@ -963,7 +1054,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//descriptor checks
QCOMPARE(chars[1].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x40));
+ HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x40));
QCOMPARE(chars[1].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[1].descriptors().at(0).type(),
@@ -977,7 +1068,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Humidity Period
temp = QString("f000aa23-0451-4000-b000-000000000000");
QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x42));
+ HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x42));
QCOMPARE(chars[2].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[2].value(), QByteArray::fromHex("64"));
@@ -987,7 +1078,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[2].descriptors().count(), 1);
//descriptor checks
QCOMPARE(chars[2].descriptors().at(0).isValid(), true);
- QCOMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x43));
+ HANDLE_COMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x43));
QCOMPARE(chars[2].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[2].descriptors().at(0).type(),
@@ -1006,7 +1097,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QString temp("f000aa31-0451-4000-b000-000000000000");
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x46));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x46));
QCOMPARE(chars[0].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify));
QCOMPARE(chars[0].value(), QByteArray::fromHex("000000000000"));
@@ -1017,7 +1108,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x47));
+ HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x47));
QCOMPARE(chars[0].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration));
QCOMPARE(chars[0].descriptors().at(0).type(),
@@ -1027,7 +1118,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().at(1).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x48));
+ HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x48));
QCOMPARE(chars[0].descriptors().at(1).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[0].descriptors().at(1).type(),
@@ -1040,7 +1131,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
temp = QString("f000aa32-0451-4000-b000-000000000000");
QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x4a));
+ HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x4a));
QCOMPARE(chars[1].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[1].value(), QByteArray::fromHex("00"));
@@ -1050,7 +1141,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[1].descriptors().count(), 1);
QCOMPARE(chars[1].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x4b));
+ HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x4b));
QCOMPARE(chars[1].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[1].descriptors().at(0).type(),
@@ -1064,7 +1155,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
temp = QString("f000aa33-0451-4000-b000-000000000000");
QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x4d));
+ HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x4d));
QCOMPARE(chars[2].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[2].value(), QByteArray::fromHex("c8")); // don't change it or set it to 0xc8
@@ -1074,7 +1165,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[2].descriptors().count(), 1);
QCOMPARE(chars[2].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x4e));
+ HANDLE_COMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x4e));
QCOMPARE(chars[2].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[2].descriptors().at(0).type(),
@@ -1093,7 +1184,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QString temp("f000aa41-0451-4000-b000-000000000000");
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x51));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x51));
QCOMPARE(chars[0].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify));
QCOMPARE(chars[0].value(), QByteArray::fromHex("00000000"));
@@ -1104,7 +1195,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//descriptor checks
QCOMPARE(chars[0].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x52));
+ HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x52));
QCOMPARE(chars[0].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration));
QCOMPARE(chars[0].descriptors().at(0).type(),
@@ -1114,7 +1205,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().at(1).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x53));
+ HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x53));
QCOMPARE(chars[0].descriptors().at(1).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[0].descriptors().at(1).type(),
@@ -1128,7 +1219,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
temp = QString("f000aa42-0451-4000-b000-000000000000");
QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x55));
+ HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x55));
QCOMPARE(chars[1].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[1].value(), QByteArray::fromHex("00"));
@@ -1138,7 +1229,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[1].descriptors().count(), 1);
QCOMPARE(chars[1].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x56));
+ HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x56));
QCOMPARE(chars[1].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[1].descriptors().at(0).type(),
@@ -1162,7 +1253,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
temp = QString("f000aa43-0451-4000-b000-000000000000");
QCOMPARE(calibration.uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(calibration.handle(), QLowEnergyHandle(0x5b));
+ HANDLE_COMPARE(calibration.handle(), QLowEnergyHandle(0x5b));
QCOMPARE(calibration.properties(),
(QLowEnergyCharacteristic::Read));
QCOMPARE(calibration.value(), QByteArray::fromHex("00000000000000000000000000000000")); // don't change it
@@ -1173,7 +1264,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//descriptor checks
QCOMPARE(calibration.descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(calibration.descriptors().at(0).handle(), QLowEnergyHandle(0x5c));
+ HANDLE_COMPARE(calibration.descriptors().at(0).handle(), QLowEnergyHandle(0x5c));
QCOMPARE(calibration.descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration));
QCOMPARE(calibration.descriptors().at(0).type(),
@@ -1183,7 +1274,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(calibration.descriptors().at(1).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(calibration.descriptors().at(1).handle(), QLowEnergyHandle(0x5d));
+ HANDLE_COMPARE(calibration.descriptors().at(1).handle(), QLowEnergyHandle(0x5d));
QCOMPARE(calibration.descriptors().at(1).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(calibration.descriptors().at(1).type(),
@@ -1198,7 +1289,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
temp = QString("f000aa44-0451-4000-b000-000000000000");
QCOMPARE(period.uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(period.handle(), QLowEnergyHandle(0x58));
+ HANDLE_COMPARE(period.handle(), QLowEnergyHandle(0x58));
QCOMPARE(period.properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(period.value(), QByteArray::fromHex("64"));
@@ -1209,7 +1300,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//descriptor checks
QCOMPARE(period.descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(period.descriptors().at(0).handle(), QLowEnergyHandle(0x59));
+ HANDLE_COMPARE(period.descriptors().at(0).handle(), QLowEnergyHandle(0x59));
QCOMPARE(period.descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(period.descriptors().at(0).type(),
@@ -1228,7 +1319,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QString temp("f000aa51-0451-4000-b000-000000000000");
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x60));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x60));
QCOMPARE(chars[0].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify));
QCOMPARE(chars[0].value(), QByteArray::fromHex("000000000000"));
@@ -1239,7 +1330,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//descriptor checks
QCOMPARE(chars[0].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x61));
+ HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x61));
QCOMPARE(chars[0].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration));
QCOMPARE(chars[0].descriptors().at(0).type(),
@@ -1249,7 +1340,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().at(1).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x62));
+ HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x62));
QCOMPARE(chars[0].descriptors().at(1).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[0].descriptors().at(1).type(),
@@ -1263,7 +1354,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
temp = QString("f000aa52-0451-4000-b000-000000000000");
QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x64));
+ HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x64));
QCOMPARE(chars[1].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[1].value(), QByteArray::fromHex("00"));
@@ -1274,7 +1365,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//descriptor checks
QCOMPARE(chars[1].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x65));
+ HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x65));
QCOMPARE(chars[1].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[1].descriptors().at(0).type(),
@@ -1287,7 +1378,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
temp = QString("f000aa53-0451-4000-b000-000000000000");
QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x67));
+ HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x67));
QCOMPARE(chars[2].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[2].value(), QByteArray::fromHex("64"));
@@ -1297,7 +1388,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[2].descriptors().count(), 1);
//descriptor checks
QCOMPARE(chars[2].descriptors().at(0).isValid(), true);
- QCOMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x68));
+ HANDLE_COMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x68));
QCOMPARE(chars[2].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[2].descriptors().at(0).type(),
@@ -1315,7 +1406,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QString temp("f000aa61-0451-4000-b000-000000000000");
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x70));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x70));
QCOMPARE(chars[0].properties(),
(QLowEnergyCharacteristic::Read));
QCOMPARE(chars[0].value(), QByteArray::fromHex("3f00"));
@@ -1325,7 +1416,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().count(), 1);
QCOMPARE(chars[0].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x71));
+ HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x71));
QCOMPARE(chars[0].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[0].descriptors().at(0).type(),
@@ -1337,7 +1428,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
// Test Config
temp = QString("f000aa62-0451-4000-b000-000000000000");
QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x73));
+ HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x73));
QCOMPARE(chars[1].properties(),
(QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write));
QCOMPARE(chars[1].value(), QByteArray::fromHex("00"));
@@ -1348,7 +1439,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//descriptor checks
QCOMPARE(chars[1].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x74));
+ HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x74));
QCOMPARE(chars[1].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[1].descriptors().at(0).type(),
@@ -1365,7 +1456,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//first characteristic
QString temp("f000ccc1-0451-4000-b000-000000000000");
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x77));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x77));
QCOMPARE(chars[0].properties(),
(QLowEnergyCharacteristic::Notify|QLowEnergyCharacteristic::Read));
// the connection control parameter change from platform to platform
@@ -1377,7 +1468,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().count(), 2);
//descriptor checks
QCOMPARE(chars[0].descriptors().at(0).isValid(), true);
- QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x78));
+ HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x78));
QCOMPARE(chars[0].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration));
QCOMPARE(chars[0].descriptors().at(0).type(),
@@ -1388,7 +1479,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().at(1).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x79));
+ HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x79));
QCOMPARE(chars[0].descriptors().at(1).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[0].descriptors().at(1).type(),
@@ -1400,7 +1491,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//second characteristic
temp = QString("f000ccc2-0451-4000-b000-000000000000");
QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x7b));
+ HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x7b));
QCOMPARE(chars[1].properties(), QLowEnergyCharacteristic::Write);
QCOMPARE(chars[1].value(), QByteArray());
QVERIFY(chars[1].isValid());
@@ -1408,7 +1499,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[1].descriptors().count(), 1);
QCOMPARE(chars[1].descriptors().at(0).isValid(), true);
- QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x7c));
+ HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x7c));
QCOMPARE(chars[1].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[1].descriptors().at(0).type(),
@@ -1420,7 +1511,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//third characteristic
temp = QString("f000ccc3-0451-4000-b000-000000000000");
QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp));
- QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x7e));
+ HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x7e));
QCOMPARE(chars[2].properties(), QLowEnergyCharacteristic::Write);
QCOMPARE(chars[2].value(), QByteArray());
QVERIFY(chars[2].isValid());
@@ -1428,7 +1519,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[2].descriptors().count(), 1);
QCOMPARE(chars[2].descriptors().at(0).isValid(), true);
- QCOMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x7f));
+ HANDLE_COMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x7f));
QCOMPARE(chars[2].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[2].descriptors().at(0).type(),
@@ -1446,7 +1537,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QString temp("f000ffc1-0451-4000-b000-000000000000");
QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x82));
+ HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x82));
QCOMPARE(chars[0].properties(),
(QLowEnergyCharacteristic::Notify|QLowEnergyCharacteristic::Write|QLowEnergyCharacteristic::WriteNoResponse));
QCOMPARE(chars[0].value(), QByteArray());
@@ -1456,7 +1547,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().count(), 2);
//descriptor checks
QCOMPARE(chars[0].descriptors().at(0).isValid(), true);
- QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x83));
+ HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x83));
QCOMPARE(chars[0].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration));
QCOMPARE(chars[0].descriptors().at(0).type(),
@@ -1467,7 +1558,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[0].descriptors().at(1).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x84));
+ HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x84));
QCOMPARE(chars[0].descriptors().at(1).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[0].descriptors().at(1).type(),
@@ -1480,7 +1571,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
temp = QString("f000ffc2-0451-4000-b000-000000000000");
QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp));
// value different in other revisions and test may fail
- QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x86));
+ HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x86));
QCOMPARE(chars[1].properties(),
(QLowEnergyCharacteristic::Notify|QLowEnergyCharacteristic::Write|QLowEnergyCharacteristic::WriteNoResponse));
QCOMPARE(chars[1].value(), QByteArray());
@@ -1491,7 +1582,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
//descriptor checks
QCOMPARE(chars[1].descriptors().at(0).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x87));
+ HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x87));
QCOMPARE(chars[1].descriptors().at(0).uuid(),
QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration));
QCOMPARE(chars[1].descriptors().at(0).type(),
@@ -1502,7 +1593,7 @@ void tst_QLowEnergyController::verifyServiceProperties(
QCOMPARE(chars[1].descriptors().at(1).isValid(), true);
// value different in other revisions and test may fail
- QCOMPARE(chars[1].descriptors().at(1).handle(), QLowEnergyHandle(0x88));
+ HANDLE_COMPARE(chars[1].descriptors().at(1).handle(), QLowEnergyHandle(0x88));
QCOMPARE(chars[1].descriptors().at(1).uuid(),
QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription));
QCOMPARE(chars[1].descriptors().at(1).type(),
@@ -1566,12 +1657,19 @@ void tst_QLowEnergyController::tst_defaultBehavior()
void tst_QLowEnergyController::tst_writeCharacteristic()
{
+#ifndef Q_OS_MAC
QList<QBluetoothHostInfo> localAdapters = QBluetoothLocalDevice::allDevices();
if (localAdapters.isEmpty() || remoteDevice.isNull())
QSKIP("No local Bluetooth or remote BTLE device found. Skipping test.");
// quick setup - more elaborate test is done by connect()
QLowEnergyController control(remoteDevice);
+#else
+ if (remoteDeviceInfo.deviceUuid().isNull())
+ QSKIP("No local Bluetooth or remote BTLE device found. Skipping test.");
+ QLowEnergyController control(remoteDeviceInfo);
+#endif
+
QCOMPARE(control.error(), QLowEnergyController::NoError);
control.connectToDevice();
@@ -1590,7 +1688,7 @@ void tst_QLowEnergyController::tst_writeCharacteristic()
QSignalSpy discoveryFinishedSpy(&control, SIGNAL(discoveryFinished()));
QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState)));
control.discoverServices();
- QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000);
+ QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000);
QCOMPARE(stateSpy.count(), 2);
QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(),
QLowEnergyController::DiscoveringState);
@@ -1624,6 +1722,7 @@ void tst_QLowEnergyController::tst_writeCharacteristic()
QVERIFY(service->contains(dataChar));
QVERIFY(configChar.isValid());
QVERIFY(configChar.properties() & QLowEnergyCharacteristic::Write);
+ QVERIFY(configChar.properties() & QLowEnergyCharacteristic::Read);
QVERIFY(service->contains(configChar));
QCOMPARE(dataChar.value(), QByteArray::fromHex("3f00"));
@@ -1632,11 +1731,13 @@ void tst_QLowEnergyController::tst_writeCharacteristic()
QSignalSpy writeSpy(service,
SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray)));
+ QSignalSpy readSpy(service,
+ SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)));
// *******************************************
// test writing of characteristic
// enable Blinking LED if not already enabled
- if (configChar.value() != QByteArray("81")) {
+ if (configChar.value() != QByteArray::fromHex("81")) {
service->writeCharacteristic(configChar, QByteArray::fromHex("81")); //0x81 blink LED D1
QTRY_VERIFY_WITH_TIMEOUT(!writeSpy.isEmpty(), 10000);
QCOMPARE(configChar.value(), QByteArray::fromHex("81"));
@@ -1648,9 +1749,27 @@ void tst_QLowEnergyController::tst_writeCharacteristic()
QVERIFY(signalChar == configChar);
writeSpy.clear();
+
}
- service->writeCharacteristic(configChar, QByteArray::fromHex("00")); //0x81 blink LED D1
+ // test direct read of configChar
+ QVERIFY(readSpy.isEmpty());
+ service->readCharacteristic(configChar);
+ QTRY_VERIFY_WITH_TIMEOUT(!readSpy.isEmpty(), 10000);
+ QCOMPARE(configChar.value(), QByteArray::fromHex("81"));
+ QCOMPARE(readSpy.count(), 1); //expect one characteristicRead signal
+ {
+ //verify the readCharacteristic()
+ QList<QVariant> firstSignalData = readSpy.first();
+ QLowEnergyCharacteristic signalChar = firstSignalData[0].value<QLowEnergyCharacteristic>();
+ QByteArray signalValue = firstSignalData[1].toByteArray();
+
+ QCOMPARE(signalValue, QByteArray::fromHex("81"));
+ QCOMPARE(signalValue, configChar.value());
+ QVERIFY(signalChar == configChar);
+ }
+
+ service->writeCharacteristic(configChar, QByteArray::fromHex("00")); //turn LED D1 off
QTRY_VERIFY_WITH_TIMEOUT(!writeSpy.isEmpty(), 10000);
QCOMPARE(configChar.value(), QByteArray::fromHex("00"));
QList<QVariant> firstSignalData = writeSpy.first();
@@ -1684,8 +1803,8 @@ void tst_QLowEnergyController::tst_writeCharacteristic()
QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 10000);
QCOMPARE(errorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
- QLowEnergyService::OperationError);
- QCOMPARE(service->error(), QLowEnergyService::OperationError);
+ QLowEnergyService::CharacteristicWriteError);
+ QCOMPARE(service->error(), QLowEnergyService::CharacteristicWriteError);
QCOMPARE(writeSpy.count(), 0);
QCOMPARE(dataChar.value(), QByteArray::fromHex("3f00"));
@@ -1713,14 +1832,19 @@ void tst_QLowEnergyController::tst_writeCharacteristic()
delete service;
}
-void tst_QLowEnergyController::tst_writeDescriptor()
+void tst_QLowEnergyController::tst_readWriteDescriptor()
{
+#ifndef Q_OS_MAC
QList<QBluetoothHostInfo> localAdapters = QBluetoothLocalDevice::allDevices();
if (localAdapters.isEmpty() || remoteDevice.isNull())
QSKIP("No local Bluetooth or remote BTLE device found. Skipping test.");
-
- // quick setup - more elaborate test is done by connect()
QLowEnergyController control(remoteDevice);
+#else
+ if (remoteDeviceInfo.deviceUuid().isNull())
+ QSKIP("No local Bluetooth or remote BTLE device found. Skipping test.");
+ QLowEnergyController control(remoteDeviceInfo);
+#endif
+ // quick setup - more elaborate test is done by connect()
control.connectToDevice();
{
QTRY_IMPL(control.state() != QLowEnergyController::ConnectingState,
@@ -1737,7 +1861,7 @@ void tst_QLowEnergyController::tst_writeDescriptor()
QSignalSpy discoveryFinishedSpy(&control, SIGNAL(discoveryFinished()));
QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState)));
control.discoverServices();
- QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000);
+ QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000);
QCOMPARE(stateSpy.count(), 2);
QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(),
QLowEnergyController::DiscoveringState);
@@ -1787,9 +1911,11 @@ void tst_QLowEnergyController::tst_writeDescriptor()
QCOMPARE(tempConfig.value(), QByteArray::fromHex("00"));
}
- // 3. Test writing to descriptor -> activate notifications
+ // 3. Test reading and writing to descriptor -> activate notifications
QSignalSpy descWrittenSpy(service,
SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray)));
+ QSignalSpy descReadSpy(service,
+ SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray)));
QSignalSpy charWrittenSpy(service,
SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray)));
QSignalSpy charChangedSpy(service,
@@ -1836,12 +1962,31 @@ void tst_QLowEnergyController::tst_writeDescriptor()
const QLowEnergyCharacteristic ch = entry[0].value<QLowEnergyCharacteristic>();
QCOMPARE(tempData, ch);
+
+ //check last characteristic changed value matches the characteristics current value
+ if (i == (charChangedSpy.count() - 1)) {
+ writtenValue = entry[1].toByteArray();
+ QCOMPARE(ch.value(), writtenValue);
+ QCOMPARE(tempData.value(), writtenValue);
+ }
}
service->writeCharacteristic(tempConfig, QByteArray::fromHex("00"));
}
- // 5. Test writing to descriptor -> deactivate notifications
+ // 5. Test reading and writing of/to descriptor -> deactivate notifications
+
+ service->readDescriptor(notification);
+ QTRY_VERIFY_WITH_TIMEOUT(!descReadSpy.isEmpty(), 3000);
+ QCOMPARE(descReadSpy.count(), 1);
+ firstSignalData = descReadSpy.first();
+ signalDesc = firstSignalData[0].value<QLowEnergyDescriptor>();
+ signalValue = firstSignalData[1].toByteArray();
+ QCOMPARE(signalValue, notification.value());
+ QCOMPARE(notification.value(), QByteArray::fromHex("0100"));
+ descReadSpy.clear();
+
+
service->writeDescriptor(notification, QByteArray::fromHex("0000"));
// verify
QTRY_VERIFY_WITH_TIMEOUT(!descWrittenSpy.isEmpty(), 3000);
@@ -1853,6 +1998,41 @@ void tst_QLowEnergyController::tst_writeDescriptor()
QVERIFY(notification == signalDesc);
descWrittenSpy.clear();
+ // test concurrent writeRequests
+ // they need to be queued up
+ service->writeDescriptor(notification,QByteArray::fromHex("0100"));
+ service->writeDescriptor(notification, QByteArray::fromHex("0000"));
+ service->writeDescriptor(notification, QByteArray::fromHex("0100"));
+ service->writeDescriptor(notification, QByteArray::fromHex("0000"));
+ QTRY_VERIFY_WITH_TIMEOUT(descWrittenSpy.count() == 4, 10000);
+
+ QCOMPARE(notification.value(), QByteArray::fromHex("0000"));
+ for (int i = 0; i < descWrittenSpy.count(); i++) {
+ firstSignalData = descWrittenSpy.at(i);
+ signalDesc = firstSignalData[0].value<QLowEnergyDescriptor>();
+ signalValue = firstSignalData[1].toByteArray();
+ if (i & 0x1) // odd
+ QCOMPARE(signalValue, QByteArray::fromHex("0000"));
+ else // even
+ QCOMPARE(signalValue, QByteArray::fromHex("0100"));
+ QVERIFY(notification == signalDesc);
+
+ }
+
+ // 5. Test reading and writing of/to descriptor -> deactivate notifications
+
+ service->readDescriptor(notification);
+ QTRY_VERIFY_WITH_TIMEOUT(!descReadSpy.isEmpty(), 3000);
+ QCOMPARE(descReadSpy.count(), 1);
+ firstSignalData = descReadSpy.first();
+ signalDesc = firstSignalData[0].value<QLowEnergyDescriptor>();
+ signalValue = firstSignalData[1].toByteArray();
+ QCOMPARE(signalValue, notification.value());
+ QCOMPARE(notification.value(), QByteArray::fromHex("0000"));
+ descReadSpy.clear();
+
+ descWrittenSpy.clear();
+
// *******************************************
// write wrong value -> error response required
QSignalSpy errorSpy(service, SIGNAL(error(QLowEnergyService::ServiceError)));
@@ -1862,7 +2042,15 @@ void tst_QLowEnergyController::tst_writeDescriptor()
// write 4 byte value to 2 byte characteristic
service->writeDescriptor(notification, QByteArray::fromHex("11112222"));
+#ifdef Q_OS_MAC
+ // On OS X/iOS we have a special method to set notify value,
+ // it accepts only false/true and not
+ // writing descriptors, there is only one way to find this error -
+ // immediately intercept in LE controller and set the error.
+ QVERIFY(!errorSpy.isEmpty());
+#else
QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 30000);
+#endif
QCOMPARE(errorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
QLowEnergyService::DescriptorWriteError);
QCOMPARE(service->error(), QLowEnergyService::DescriptorWriteError);
@@ -1886,12 +2074,32 @@ void tst_QLowEnergyController::tst_writeDescriptor()
}
/*
- * Tests encrypted read/write.
+ * By default this test is skipped.
+ *
+ * Following tests are performed:
+ * - encrypted read and discovery
+ * - readCharacteristic() of values longer than MTU
+ * - readCharacteristic() if values equal to MTU
+ *
* This test is semi manual as the test device environment is very specific.
- * Adjust the various uuids and addresses at the top to cater for the current
- * situation. By default this test is skipped.
+ * A programmable BTLE device is required. Currently, the test requires
+ * the CSR Dev Kit using the hr_sensor example.
+ *
+ * The following changes must be done to example to be able to fully
+ * utilise the test:
+ * 1.) gap_service_db.db -> UUID_DEVICE_NAME char - add FLAG_ENCR_R
+ * => tests encrypted read/discovery
+ * 2.) dev_info_service_db.db -> UUID_DEVICE_INFO_MANUFACTURER_NAME
+ * => The default name "Cambridge Silicon Radio" must be changed
+ * to "Cambridge Silicon Radi" (new length 22)
+ * 3.) revert change 1 above and redo test. This attempts to write a
+ * char that is readable w/o encryption but writeable with encryption
+ * => tests encryption code lines in writeCharacteristic()
+ * => otherwise the read encryption would have increased security level already
+ * => programmable CSR device must be reset before each run of this test
+ * (to undo the previous write)
*/
-void tst_QLowEnergyController::tst_encryption()
+void tst_QLowEnergyController::tst_customProgrammableDevice()
{
QSKIP("Skipping encryption");
@@ -1922,7 +2130,7 @@ void tst_QLowEnergyController::tst_encryption()
QSignalSpy discoveryFinishedSpy(&control, SIGNAL(discoveryFinished()));
QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState)));
control.discoverServices();
- QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000);
+ QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000);
QCOMPARE(stateSpy.count(), 2);
QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(),
QLowEnergyController::DiscoveringState);
@@ -1934,33 +2142,360 @@ void tst_QLowEnergyController::tst_encryption()
QLowEnergyService *service = control.createServiceObject(serviceUuid, this);
QVERIFY(service);
+
+ // 1.) discovery triggers read of device name char which is encrypted
service->discoverDetails();
QTRY_VERIFY_WITH_TIMEOUT(
service->state() == QLowEnergyService::ServiceDiscovered, 30000);
- QLowEnergyCharacteristic characteristic = service->characteristic(
+ QLowEnergyCharacteristic encryptedChar = service->characteristic(
characterristicUuid);
+ const QByteArray encryptedReference("CSR HR Sensor");
+ QVERIFY(encryptedChar.isValid());
+ QCOMPARE(encryptedChar.value(), encryptedReference);
+
+ // 2.) read of encrypted characteristic
+ // => the discovery of the encrypted char above will have switched to
+ // encryption already.
+ QSignalSpy encryptedReadSpy(service,
+ SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)));
+ QSignalSpy encryptedErrorSpy(service,
+ SIGNAL(error(QLowEnergyService::ServiceError)));
+ service->readCharacteristic(encryptedChar);
+ QTRY_VERIFY_WITH_TIMEOUT(!encryptedReadSpy.isEmpty(), 10000);
+ QVERIFY(encryptedErrorSpy.isEmpty());
+ QCOMPARE(encryptedReadSpy.count(), 1);
+ QList<QVariant> entry = encryptedReadSpy[0];
+ QVERIFY(entry[0].value<QLowEnergyCharacteristic>() == encryptedChar);
+ QCOMPARE(entry[1].toByteArray(), encryptedReference);
+ QCOMPARE(encryptedChar.value(), encryptedReference);
+
+ // 3.) write to encrypted characteristic
+ QSignalSpy encryptedWriteSpy(service,
+ SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray)));
+ encryptedReadSpy.clear();
+ encryptedErrorSpy.clear();
+ const QByteArray newValue("ZZZ HR Sensor");
+ service->writeCharacteristic(encryptedChar, newValue);
+ QTRY_VERIFY_WITH_TIMEOUT(!encryptedWriteSpy.isEmpty(), 10000);
+ QVERIFY(encryptedErrorSpy.isEmpty());
+ QVERIFY(encryptedReadSpy.isEmpty());
+ QCOMPARE(encryptedWriteSpy.count(), 1);
+ entry = encryptedWriteSpy[0];
+ QVERIFY(entry[0].value<QLowEnergyCharacteristic>() == encryptedChar);
+ QCOMPARE(entry[1].toByteArray(), newValue);
+ QCOMPARE(encryptedChar.value(), newValue);
+
+ delete service;
- QVERIFY(characteristic.isValid());
- qDebug() << "Encrypted char value:" << characteristic.value().toHex() << characteristic.value();
- QVERIFY(!characteristic.value().isEmpty());
+ //change to Device Information service
+ QVERIFY(uuids.contains(QBluetoothUuid::DeviceInformation));
+ service = control.createServiceObject(QBluetoothUuid::DeviceInformation);
+ QVERIFY(service);
+
+ service->discoverDetails();
+ QTRY_VERIFY_WITH_TIMEOUT(
+ service->state() == QLowEnergyService::ServiceDiscovered, 30000);
+
+ // 4.) read of software revision string which is longer than mtu
+ // tests readCharacteristic() including blob reads
+ QSignalSpy readSpy(service,
+ SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)));
+ QSignalSpy errorSpy(service,
+ SIGNAL(error(QLowEnergyService::ServiceError)));
+
+ const QByteArray expectedSoftRev("Application version 2.3.0.0");
+ QLowEnergyCharacteristic softwareRevChar
+ = service->characteristic(QBluetoothUuid::SoftwareRevisionString);
+ QVERIFY(softwareRevChar.isValid());
+ QCOMPARE(softwareRevChar.value(), expectedSoftRev);
+
+ service->readCharacteristic(softwareRevChar);
+ QTRY_VERIFY_WITH_TIMEOUT(!readSpy.isEmpty(), 10000);
+ QVERIFY(errorSpy.isEmpty());
+ QCOMPARE(readSpy.count(), 1);
+ entry = readSpy[0];
+ QVERIFY(entry[0].value<QLowEnergyCharacteristic>() == softwareRevChar);
+ QCOMPARE(entry[1].toByteArray(), expectedSoftRev);
+ QCOMPARE(softwareRevChar.value(), expectedSoftRev);
+
+
+ // 5.) read of manufacturer string which is exactly as long as single
+ // MTU size (assuming negotiated MTU is 23)
+ // => blob read test without blob being required
+ // => the read blob answer will have zero length
+
+ readSpy.clear();
+
+ // This assumes the manufacturer string was mondified via CSR SDK
+ // see function description above
+ const QByteArray expectedManufacturer("Cambridge Silicon Radi");
+ QLowEnergyCharacteristic manufacturerChar = service->characteristic(
+ QBluetoothUuid::ManufacturerNameString);
+ QVERIFY(manufacturerChar.isValid());
+ QCOMPARE(manufacturerChar.value(), expectedManufacturer);
+
+ service->readCharacteristic(manufacturerChar);
+ QTRY_VERIFY_WITH_TIMEOUT(!readSpy.isEmpty(), 10000);
+ QVERIFY(errorSpy.isEmpty());
+ QCOMPARE(readSpy.count(), 1);
+ entry = readSpy[0];
+ QVERIFY(entry[0].value<QLowEnergyCharacteristic>() == manufacturerChar);
+ QCOMPARE(entry[1].toByteArray(), expectedManufacturer);
+ QCOMPARE(manufacturerChar.value(), expectedManufacturer);
delete service;
control.disconnectFromDevice();
}
+
+/* 1.) Test with undiscovered devices
+ - read and write invalid char
+ 2.) Test with discovered devices
+ - read non-readable char
+ - write non-writable char
+ */
+void tst_QLowEnergyController::tst_errorCases()
+{
+#ifndef Q_OS_MAC
+ QList<QBluetoothHostInfo> localAdapters = QBluetoothLocalDevice::allDevices();
+ if (localAdapters.isEmpty() || remoteDevice.isNull())
+ QSKIP("No local Bluetooth or remote BTLE device found. Skipping test.");
+
+ // quick setup - more elaborate test is done by connect()
+ QLowEnergyController control(remoteDevice);
+#else
+ if (remoteDeviceInfo.deviceUuid().isNull())
+ QSKIP("No local Bluetooth or remote BTLE device found. Skipping test.");
+
+ QLowEnergyController control(remoteDeviceInfo);
+#endif
+ QCOMPARE(control.error(), QLowEnergyController::NoError);
+
+ control.connectToDevice();
+ {
+ QTRY_IMPL(control.state() != QLowEnergyController::ConnectingState,
+ 30000);
+ }
+
+ if (control.state() == QLowEnergyController::ConnectingState
+ || control.error() != QLowEnergyController::NoError) {
+ // default BTLE backend forever hangs in ConnectingState
+ QSKIP("Cannot connect to remote device");
+ }
+
+ QCOMPARE(control.state(), QLowEnergyController::ConnectedState);
+ QSignalSpy discoveryFinishedSpy(&control, SIGNAL(discoveryFinished()));
+ QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState)));
+ control.discoverServices();
+ QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000);
+ QCOMPARE(stateSpy.count(), 2);
+ QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(),
+ QLowEnergyController::DiscoveringState);
+ QCOMPARE(stateSpy.at(1).at(0).value<QLowEnergyController::ControllerState>(),
+ QLowEnergyController::DiscoveredState);
+
+
+ // Setup required uuids
+ const QBluetoothUuid irTemperaturServiceUuid(QStringLiteral("f000aa00-0451-4000-b000-000000000000"));
+ const QBluetoothUuid irCharUuid(QString("f000aa01-0451-4000-b000-000000000000"));
+ const QBluetoothUuid oadServiceUuid(QStringLiteral("f000ffc0-0451-4000-b000-000000000000"));
+ const QBluetoothUuid oadCharUuid(QString("f000ffc1-0451-4000-b000-000000000000"));
+
+ QVERIFY(control.services().contains(irTemperaturServiceUuid));
+ QVERIFY(control.services().contains(oadServiceUuid));
+
+ // Create service objects and basic tests
+ QLowEnergyService *irService = control.createServiceObject(irTemperaturServiceUuid);
+ QVERIFY(irService);
+ QCOMPARE(irService->state(), QLowEnergyService::DiscoveryRequired);
+ QVERIFY(irService->characteristics().isEmpty());
+ QLowEnergyService *oadService = control.createServiceObject(oadServiceUuid);
+ QVERIFY(oadService);
+ QCOMPARE(oadService->state(), QLowEnergyService::DiscoveryRequired);
+ QVERIFY(oadService->characteristics().isEmpty());
+
+ QLowEnergyCharacteristic invalidChar;
+ QLowEnergyDescriptor invalidDesc;
+
+ QVERIFY(!irService->contains(invalidChar));
+ QVERIFY(!irService->contains(invalidDesc));
+
+ QSignalSpy irErrorSpy(irService, SIGNAL(error(QLowEnergyService::ServiceError)));
+ QSignalSpy oadErrorSpy(oadService, SIGNAL(error(QLowEnergyService::ServiceError)));
+
+ QSignalSpy irReadSpy(irService, SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)));
+ QSignalSpy irWrittenSpy(irService, SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray)));
+ QSignalSpy irDescReadSpy(irService, SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray)));
+ QSignalSpy irDescWrittenSpy(irService, SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray)));
+
+ QSignalSpy oadCharReadSpy(oadService, SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray)));
+
+ // ********************************************************
+ // Test read/write to discovered service
+ // with invalid characteristic & descriptor
+
+ // discover IR Service
+ irService->discoverDetails();
+ QTRY_VERIFY_WITH_TIMEOUT(
+ irService->state() == QLowEnergyService::ServiceDiscovered, 30000);
+ QVERIFY(!irService->contains(invalidChar));
+ QVERIFY(!irService->contains(invalidDesc));
+ irErrorSpy.clear();
+
+ // read invalid characteristic
+ irService->readCharacteristic(invalidChar);
+ QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000);
+ QCOMPARE(irErrorSpy.count(), 1);
+ QVERIFY(irWrittenSpy.isEmpty());
+ QVERIFY(irReadSpy.isEmpty());
+ QCOMPARE(irErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
+ QLowEnergyService::OperationError);
+ irErrorSpy.clear();
+
+ // read invalid descriptor
+ irService->readDescriptor(invalidDesc);
+ QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000);
+ QCOMPARE(irErrorSpy.count(), 1);
+ QVERIFY(irDescWrittenSpy.isEmpty());
+ QVERIFY(irDescReadSpy.isEmpty());
+ QCOMPARE(irErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
+ QLowEnergyService::OperationError);
+ irErrorSpy.clear();
+
+ // write invalid characteristic
+ irService->writeCharacteristic(invalidChar, QByteArray("foo"));
+ QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000);
+ QCOMPARE(irErrorSpy.count(), 1);
+ QVERIFY(irWrittenSpy.isEmpty());
+ QVERIFY(irReadSpy.isEmpty());
+ QCOMPARE(irErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
+ QLowEnergyService::OperationError);
+ irErrorSpy.clear();
+
+ // write invalid descriptor
+ irService->readDescriptor(invalidDesc);
+ QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000);
+ QCOMPARE(irErrorSpy.count(), 1);
+ QVERIFY(irDescWrittenSpy.isEmpty());
+ QVERIFY(irDescReadSpy.isEmpty());
+ QCOMPARE(irErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
+ QLowEnergyService::OperationError);
+ irErrorSpy.clear();
+
+ // ********************************************************
+ // Test read/write to undiscovered service
+ // with invalid characteristic & descriptor
+
+ // read invalid characteristic
+ oadService->readCharacteristic(invalidChar);
+ QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000);
+ QCOMPARE(oadErrorSpy.count(), 1);
+ QCOMPARE(oadErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
+ QLowEnergyService::OperationError);
+ oadErrorSpy.clear();
+
+ // read invalid descriptor
+ oadService->readDescriptor(invalidDesc);
+ QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000);
+ QCOMPARE(oadErrorSpy.count(), 1);
+ QCOMPARE(oadErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
+ QLowEnergyService::OperationError);
+ oadErrorSpy.clear();
+
+ // write invalid characteristic
+ oadService->writeCharacteristic(invalidChar, QByteArray("foo"));
+ QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000);
+ QCOMPARE(oadErrorSpy.count(), 1);
+ QCOMPARE(oadErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
+ QLowEnergyService::OperationError);
+ oadErrorSpy.clear();
+
+ // write invalid descriptor
+ oadService->readDescriptor(invalidDesc);
+ QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000);
+ QCOMPARE(oadErrorSpy.count(), 1);
+ QCOMPARE(oadErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
+ QLowEnergyService::OperationError);
+ oadErrorSpy.clear();
+
+ // ********************************************************
+ // Write to non-writable char
+
+ QLowEnergyCharacteristic nonWritableChar = irService->characteristic(irCharUuid);
+ QVERIFY(nonWritableChar.isValid());
+ // not writeable in any form
+ QVERIFY(!(nonWritableChar.properties()
+ & (QLowEnergyCharacteristic::Write|QLowEnergyCharacteristic::WriteNoResponse
+ |QLowEnergyCharacteristic::WriteSigned)));
+ irService->writeCharacteristic(nonWritableChar, QByteArray("ABCD"));
+ QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000);
+ QVERIFY(irWrittenSpy.isEmpty());
+ QVERIFY(irReadSpy.isEmpty());
+ QCOMPARE(irErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
+ QLowEnergyService::CharacteristicWriteError);
+ irErrorSpy.clear();
+
+ // ********************************************************
+ // Write to non-writable desc
+ // CharacteristicUserDescription is not writable
+
+ QLowEnergyDescriptor nonWritableDesc = nonWritableChar.descriptor(
+ QBluetoothUuid::CharacteristicUserDescription);
+ QVERIFY(nonWritableDesc.isValid());
+ irService->writeDescriptor(nonWritableDesc, QByteArray("ABCD"));
+ QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000);
+ QVERIFY(irWrittenSpy.isEmpty());
+ QVERIFY(irReadSpy.isEmpty());
+ QCOMPARE(irErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
+ QLowEnergyService::DescriptorWriteError);
+ irErrorSpy.clear();
+
+
+ // ********************************************************
+ // Read non-readable char
+
+ // discover OAD Service
+ oadService->discoverDetails();
+ QTRY_VERIFY_WITH_TIMEOUT(
+ oadService->state() == QLowEnergyService::ServiceDiscovered, 30000);
+ oadErrorSpy.clear();
+
+ // Test reading
+ QLowEnergyCharacteristic oadChar = oadService->characteristic(oadCharUuid);
+ QVERIFY(oadChar.isValid());
+ oadService->readCharacteristic(oadChar);
+ QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000);
+ QCOMPARE(oadErrorSpy.count(), 1);
+ QVERIFY(oadCharReadSpy.isEmpty());
+ QCOMPARE(oadErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
+ QLowEnergyService::CharacteristicReadError);
+ oadErrorSpy.clear();
+
+ delete irService;
+ delete oadService;
+ control.disconnectFromDevice();
+}
+
/*
Tests write without responses. We utilize the Over-The-Air image update
service of the SensorTag.
*/
void tst_QLowEnergyController::tst_writeCharacteristicNoResponse()
{
+#ifndef Q_OS_MAC
QList<QBluetoothHostInfo> localAdapters = QBluetoothLocalDevice::allDevices();
if (localAdapters.isEmpty() || remoteDevice.isNull())
QSKIP("No local Bluetooth or remote BTLE device found. Skipping test.");
// quick setup - more elaborate test is done by connect()
QLowEnergyController control(remoteDevice);
+#else
+ if (remoteDeviceInfo.deviceUuid().isNull())
+ QSKIP("No local Bluetooth or remote BTLE device found. Skipping test.");
+
+ QLowEnergyController control(remoteDeviceInfo);
+#endif
QCOMPARE(control.error(), QLowEnergyController::NoError);
control.connectToDevice();
@@ -1979,7 +2514,7 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse()
QSignalSpy discoveryFinishedSpy(&control, SIGNAL(discoveryFinished()));
QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState)));
control.discoverServices();
- QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000);
+ QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000);
QCOMPARE(stateSpy.count(), 2);
QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(),
QLowEnergyController::DiscoveringState);
@@ -2005,6 +2540,7 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse()
QVERIFY(imageIdentityChar.isValid());
QVERIFY(imageIdentityChar.properties() & QLowEnergyCharacteristic::Write);
QVERIFY(imageIdentityChar.properties() & QLowEnergyCharacteristic::WriteNoResponse);
+ QVERIFY(!(imageIdentityChar.properties() & QLowEnergyCharacteristic::Read)); //not readable
QVERIFY(imageBlockChar.isValid());
// 2. Get "Image Identity" notification descriptor
@@ -2024,7 +2560,15 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse()
SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray)));
QSignalSpy charWrittenSpy(service,
SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray)));
+ QSignalSpy charReadSpy(service,
+ SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)));
+ QSignalSpy errorSpy(service,
+ SIGNAL(error(QLowEnergyService::ServiceError)));
+
+ // by default the device enables the notification bit already
+ // no need to enable it. If notifications fail to arrive the
+ // platform must check default enabled notifications.
if (notification.value() != QByteArray::fromHex("0100")) {
service->writeDescriptor(notification, QByteArray::fromHex("0100"));
QTRY_VERIFY_WITH_TIMEOUT(!descWrittenSpy.isEmpty(), 3000);
@@ -2037,8 +2581,20 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse()
descWrittenSpy.clear();
}
- // 4. Trigger image identity announcement (using traditional write)
QList<QVariant> entry;
+
+ // Test direct read of non-readable characteristic
+ QVERIFY(errorSpy.isEmpty());
+ QVERIFY(charReadSpy.isEmpty());
+ service->readCharacteristic(imageIdentityChar);
+ QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 10000);
+ QCOMPARE(errorSpy.count(), 1); // should throw CharacteristicReadError
+ QVERIFY(charReadSpy.isEmpty());
+ entry = errorSpy[0];
+ QCOMPARE(entry[0].value<QLowEnergyService::ServiceError>(),
+ QLowEnergyService::CharacteristicReadError);
+
+ // 4. Trigger image identity announcement (using traditional write)
bool foundOneImage = false;
// Image A
@@ -2060,6 +2616,8 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse()
QCOMPARE(imageIdentityChar, first);
foundOneImage = true;
} else {
+ // we received a notification for imageBlockChar without explicitly
+ // enabling them. This is caused by the device's default settings.
QCOMPARE(imageBlockChar, first);
qWarning() << "Invalid image A ident info";
}
@@ -2068,7 +2626,11 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse()
QLowEnergyCharacteristic second = entry[0].value<QLowEnergyCharacteristic>();
QByteArray val2 = entry[1].toByteArray();
QCOMPARE(imageIdentityChar, second);
- QCOMPARE(val2, QByteArray::fromHex("0"));
+ QVERIFY(val2 == QByteArray::fromHex("0") || val2 == val1);
+
+ // notifications on non-readable characteristics do not update cache
+ QVERIFY(imageIdentityChar.value().isEmpty());
+ QVERIFY(imageBlockChar.value().isEmpty());
charChangedSpy.clear();
charWrittenSpy.clear();
@@ -2086,6 +2648,8 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse()
QCOMPARE(imageIdentityChar, first);
foundOneImage = true;
} else {
+ // we received a notification for imageBlockChar without explicitly
+ // enabling them. This is caused by the device's default settings.
QCOMPARE(imageBlockChar, first);
qWarning() << "Invalid image B ident info";
}
@@ -2094,7 +2658,16 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse()
second = entry[0].value<QLowEnergyCharacteristic>();
val2 = entry[1].toByteArray();
QCOMPARE(imageIdentityChar, second);
- QCOMPARE(val2, QByteArray::fromHex("1"));
+
+ // notifications on non-readable characteristics do not update cache
+ QVERIFY(imageIdentityChar.value().isEmpty());
+ QVERIFY(imageBlockChar.value().isEmpty());
+
+ /* Bluez resends the last confirmed write value, other platforms
+ * send the value received by the change notification value.
+ */
+ qDebug() << "Image B(1):" << val1.toHex() << val2.toHex();
+ QVERIFY(val2 == QByteArray::fromHex("1") || val2 == val1);
QVERIFY2(foundOneImage, "The SensorTag doesn't have a valid image? (1)");
@@ -2117,15 +2690,25 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse()
first = entry[0].value<QLowEnergyCharacteristic>();
val1 = entry[1].toByteArray();
+#ifdef Q_OS_ANDROID
+ QEXPECT_FAIL("", "Android sends write confirmation when using WriteWithoutResponse",
+ Continue);
+#endif
QVERIFY(charWrittenSpy.isEmpty());
if (val1.size() == 8) {
QCOMPARE(first, imageIdentityChar);
foundOneImage = true;
} else {
+ // we received a notification for imageBlockChar without explicitly
+ // enabling them. This is caused by the device's default settings.
QCOMPARE(imageBlockChar, first);
qWarning() << "Image A not set?";
}
+ // notifications on non-readable characteristics do not update cache
+ QVERIFY(imageIdentityChar.value().isEmpty());
+ QVERIFY(imageBlockChar.value().isEmpty());
+
charChangedSpy.clear();
// Image B
@@ -2142,15 +2725,26 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse()
first = entry[0].value<QLowEnergyCharacteristic>();
val1 = entry[1].toByteArray();
+#ifdef Q_OS_ANDROID
+ QEXPECT_FAIL("", "Android sends write confirmation when using WriteWithoutResponse",
+ Continue);
+#endif
QVERIFY(charWrittenSpy.isEmpty());
if (val1.size() == 8) {
QCOMPARE(first, imageIdentityChar);
foundOneImage = true;
} else {
+ // we received a notification for imageBlockChar without explicitly
+ // enabling them. This is caused by the device's default settings.
QCOMPARE(imageBlockChar, first);
qWarning() << "Image B not set?";
}
+ // notifications on non-readable characteristics do not update cache
+ QVERIFY(imageIdentityChar.value().isEmpty());
+ QVERIFY(imageBlockChar.value().isEmpty());
+
+
QVERIFY2(foundOneImage, "The SensorTag doesn't have a valid image? (2)");
delete service;