Index: sources/view/VBluetooth.cpp =================================================================== diff -u -r9efb7cf51c882dc1f374df0b2a8b8c20efafaa4e -r7249125bb71e6fab4139590ee777c64ece9cf3be --- sources/view/VBluetooth.cpp (.../VBluetooth.cpp) (revision 9efb7cf51c882dc1f374df0b2a8b8c20efafaa4e) +++ sources/view/VBluetooth.cpp (.../VBluetooth.cpp) (revision 7249125bb71e6fab4139590ee777c64ece9cf3be) @@ -9,6 +9,7 @@ VBluetooth::VBluetooth(QObject *parent) : QObject(parent) { + // incoming connect(&_BLEScanner, SIGNAL(didReceiveScanForDevicesError(QBluetoothDeviceDiscoveryAgent::Error)), this, SLOT(onScanForDevicesError(QBluetoothDeviceDiscoveryAgent::Error))); @@ -18,11 +19,23 @@ connect(&_BLEScanner, SIGNAL(didDiscoverDevice(QBluetoothDeviceInfo)), this, SLOT(onDeviceDiscovered(const QBluetoothDeviceInfo))); + connect(&_BLEScanner, SIGNAL(didStartConnectingToDevice()), + this, SLOT(onConnectingToDevice())); + + connect(&_BLEScanner, SIGNAL(didReceiveControllerError(QLowEnergyController::Error)), + this, SLOT(onControllerError(QLowEnergyController::Error))); + + connect(&_BLEScanner, SIGNAL(didConnectToDevice(QBluetoothDeviceInfo)), + this, SLOT(onConnectedToDevice(QBluetoothDeviceInfo))); + + // outgoing connect(this, SIGNAL(didSelectDevice(const QString)), &_BLEScanner, SLOT(doSelectDevice(const QString))); connect(this, SIGNAL(didRequestScanForDevices()), &_BLEScanner, SLOT(doScanForDevices())); + + } /*! @@ -36,8 +49,7 @@ bleDevices.clear(); emit didDevicesChanged(); emit didRequestScanForDevices(); - status = "Scanning..."; - emit didStatusChanged(); + onUpdateStatus(tr("Scanning...")); } /*! @@ -50,13 +62,12 @@ { switch (error) { case QBluetoothDeviceDiscoveryAgent::PoweredOffError: - status = tr("Error: The bluetooth module is powered off."); + onUpdateStatus(tr("Error: The bluetooth module is powered off.")); break; default: - status = tr("Error: Scan for devices error."); + onUpdateStatus(tr("Error: Scan for devices error.")); break; } - emit didStatusChanged(); } /*! @@ -67,7 +78,8 @@ void VBluetooth::onDeviceDiscovered(const QBluetoothDeviceInfo &device) { VBluetoothDeviceInfo *info = new VBluetoothDeviceInfo(device); - bleDevices.append(info); + if (!isDeviceAlreadyPaired(device)) + bleDevices.append(info); qDebug() << "VBluetooth: Discovered " << device.address(); emit didDevicesChanged(); } @@ -79,8 +91,7 @@ void VBluetooth::onScanForDevicesFinished() { emit didScanFinished(); - status = "Scan Finished."; - emit didStatusChanged(); + onUpdateStatus(tr("Scan Finished.")); } /*! @@ -94,6 +105,16 @@ } /*! + * \brief VBluetooth::getDevices + * Gets the paired devices BLE modelData for QML + * \return QVariant - the modelData + */ +QVariant VBluetooth::doGetPairedDevices() +{ + return QVariant::fromValue(pairedDevices); +} + +/*! * \brief VBluetooth::onSelectedDevice * Emits a signal that the device was selected * \param addr - the selected BLE mac address @@ -103,3 +124,135 @@ emit didSelectDevice(addr); } +/*! + * \brief onUpdateStatus + * Updates the status and emits a signal to notify the QML + * \param message + */ +void VBluetooth::onUpdateStatus(const QString &message) +{ + status = message; + emit didStatusChanged(); +} + +/*! + * \brief VBluetooth::onConnectingToDevice + * Called when attempting to connect to a device + */ +void VBluetooth::onConnectingToDevice() +{ + onUpdateStatus(tr("Connecting...")); +} + +/*! + * \brief VBluetooth::controllerErrorToString + * Converts a QLowEnergyController::Error enum to QString + * \param error - the QLowEnergyController::Error enum + * \return QString - the enum converted to a QString + */ +QString VBluetooth::controllerErrorToString(QLowEnergyController::Error error) +{ + switch (error) + { + case QLowEnergyController::NoError: + return tr("No Error."); + break; + case QLowEnergyController::UnknownError: + return tr("Unknown Error."); + break; + case QLowEnergyController::UnknownRemoteDeviceError: + return tr("Unknown Remote Device Error."); + break; + case QLowEnergyController::NetworkError: + return tr("Bluetooth Network Error."); + break; + case QLowEnergyController::InvalidBluetoothAdapterError: + return tr("Bluetooth Adapter Error."); + break; + case QLowEnergyController::ConnectionError: + case QLowEnergyController::AdvertisingError: + case QLowEnergyController::RemoteHostClosedError: + return tr("Connection Error."); + break; + default: + const QMetaObject *mo = qt_getEnumMetaObject(error); + int idx = mo->indexOfEnumerator(qt_getEnumName(error)); + const char *text = mo->enumerator(idx).valueToKey(error); + if (!QString(text).isEmpty()) { + return tr(text); + } + } + + return tr("Unexpected Error."); +} + +/*! + * \brief VBluetooth::onControllerError + * Called when BLE interface reports a controller error. Updates + * the bluetooth status message according to the error reported. + * \param error - the low energy controller error reported + */ +void VBluetooth::onControllerError(QLowEnergyController::Error error) +{ + onUpdateStatus(controllerErrorToString(error)); +} + +/*! + * \brief VBluetooth::isDeviceAlreadyPaired + * Determines if a device has already been paired + * \param deviceInfo - the device info to check if paired + * \return bool - true if already paired, false otherwise + */ +bool VBluetooth::isDeviceAlreadyPaired(const QBluetoothDeviceInfo &deviceInfo) +{ + bool alreadyPaired = false; + for (QObject *device : pairedDevices) { + VBluetoothDeviceInfo *pairedDevice = static_cast(device); + if (pairedDevice->getAddress() == deviceInfo.address().toString()) + alreadyPaired = true; + } + return alreadyPaired; +} + +/*! + * \brief VBluetooth::removeFromDevices + * Removes a device from the non-paired bluetooth devices list + * Adds that devices to the non-paired bluetooth devices blacklist + * \param info - the bluetooth device info object to remove + */ +void VBluetooth::removeFromDevices(const VBluetoothDeviceInfo *info) +{ + QList idxs; + int i = 0; + for (QObject *bleDevice : bleDevices) { + VBluetoothDeviceInfo *device = static_cast(bleDevice); + if (device->getAddress() == info->getAddress()) + idxs.append(i); + ++i; + } + for (int i : idxs) + bleDevices.removeAt(i); + + // update the QML + emit didDevicesChanged(); +} + +/*! + * \brief VBluetooth::onConnectedToDevice + * Slot called when BLEScanner connects to a device. Moves a device + * from the devices list to the my devices list + * \param deviceInfo - the device connected to + */ +void VBluetooth::onConnectedToDevice(const QBluetoothDeviceInfo &deviceInfo) +{ + VBluetoothDeviceInfo *info = new VBluetoothDeviceInfo(deviceInfo); + bool alreadyPaired = isDeviceAlreadyPaired(deviceInfo); + if (!alreadyPaired) + { + pairedDevices.append(info); + emit didPairedDevicesChanged(); + + removeFromDevices(info); + } + onUpdateStatus(tr("Connected.")); +}