Index: sources/bluetooth/BluetoothInterface.cpp =================================================================== diff -u -rf11dd9cd2c07f96d9d939d70ed9c4ce2edef2a9d -re4a0e2fc4c7ae0cbce0d670772276bf7f5ff3845 --- sources/bluetooth/BluetoothInterface.cpp (.../BluetoothInterface.cpp) (revision f11dd9cd2c07f96d9d939d70ed9c4ce2edef2a9d) +++ sources/bluetooth/BluetoothInterface.cpp (.../BluetoothInterface.cpp) (revision e4a0e2fc4c7ae0cbce0d670772276bf7f5ff3845) @@ -21,7 +21,6 @@ // Project #include "Logger.h" -#include "types.h" // namespace using namespace Bluetooth; @@ -34,8 +33,6 @@ * Qt handles the children destruction by their parent objects life-cycle. */ BluetoothInterface::BluetoothInterface(QObject *parent) : QObject(parent) { - _local = new QBluetoothLocalDevice (this); - _agent = new QBluetoothDeviceDiscoveryAgent (this); startTimer(_interval); } @@ -46,7 +43,8 @@ */ bool BluetoothInterface::init() { - if ( _init ) return false; + if ( ! _isValid ) return false; + if ( _init ) return false; _init = true; // runs in BluetoothInterface thread @@ -78,13 +76,14 @@ */ void BluetoothInterface::quit() { + if ( ! _isValid ) return; // coco begin validated: Application termination is not correctly done in coco!!! // it has been tested and works perfectly fine in normal run. quitThread(); // validated if ( _local ) _local ->deleteLater(); if ( _agent ) _agent ->deleteLater(); - if ( _device ) _device ->deleteLater(); + quitDevice(); } // coco end @@ -95,6 +94,7 @@ */ void BluetoothInterface::initConnections() { + if ( ! isLocalValid() ) return; // Local connections connect(_local , &QBluetoothLocalDevice :: deviceConnected , this , &BluetoothInterface ::onLocalDeviceConnect ); @@ -103,6 +103,7 @@ connect(_local , &QBluetoothLocalDevice :: error , this , &BluetoothInterface ::onLocalError ); + if ( ! isAgentValid() ) return; // Agent connections connect(_agent , &QBluetoothDeviceDiscoveryAgent ::deviceDiscovered , this , &BluetoothInterface ::onAgentDiscoverDevice ); @@ -159,6 +160,7 @@ #define NOTIFY_LOCAL_CONNECT notifyStateChange(MBluetooth(MBluetooth::eIS_Local_Connect , vAddress.toString()) ); #define NOTIFY_LOCAL_ERROR notifyStateChange(MBluetooth(MBluetooth::eIS_Local_Error )); +#define NOTIFY_LOCAL_ERROR_POST notifyStateChange(MBluetooth(MBluetooth::eIS_Local_Error_POST )); #define NOTIFY_LOCAL_ERROR_IO notifyStateChange(MBluetooth(MBluetooth::eIS_Local_Error_IO )); #define NOTIFY_LOCAL_ERROR_OFF notifyStateChange(MBluetooth(MBluetooth::eIS_Local_Error_Off )); #define NOTIFY_LOCAL_ERROR_INVALID notifyStateChange(MBluetooth(MBluetooth::eIS_Local_Error_Invalid )); @@ -291,13 +293,28 @@ // ~~~~~ Public interface to initialize and start the scan // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /*! - * \brief BluetoothInterface::onstart + * \brief BluetoothInterface::ondoStart * \details the thread safe slot to be called when the public function start is called. * initializes the local Bluetooth device _local and setups up the interface. */ -void BluetoothInterface::onstart() +void BluetoothInterface::ondoStart() { - if ( ! isLocalValid() ) return; + // check the POST was successful and Bluetooth adapter is up. + if ( ! isValid() ) { // POST failed. + NOTIFY_LOCAL_ERROR_POST + return; + } + + _local = new QBluetoothLocalDevice (this); + if ( _local->address().toString() == _invalidLocalAddress ) { + _isValid = false; + NOTIFY_LOCAL_ERROR_POST + quit(); + return; + } + + _agent = new QBluetoothDeviceDiscoveryAgent (this); + _local->powerOn(); quitDevice(); _agent->setLowEnergyDiscoveryTimeout(5000); NOTIFY_LOCAL_INIT @@ -311,6 +328,8 @@ */ void BluetoothInterface::ondoScan() { + if ( ! isValid() ) return; // POST failed. + if (_agent && _agent->isActive()) { NOTIFY_SCAN_REJECT return; @@ -388,9 +407,12 @@ case QBluetoothDeviceDiscoveryAgent::InputOutputError : NOTIFY_LOCAL_ERROR_IO break; default : NOTIFY_LOCAL_ERROR break; } - quitDevice(); } +void BluetoothInterface::ondoConnectToDevice() { + connectToDevice(); +} + /*! * \brief BluetoothInterface::onAgentDiscoverFinish * \details Notifies the observers (view: VBluetooth) that the discovery agent has done discovery, and @@ -425,6 +447,7 @@ bool BluetoothInterface::connectToDevice() { if ( ! isLocalValid() ) return false; + if ( ! isAgentValid() ) return false; if ( ! isInfoValid () ) return false; if ( ! initDevice () ) return false; @@ -437,18 +460,25 @@ bool BluetoothInterface::reconnectToDevice() { if ( ! isLocalValid() ) return false; + if ( ! isAgentValid() ) return false; + NOTIFY_DEVICE_START _device->connectToDevice(); return true; } +void BluetoothInterface::ondoDiscoverServices() { + discoverServices(); +} + /*! * \brief BluetoothInterface::discoverServices * \details The function to be called to start retrieving the remote Bluetooth device _device's services, and * notifies the observers (view: VBluetooth) that the state is MBluetooth::eIS_Service_Start. */ void BluetoothInterface::discoverServices() { + if ( ! isDeviceValid() ) return; NOTIFY_SERVICE_START _device->discoverServices(); } @@ -487,6 +517,7 @@ void BluetoothInterface::discoverServicesDetails() { + if ( ! isValid() ) return; if ( _serviceDeviceInformation ) { NOTIFY_SERVICE_DETAILS (_serviceDeviceInformation ) _serviceDeviceInformation ->discoverDetails(); @@ -588,6 +619,7 @@ * \details sets up the remote Bluetooth device _device connections. */ void BluetoothInterface::initConnectionsDevice() { + if ( ! isDeviceValid() ) return; // Device controller connect( _device, SIGNAL( connected ( )), this , SLOT(onDeviceConnect ( ))); @@ -632,7 +664,70 @@ NOTIFY_SERVICE_ERROR } +void BluetoothInterface::ondoReadMeasurements() { + readMeasurements(); +} + +void BluetoothInterface::readMeasurements() +{ + if ( ! _serviceBloodPressure ) { + NOTIFY_DETAILS_INVALID + return; + } + // blood pressure feature + const QLowEnergyCharacteristic detailBPFeat = _serviceBloodPressure->characteristic(QBluetoothUuid(QBluetoothUuid::BloodPressureFeature)); + if (!detailBPFeat.isValid()) { + qDebug() << "Blood pressure feature not found."; + return; + } + _serviceBloodPressure->readCharacteristic(detailBPFeat); +} + +void BluetoothInterface::ondoReadInformation() { + readInformation(); +} + +void BluetoothInterface::readInformation() +{ + if ( ! _serviceDeviceInformation ) { + NOTIFY_DETAILS_INVALID + return; + } + + // device information + const QLowEnergyCharacteristic detailInfo = _serviceDeviceInformation->characteristic(QBluetoothUuid(QBluetoothUuid::DeviceInformation)); + if (!detailInfo.isValid()) { + qDebug() << "Device Information feature not found."; + return; + } + _serviceDeviceInformation->readCharacteristic(detailInfo); +} + +void BluetoothInterface::printCharacteristics(QLowEnergyService *vService) +{ + for ( auto const &detail: vService->characteristics()) { + qDebug() << " ~~~~~ " << detail.name() << detail.uuid() << detail.value(); + } +} + +void BluetoothInterface::ondoEnableNotify() { + enableNotify(); +} + +void BluetoothInterface::enableNotify() { + if ( ! _serviceBloodPressure ) { + NOTIFY_DETAILS_INVALID + return; + } + + // blood pressure measurements + const QLowEnergyCharacteristic detailBPMeas = _serviceBloodPressure->characteristic(QBluetoothUuid(QBluetoothUuid::BloodPressureMeasurement)); + QLowEnergyDescriptor configBPMeas = detailBPMeas.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration); + if (configBPMeas.isValid()) _serviceBloodPressure->writeDescriptor(configBPMeas, QByteArray::fromHex("0100")); +} + void BluetoothInterface::onServiceStateChanged(QLowEnergyService::ServiceState vState) { + if ( ! sender() ) return; QLowEnergyService *service = reinterpret_cast(sender()); qDebug() << "Service State:" << service->serviceUuid() << service->serviceName() << vState; switch (vState) { @@ -642,24 +737,15 @@ case QLowEnergyService::ServiceDiscovered : NOTIFY_SERVICE_DETAILS_DONE - for ( auto const &detail: service->characteristics()) { - qDebug() << " ~~~~~ " << detail.name() << detail.uuid() << detail.value(); - } - if ( service->serviceUuid() == QBluetoothUuid (QBluetoothUuid::BloodPressure)) { - // blood pressure measurements - const QLowEnergyCharacteristic detailBPMeas = service->characteristic(QBluetoothUuid(QBluetoothUuid::BloodPressureMeasurement)); - QLowEnergyDescriptor configBPMeas = detailBPMeas.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration); - if (configBPMeas.isValid()) service->writeDescriptor(configBPMeas, QByteArray::fromHex("0100")); - - // blood pressure feature - const QLowEnergyCharacteristic detailBPFeat = service->characteristic(QBluetoothUuid(QBluetoothUuid::BloodPressureFeature)); - if (!detailBPFeat.isValid()) { - qDebug() << "Blood pressure feature not found."; - return; - } - service->readCharacteristic(detailBPFeat); + printCharacteristics(service); + if ( service->serviceUuid() == QBluetoothUuid (QBluetoothUuid::BloodPressure )) { + enableNotify(); + readMeasurements(); _reconnectionActive = true; } + if (service->serviceUuid() == QBluetoothUuid (QBluetoothUuid::DeviceInformation )) { + readInformation(); + } break; default: @@ -740,21 +826,30 @@ * \return false if the local Bluetooth device _local is not valid */ bool BluetoothInterface::isLocalValid() { - if (! _local->isValid() ) { + if ( ! _isValid ) return false; + if ( ! _local ) return false; + if ( ! _local->isValid() ) { NOTIFY_LOCAL_ERROR_INVALID quitDevice(); return false; } return true; } +bool BluetoothInterface::isAgentValid() { + if (! _agent ) { + return false; + } + return true; +} + /*! * \brief BluetoothInterface::isInfoValid * \details checks if the device info _temp is valid. * notifies the observers (view: VBluetooth) that the device info is not valid. * \return false if the device info _local is not valid * \note the device info _temp is set to a default QBluetoothDeviceInfo which is invalid by default, - * when the interface initialized (onStart), and + * when the interface initialized (doStart), and * when a scan started (ondoScan) */ bool BluetoothInterface::isInfoValid() {