summaryrefslogtreecommitdiff
path: root/bluetoothgpsserver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'bluetoothgpsserver.cpp')
-rw-r--r--bluetoothgpsserver.cpp137
1 files changed, 137 insertions, 0 deletions
diff --git a/bluetoothgpsserver.cpp b/bluetoothgpsserver.cpp
new file mode 100644
index 0000000..efbddf0
--- /dev/null
+++ b/bluetoothgpsserver.cpp
@@ -0,0 +1,137 @@
+#include <QtCore/QDebug>
+
+#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 QRfcommServer(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<quint16>(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<QBluetoothSocket*>(sender());
+ Q_ASSERT(socket);
+
+ m_clients.removeOne(socket);
+ socket->deleteLater();
+
+ if (m_clients.isEmpty()) {
+ qDebug() << "Stopping GPS for BT";
+ m_source->stop();
+ }
+}