Index: sources/bluetooth/BLEScanner.cpp =================================================================== diff -u -r3a238930f8d939800512c9a786e96f15b35a2001 -r2fde0cfeb28b3fab9437e9bd15c1ec775785f103 --- sources/bluetooth/BLEScanner.cpp (.../BLEScanner.cpp) (revision 3a238930f8d939800512c9a786e96f15b35a2001) +++ sources/bluetooth/BLEScanner.cpp (.../BLEScanner.cpp) (revision 2fde0cfeb28b3fab9437e9bd15c1ec775785f103) @@ -105,6 +105,17 @@ } /*! + * \brief BLEScanner::doReselectDevice + * Called when reselecting a device (e.g. on reboot) + * \param deviceInfo - the device info to connect to + */ +void BLEScanner::doReselectDevice(const QBluetoothDeviceInfo &deviceInfo) +{ + selectedDeviceInfo = deviceInfo; + onConnectToDevice(deviceInfo); +} + +/*! * \brief BLEScanner::onDeviceDiscovered * When a new mac address was discovered * \param deviceInfo - The discovered device's information @@ -150,43 +161,47 @@ discoveryAgent->start(); } +QLowEnergyService* BLEScanner::setupService(const QBluetoothUuid &uuid) +{ + QLowEnergyService *service = lowEnergyController->createServiceObject(uuid, this); + + service->discoverDetails(); + + qDebug() << "Service " << service->serviceName() << "UUID: " << uuid << " state: " << service->state(); + + foreach (const QLowEnergyCharacteristic &c, service->characteristics()) { + qDebug() << "----> Characteristic: " << c.name() + << " uuid: " << c.uuid(); + } + return service; +} + /*! * \brief BLEScanner::onServiceDiscovered * Called when a new service is discovered on the paired BLE device. * \param uuid - the QBluetoothUuid of the discovered service */ void BLEScanner::onServiceDiscovered(const QBluetoothUuid &uuid) { - - QLowEnergyService* service = lowEnergyController->createServiceObject(uuid, this); - - services.append(service); - if (uuid.toString() == omronUnknownServiceName) { - omronUnknownService = service; - + omronUnknownService = setupService(uuid); } else if (uuid.toString() == omronBloodPressureServiceName) { - omronBloodPressureService = service; + omronBloodPressureService = setupService(uuid); } else if (uuid.toString() == omronCurrentTimeServiceName) { - omronCurrentTimeService = service; + omronCurrentTimeService = setupService(uuid); } else if (uuid.toString() == omronBatteryLevelServiceName) { - omronBatteryLevelService = service; + omronBatteryLevelService = setupService(uuid); } else if (uuid.toString() == omronDeviceInformationServiceName) { - omronDeviceInformationService = service; - } - - service->discoverDetails(); - - qDebug() << "Service " << service->serviceName() << "UUID: " << uuid << " state: " << service->state(); - - foreach (const QLowEnergyCharacteristic &c, service->characteristics()) { - qDebug() << "----> Characteristic: " << c.name() - << " uuid: " << c.uuid(); - } + omronDeviceInformationService = setupService(uuid); + } /*else { + QLowEnergyService *service = setupService(uuid); + if (service != NULL) + services.append(service); + }*/ } /*! @@ -216,7 +231,7 @@ */ void BLEScanner::onRequestDeviceInformation() { - qDebug() << __FUNCTION__; + LOG_DEBUG("Requesting BLE device information"); onRequestDeviceSerialNumber(); } @@ -402,6 +417,26 @@ } /*! + * \brief BLEScanner::makeServiceConnections + * Makes the necessary connections to interact with the given service + * \param service - the service with connections we need + */ +void BLEScanner::makeServiceConnections(QLowEnergyService *service) +{ + connect(service, SIGNAL(stateChanged(QLowEnergyService::ServiceState)), + this, SLOT(onServiceStateChanged(QLowEnergyService::ServiceState))); + + connect(service, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)), + this, SLOT(onCharacteristicChanged(QLowEnergyCharacteristic,QByteArray))); + + connect(service, SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)), + this, SLOT(onServiceCharacteristicsRead(QLowEnergyCharacteristic,QByteArray))); + + connect(service, SIGNAL(descriptorWritten(QLowEnergyDescriptor, QByteArray)), + this, SLOT(onConfirmedDescriptorWrite(QLowEnergyDescriptor, QByteArray))); +} + +/*! * \brief BLEScanner::onServiceScanDone * Called when we have finished scanning the services provided by BLE device */ @@ -414,20 +449,29 @@ qDebug() << "##############################"; qDebug() << "##############################"; - foreach (QLowEnergyService* service, services) { + foreach (QLowEnergyService *service, services) + makeServiceConnections(service); - connect(service, SIGNAL(stateChanged(QLowEnergyService::ServiceState)), - this, SLOT(onServiceStateChanged(QLowEnergyService::ServiceState))); - - connect(service, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)), - this, SLOT(onCharacteristicChanged(QLowEnergyCharacteristic,QByteArray))); - - connect(service, SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)), - this, SLOT(onServiceCharacteristicsRead(QLowEnergyCharacteristic,QByteArray))); - - connect(service, SIGNAL(descriptorWritten(QLowEnergyDescriptor, QByteArray)), - this, SLOT(onConfirmedDescriptorWrite(QLowEnergyDescriptor, QByteArray))); - } + if (omronUnknownService != NULL) + makeServiceConnections(omronUnknownService); + else + LOG_DEBUG("Unknown service is null"); + if (omronCurrentTimeService != NULL) + makeServiceConnections(omronCurrentTimeService); + else + LOG_DEBUG("Current time service is null"); + if (omronBatteryLevelService != NULL) + makeServiceConnections(omronBatteryLevelService); + else + LOG_DEBUG("Battery level service is null"); + if (omronBloodPressureService != NULL) + makeServiceConnections(omronBloodPressureService); + else + LOG_DEBUG("Blood Pressure service is null"); + if (omronDeviceInformationService != NULL) + makeServiceConnections(omronDeviceInformationService); + else + LOG_DEBUG("Device Information service is null"); } /*! @@ -471,7 +515,7 @@ */ void BLEScanner::onDeviceConnected() { - qDebug() << __FUNCTION__; + LOG_DEBUG("Device Connected"); lowEnergyController->discoverServices(); @@ -487,7 +531,7 @@ */ void BLEScanner::onDeviceDisconnected() { - qDebug() << __FUNCTION__; + LOG_DEBUG("Device Disconnected."); emit didDisconnectFromDevice(selectedDeviceInfo); } @@ -500,6 +544,7 @@ */ void BLEScanner::onConnectToDevice(const QBluetoothDeviceInfo& deviceInfo) { + LOG_DEBUG(QString("Connecting to (%1, %2)").arg(deviceInfo.name()).arg(deviceInfo.address().toString())); lowEnergyController = QLowEnergyController::createCentral(deviceInfo); @@ -525,6 +570,6 @@ void BLEScanner::onRetryConnectToDevice() { - qDebug() << __FUNCTION__ << "Retrying to connect to device..."; + LOG_DEBUG("Retrying to connect to BLE device..."); lowEnergyController->connectToDevice(); } Index: sources/bluetooth/BLEScanner.h =================================================================== diff -u -r3a238930f8d939800512c9a786e96f15b35a2001 -r2fde0cfeb28b3fab9437e9bd15c1ec775785f103 --- sources/bluetooth/BLEScanner.h (.../BLEScanner.h) (revision 3a238930f8d939800512c9a786e96f15b35a2001) +++ sources/bluetooth/BLEScanner.h (.../BLEScanner.h) (revision 2fde0cfeb28b3fab9437e9bd15c1ec775785f103) @@ -82,6 +82,8 @@ void onConnectToDevice(const QBluetoothDeviceInfo& deviceInfo); void onSetMacAddress(const QString &mac); void updateBLECuffCheckinType(bool retryConnection); + void makeServiceConnections(QLowEnergyService *service); + QLowEnergyService* setupService(const QBluetoothUuid &uuid); signals: void didReceiveBPMeasurement(BLEMeasurementData); @@ -100,6 +102,7 @@ void doScanForDevices(); void doParseMeasurement(const QByteArray &byteArray); void doRequestBPMeasurement(); + void doReselectDevice(const QBluetoothDeviceInfo &deviceInfo); private slots: Index: sources/view/VBluetooth.cpp =================================================================== diff -u -r3a238930f8d939800512c9a786e96f15b35a2001 -r2fde0cfeb28b3fab9437e9bd15c1ec775785f103 --- sources/view/VBluetooth.cpp (.../VBluetooth.cpp) (revision 3a238930f8d939800512c9a786e96f15b35a2001) +++ sources/view/VBluetooth.cpp (.../VBluetooth.cpp) (revision 2fde0cfeb28b3fab9437e9bd15c1ec775785f103) @@ -44,6 +44,9 @@ connect(this, SIGNAL(didRequestConcurrentSave(QString,QString,bool)), &_FileSaver, SLOT(onConcurrentSave(QString,QString,bool))); + connect(this, SIGNAL(didRequestReconnectToDevice(QBluetoothDeviceInfo)), + &_BLEScanner, SLOT(doReselectDevice(QBluetoothDeviceInfo))); + onLoadMyDevices(); } @@ -56,7 +59,7 @@ void VBluetooth::doScanForDevices() { onUpdateStatus(tr("Scanning...")); - bleDevices.clear(); + _unpairedDevices.clear(); emit didDevicesChanged(); emit didRequestScanForDevices(); } @@ -88,7 +91,7 @@ { VBluetoothDeviceInfo *info = new VBluetoothDeviceInfo(device); if (!isDeviceAlreadyPaired(device)) - bleDevices.insert(0, info); + _unpairedDevices.insert(0, info); qDebug() << "VBluetooth: Discovered " << device.name(); emit didDevicesChanged(); } @@ -110,7 +113,7 @@ */ QVariant VBluetooth::doGetDevices() { - return QVariant::fromValue(bleDevices); + return QVariant::fromValue(_unpairedDevices); } /*! @@ -120,7 +123,7 @@ */ QVariant VBluetooth::doGetPairedDevices() { - return QVariant::fromValue(pairedDevices); + return QVariant::fromValue(_pairedDevices); } /*! @@ -130,7 +133,15 @@ */ void VBluetooth::doSelectDevice(const QString &addr) { - emit didSelectDevice(addr); + for (QObject *device : _unpairedDevices) { + VBluetoothDeviceInfo *d = static_cast(device); + if (addr == d->getAddress()) + { + delete _lastSelectedDevice; + _lastSelectedDevice = new VBluetoothDeviceInfo(addr, d->getName()); + emit didSelectDevice(addr); + } + } } /*! @@ -140,7 +151,7 @@ */ void VBluetooth::onUpdateStatus(const QString &message) { - status = message; + _status = message; emit didStatusChanged(); } @@ -214,7 +225,7 @@ */ bool VBluetooth::isDeviceAlreadyPaired(const QBluetoothDeviceInfo &deviceInfo) { - for (QObject *device : pairedDevices) { + for (QObject *device : _pairedDevices) { VBluetoothDeviceInfo *pairedDevice = static_cast(device); if (pairedDevice->getAddress() == deviceInfo.address().toString()) return true; @@ -232,14 +243,14 @@ { QList idxs; int i = 0; - for (QObject *bleDevice : bleDevices) { + for (QObject *bleDevice : _unpairedDevices) { VBluetoothDeviceInfo *device = static_cast(bleDevice); if (device->getAddress() == info->getAddress()) idxs.append(i); ++i; } for (int i : idxs) - bleDevices.removeAt(i); + _unpairedDevices.removeAt(i); // update the QML emit didDevicesChanged(); @@ -259,7 +270,7 @@ if (alreadyPaired) { setDeviceConnected(deviceInfo, true); } else { - pairedDevices.append(info); + _pairedDevices.append(info); emit didPairedDevicesChanged(); removeFromDevices(info); @@ -276,14 +287,14 @@ void VBluetooth::setDeviceConnected(const QBluetoothDeviceInfo &deviceInfo, const bool &connected) { if (isDeviceAlreadyPaired(deviceInfo)) { - for (QList::iterator iter = pairedDevices.begin(); iter != pairedDevices.end(); ++iter) + for (QList::iterator iter = _pairedDevices.begin(); iter != _pairedDevices.end(); ++iter) { if (deviceInfo.address().toString() == ((VBluetoothDeviceInfo*)(*iter))->getAddress()) ((VBluetoothDeviceInfo*)(*iter))->setConnected(connected); } emit didPairedDevicesChanged(); } else { - for (QList::iterator iter = bleDevices.begin(); iter != bleDevices.end(); ++iter) + for (QList::iterator iter = _unpairedDevices.begin(); iter != _unpairedDevices.end(); ++iter) { if (deviceInfo.address().toString() == ((VBluetoothDeviceInfo*)(*iter))->getAddress()) ((VBluetoothDeviceInfo*)(*iter))->setConnected(connected); @@ -306,23 +317,49 @@ } /*! + * \brief VBluetooth::onLoadAndConnectToLastSelectedDevice + * + * \param obj + */ +void VBluetooth::onLoadAndConnectToLastSelectedDevice(const QJsonObject &obj) +{ + if (obj.keys().contains(_lastSelectedDeviceAddrKey)) { + QJsonObject lastSelectDeviceObj = obj.value(_lastSelectedDeviceAddrKey).toObject(); + if (!lastSelectDeviceObj.isEmpty()) { + if (_lastSelectedDevice == nullptr) + { + _lastSelectedDevice = new VBluetoothDeviceInfo(lastSelectDeviceObj.value("Address").toString(), + lastSelectDeviceObj.value("Name").toString()); + LOG_DEBUG(QString("Trying to connect to last selected BLE device %1").arg(_lastSelectedDevice->getAddress())); + onReconnectToDevice(_lastSelectedDevice); + } + } + } +} + +/*! * \brief VBluetooth::loadMyDevices * Loads previously selected devices from disk */ void VBluetooth::onLoadMyDevices(const QString &path) { - pairedDevices.clear(); + _pairedDevices.clear(); QJsonObject obj; if (!FileHandler::readJSON(path, obj)) { LOG_EVENT(tr("Could not load my bluetooth devices from %1").arg(path)); return; } + onLoadAndConnectToLastSelectedDevice(obj); + for (const QString& key : obj.keys()) { - VBluetoothDeviceInfo *info = new VBluetoothDeviceInfo(key, obj[key].toString()); - pairedDevices.append(info); + if (key != _lastSelectedDeviceAddrKey) + { + VBluetoothDeviceInfo *info = new VBluetoothDeviceInfo(key, obj[key].toString()); + _pairedDevices.append(info); + } } } @@ -334,9 +371,28 @@ { QJsonObject obj; - for (QList::iterator iter = pairedDevices.begin(); iter != pairedDevices.end(); ++iter) + if (_lastSelectedDevice->isValid()) + { + QJsonObject subObj; + subObj["Name"] = _lastSelectedDevice->getName(); + subObj["Address"] = _lastSelectedDevice->getAddress(); + obj[_lastSelectedDeviceAddrKey] = subObj; + } + + for (QList::iterator iter = _pairedDevices.begin(); iter != _pairedDevices.end(); ++iter) obj[((VBluetoothDeviceInfo*)(*iter))->getAddress()] = ((VBluetoothDeviceInfo*)(*iter))->getName(); QJsonDocument document(obj); emit didRequestConcurrentSave(path, document.toJson(), false); } + +/*! + * \brief VBluetooth::onReconnectToDevice + * Reconnects to the specified device + * \param deviceInfo - the device to reconnect to + */ +void VBluetooth::onReconnectToDevice(const VBluetoothDeviceInfo *deviceInfo) +{ + QBluetoothDeviceInfo device(QBluetoothAddress(deviceInfo->getAddress()), deviceInfo->getName(), 0); + emit didRequestReconnectToDevice(device); +} Index: sources/view/VBluetooth.h =================================================================== diff -u -r5220c64dd3a0fc9c322a68884e73503bb7893d12 -r2fde0cfeb28b3fab9437e9bd15c1ec775785f103 --- sources/view/VBluetooth.h (.../VBluetooth.h) (revision 5220c64dd3a0fc9c322a68884e73503bb7893d12) +++ sources/view/VBluetooth.h (.../VBluetooth.h) (revision 2fde0cfeb28b3fab9437e9bd15c1ec775785f103) @@ -43,13 +43,16 @@ void didRequestScanForDevices(); void didPairedDevicesChanged(); void didRequestConcurrentSave(QString, QString, bool); + void didRequestReconnectToDevice(QBluetoothDeviceInfo); private: - QList bleDevices; - QList pairedDevices; - QString status; + QList _unpairedDevices; + QList _pairedDevices; + QString _status; + const QString _lastSelectedDeviceAddrKey = "LastSelectedDevice"; + VBluetoothDeviceInfo *_lastSelectedDevice = nullptr; - QString getStatus() { return status; } + QString getStatus() { return _status; } QString controllerErrorToString(QLowEnergyController::Error error); bool isDeviceAlreadyPaired(const QBluetoothDeviceInfo &deviceInfo); void removeFromDevices(const VBluetoothDeviceInfo *info); @@ -65,6 +68,8 @@ void onConnectedToDevice(const QBluetoothDeviceInfo &deviceInfo); void onDisconnectedFromDevice(const QBluetoothDeviceInfo &deviceInfo); void onLoadMyDevices(const QString &path = Bluetooth_Saved_Devices_Path_JSON); + void onReconnectToDevice(const VBluetoothDeviceInfo *deviceInfo); + void onLoadAndConnectToLastSelectedDevice(const QJsonObject &obj); }; } #endif // VBLUETOOTH_H Index: sources/view/VBluetoothDeviceInfo.cpp =================================================================== diff -u -r5220c64dd3a0fc9c322a68884e73503bb7893d12 -r2fde0cfeb28b3fab9437e9bd15c1ec775785f103 --- sources/view/VBluetoothDeviceInfo.cpp (.../VBluetoothDeviceInfo.cpp) (revision 5220c64dd3a0fc9c322a68884e73503bb7893d12) +++ sources/view/VBluetoothDeviceInfo.cpp (.../VBluetoothDeviceInfo.cpp) (revision 2fde0cfeb28b3fab9437e9bd15c1ec775785f103) @@ -69,3 +69,19 @@ { return _connected; } + +/*! + * \brief VBluetoothDeviceInfo::isValid + * Checks whether the VBluetoothDeviceInfo object is valid or not. + * \return true if valid, false otherwise + */ +bool VBluetoothDeviceInfo::isValid() const +{ + if (_address.length() != 17) + return false; + + if (_name.length() == 0) + return false; + + return true; +} Index: sources/view/VBluetoothDeviceInfo.h =================================================================== diff -u -r5220c64dd3a0fc9c322a68884e73503bb7893d12 -r2fde0cfeb28b3fab9437e9bd15c1ec775785f103 --- sources/view/VBluetoothDeviceInfo.h (.../VBluetoothDeviceInfo.h) (revision 5220c64dd3a0fc9c322a68884e73503bb7893d12) +++ sources/view/VBluetoothDeviceInfo.h (.../VBluetoothDeviceInfo.h) (revision 2fde0cfeb28b3fab9437e9bd15c1ec775785f103) @@ -19,11 +19,12 @@ public: explicit VBluetoothDeviceInfo(const QBluetoothDeviceInfo &device); - VBluetoothDeviceInfo(const QString &_address, const QString &_name); + VBluetoothDeviceInfo(const QString &address, const QString &name); QString getName() const; QString getAddress() const; bool isConnected() const; void setConnected(const bool &conn); + bool isValid() const; signals: void deviceChanged();