Index: sources/bluetooth/BluetoothInterface.cpp =================================================================== diff -u -rc9f8f8cf3c6c37fc6460d8675c62c9442c4d4263 -rc447018bc6c50996f402e01f951d40b17a120705 --- sources/bluetooth/BluetoothInterface.cpp (.../BluetoothInterface.cpp) (revision c9f8f8cf3c6c37fc6460d8675c62c9442c4d4263) +++ sources/bluetooth/BluetoothInterface.cpp (.../BluetoothInterface.cpp) (revision c447018bc6c50996f402e01f951d40b17a120705) @@ -150,6 +150,8 @@ #define NOTIFY_LOCAL_ERROR_OFF notifyStateChange(MBluetooth(MBluetooth::eIS_Local_Error_Off )); #define NOTIFY_LOCAL_ERROR_INVALID notifyStateChange(MBluetooth(MBluetooth::eIS_Local_Error_Invalid )); #define NOTIFY_LOCAL_DISCONNECT notifyStateChange(MBluetooth(MBluetooth::eIS_Local_Disconnect , vAddress.toString()) ); +#define NOTIFY_LOCAL_PAIRING notifyStateChange(MBluetooth(MBluetooth::eIS_Device_Pairing )); + // ~~~~~~~~~~ Scan #define NOTIFY_SCAN_DISCOVER notifyStateChange(MBluetooth(MBluetooth::eIS_Scan_Discover , \ vInfo.address().toString() , \ @@ -194,6 +196,8 @@ #define NOTIFY_DEVICE_DISCONNECT notifyStateChange(MBluetooth(MBluetooth::eIS_Device_Disconnect , \ _device->remoteAddress().toString() , \ _device->remoteName() )); + + // ~~~~~~~~~~ Service #define NOTIFY_SERVICE_START notifyStateChange(MBluetooth(MBluetooth::eIS_Service_Start )); #define NOTIFY_SERVICE_DISCOVER notifyStateChange(MBluetooth(MBluetooth::eIS_Service_Discover )); @@ -290,7 +294,10 @@ this , SLOT(onLocalDeviceDisconnect (QBluetoothAddress ))); connect(_local , SIGNAL( error (QBluetoothLocalDevice::Error )), this , SLOT(onLocalError (QBluetoothLocalDevice::Error ))); + connect(_local , SIGNAL( pairingFinished (QBluetoothAddress, QBluetoothLocalDevice::Pairing)), + this , SLOT(onLocalPairingFinished (QBluetoothAddress, QBluetoothLocalDevice::Pairing))); + if ( ! isAgentValid() ) return; // Agent connections connect(_agent , SIGNAL( deviceDiscovered (QBluetoothDeviceInfo )), @@ -407,12 +414,17 @@ } _local->powerOn(); + _agent = new QBluetoothDeviceDiscoveryAgent (this); quitDevice(); _agent->setLowEnergyDiscoveryTimeout(5000); + initConnections(); NOTIFY_LOCAL_INIT NOTIFY_IDLE + + // initial scan to populate bluetooth device list + startScan(); } /*! @@ -436,6 +448,17 @@ */ void BluetoothInterface::onLocalDeviceConnect (const QBluetoothAddress &vAddress ) { NOTIFY_LOCAL_CONNECT + + // This indicates the local/host bluetooth have connected passively to the remote device + _reconnectionActive = true; + + if ( _local->pairingStatus(vAddress) == QBluetoothLocalDevice::Unpaired ) { + requestDevicePairing(vAddress); + } else { + if ( isDeviceValid() ) { + _device->connectToDevice(); + } + } } /*! @@ -452,9 +475,14 @@ * \details Notifies the observers (view: VBluetooth) that the local adapter has error * \param vError - The error */ -void BluetoothInterface::onLocalError ( QBluetoothLocalDevice::Error /*vError*/ ) { - NOTIFY_LOCAL_ERROR - quitDevice(); +void BluetoothInterface::onLocalError ( QBluetoothLocalDevice::Error vError ) { + if ( vError == QBluetoothLocalDevice::UnknownError ) { + NOTIFY_LOCAL_ERROR + quitDevice(); + } else { + // Could be a pairing error, continue polling for device connection + _reconnectionActive = true; + } } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -471,12 +499,28 @@ void BluetoothInterface::onAgentDiscoverDevice(const QBluetoothDeviceInfo &vInfo) { NOTIFY_SCAN_DISCOVER + if (vInfo.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) { if ( isDeviceSupported( vInfo.name() ) ) { BluetoothDeviceData data; data.addr = vInfo.address().toString(); data.name = vInfo.name(); - data.pair = _local->pairingStatus(vInfo.address()); + + bool isPaired = _local->pairingStatus(vInfo.address()) == QBluetoothLocalDevice::Paired; + bool isAuthPaired = _local->pairingStatus(vInfo.address()) == QBluetoothLocalDevice::AuthorizedPaired; + + data.pair = isPaired || isAuthPaired; + + if(data.pair){ + // Enable the polling since previously paired device found + _reconnectionActive = true; + + // sets up the bluetooth device info to create the device later for pairing + _temp = QBluetoothDeviceInfo(QBluetoothAddress(data.addr), data.name, QBluetoothDeviceInfo::HealthBloodPressureMonitor); + + // using signal to re-use the slot function of a device selected + emit _BluetoothInterface.didDeviceSelect(data); + } emit didDeviceChange(data); NOTIFY_SCAN_FOUND } @@ -526,9 +570,37 @@ void BluetoothInterface::onDeviceSelect(const BluetoothDeviceData &vDevice) { stopScan(); _temp = QBluetoothDeviceInfo(QBluetoothAddress(vDevice.addr), vDevice.name, QBluetoothDeviceInfo::HealthBloodPressureMonitor); - connectToDevice(); + + requestDevicePairing(QBluetoothAddress(vDevice.addr)); } +/*! + * \brief BluetoothInterface::requestDevicePairing + * \details Request the pairing of the local/host bluetooth with the remote device + * \param vAddress - the address of the remote device + */ +void BluetoothInterface::requestDevicePairing(const QBluetoothAddress &vAddress) { + if ( ! isLocalValid() ) return; + + NOTIFY_LOCAL_PAIRING + _local->requestPairing(vAddress, QBluetoothLocalDevice::AuthorizedPaired); +} + +/*! + * \brief BluetoothInterface::onLocalPairingFinished + * \details Request the pairing of the local/host bluetooth with the remote device + * \param addr - the address of the remote device + * \param pair - the pairing type + */ +void BluetoothInterface::onLocalPairingFinished(const QBluetoothAddress addr, QBluetoothLocalDevice::Pairing pair) { + Q_UNUSED(addr) + if( pair == QBluetoothLocalDevice::Paired || pair == QBluetoothLocalDevice::AuthorizedPaired) { + connectToDevice(); + } else { + // not handling unpairing case + } +} + void BluetoothInterface::onAttributeResponse(const DeviceBluetoothPairedQueryResponseData &vData) { if ( ! vData.mAccepted ) { @@ -567,9 +639,16 @@ * notifies the observers (view: VBluetooth) that the state is MBluetooth::eIS_Device_Connect. */ void BluetoothInterface::onDeviceConnect() { - _reconnectionActive = false; + if ( ! isLocalValid() ) return; + if ( ! isDeviceValid()) return; + NOTIFY_DEVICE_CONNECT - discoverServices(); + _reconnectionActive = false; + if(_local->pairingStatus(_device->remoteAddress()) == QBluetoothLocalDevice::Unpaired) { + requestDevicePairing(_device->remoteAddress()); + } else { + discoverServices(); + } } /*! @@ -580,6 +659,19 @@ */ void BluetoothInterface::onDeviceError(QLowEnergyController::Error vError) { + bool isErrorUnknown = ( vError == QLowEnergyController::UnknownError ); + bool isLocalAndDeviceValid = isLocalValid() && isDeviceValid(); + if ( isErrorUnknown ) { + // When polling to reconnect to the remote device, the application encounters an unknown + // error occasionally when the connection fails, but does not report it as a connection error. + + if ( isLocalAndDeviceValid && ( _local->pairingStatus(_device->remoteAddress()) != QBluetoothLocalDevice::Unpaired) ) { + // Code is opting to set _reconnectionActive to true to allow polling to continue since the device + // is still paired and the error encountered is due to not being able to connect to remote device + _reconnectionActive = true; + } + } + // if the device is trying to connect to the previously paired device and the device was not on at this moment it should go to the reconnection state. if ( _tryingrepairActive ) _reconnectionActive = true; @@ -724,7 +816,7 @@ switch( service->serviceUuid().toUInt32() ) { case QBluetoothUuid::BloodPressure: enableNotify(); - break; + break; case QBluetoothUuid::DeviceInformation: interpretInformation(); @@ -959,12 +1051,11 @@ // - For QLowEnergyController::DiscoveredState : // This is the first time after the device is free and reconnect starts. // And the last state of the device after it is done with services and all the things. - // At this moment the device has to disconnect to be able to reconnect and read measurements. // - For QLowEnergyController::ConnectingState : // After some testing figured the connecting state take so long to reconnect. // so to move to Unconnected state if instead of waiting for the connecting state timeout (nowhere int the Qt documentation, cannot find a timeout for connecting state.). SKIPPER_TST(break); - _device->disconnectFromDevice(); + // No Operation needed SKIPPER_RST; break;