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; Index: sources/bluetooth/BluetoothInterface.h =================================================================== diff -u -rc9f8f8cf3c6c37fc6460d8675c62c9442c4d4263 -rc447018bc6c50996f402e01f951d40b17a120705 --- sources/bluetooth/BluetoothInterface.h (.../BluetoothInterface.h) (revision c9f8f8cf3c6c37fc6460d8675c62c9442c4d4263) +++ sources/bluetooth/BluetoothInterface.h (.../BluetoothInterface.h) (revision c447018bc6c50996f402e01f951d40b17a120705) @@ -101,6 +101,7 @@ void onLocalDeviceConnect (const QBluetoothAddress &vAddress ); void onLocalDeviceDisconnect (const QBluetoothAddress &vAddress ); void onLocalError ( QBluetoothLocalDevice::Error vError ); + void onLocalPairingFinished (const QBluetoothAddress addr , QBluetoothLocalDevice::Pairing pair ); // Discovery Agent Slots void onAgentDiscoverDevice (const QBluetoothDeviceInfo & vDevice ); @@ -168,8 +169,8 @@ void interpretBloodPressure (const QByteArray &vData); void interpretInformation (); void interpretBattery (const QByteArray &vData); + void requestDevicePairing (const QBluetoothAddress &vAddress); - signals: void didStateChange (const BluetoothData &vData); void didActionReceive (const UIBloodPressureData &vData); Index: sources/gui/qml/pages/settings/SettingsBluetoothCuff.qml =================================================================== diff -u -rc9f8f8cf3c6c37fc6460d8675c62c9442c4d4263 -rc447018bc6c50996f402e01f951d40b17a120705 --- sources/gui/qml/pages/settings/SettingsBluetoothCuff.qml (.../SettingsBluetoothCuff.qml) (revision c9f8f8cf3c6c37fc6460d8675c62c9442c4d4263) +++ sources/gui/qml/pages/settings/SettingsBluetoothCuff.qml (.../SettingsBluetoothCuff.qml) (revision c447018bc6c50996f402e01f951d40b17a120705) @@ -65,7 +65,7 @@ readonly property color selectedColor: Colors.borderButtonSelected readonly property color pairedColor: Colors.borderButton readonly property color normalColor: Colors.borderButtonUnselected - property bool selectedDevice: addr === vBluetooth.pairedAddr + property bool selectedDevice: pair || addr === vBluetooth.pairedAddr clip : true radius : 10 width : 500 - 10 // give room to scrollbar Index: sources/model/settings/MBluetooth.h =================================================================== diff -u -rc9f8f8cf3c6c37fc6460d8675c62c9442c4d4263 -rc447018bc6c50996f402e01f951d40b17a120705 --- sources/model/settings/MBluetooth.h (.../MBluetooth.h) (revision c9f8f8cf3c6c37fc6460d8675c62c9442c4d4263) +++ sources/model/settings/MBluetooth.h (.../MBluetooth.h) (revision c447018bc6c50996f402e01f951d40b17a120705) @@ -57,6 +57,7 @@ eIS_Device_Error , eIS_Device_Done , eIS_Device_Disconnect , + eIS_Device_Pairing , eIS_Service_Start , eIS_Service_Invalid , Index: sources/view/settings/VBluetooth.cpp =================================================================== diff -u -rc9f8f8cf3c6c37fc6460d8675c62c9442c4d4263 -rc447018bc6c50996f402e01f951d40b17a120705 --- sources/view/settings/VBluetooth.cpp (.../VBluetooth.cpp) (revision c9f8f8cf3c6c37fc6460d8675c62c9442c4d4263) +++ sources/view/settings/VBluetooth.cpp (.../VBluetooth.cpp) (revision c447018bc6c50996f402e01f951d40b17a120705) @@ -129,11 +129,13 @@ break; case MBluetooth::eIS_Scan_Start : + scanEnabled(false); // disable the scan button while it is scanning reset(); break; case MBluetooth::eIS_Scan_Done : if (! _devices.count()) state = MBluetooth::eIS_Scan_NotFound; + scanEnabled(true); // enable the scan button when scanning is not happening break; case MBluetooth::eIS_Device_Waiting : // Selected device connected and is in waiting mode for read. @@ -163,6 +165,7 @@ case MBluetooth::eIS_Device_Error : case MBluetooth::eIS_Device_Done : case MBluetooth::eIS_Device_Disconnect : + case MBluetooth::eIS_Device_Pairing : case MBluetooth::eIS_Service_Start : case MBluetooth::eIS_Service_Invalid : @@ -257,11 +260,12 @@ case MBluetooth::eIS_Device_Init : message = tr("Device Initializing ..." ); break; case MBluetooth::eIS_Device_Error_Init : message = tr("Device Initialization Error" ); break; case MBluetooth::eIS_Device_Start : message = tr("Device Connecting ..." ); break; - case MBluetooth::eIS_Device_Waiting : message = tr("Device Waiting To Connect ..." ); break; // received feedback and changed the "Waiting" to this to avoid user confusion. + case MBluetooth::eIS_Device_Waiting : message = tr("Device Waiting For Measurement ..." ); break; // received feedback and changed the "Waiting" to this to avoid user confusion. case MBluetooth::eIS_Device_Error : message = tr("Device Connection Error" ); break; case MBluetooth::eIS_Device_Connect : message = tr("Device Connected" ); break; case MBluetooth::eIS_Device_Done : message = tr("Device Clean Up" ); break; case MBluetooth::eIS_Device_Disconnect : message = tr("Device In Power Saving Mode" ); break; // received feedback and changed the "Disconnected" to this to avoid user confusion. + case MBluetooth::eIS_Device_Pairing : message = tr("Device Is Pairing..." ); break; case MBluetooth::eIS_Service_Start : message = tr("Service Scanning ..." ); break; case MBluetooth::eIS_Service_Error : message = tr("Service Error: %1" ).arg(_error ); break;