/*Connect to sensor with bluetooth */ bool CSensorBluetoothWrapper::PrivateConnect(::std::unique_lock<::std::mutex> & _oManagementLock) { warble_gatt_connect_async(m_poWarble, &m_stConnectContext, [](void * _pvContext, WarbleGatt* caller, char const * _pszMessage) { td_stConnectContext * const pstConnectContext = static_cast(_pvContext); CSensorBluetoothWrapper * const poSensorBluetoothWrapper = pstConnectContext->poSensorBluetoothWrapper; if (nullptr != _pszMessage) { // error // lock management ::std::unique_lock<::std::mutex> oManagementLock(poSensorBluetoothWrapper->m_oWrapperManagementMutex); // update : m_isConnected = false, notify m_oConnectionSignal pstConnectContext->ManageConnectionEnd(false); } else { mbl_mw_metawearboard_initialize(poSensorBluetoothWrapper->m_poSensor, _pvContext, [](void * _pvContext, MblMwMetaWearBoard* _poSensor, ::std::int32_t _dwStatus) -> void { td_stConnectContext * const pstConnectContext = static_cast(_pvContext); CSensorBluetoothWrapper * const poSensorBluetoothWrapper = pstConnectContext->poSensorBluetoothWrapper; // lock management ::std::unique_lock<::std::mutex> oManagementLock(poSensorBluetoothWrapper->m_oWrapperManagementMutex); if (_dwStatus != MBL_MW_STATUS_OK) { // error // update : m_isConnected = false, notify m_oConnectionSignal pstConnectContext->ManageConnectionEnd(false); } else { // update : m_isConnected = true, notify m_oConnectionSignal pstConnectContext->ManageConnectionEnd(true); } }); } }); // wait for connection end ::std::chrono::milliseconds const oWaitDuration(15000); ::std::cv_status const waitResult = m_oConnectionSignal.wait_for(_oManagementLock, oWaitDuration); // if time out if (::std::cv_status::timeout == waitResult) { // error // exit break; } // lock access m_oWrapperStateMutex.lock(); // update isConnected = m_isConnected; // unlock access m_oWrapperStateMutex.unlock(); return isConnected; } void CBluetooth::configure_sensor_fusion() { ::MblMwMetaWearBoard* board = m_oBluetoothWrapper.getBoard(); // set fusion mode to ndof (n degress of freedom) ::mbl_mw_sensor_fusion_set_mode(board, MBL_MW_SENSOR_FUSION_MODE_NDOF); // set acceleration range to +/-8G, note accelerometer is configured here ::mbl_mw_sensor_fusion_set_acc_range(board, MBL_MW_SENSOR_FUSION_ACC_RANGE_8G); // set gyroscope range to +/-1000DPS, note gyroscope is configured here ::mbl_mw_sensor_fusion_set_gyro_range(board, MBL_MW_SENSOR_FUSION_GYRO_RANGE_1000DPS); // write changes to the board ::mbl_mw_sensor_fusion_write_config(board); //setting highest transmission power ::mbl_mw_settings_set_tx_power(board, 4); } /* Set signal used board data processors */ bool CBluetooth::SetDataSignalPath() { bool dataSignalPathSet = false; ::MblMwMetaWearBoard* board = m_oBluetoothWrapper.getBoard(); auto quaternion = ::mbl_mw_sensor_fusion_get_data_signal(board, MBL_MW_SENSOR_FUSION_DATA_QUATERNION); auto timeCreated = [](void* _pvContext, MblMwDataProcessor* _poProcessor) { td_stConditionVariableContext * const pstConditionVariableContext = static_cast(_pvContext); CBluetooth * const poSensor = pstConditionVariableContext->poSensor; if (nullptr != _poProcessor) { ::std::unique_lock<::std::mutex> oSignalLock(*(pstConditionVariableContext->poMutex)); poSensor->m_poTimeProcessor = _poProcessor; } poSensor->oSignalSynchronizer.notify_all(); }; m_poTimeProcessor = nullptr; ::std::mutex oSignalMutex; td_stConditionVariableContext stConditionVariableContext(this, &oSignalMutex, &oSignalSynchronizer); for (int iDataProcessorCreationTryIndex = 0; 5 > iDataProcessorCreationTryIndex; ++iDataProcessorCreationTryIndex) { ::std::unique_lock<::std::mutex> oSignalLock(oSignalMutex); ::mbl_mw_dataprocessor_time_create(quaternion, MBL_MW_TIME_ABSOLUTE, 40, &stConditionVariableContext, timeCreated); // the wait time ::std::chrono::milliseconds oWaitTime(5000); // wait for data processor creation oSignalSynchronizer.wait_for(oSignalLock, oWaitTime); // if data processor is not created if (nullptr != m_poTimeProcessor) { // exit break; } // wait ::std::this_thread::sleep_for(::std::chrono::milliseconds(500)); } // check if (nullptr != m_poTimeProcessor) { dataSignalPathSet = true; } m_poSignalProvider = (nullptr != m_poTimeProcessor) ? (MblMwDataSignal*)m_poTimeProcessor : quaternion; ::mbl_mw_datasignal_subscribe(m_poSignalProvider, this, [](void* context, const MblMwData* data) { // processing of quaternion data ... }); return dataSignalPathSet; } /* Start data send from the sensor */ bool CBluetooth::StartDataSend() { // get sensor ::MblMwMetaWearBoard * const poSensor = m_oBluetoothWrapper.getBoard(); // start data send ::mbl_mw_sensor_fusion_enable_data(poSensor, MBL_MW_SENSOR_FUSION_DATA_QUATERNION); ::mbl_mw_sensor_fusion_start(poSensor); // update m_isSendingData = true; return m_isSendingData; } for each sensor : CreateWarble(); ::mbl_mw_metawearboard_set_time_for_response(board, 5000); PrivateConnect(...); configure_sensor_fusion(); SetDataSignalPath(); StartDataSend();