Newer
Older
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/**
* @file
* @brief Definition of Bluetooth connection for unmanned vehicles
* @author Gus Grubba <mavlink@grubba.com>
*
*/
#include <QtGlobal>
#include <QTimer>
#include <QList>
#include <QDebug>
#include <iostream>
#include <QtBluetooth/QBluetoothDeviceDiscoveryAgent>
#include <QtBluetooth/QBluetoothLocalDevice>
#include <QtBluetooth/QBluetoothUuid>
#include "BluetoothLink.h"
#include "QGC.h"
BluetoothLink::BluetoothLink(SharedLinkConfigurationPointer& config)
: LinkInterface(config)
, _config(qobject_cast<BluetoothConfiguration*>(config.data()))
#ifdef __ios__
, _discoveryAgent(NULL)
#endif
, _shutDown(false)
}
BluetoothLink::~BluetoothLink()
{
_disconnect();
#ifdef __ios__
if(_discoveryAgent) {
_shutDown = true;
_discoveryAgent->stop();
_discoveryAgent->deleteLater();
_discoveryAgent = NULL;
}
#endif
}
void BluetoothLink::run()
{
}
void BluetoothLink::_restartConnection()
{
if(this->isConnected())
{
_disconnect();
_connect();
}
}
QString BluetoothLink::getName() const
{
return _config->name();
}
void BluetoothLink::_writeBytes(const QByteArray bytes)
{
if(_targetSocket)
{
if(_targetSocket->isWritable())
{
if(_targetSocket->write(bytes) > 0) {
_logOutputDataRate(bytes.size(), QDateTime::currentMSecsSinceEpoch());
}
else
qWarning() << "Bluetooth write error";
}
else
qWarning() << "Bluetooth not writable error";
}
}
void BluetoothLink::readBytes()
{
while (_targetSocket->bytesAvailable() > 0)
{
QByteArray datagram;
datagram.resize(_targetSocket->bytesAvailable());
_targetSocket->read(datagram.data(), datagram.size());
emit bytesReceived(this, datagram);
_logInputDataRate(datagram.length(), QDateTime::currentMSecsSinceEpoch());
}
}
void BluetoothLink::_disconnect(void)
{
#ifdef __ios__
if(_discoveryAgent) {
_shutDown = true;
_discoveryAgent->stop();
_discoveryAgent->deleteLater();
_discoveryAgent = NULL;
_targetSocket = NULL;
emit disconnected();
}
_connectState = false;
}
bool BluetoothLink::_connect(void)
{
return true;
}
bool BluetoothLink::_hardwareConnect()
{
#ifdef __ios__
if(_discoveryAgent) {
_shutDown = true;
_discoveryAgent->stop();
_discoveryAgent->deleteLater();
_discoveryAgent = NULL;
}
_discoveryAgent = new QBluetoothServiceDiscoveryAgent(this);
QObject::connect(_discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, this, &BluetoothLink::serviceDiscovered);
QObject::connect(_discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, this, &BluetoothLink::discoveryFinished);
QObject::connect(_discoveryAgent, &QBluetoothServiceDiscoveryAgent::canceled, this, &BluetoothLink::discoveryFinished);
_shutDown = false;
_discoveryAgent->start();
#else
_createSocket();
Gus Grubba
committed
_targetSocket->connectToService(QBluetoothAddress(_config->device().address), QBluetoothUuid(QBluetoothUuid::SerialPort));
#endif
return true;
}
void BluetoothLink::_createSocket()
{
if(_targetSocket)
{
delete _targetSocket;
_targetSocket = NULL;
}
_targetSocket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol, this);
QObject::connect(_targetSocket, &QBluetoothSocket::connected, this, &BluetoothLink::deviceConnected);
QObject::connect(_targetSocket, &QBluetoothSocket::readyRead, this, &BluetoothLink::readBytes);
QObject::connect(_targetSocket, &QBluetoothSocket::disconnected, this, &BluetoothLink::deviceDisconnected);
QObject::connect(_targetSocket, static_cast<void (QBluetoothSocket::*)(QBluetoothSocket::SocketError)>(&QBluetoothSocket::error),
this, &BluetoothLink::deviceError);
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#ifdef __ios__
void BluetoothLink::serviceDiscovered(const QBluetoothServiceInfo& info)
{
if(!info.device().name().isEmpty() && !_targetSocket)
{
if(_config->device().uuid == info.device().deviceUuid() && _config->device().name == info.device().name())
{
_createSocket();
_targetSocket->connectToService(info);
}
}
}
#endif
#ifdef __ios__
void BluetoothLink::discoveryFinished()
{
if(_discoveryAgent && !_shutDown)
{
_shutDown = true;
_discoveryAgent->deleteLater();
_discoveryAgent = NULL;
if(!_targetSocket)
{
_connectState = false;
emit communicationError("Could not locate Bluetooth device:", _config->device().name);
}
}
}
#endif
void BluetoothLink::deviceConnected()
{
_connectState = true;
emit connected();
}
void BluetoothLink::deviceDisconnected()
{
_connectState = false;
qWarning() << "Bluetooth disconnected";
}
void BluetoothLink::deviceError(QBluetoothSocket::SocketError error)
{
_connectState = false;
qWarning() << "Bluetooth error" << error;
emit communicationError(tr("Bluetooth Link Error"), _targetSocket->errorString());
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
}
bool BluetoothLink::isConnected() const
{
return _connectState;
}
qint64 BluetoothLink::getConnectionSpeed() const
{
return 1000000; // 1 Mbit
}
qint64 BluetoothLink::getCurrentInDataRate() const
{
return 0;
}
qint64 BluetoothLink::getCurrentOutDataRate() const
{
return 0;
}
//--------------------------------------------------------------------------
//-- BluetoothConfiguration
BluetoothConfiguration::BluetoothConfiguration(const QString& name)
: LinkConfiguration(name)
, _deviceDiscover(NULL)
{
}
BluetoothConfiguration::BluetoothConfiguration(BluetoothConfiguration* source)
: LinkConfiguration(source)
, _deviceDiscover(NULL)
{
}
BluetoothConfiguration::~BluetoothConfiguration()
{
if(_deviceDiscover)
{
_deviceDiscover->stop();
delete _deviceDiscover;
}
}
void BluetoothConfiguration::copyFrom(LinkConfiguration *source)
{
LinkConfiguration::copyFrom(source);
BluetoothConfiguration* usource = dynamic_cast<BluetoothConfiguration*>(source);
Q_ASSERT(usource != NULL);
}
void BluetoothConfiguration::saveSettings(QSettings& settings, const QString& root)
{
settings.beginGroup(root);
settings.setValue("deviceName", _device.name);
#ifdef __ios__
settings.setValue("uuid", _device.uuid.toString());
#else
settings.setValue("address",_device.address);
#endif
settings.endGroup();
}
void BluetoothConfiguration::loadSettings(QSettings& settings, const QString& root)
{
settings.beginGroup(root);
_device.name = settings.value("deviceName", _device.name).toString();
#ifdef __ios__
QString suuid = settings.value("uuid", _device.uuid.toString()).toString();
_device.uuid = QUuid(suuid);
#else
_device.address = settings.value("address", _device.address).toString();
settings.endGroup();
}
void BluetoothConfiguration::updateSettings()
{
if(_link) {
BluetoothLink* ulink = dynamic_cast<BluetoothLink*>(_link);
if(ulink) {
ulink->_restartConnection();
}
}
}
void BluetoothConfiguration::stopScan()
{
if(_deviceDiscover)
{
_deviceDiscover->stop();
_deviceDiscover->deleteLater();
_deviceDiscover = NULL;
emit scanningChanged();
}
}
void BluetoothConfiguration::startScan()
{
if(!_deviceDiscover)
{
_deviceDiscover = new QBluetoothDeviceDiscoveryAgent(this);
connect(_deviceDiscover, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BluetoothConfiguration::deviceDiscovered);
connect(_deviceDiscover, &QBluetoothDeviceDiscoveryAgent::finished, this, &BluetoothConfiguration::doneScanning);
emit scanningChanged();
}
else
{
_deviceDiscover->stop();
}
_deviceDiscover->setInquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry);
_deviceDiscover->start();
}
void BluetoothConfiguration::deviceDiscovered(QBluetoothDeviceInfo info)
{
if(!info.name().isEmpty() && info.isValid())
{
Gus Grubba
committed
#if 0
qDebug() << "Name: " << info.name();
qDebug() << "Address: " << info.address().toString();
qDebug() << "Service Classes:" << info.serviceClasses();
QList<QBluetoothUuid> uuids = info.serviceUuids();
foreach (QBluetoothUuid uuid, uuids) {
qDebug() << "Service UUID: " << uuid.toString();
}
#endif
BluetoothData data;
data.name = info.name();
#ifdef __ios__
data.uuid = info.deviceUuid();
#else
if(!_deviceList.contains(data))
{
_deviceList += data;
_nameList += data.name;
emit nameListChanged();
return;
}
}
}
void BluetoothConfiguration::doneScanning()
{
if(_deviceDiscover)
{
_deviceDiscover->deleteLater();
_deviceDiscover = NULL;
emit scanningChanged();
}
}
void BluetoothConfiguration::setDevName(const QString &name)
foreach(const BluetoothData& data, _deviceList)
if(data.name == name)
{
_device = data;
emit devNameChanged();
QString BluetoothConfiguration::address()
{
#ifdef __ios__
return QString("");
#else
return _device.address;
#endif
}