From 4305c76471d17bec177a50cfd39bbfd480d36069 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 29 Oct 2023 23:14:51 +0100 Subject: [PATCH 1/3] Fix building with newer gcc --- libnymea-core/ruleengine/ruleengine.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libnymea-core/ruleengine/ruleengine.cpp b/libnymea-core/ruleengine/ruleengine.cpp index 5f5ba97a..b0aa2caf 100644 --- a/libnymea-core/ruleengine/ruleengine.cpp +++ b/libnymea-core/ruleengine/ruleengine.cpp @@ -1185,7 +1185,7 @@ void RuleEngine::saveRule(const Rule &rule) for (int i = 0; i < rule.timeDescriptor().calendarItems().count(); i++) { settings.beginGroup("CalendarItem-" + QString::number(i)); - const CalendarItem &calendarItem = rule.timeDescriptor().calendarItems().at(i); + CalendarItem calendarItem = rule.timeDescriptor().calendarItems().at(i); if (calendarItem.dateTime().isValid()) settings.setValue("dateTime", calendarItem.dateTime().toTime_t()); @@ -1218,7 +1218,7 @@ void RuleEngine::saveRule(const Rule &rule) settings.beginGroup("timeEventItems"); for (int i = 0; i < rule.timeDescriptor().timeEventItems().count(); i++) { settings.beginGroup("TimeEventItem-" + QString::number(i)); - const TimeEventItem &timeEventItem = rule.timeDescriptor().timeEventItems().at(i); + TimeEventItem timeEventItem = rule.timeDescriptor().timeEventItems().at(i); if (timeEventItem.dateTime().isValid()) settings.setValue("dateTime", timeEventItem.dateTime().toTime_t()); @@ -1253,7 +1253,7 @@ void RuleEngine::saveRule(const Rule &rule) // Save Events / EventDescriptors settings.beginGroup("events"); for (int i = 0; i < rule.eventDescriptors().count(); i++) { - const EventDescriptor &eventDescriptor = rule.eventDescriptors().at(i); + EventDescriptor eventDescriptor = rule.eventDescriptors().at(i); settings.beginGroup("EventDescriptor-" + QString::number(i)); settings.setValue("thingId", eventDescriptor.thingId().toString()); settings.setValue("eventTypeId", eventDescriptor.eventTypeId().toString()); From b868035bf59ed971418cac37da88a4853b1e3cd2 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sat, 18 Nov 2023 22:21:15 +0100 Subject: [PATCH 2/3] Allow discovering on bluetooth adapter plugged in at runtime --- .../bluetoothdiscoveryreplyimplementation.cpp | 6 + .../bluetoothdiscoveryreplyimplementation.h | 1 + ...bluetoothlowenergydeviceimplementation.cpp | 45 ++--- .../bluetoothlowenergydeviceimplementation.h | 5 +- ...luetoothlowenergymanagerimplementation.cpp | 167 ++++-------------- .../bluetoothlowenergymanagerimplementation.h | 20 +-- .../nymeabluetoothagent.cpp | 7 + .../bluetoothlowenergy/nymeabluetoothagent.h | 16 ++ libnymea-core/libnymea-core.pro | 2 + .../bluetoothlowenergymanager.h | 1 + 10 files changed, 92 insertions(+), 178 deletions(-) create mode 100644 libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.cpp create mode 100644 libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.h diff --git a/libnymea-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp b/libnymea-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp index 10d00e22..6baf0531 100644 --- a/libnymea-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp +++ b/libnymea-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp @@ -68,11 +68,17 @@ void BluetoothDiscoveryReplyImplementation::setDiscoveredDevices(const QList &discoveredDevices); + void addDiscoveredDevice(const QBluetoothDeviceInfo &info); void setFinished(); }; diff --git a/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.cpp b/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.cpp index 3af752ab..adde47b4 100644 --- a/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.cpp +++ b/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.cpp @@ -33,6 +33,20 @@ namespace nymeaserver { +BluetoothLowEnergyDeviceImplementation::BluetoothLowEnergyDeviceImplementation(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType, QObject *parent) : + BluetoothLowEnergyDevice(parent), + m_deviceInfo(deviceInfo) +{ + m_controller = new QLowEnergyController(address(), this); + m_controller->setRemoteAddressType(addressType); + + connect(m_controller, &QLowEnergyController::connected, this, &BluetoothLowEnergyDeviceImplementation::onConnected); + connect(m_controller, &QLowEnergyController::disconnected, this, &BluetoothLowEnergyDeviceImplementation::onDisconnected); + connect(m_controller, &QLowEnergyController::discoveryFinished, this, &BluetoothLowEnergyDeviceImplementation::onServiceDiscoveryFinished); + connect(m_controller, &QLowEnergyController::stateChanged, this, &BluetoothLowEnergyDeviceImplementation::onStateChanged); + connect(m_controller, SIGNAL(error(QLowEnergyController::Error)), this, SLOT(onDeviceError(QLowEnergyController::Error))); +} + QString BluetoothLowEnergyDeviceImplementation::name() const { return m_deviceInfo.name(); @@ -48,21 +62,8 @@ QLowEnergyController *BluetoothLowEnergyDeviceImplementation::controller() const return m_controller; } -BluetoothLowEnergyDeviceImplementation::BluetoothLowEnergyDeviceImplementation(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType, QObject *parent) : - BluetoothLowEnergyDevice(parent), - m_deviceInfo(deviceInfo) -{ - m_controller = new QLowEnergyController(address(), this); - m_controller->setRemoteAddressType(addressType); - connect(m_controller, &QLowEnergyController::connected, this, &BluetoothLowEnergyDeviceImplementation::onConnected); - connect(m_controller, &QLowEnergyController::disconnected, this, &BluetoothLowEnergyDeviceImplementation::onDisconnected); - connect(m_controller, &QLowEnergyController::discoveryFinished, this, &BluetoothLowEnergyDeviceImplementation::onServiceDiscoveryFinished); - connect(m_controller, &QLowEnergyController::stateChanged, this, &BluetoothLowEnergyDeviceImplementation::onStateChanged); - connect(m_controller, SIGNAL(error(QLowEnergyController::Error)), this, SLOT(onDeviceError(QLowEnergyController::Error))); -} - -void BluetoothLowEnergyDeviceImplementation::setConnected(const bool &connected) +void BluetoothLowEnergyDeviceImplementation::setConnected(bool connected) { if (m_connected != connected) { m_connected = connected; @@ -71,19 +72,6 @@ void BluetoothLowEnergyDeviceImplementation::setConnected(const bool &connected) } } -void BluetoothLowEnergyDeviceImplementation::setEnabled(const bool &enabled) -{ - m_enabled = enabled; - - if (!m_enabled) { - m_controller->disconnectFromDevice(); - } else { - if (m_autoConnecting) { - m_controller->connectToDevice(); - } - } -} - void BluetoothLowEnergyDeviceImplementation::onConnected() { setConnected(true); @@ -162,8 +150,7 @@ QList BluetoothLowEnergyDeviceImplementation::serviceUuids() con void BluetoothLowEnergyDeviceImplementation::onDeviceError(const QLowEnergyController::Error &error) { - if (connected()) - qCWarning(dcBluetooth()) << "Device error:" << name() << address().toString() << ": " << error << m_controller->errorString(); + qCWarning(dcBluetooth()) << "Device error:" << name() << address().toString() << ": " << error << m_controller->errorString(); emit errorOccurred(error); } diff --git a/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.h b/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.h index ad602f13..0ece46a2 100644 --- a/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.h +++ b/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.h @@ -75,10 +75,7 @@ private: bool m_discovered = false; bool m_enabled = true; - void setConnected(const bool &connected); - - // Methods called from BluetoothLowEnergyManager - void setEnabled(const bool &enabled); + void setConnected(bool connected); private slots: void onConnected(); diff --git a/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp b/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp index ac01df36..e547b32b 100644 --- a/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp +++ b/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp @@ -54,85 +54,58 @@ BluetoothLowEnergyManagerImplementation::BluetoothLowEnergyManagerImplementation return; } - // Check which bluetooth adapter are available - QList bluetoothAdapters = QBluetoothLocalDevice::allDevices(); - if (bluetoothAdapters.isEmpty()) { - qCWarning(dcBluetooth()) << "No bluetooth adapter found. Resource not available."; - return; - } - - // Create a scanner for each adapter - foreach (const QBluetoothHostInfo &hostInfo, bluetoothAdapters) { - qCDebug(dcBluetooth()) << "Using adapter:" << hostInfo.name() << hostInfo.address().toString(); + foreach (const QBluetoothHostInfo &hostInfo, QBluetoothLocalDevice::allDevices()) { + qCDebug(dcBluetooth()) << "Enalbing bluetooth adapter:" << hostInfo.name() << hostInfo.address().toString(); QBluetoothLocalDevice localDevice(hostInfo.address()); localDevice.powerOn(); localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable); - QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(hostInfo.address(), this); - connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BluetoothLowEnergyManagerImplementation::onDeviceDiscovered); - connect(discoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), this, SLOT(onDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error))); - m_bluetoothDiscoveryAgents.append(discoveryAgent); } - // Discovery timer, interval depends on discovery call - m_timer = new QTimer(this); - m_timer->setSingleShot(true); - connect(m_timer, &QTimer::timeout, this, &BluetoothLowEnergyManagerImplementation::onDiscoveryTimeout); - - // Reconnect timer - connect(m_reconnectTimer, &PluginTimer::timeout, this, &BluetoothLowEnergyManagerImplementation::onReconnectTimeout); - qCDebug(dcHardware()) << "-->" << name() << "created successfully."; m_available = true; } -BluetoothDiscoveryReply *BluetoothLowEnergyManagerImplementation::discoverDevices(int interval) +BluetoothDiscoveryReply *BluetoothLowEnergyManagerImplementation::discoverDevices(int timeout) { - // Create the reply for this discovery request - QPointer reply = new BluetoothDiscoveryReplyImplementation(this); + BluetoothDiscoveryReplyImplementation *reply = new BluetoothDiscoveryReplyImplementation(this); if (!available()) { qCWarning(dcBluetooth()) << "is not avilable."; reply->setError(BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyErrorNotAvailable); reply->setFinished(); - return reply.data(); + return reply; } - if (!enabled()) { qCWarning(dcBluetooth()) << "is not enabled."; reply->setError(BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyErrorNotEnabled); reply->setFinished(); - return reply.data(); + return reply; } - if (!m_currentReply.isNull()) { - qCWarning(dcBluetooth()) << "resource busy. There is already a discovery running."; - reply->setError(BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyErrorBusy); - reply->setFinished(); - return reply.data(); - } + // Create a scanner for each adapter + foreach (const QBluetoothHostInfo &hostInfo, QBluetoothLocalDevice::allDevices()) { + qCDebug(dcBluetooth()) << "Starting discovery on adapter:" << hostInfo.name() << hostInfo.address().toString(); + QBluetoothLocalDevice localDevice(hostInfo.address()); + localDevice.powerOn(); + localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable); + QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(hostInfo.address(), reply); + discoveryAgent->setLowEnergyDiscoveryTimeout(qMax(5000, qMin(30000, timeout))); + connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, reply, [=](const QBluetoothDeviceInfo &info){ + // Note: only show low energy devices + if (info.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) { + qCDebug(dcBluetooth()) << "device discovered" << info.name() << info.address().toString(); + reply->addDiscoveredDevice(info); + } + }); + connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, reply, [=](){ + qCDebug(dcBluetooth()) << "Discovery finished"; + reply->setFinished(); + }); +// connect(discoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), this, SLOT(onDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error))); - m_currentReply = reply; - m_discoveredDevices.clear(); - - // Start discovery on all adapters - qCDebug(dcBluetooth()) << "Start bluetooth discovery"; - foreach (QBluetoothDeviceDiscoveryAgent *discoveryAgent, m_bluetoothDiscoveryAgents) { discoveryAgent->start(); } - // Prevent blocking the hardware resource from plugins - int finalInterval = interval; - if (finalInterval > 30000) { - qCWarning(dcBluetooth()) << "Discovery interval out of range. Reset to 30 seconds."; - finalInterval = 30000; - } - - if (finalInterval <= 0) { - qCWarning(dcBluetooth()) << "Discovery interval out of range. Reset to 5 seconds."; - finalInterval = 5000; - } - - m_timer->start(finalInterval); - return reply.data(); + return reply; } BluetoothLowEnergyDevice *BluetoothLowEnergyManagerImplementation::registerDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType) @@ -182,17 +155,17 @@ void BluetoothLowEnergyManagerImplementation::setEnabled(bool enabled) return; } - bool success = false; - if (enabled) { - success = enable(); - } else { - success = disable(); + foreach (QBluetoothHostInfo info, QBluetoothLocalDevice::allDevices()) { + QBluetoothLocalDevice localDevice(info.address()); + if (enabled) { + localDevice.setHostMode(QBluetoothLocalDevice::HostConnectable); + } else { + localDevice.setHostMode(QBluetoothLocalDevice::HostPoweredOff); + } } - if (success) { - m_enabled = enabled; - emit enabledChanged(m_enabled); - } + m_enabled = enabled; + emit enabledChanged(m_enabled); } void BluetoothLowEnergyManagerImplementation::onReconnectTimeout() @@ -205,72 +178,4 @@ void BluetoothLowEnergyManagerImplementation::onReconnectTimeout() } } -void BluetoothLowEnergyManagerImplementation::onDiscoveryTimeout() -{ - // Stop discovery on all adapters - qCDebug(dcBluetooth()) << "Stop bluetooth discovery"; - foreach (QBluetoothDeviceDiscoveryAgent *discoveryAgent, m_bluetoothDiscoveryAgents) { - discoveryAgent->stop(); - } - - qCDebug(dcBluetooth()) << "Discovery finished. Found" << m_discoveredDevices.count() << "bluetooth devices."; - - if (m_currentReply.isNull()) { - qCWarning(dcBluetooth()) << "Reply does not exist any more. Please don't delete the reply before it has finished."; - m_currentReply.clear(); - return; - } - - m_currentReply->setError(BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorNoError); - m_currentReply->setDiscoveredDevices(m_discoveredDevices); - m_currentReply->setFinished(); - - m_currentReply.clear(); -} - -void BluetoothLowEnergyManagerImplementation::onDeviceDiscovered(const QBluetoothDeviceInfo &deviceInfo) -{ - // Add the device to the list if not already added - bool alreadyAdded = false; - foreach (const QBluetoothDeviceInfo &device, m_discoveredDevices) { - if (device.address() == deviceInfo.address()) { - alreadyAdded = true; - } - } - - // Note: only show low energy devices - if (!alreadyAdded && deviceInfo.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) { - qCDebug(dcBluetooth()) << "device discovered" << deviceInfo.name() << deviceInfo.address().toString(); - m_discoveredDevices.append(deviceInfo); - } -} - -void BluetoothLowEnergyManagerImplementation::onDiscoveryError(const QBluetoothDeviceDiscoveryAgent::Error &error) -{ - QBluetoothDeviceDiscoveryAgent *discoveryAgent = static_cast(sender()); - qCWarning(dcBluetooth()) << "Discovery error:" << error << discoveryAgent->errorString(); -} - -bool BluetoothLowEnergyManagerImplementation::enable() -{ - if (!available()) { - qCWarning(dcBluetooth()) << "Bluetooth hardware not available. Cannot enable Hardware resource"; - return false; - } - foreach (QPointer bluetoothDevice, m_devices) { - bluetoothDevice->setEnabled(true); - } - qCDebug(dcBluetooth()) << "Hardware resource enabled."; - return true; -} - -bool BluetoothLowEnergyManagerImplementation::disable() -{ - foreach (QPointer bluetoothDevice, m_devices) { - bluetoothDevice->setEnabled(false); - } - qCDebug(dcBluetooth()) << "Hardware resource disabled."; - return true; -} - } diff --git a/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h b/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h index b4ee2cc3..9e30c9e5 100644 --- a/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h +++ b/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h @@ -55,7 +55,7 @@ class BluetoothLowEnergyManagerImplementation : public BluetoothLowEnergyManager public: explicit BluetoothLowEnergyManagerImplementation(PluginTimer *reconnectTimer, QObject *parent = nullptr); - BluetoothDiscoveryReply *discoverDevices(int interval = 5000) override; + BluetoothDiscoveryReply *discoverDevices(int timeout = 5000) override; // Bluetooth device registration methods BluetoothLowEnergyDevice *registerDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType = QLowEnergyController::RandomAddress) override; @@ -64,31 +64,23 @@ public: bool available() const override; bool enabled() const override; + protected: void setEnabled(bool enabled) override; + +private slots: + void onReconnectTimeout(); + private: PluginTimer *m_reconnectTimer = nullptr; - QTimer *m_timer = nullptr; QList> m_devices; bool m_available = false; bool m_enabled = false; - QList m_bluetoothDiscoveryAgents; - QList m_discoveredDevices; QPointer m_currentReply; -private slots: - void onReconnectTimeout(); - void onDeviceDiscovered(const QBluetoothDeviceInfo &deviceInfo); - void onDiscoveryError(const QBluetoothDeviceDiscoveryAgent::Error &error); - void onDiscoveryTimeout(); - -public slots: - bool enable(); - bool disable(); - }; } diff --git a/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.cpp b/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.cpp new file mode 100644 index 00000000..1139e0ea --- /dev/null +++ b/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.cpp @@ -0,0 +1,7 @@ +#include "nymeabluetoothagent.h" + +NymeaBluetoothAgent::NymeaBluetoothAgent(QObject *parent) + : QObject{parent} +{ + +} diff --git a/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.h b/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.h new file mode 100644 index 00000000..0aad0f55 --- /dev/null +++ b/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.h @@ -0,0 +1,16 @@ +#ifndef NYMEABLUETOOTHAGENT_H +#define NYMEABLUETOOTHAGENT_H + +#include + +class NymeaBluetoothAgent : public QObject +{ + Q_OBJECT +public: + explicit NymeaBluetoothAgent(QObject *parent = nullptr); + +signals: + +}; + +#endif // NYMEABLUETOOTHAGENT_H diff --git a/libnymea-core/libnymea-core.pro b/libnymea-core/libnymea-core.pro index b003abb6..7b7800a0 100644 --- a/libnymea-core/libnymea-core.pro +++ b/libnymea-core/libnymea-core.pro @@ -58,6 +58,7 @@ RESOURCES += $$top_srcdir/icons.qrc \ $$top_srcdir/data/debug-interface/debug-interface.qrc HEADERS += nymeacore.h \ + hardware/bluetoothlowenergy/nymeabluetoothagent.h \ hardware/network/macaddressdatabasereplyimpl.h \ hardware/serialport/serialportmonitor.h \ hardware/zwave/zwavehardwareresourceimplementation.h \ @@ -165,6 +166,7 @@ HEADERS += nymeacore.h \ SOURCES += nymeacore.cpp \ + hardware/bluetoothlowenergy/nymeabluetoothagent.cpp \ hardware/network/macaddressdatabasereplyimpl.cpp \ hardware/serialport/serialportmonitor.cpp \ hardware/zwave/zwavehardwareresourceimplementation.cpp \ diff --git a/libnymea/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h b/libnymea/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h index f681f6eb..d6b31a71 100644 --- a/libnymea/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h +++ b/libnymea/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h @@ -53,6 +53,7 @@ public: explicit BluetoothLowEnergyManager(QObject *parent = nullptr); virtual ~BluetoothLowEnergyManager() = default; + virtual BluetoothDiscoveryReply *discoverDevices(int interval = 5000) = 0; // Bluetooth device registration methods From cc26006a831480ad5c79902973e9448398439377 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Thu, 23 Nov 2023 23:08:04 +0100 Subject: [PATCH 3/3] Add support for Bluetooth pairing during thing setup --- .../bluetoothdiscoveryreplyimplementation.cpp | 8 +- .../bluetoothdiscoveryreplyimplementation.h | 9 +- ...luetoothlowenergymanagerimplementation.cpp | 63 +++++++- .../bluetoothlowenergymanagerimplementation.h | 7 +- .../bluetoothpairingjobimplementation.cpp | 52 +++++++ .../bluetoothpairingjobimplementation.h | 38 +++++ .../nymeabluetoothagent.cpp | 139 ++++++++++++++++++ .../bluetoothlowenergy/nymeabluetoothagent.h | 50 ++++++- libnymea-core/libnymea-core.pro | 2 + .../bluetoothdiscoveryreply.h | 3 +- .../bluetoothlowenergymanager.cpp | 14 ++ .../bluetoothlowenergymanager.h | 28 ++++ nymea.pro | 4 +- plugins/mock/plugininfo.h | 2 +- 14 files changed, 402 insertions(+), 17 deletions(-) create mode 100644 libnymea-core/hardware/bluetoothlowenergy/bluetoothpairingjobimplementation.cpp create mode 100644 libnymea-core/hardware/bluetoothlowenergy/bluetoothpairingjobimplementation.h diff --git a/libnymea-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp b/libnymea-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp index 6baf0531..9b02a8de 100644 --- a/libnymea-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp +++ b/libnymea-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp @@ -50,7 +50,7 @@ BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyError BluetoothDis return m_error; } -QList BluetoothDiscoveryReplyImplementation::discoveredDevices() const +QList> BluetoothDiscoveryReplyImplementation::discoveredDevices() const { return m_discoveredDevices; } @@ -63,14 +63,14 @@ void BluetoothDiscoveryReplyImplementation::setError(const BluetoothDiscoveryRep } } -void BluetoothDiscoveryReplyImplementation::setDiscoveredDevices(const QList &discoveredDevices) +void BluetoothDiscoveryReplyImplementation::setDiscoveredDevices(const QList> &discoveredDevices) { m_discoveredDevices = discoveredDevices; } -void BluetoothDiscoveryReplyImplementation::addDiscoveredDevice(const QBluetoothDeviceInfo &info) +void BluetoothDiscoveryReplyImplementation::addDiscoveredDevice(const QBluetoothDeviceInfo &info, const QBluetoothHostInfo &hostInfo) { - m_discoveredDevices.append(info); + m_discoveredDevices.append(qMakePair(info, hostInfo)); } void BluetoothDiscoveryReplyImplementation::setFinished() diff --git a/libnymea-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.h b/libnymea-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.h index 0f2906af..7a096cc0 100644 --- a/libnymea-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.h +++ b/libnymea-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.h @@ -33,6 +33,7 @@ #include #include +#include #include "hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h" @@ -49,16 +50,16 @@ public: bool isFinished() const override; BluetoothDiscoveryReplyError error() const override; - QList discoveredDevices() const override; + QList > discoveredDevices() const override; private: bool m_finished = false; BluetoothDiscoveryReplyError m_error = BluetoothDiscoveryReplyErrorNoError; - QList m_discoveredDevices; + QList> m_discoveredDevices; void setError(const BluetoothDiscoveryReplyError &error); - void setDiscoveredDevices(const QList &discoveredDevices); - void addDiscoveredDevice(const QBluetoothDeviceInfo &info); + void setDiscoveredDevices(const QList > &discoveredDevices); + void addDiscoveredDevice(const QBluetoothDeviceInfo &info, const QBluetoothHostInfo &hostInfo); void setFinished(); }; diff --git a/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp b/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp index e547b32b..b66ac8e7 100644 --- a/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp +++ b/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp @@ -30,10 +30,13 @@ #include "bluetoothlowenergymanagerimplementation.h" #include "loggingcategories.h" +#include "nymeabluetoothagent.h" +#include "bluetoothpairingjobimplementation.h" #include #include #include +#include namespace nymeaserver { @@ -54,8 +57,10 @@ BluetoothLowEnergyManagerImplementation::BluetoothLowEnergyManagerImplementation return; } + m_agent = new NymeaBluetoothAgent(this); + foreach (const QBluetoothHostInfo &hostInfo, QBluetoothLocalDevice::allDevices()) { - qCDebug(dcBluetooth()) << "Enalbing bluetooth adapter:" << hostInfo.name() << hostInfo.address().toString(); + qCDebug(dcBluetooth()) << "Enabling bluetooth adapter:" << hostInfo.name() << hostInfo.address().toString(); QBluetoothLocalDevice localDevice(hostInfo.address()); localDevice.powerOn(); localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable); @@ -81,6 +86,13 @@ BluetoothDiscoveryReply *BluetoothLowEnergyManagerImplementation::discoverDevice return reply; } + if (QBluetoothLocalDevice::allDevices().isEmpty()) { + qCWarning(dcBluetooth()) << "No Bluetooth adapter available."; + reply->setError(BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyErrorNotAvailable); + reply->setFinished(); + return reply; + } + // Create a scanner for each adapter foreach (const QBluetoothHostInfo &hostInfo, QBluetoothLocalDevice::allDevices()) { qCDebug(dcBluetooth()) << "Starting discovery on adapter:" << hostInfo.name() << hostInfo.address().toString(); @@ -93,7 +105,7 @@ BluetoothDiscoveryReply *BluetoothLowEnergyManagerImplementation::discoverDevice // Note: only show low energy devices if (info.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) { qCDebug(dcBluetooth()) << "device discovered" << info.name() << info.address().toString(); - reply->addDiscoveredDevice(info); + reply->addDiscoveredDevice(info, hostInfo); } }); connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, reply, [=](){ @@ -108,6 +120,53 @@ BluetoothDiscoveryReply *BluetoothLowEnergyManagerImplementation::discoverDevice return reply; } +BluetoothPairingJob *BluetoothLowEnergyManagerImplementation::pairDevice(const QBluetoothAddress &device, const QBluetoothAddress &adapter) +{ + qCDebug(dcBluetooth()) << "pairDevice"; + BluetoothPairingJobImplementation *job = new BluetoothPairingJobImplementation(m_agent, device, this); + + QBluetoothLocalDevice *localDevice = nullptr; + if (adapter.isNull()) { + localDevice = new QBluetoothLocalDevice(this); + } else { + localDevice = new QBluetoothLocalDevice(adapter, this); + } + + if (!localDevice->isValid()) { + qCWarning(dcBluetooth()) << "Local device" << adapter.toString() << "is not valid"; + job->finish(false); + return job; + } + localDevice->requestPairing(device, QBluetoothLocalDevice::AuthorizedPaired); + connect(localDevice, &QBluetoothLocalDevice::error, job, [=](QBluetoothLocalDevice::Error error){ + qCDebug(dcBluetooth()) << "Pairing error" << error; + job->finish(false); + localDevice->deleteLater(); + }); + connect(localDevice, &QBluetoothLocalDevice::pairingFinished, job, [=](const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing){ + qCDebug(dcBluetooth()) << "Pairing finished" << address.toString() << pairing; + job->finish(true); + localDevice->deleteLater(); + }); + return job; +} + +void BluetoothLowEnergyManagerImplementation::unpairDevice(const QBluetoothAddress &device, const QBluetoothAddress &adapter) +{ + QBluetoothLocalDevice *localDevice = nullptr; + if (adapter.isNull()) { + localDevice = new QBluetoothLocalDevice(this); + } else { + localDevice = new QBluetoothLocalDevice(adapter, this); + } + + if (!localDevice->isValid()) { + qCWarning(dcBluetooth()) << "Local device" << adapter.toString() << "is not valid"; + return; + } + localDevice->requestPairing(device, QBluetoothLocalDevice::Unpaired); +} + BluetoothLowEnergyDevice *BluetoothLowEnergyManagerImplementation::registerDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType) { QPointer bluetoothDevice = new BluetoothLowEnergyDeviceImplementation(deviceInfo, addressType, this); diff --git a/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h b/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h index 9e30c9e5..0732cf98 100644 --- a/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h +++ b/libnymea-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h @@ -46,6 +46,8 @@ namespace nymeaserver { +class NymeaBluetoothAgent; + class BluetoothLowEnergyManagerImplementation : public BluetoothLowEnergyManager { Q_OBJECT @@ -58,13 +60,14 @@ public: BluetoothDiscoveryReply *discoverDevices(int timeout = 5000) override; // Bluetooth device registration methods + BluetoothPairingJob *pairDevice(const QBluetoothAddress &device, const QBluetoothAddress &adapter) override; + void unpairDevice(const QBluetoothAddress &device, const QBluetoothAddress &adapter) override; BluetoothLowEnergyDevice *registerDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType = QLowEnergyController::RandomAddress) override; void unregisterDevice(BluetoothLowEnergyDevice *bluetoothDevice) override; bool available() const override; bool enabled() const override; - protected: void setEnabled(bool enabled) override; @@ -78,8 +81,8 @@ private: bool m_available = false; bool m_enabled = false; + NymeaBluetoothAgent *m_agent = nullptr; - QPointer m_currentReply; }; diff --git a/libnymea-core/hardware/bluetoothlowenergy/bluetoothpairingjobimplementation.cpp b/libnymea-core/hardware/bluetoothlowenergy/bluetoothpairingjobimplementation.cpp new file mode 100644 index 00000000..6227ed93 --- /dev/null +++ b/libnymea-core/hardware/bluetoothlowenergy/bluetoothpairingjobimplementation.cpp @@ -0,0 +1,52 @@ +#include "bluetoothpairingjobimplementation.h" + +#include "nymeabluetoothagent.h" + +namespace nymeaserver +{ + +BluetoothPairingJobImplementation::BluetoothPairingJobImplementation(NymeaBluetoothAgent *agent, const QBluetoothAddress &address, QObject *parent) + : BluetoothPairingJob{address, parent}, + m_agent{agent}, + m_address{address} +{ + connect(m_agent, &NymeaBluetoothAgent::passKeyRequested, this, [address, this](const QBluetoothAddress &addr){ + if (address != addr) { + // Not for us... + return; + } + emit passKeyRequested(); + }); + connect(m_agent, &NymeaBluetoothAgent::displayPinCode, this, [address, this](const QBluetoothAddress &addr, const QString &pinCode){ + if (address != addr) { + // Not for us... + return; + } + emit displayPinCode(pinCode); + }); + +} + +bool BluetoothPairingJobImplementation::isFinished() const +{ + return m_finished; +} + +bool BluetoothPairingJobImplementation::success() const +{ + return m_success; +} + +void BluetoothPairingJobImplementation::passKeyEntered(const QString passKey) +{ + m_agent->passKeyEntered(m_address, passKey); +} + +void BluetoothPairingJobImplementation::finish(bool success) +{ + m_finished = true; + m_success = success; + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection, Q_ARG(bool, success)); +} + +} diff --git a/libnymea-core/hardware/bluetoothlowenergy/bluetoothpairingjobimplementation.h b/libnymea-core/hardware/bluetoothlowenergy/bluetoothpairingjobimplementation.h new file mode 100644 index 00000000..16304fba --- /dev/null +++ b/libnymea-core/hardware/bluetoothlowenergy/bluetoothpairingjobimplementation.h @@ -0,0 +1,38 @@ +#ifndef BLUETOOTHPAIRINGJOBIMPLEMENTATION_H +#define BLUETOOTHPAIRINGJOBIMPLEMENTATION_H + +#include "hardware/bluetoothlowenergy/bluetoothlowenergymanager.h" +#include + +namespace nymeaserver +{ + +class NymeaBluetoothAgent; +class BluetoothLowEnergyManagerImplementation; + +class BluetoothPairingJobImplementation : public BluetoothPairingJob +{ + Q_OBJECT +public: + explicit BluetoothPairingJobImplementation(NymeaBluetoothAgent *agent, const QBluetoothAddress &address, QObject *parent = nullptr); + + bool isFinished() const override; + bool success() const override; + + void passKeyEntered(const QString passKey) override; + +private: + friend BluetoothLowEnergyManagerImplementation; + void finish(bool success); + +private: + bool m_finished = false; + bool m_success = false; + + NymeaBluetoothAgent *m_agent = nullptr; + QBluetoothAddress m_address; + +}; + +} +#endif // BLUETOOTHPAIRINGJOBIMPLEMENTATION_H diff --git a/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.cpp b/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.cpp index 1139e0ea..2aa8adba 100644 --- a/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.cpp +++ b/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.cpp @@ -1,7 +1,146 @@ #include "nymeabluetoothagent.h" +#include +#include + +Q_DECLARE_LOGGING_CATEGORY(dcBluetooth) + +namespace nymeaserver +{ + +NymeaBluetoothAgentAdapter::NymeaBluetoothAgentAdapter(NymeaBluetoothAgent *agent, QObject *parent): + QObject{parent}, + m_agent{agent} +{ + +} + +QString NymeaBluetoothAgentAdapter::RequestPinCode(const QDBusObjectPath &device, const QDBusMessage &message) +{ + qCDebug(dcBluetooth) << "RequestPinCode" << device.path() << message.arguments(); + message.setDelayedReply(true); + m_agent->onRequestPassKey(device, message); + return 0; +} + +void NymeaBluetoothAgentAdapter::DisplayPinCode(const QDBusObjectPath &device, const QString &pinCode) +{ + qCDebug(dcBluetooth) << "DisplayPinCode" << device.path() << pinCode; + m_agent->onDisplayPinCode(device, pinCode); +} + +quint32 NymeaBluetoothAgentAdapter::RequestPasskey(const QDBusObjectPath &device, const QDBusMessage &message) +{ + qCDebug(dcBluetooth) << "RequestPasskey" << device.path() << message.arguments(); + message.setDelayedReply(true); + m_agent->onRequestPassKey(device, message); + return 0; +} + +void NymeaBluetoothAgentAdapter::DisplayPasskey(const QDBusObjectPath &device, quint32 passKey, quint16 entered) +{ + qCDebug(dcBluetooth) << "DisplayPasskey" << device.path() << passKey << entered; + // Not using "entered" value which would update whenever the user enters a (wrong) pin on the other end... + m_agent->onDisplayPinCode(device, QString("%1").arg(passKey, 6, QChar('0'))); +} + +void NymeaBluetoothAgentAdapter::RequestConfirmation(const QDBusObjectPath &device, quint32 passKey, const QDBusMessage &message) +{ + qCDebug(dcBluetooth) << "RequestConfirmation" << device.path() << passKey << message.arguments(); + // TODO: Not implemented + qCWarning(dcBluetooth()) << "Request confirmation pairing mechanism is not implemented."; +} + +void NymeaBluetoothAgentAdapter::RequestAuthorization(const QDBusObjectPath &device, const QDBusMessage &message) +{ + qCDebug(dcBluetooth) << "RequestAuthorization" << device.path() << message.arguments(); + // TODO: Not implemented + qCWarning(dcBluetooth()) << "RequestAuthorization mechanism is not implemented."; +} + +void NymeaBluetoothAgentAdapter::AuthorizeService(const QDBusObjectPath &device, const QString &uuid, const QDBusMessage &message) +{ + qCDebug(dcBluetooth) << "AuthorizeService" << device.path() << uuid << message.arguments(); + // TODO: Not implemented + qCWarning(dcBluetooth()) << "AuthorizeService mechanism is not implemented."; + +} + +void NymeaBluetoothAgentAdapter::Cancel() +{ + qCDebug(dcBluetooth()) << "Cancel called on bluetooth agent"; +} + +void NymeaBluetoothAgentAdapter::Release() +{ + qCDebug(dcBluetooth()) << "Release called on bluetooth agent"; +} + NymeaBluetoothAgent::NymeaBluetoothAgent(QObject *parent) : QObject{parent} { + m_adapter = new NymeaBluetoothAgentAdapter(this); + bool success = QDBusConnection::systemBus().registerObject("/nymea/bluetoothagent", m_adapter, QDBusConnection::ExportScriptableContents); + qCInfo(dcBluetooth) << "Registered Bluetooth pairing agent" << success; + + QDBusMessage message = QDBusMessage::createMethodCall("org.bluez", "/org/bluez", "org.bluez.AgentManager1", "RegisterAgent"); + message << QVariant::fromValue(QDBusObjectPath("/nymea/bluetoothagent")); + message << "KeyboardDisplay"; + QDBusMessage registerReply = QDBusConnection::systemBus().call(message); + if (!registerReply.errorName().isEmpty()) { + qCWarning(dcBluetooth()) << "Error registering pairing agent:" << registerReply.errorMessage(); + } else { + qCDebug(dcBluetooth()) << "Pairing agent registered."; + } + +} + +void NymeaBluetoothAgent::passKeyEntered(const QBluetoothAddress &address, const QString passKey) +{ + if (!m_pendingPairings.contains(address.toString())) { + qCWarning(dcBluetooth()) << "No ongoing pairing process for" << address.toString(); + return; + } + + qCInfo(dcBluetooth()) << "Providing passkey to" << address.toString() << passKey; + QDBusMessage message = m_pendingPairings.take(address.toString()); + message << static_cast(passKey.toUInt()); + QDBusConnection::systemBus().send(message); +} + +QBluetoothAddress NymeaBluetoothAgent::deviceForPath(const QDBusObjectPath &path) +{ +// qdbus --system org.bluez /org/bluez/hci0/dev_00_1A_22_0B_12_EB org.freedesktop.DBus.Properties.Get org.bluez.Device1 Address + + QDBusMessage message = QDBusMessage::createMethodCall("org.bluez", path.path(), "org.freedesktop.DBus.Properties", "Get"); + message << "org.bluez.Device1" << "Address"; + QDBusMessage reply = QDBusConnection::systemBus().call(message); + if (!reply.errorName().isEmpty()) { + qCWarning(dcBluetooth()) << "Error reading Address property for" << path.path() << reply.errorMessage(); + return QBluetoothAddress(); + } + + if (reply.arguments().count() != 1) { + qCWarning(dcBluetooth) << "Read property reply received an unexpected argument count"; + return QBluetoothAddress(); + } + + return QBluetoothAddress(reply.arguments().at(0).value().variant().toString()); +} + +void NymeaBluetoothAgent::onRequestPassKey(const QDBusObjectPath &path, const QDBusMessage &message) +{ + QBluetoothAddress address = deviceForPath(path); + qCDebug(dcBluetooth()) << "RequestPassKey" << path.path() << address; + m_pendingPairings[address.toString()] = message.createReply(); + emit passKeyRequested(address); +} + +void NymeaBluetoothAgent::onDisplayPinCode(const QDBusObjectPath &path, const QString &pinCode) +{ + QBluetoothAddress address = deviceForPath(path); + qCDebug(dcBluetooth()) << "RequestPassKey" << path.path() << address; + emit displayPinCode(address, pinCode); +} } diff --git a/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.h b/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.h index 0aad0f55..2990548c 100644 --- a/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.h +++ b/libnymea-core/hardware/bluetoothlowenergy/nymeabluetoothagent.h @@ -2,15 +2,63 @@ #define NYMEABLUETOOTHAGENT_H #include +#include +#include +#include + +namespace nymeaserver +{ + +class NymeaBluetoothAgent; + +class NymeaBluetoothAgentAdapter: public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.Agent1") + +public: + explicit NymeaBluetoothAgentAdapter(NymeaBluetoothAgent *agent, QObject *parent = nullptr); + +public slots: + Q_SCRIPTABLE QString RequestPinCode(const QDBusObjectPath &device, const QDBusMessage &message); + Q_SCRIPTABLE void DisplayPinCode(const QDBusObjectPath &device, const QString &pinCode); + Q_SCRIPTABLE quint32 RequestPasskey(const QDBusObjectPath &device, const QDBusMessage &message); + Q_SCRIPTABLE void DisplayPasskey(const QDBusObjectPath &device, quint32 passKey, quint16 entered); + + Q_SCRIPTABLE void RequestConfirmation(const QDBusObjectPath &device, quint32 passKey, const QDBusMessage &message); + Q_SCRIPTABLE void RequestAuthorization(const QDBusObjectPath &device, const QDBusMessage &message); + Q_SCRIPTABLE void AuthorizeService(const QDBusObjectPath &device, const QString &uuid, const QDBusMessage &message); + + Q_SCRIPTABLE void Cancel(); + Q_SCRIPTABLE void Release(); + +private: + NymeaBluetoothAgent *m_agent = nullptr; + +}; class NymeaBluetoothAgent : public QObject { Q_OBJECT + public: explicit NymeaBluetoothAgent(QObject *parent = nullptr); -signals: + void passKeyEntered(const QBluetoothAddress &address, const QString passKey); +signals: + void passKeyRequested(const QBluetoothAddress &address); + void displayPinCode(const QBluetoothAddress &address, const QString &pinCode); + +private: + friend class NymeaBluetoothAgentAdapter; + QBluetoothAddress deviceForPath(const QDBusObjectPath &path); + void onRequestPassKey(const QDBusObjectPath &path, const QDBusMessage &message); + void onDisplayPinCode(const QDBusObjectPath &path, const QString &pinCode); + NymeaBluetoothAgentAdapter *m_adapter = nullptr; + QHash m_pendingPairings; }; +} + #endif // NYMEABLUETOOTHAGENT_H diff --git a/libnymea-core/libnymea-core.pro b/libnymea-core/libnymea-core.pro index 7b7800a0..98253acc 100644 --- a/libnymea-core/libnymea-core.pro +++ b/libnymea-core/libnymea-core.pro @@ -58,6 +58,7 @@ RESOURCES += $$top_srcdir/icons.qrc \ $$top_srcdir/data/debug-interface/debug-interface.qrc HEADERS += nymeacore.h \ + hardware/bluetoothlowenergy/bluetoothpairingjobimplementation.h \ hardware/bluetoothlowenergy/nymeabluetoothagent.h \ hardware/network/macaddressdatabasereplyimpl.h \ hardware/serialport/serialportmonitor.h \ @@ -166,6 +167,7 @@ HEADERS += nymeacore.h \ SOURCES += nymeacore.cpp \ + hardware/bluetoothlowenergy/bluetoothpairingjobimplementation.cpp \ hardware/bluetoothlowenergy/nymeabluetoothagent.cpp \ hardware/network/macaddressdatabasereplyimpl.cpp \ hardware/serialport/serialportmonitor.cpp \ diff --git a/libnymea/hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h b/libnymea/hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h index a3706e7b..c704c052 100644 --- a/libnymea/hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h +++ b/libnymea/hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h @@ -33,6 +33,7 @@ #include #include +#include #include "libnymea.h" @@ -54,7 +55,7 @@ public: virtual bool isFinished() const = 0; virtual BluetoothDiscoveryReplyError error() const = 0; - virtual QList discoveredDevices() const = 0; + virtual QList> discoveredDevices() const = 0; signals: void finished(); diff --git a/libnymea/hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp b/libnymea/hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp index ed9e1ea3..77db8586 100644 --- a/libnymea/hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp +++ b/libnymea/hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp @@ -66,6 +66,7 @@ BluetoothLowEnergyManager::BluetoothLowEnergyManager(QObject *parent) : { } + /*! This method enables / disables this hardwareresource for all plugins. This method is available on the D-Bus. This can be useful if a Bluetooth LE server needs access to the hardware. By disabling the bluetooth support, nymea will not allow to use the hardware until it gets reenabled. */ @@ -73,3 +74,16 @@ void BluetoothLowEnergyManager::EnableBluetooth(bool enabled) { setEnabled(enabled); } + +BluetoothPairingJob::BluetoothPairingJob(const QBluetoothAddress &address, QObject *parent): + QObject(parent), + m_address(address) +{ + +} + +QBluetoothAddress BluetoothPairingJob::address() const +{ + return m_address; +} + diff --git a/libnymea/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h b/libnymea/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h index d6b31a71..6e7e7e72 100644 --- a/libnymea/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h +++ b/libnymea/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h @@ -45,6 +45,31 @@ #include "libnymea.h" +class NymeaBluetoothAgent; + +class LIBNYMEA_EXPORT BluetoothPairingJob: public QObject +{ + Q_OBJECT +public: + explicit BluetoothPairingJob(const QBluetoothAddress &address, QObject *parent = nullptr); + virtual ~BluetoothPairingJob() = default; + + QBluetoothAddress address() const; + + virtual bool isFinished() const = 0; + virtual bool success() const = 0; + + virtual void passKeyEntered(const QString passKey) = 0; + +signals: + void finished(bool success); + void passKeyRequested(); + void displayPinCode(const QString &pinCode); + +private: + QBluetoothAddress m_address; +}; + class LIBNYMEA_EXPORT BluetoothLowEnergyManager : public HardwareResource { Q_OBJECT @@ -57,11 +82,14 @@ public: virtual BluetoothDiscoveryReply *discoverDevices(int interval = 5000) = 0; // Bluetooth device registration methods + virtual BluetoothPairingJob *pairDevice(const QBluetoothAddress &device, const QBluetoothAddress &adapter) = 0; + virtual void unpairDevice(const QBluetoothAddress &device, const QBluetoothAddress &adapter) = 0; virtual BluetoothLowEnergyDevice *registerDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType = QLowEnergyController::RandomAddress) = 0; virtual void unregisterDevice(BluetoothLowEnergyDevice *bluetoothDevice) = 0; public slots: Q_SCRIPTABLE void EnableBluetooth(bool enabled); + }; #endif // BLUETOOTHLOWENERGYMANAGER_H diff --git a/nymea.pro b/nymea.pro index ad128742..57b62033 100644 --- a/nymea.pro +++ b/nymea.pro @@ -7,8 +7,8 @@ NYMEA_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p" JSON_PROTOCOL_VERSION_MAJOR=8 JSON_PROTOCOL_VERSION_MINOR=0 JSON_PROTOCOL_VERSION="$${JSON_PROTOCOL_VERSION_MAJOR}.$${JSON_PROTOCOL_VERSION_MINOR}" -LIBNYMEA_API_VERSION_MAJOR=7 -LIBNYMEA_API_VERSION_MINOR=4 +LIBNYMEA_API_VERSION_MAJOR=8 +LIBNYMEA_API_VERSION_MINOR=0 LIBNYMEA_API_VERSION_PATCH=0 LIBNYMEA_API_VERSION="$${LIBNYMEA_API_VERSION_MAJOR}.$${LIBNYMEA_API_VERSION_MINOR}.$${LIBNYMEA_API_VERSION_PATCH}" diff --git a/plugins/mock/plugininfo.h b/plugins/mock/plugininfo.h index d1e42f09..40fa81fb 100644 --- a/plugins/mock/plugininfo.h +++ b/plugins/mock/plugininfo.h @@ -14,7 +14,7 @@ #include #include -extern "C" const QString libnymea_api_version() { return QString("7.4.0");} +extern "C" const QString libnymea_api_version() { return QString("8.0.0");} Q_DECLARE_LOGGING_CATEGORY(dcMock) Q_LOGGING_CATEGORY(dcMock, "Mock")