#include #include "nmeasource.h" #include "bluetoothgpsserver.h" BluetoothGpsServer::BluetoothGpsServer(uint port, QObject *parent) : QObject(parent), m_port(port), m_source(new NmeaSource(this)), m_server(0) { connect(m_source, SIGNAL(dataReady(QString)), this, SLOT(sendData(QString))); } BluetoothGpsServer::~BluetoothGpsServer() { stop(); } void BluetoothGpsServer::start() { if (m_server) { return; } m_server = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this); connect(m_server, SIGNAL(newConnection()), this, SLOT(acceptConnection())); if (!m_server->listen(QBluetoothAddress(), m_port)) { qWarning() << "Failed to start Bluetooth listener socket"; stop(); return; } quint8 serverPort = m_server->serverPort(); const QBluetoothUuid service_uuid(QLatin1String("2af0b21d-2d9d-43bd-9693-5d9235fa2033")); const QBluetoothUuid gnss_profile_uuid(quint16(0x1135)); const QBluetoothUuid gnss_server_uuid(quint16(0x1136)); m_service.setServiceName("GPS"); m_service.setServiceDescription("GPS/NMEA emulator over Serial Port"); m_service.setServiceProvider("btgpsd"); m_service.setServiceUuid(service_uuid); QBluetoothServiceInfo::Sequence classIds; classIds.append(QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort))); classIds.append(QVariant::fromValue(gnss_server_uuid)); m_service.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classIds); QBluetoothServiceInfo::Sequence browseGroupList; browseGroupList.append(QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup))); m_service.setAttribute(QBluetoothServiceInfo::BrowseGroupList, browseGroupList); QBluetoothServiceInfo::Sequence protocolDescriptorList; QBluetoothServiceInfo::Sequence protocol; protocol.append(QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap))); protocolDescriptorList.append(QVariant::fromValue(protocol)); protocol.clear(); protocol.append(QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))); protocol.append(QVariant::fromValue(serverPort)); protocolDescriptorList.append(QVariant::fromValue(protocol)); protocol.clear(); m_service.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); QBluetoothServiceInfo::Sequence profileDescriptorList; protocol.append(QVariant::fromValue(gnss_profile_uuid)); protocol.append(QVariant::fromValue(0x100)); profileDescriptorList.append(QVariant::fromValue(protocol)); protocol.clear(); // Profile Descriptor list m_service.setAttribute(0x0009, QVariant::fromValue(profileDescriptorList)); if (!m_service.registerService()) { qWarning() << "Failed to register the Serial Port service"; } } void BluetoothGpsServer::stop() { if (!m_server) { return; } if (!m_service.unregisterService()) { qWarning() << "Failed to unregister Serial Port service"; } qDeleteAll(m_clients); m_clients.clear(); m_source->stop(); delete m_server; m_server = 0; } void BluetoothGpsServer::sendData(const QString &data) { QByteArray text = data.toLatin1(); foreach (QBluetoothSocket *socket, m_clients) { socket->write(text); } } void BluetoothGpsServer::acceptConnection() { qDebug() << "Incoming BT connection"; QBluetoothSocket *socket = m_server->nextPendingConnection(); if (!socket) { qWarning() << "Actually, no incoming connection"; return; } connect(socket, SIGNAL(disconnected()), this, SLOT(handleDisconnection())); m_clients.append(socket); if (m_clients.size() == 1) { // This was the first client; start listening to GPS qDebug() << "Starting GPS for BT"; m_source->start(); } } void BluetoothGpsServer::handleDisconnection() { QBluetoothSocket *socket = qobject_cast(sender()); Q_ASSERT(socket); m_clients.removeOne(socket); socket->deleteLater(); if (m_clients.isEmpty()) { qDebug() << "Stopping GPS for BT"; m_source->stop(); } }