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>
BluetoothLink::BluetoothLink(SharedLinkConfigurationPointer& config)
: LinkInterface(config)
, _config(qobject_cast<BluetoothConfiguration*>(config.data()))
}
BluetoothLink::~BluetoothLink()
{
_disconnect();
#ifdef __ios__
if(_discoveryAgent) {
_shutDown = true;
_discoveryAgent->stop();
_discoveryAgent->deleteLater();
}
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->write(bytes) > 0) {
_logOutputDataRate(bytes.size(), QDateTime::currentMSecsSinceEpoch());
} else {
qWarning() << "Bluetooth write error";
}
}
}
void BluetoothLink::readBytes()
{
if (_targetSocket) {
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();
emit disconnected();
}
_connectState = false;
}
bool BluetoothLink::_connect(void)
{
return true;
}
bool BluetoothLink::_hardwareConnect()
{
#ifdef __ios__
if(_discoveryAgent) {
_shutDown = true;
_discoveryAgent->stop();
_discoveryAgent->deleteLater();
}
_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 = 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);
#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();
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());
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
}
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)
{
}
BluetoothConfiguration::BluetoothConfiguration(BluetoothConfiguration* source)
: LinkConfiguration(source)
, _device(source->device())
{
}
BluetoothConfiguration::~BluetoothConfiguration()
{
if(_deviceDiscover)
{
_deviceDiscover->stop();
delete _deviceDiscover;
}
}
QString BluetoothConfiguration::settingsTitle()
{
if(qgcApp()->toolbox()->linkManager()->isBluetoothAvailable()) {
return tr("Bluetooth Link Settings");
} else {
return tr("Bluetooth Not Available");
}
}
void BluetoothConfiguration::copyFrom(LinkConfiguration *source)
{
LinkConfiguration::copyFrom(source);
auto* usource = qobject_cast<BluetoothConfiguration*>(source);
}
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) {
auto* ulink = qobject_cast<BluetoothLink*>(_link);
if(ulink) {
ulink->_restartConnection();
}
}
}
void BluetoothConfiguration::stopScan()
{
if(_deviceDiscover)
{
_deviceDiscover->stop();
_deviceDiscover->deleteLater();
}
}
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();
for (QBluetoothUuid uuid: uuids) {
Gus Grubba
committed
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();
void BluetoothConfiguration::setDevName(const QString &name)
for(const BluetoothData& data: _deviceList)
if(data.name == name)
{
_device = data;
emit devNameChanged();
QString BluetoothConfiguration::address()
{
#ifdef __ios__