summaryrefslogtreecommitdiffstats
path: root/tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp')
-rw-r--r--tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp240
1 files changed, 240 insertions, 0 deletions
diff --git a/tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp b/tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp
new file mode 100644
index 00000000..1275aa65
--- /dev/null
+++ b/tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtBluetooth/qlowenergyadvertisingdata.h>
+#include <QtBluetooth/qlowenergyadvertisingparameters.h>
+#include <QtBluetooth/qlowenergyconnectionparameters.h>
+#include <QtBluetooth/qlowenergycontroller.h>
+#include <QtBluetooth/qlowenergycharacteristicdata.h>
+#include <QtBluetooth/qlowenergydescriptordata.h>
+#include <QtBluetooth/qlowenergyservicedata.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qendian.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qvector.h>
+
+static QByteArray deviceName() { return "Qt GATT server"; }
+
+static QScopedPointer<QLowEnergyController> leController;
+typedef QSharedPointer<QLowEnergyService> ServicePtr;
+static QHash<QBluetoothUuid, ServicePtr> services;
+static int descriptorWriteCount = 0;
+static int disconnectCount = 0;
+static QBluetoothAddress remoteDevice;
+
+void addService(const QLowEnergyServiceData &serviceData)
+{
+ const ServicePtr service(leController->addService(serviceData));
+ Q_ASSERT(service);
+ services.insert(service->serviceUuid(), service);
+}
+
+void addRunningSpeedService()
+{
+ QLowEnergyServiceData serviceData;
+ serviceData.setUuid(QBluetoothUuid::RunningSpeedAndCadence);
+ serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
+
+ QLowEnergyDescriptorData desc;
+ desc.setUuid(QBluetoothUuid::ClientCharacteristicConfiguration);
+ desc.setValue(QByteArray(2, 0)); // Default: No indication, no notification.
+ QLowEnergyCharacteristicData charData;
+ charData.setUuid(QBluetoothUuid::RSCMeasurement);
+ charData.addDescriptor(desc);
+ charData.setProperties(QLowEnergyCharacteristic::Notify);
+ QByteArray value(4, 0);
+ value[0] = 1 << 2; // "Running", no optional fields.
+ charData.setValue(value);
+ serviceData.addCharacteristic(charData);
+
+ charData = QLowEnergyCharacteristicData();
+ charData.setUuid(QBluetoothUuid::RSCFeature);
+ charData.setProperties(QLowEnergyCharacteristic::Read);
+ value = QByteArray(2, 0);
+ qToLittleEndian<quint16>(1 << 2, reinterpret_cast<uchar *>(value.data()));
+ charData.setValue(value);
+ serviceData.addCharacteristic(charData);
+ addService(serviceData);
+}
+
+void addGenericAccessService()
+{
+ QLowEnergyServiceData serviceData;
+ serviceData.setUuid(QBluetoothUuid::GenericAccess);
+ serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
+
+ QLowEnergyCharacteristicData charData;
+ charData.setUuid(QBluetoothUuid::DeviceName);
+ charData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Write);
+ charData.setValue(deviceName());
+ serviceData.addCharacteristic(charData);
+
+ charData = QLowEnergyCharacteristicData();
+ charData.setUuid(QBluetoothUuid::Appearance);
+ charData.setProperties(QLowEnergyCharacteristic::Read);
+ QByteArray value(2, 0);
+ qToLittleEndian<quint16>(128, reinterpret_cast<uchar *>(value.data())); // Generic computer.
+ charData.setValue(value);
+ serviceData.addCharacteristic(charData);
+
+ serviceData.addIncludedService(services.value(QBluetoothUuid::RunningSpeedAndCadence).data());
+ addService(serviceData);
+}
+
+void addCustomService()
+{
+ QLowEnergyServiceData serviceData;
+ serviceData.setUuid(QBluetoothUuid(quint16(0x2000)));
+ serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
+
+ QLowEnergyCharacteristicData charData;
+ charData.setUuid(QBluetoothUuid(quint16(0x5000))); // Made up.
+ charData.setProperties(QLowEnergyCharacteristic::Read);
+ charData.setValue(QByteArray(1024, 'x')); // Long value to test "Read Blob".
+ serviceData.addCharacteristic(charData);
+
+ charData.setUuid(QBluetoothUuid(quint16(0x5001)));
+ charData.setProperties(QLowEnergyCharacteristic::Read);
+ charData.setReadConstraints(QBluetooth::AttAuthorizationRequired); // To test read failure.
+ serviceData.addCharacteristic(charData);
+ charData.setValue("something");
+
+ charData.setUuid(QBluetoothUuid(quint16(0x5002)));
+ charData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Indicate);
+ charData.setReadConstraints(QBluetooth::AttAccessConstraints());
+ const QLowEnergyDescriptorData desc(QBluetoothUuid::ClientCharacteristicConfiguration,
+ QByteArray(2, 0));
+ charData.addDescriptor(desc);
+ serviceData.addCharacteristic(charData);
+
+ charData.setUuid(QBluetoothUuid(quint16(0x5003)));
+ charData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Notify);
+ serviceData.addCharacteristic(charData);
+
+ charData.setUuid(QBluetoothUuid(quint16(0x5004)));
+ charData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::WriteSigned);
+ charData.setDescriptors(QList<QLowEnergyDescriptorData>());
+ charData.setValue("initial");
+ serviceData.addCharacteristic(charData);
+
+ addService(serviceData);
+
+ // service with full 128 bit custom uuids
+ QLowEnergyServiceData serviceData128;
+ serviceData128.setUuid(QBluetoothUuid(QString("c47774c7-f237-4523-8968-e4ae75431daf")));
+ serviceData128.setType(QLowEnergyServiceData::ServiceTypePrimary);
+
+ QLowEnergyCharacteristicData charData128;
+ charData128.setUuid(QBluetoothUuid(QString("c0ad61b1-79e7-42f9-ace0-0a9aa0d0a4f8")));
+ charData128.setProperties(QLowEnergyCharacteristic::Read);
+ charData128.setValue(QByteArray(15, 'a'));
+ serviceData128.addCharacteristic(charData128);
+
+ addService(serviceData128);
+}
+
+void startAdvertising()
+{
+ QLowEnergyAdvertisingParameters params;
+ params.setMode(QLowEnergyAdvertisingParameters::AdvInd);
+ QLowEnergyAdvertisingData data;
+ data.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityLimited);
+ data.setServices(services.keys());
+ data.setIncludePowerLevel(true);
+ data.setLocalName(deviceName());
+ leController->startAdvertising(params, data);
+}
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+ leController.reset(QLowEnergyController::createPeripheral());
+ addRunningSpeedService();
+ addGenericAccessService();
+ addCustomService();
+ startAdvertising();
+
+ const ServicePtr customService = services.value(QBluetoothUuid(quint16(0x2000)));
+ Q_ASSERT(customService);
+
+ const auto stateChangedHandler = [customService]() {
+ switch (leController->state()) {
+ case QLowEnergyController::ConnectedState:
+ remoteDevice = leController->remoteAddress();
+ break;
+ case QLowEnergyController::UnconnectedState: {
+ if (++disconnectCount == 2) {
+ qApp->quit();
+ break;
+ }
+ Q_ASSERT(disconnectCount == 1);
+ const QLowEnergyCharacteristic indicatableChar
+ = customService->characteristic(QBluetoothUuid(quint16(0x5002)));
+ Q_ASSERT(indicatableChar.isValid());
+ customService->writeCharacteristic(indicatableChar, "indicated2");
+ Q_ASSERT(indicatableChar.value() == "indicated2");
+ const QLowEnergyCharacteristic notifiableChar
+ = customService->characteristic(QBluetoothUuid(quint16(0x5003)));
+ Q_ASSERT(notifiableChar.isValid());
+ customService->writeCharacteristic(notifiableChar, "notified2");
+ Q_ASSERT(notifiableChar.value() == "notified2");
+ startAdvertising();
+ break;
+ }
+ default:
+ break;
+ }
+ };
+
+ QObject::connect(leController.data(), &QLowEnergyController::stateChanged, stateChangedHandler);
+ const auto descriptorWriteHandler = [customService]() {
+ if (++descriptorWriteCount != 2)
+ return;
+ const QLowEnergyCharacteristic indicatableChar
+ = customService->characteristic(QBluetoothUuid(quint16(0x5002)));
+ Q_ASSERT(indicatableChar.isValid());
+ customService->writeCharacteristic(indicatableChar, "indicated");
+ Q_ASSERT(indicatableChar.value() == "indicated");
+ const QLowEnergyCharacteristic notifiableChar
+ = customService->characteristic(QBluetoothUuid(quint16(0x5003)));
+ Q_ASSERT(notifiableChar.isValid());
+ customService->writeCharacteristic(notifiableChar, "notified");
+ Q_ASSERT(notifiableChar.value() == "notified");
+ QLowEnergyConnectionParameters connParams;
+ connParams.setIntervalRange(30, 62.5);
+ connParams.setLatency(5);
+ connParams.setSupervisionTimeout(5500);
+ leController->requestConnectionUpdate(connParams);
+ };
+ QObject::connect(customService.data(), &QLowEnergyService::descriptorWritten,
+ descriptorWriteHandler);
+
+ return app.exec();
+}