basic bluetooth server infrastructure
This commit is contained in:
parent
174a83cd0b
commit
ec0a9a5c9d
158
server/bluetoothserver.cpp
Normal file
158
server/bluetoothserver.cpp
Normal file
@ -0,0 +1,158 @@
|
||||
#include "bluetoothserver.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QBluetoothLocalDevice>
|
||||
|
||||
namespace guhserver {
|
||||
|
||||
static const QLatin1String serviceUuid("81679f09-1404-4242-b685-a7f7e23df8cf");
|
||||
|
||||
BluetoothServer::BluetoothServer(QObject *parent) :
|
||||
TransportInterface(parent),
|
||||
m_server(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BluetoothServer::~BluetoothServer()
|
||||
{
|
||||
stopServer();
|
||||
}
|
||||
|
||||
bool BluetoothServer::hardwareAvailable()
|
||||
{
|
||||
QBluetoothLocalDevice localDevice;
|
||||
return localDevice.isValid();
|
||||
}
|
||||
|
||||
void BluetoothServer::sendData(const QUuid &clientId, const QVariantMap &data)
|
||||
{
|
||||
QBluetoothSocket *client = 0;
|
||||
client = m_clientList.value(clientId);
|
||||
if (client)
|
||||
client->write(QJsonDocument::fromVariant(data).toJson() + "\n");
|
||||
}
|
||||
|
||||
void BluetoothServer::sendData(const QList<QUuid> &clients, const QVariantMap &data)
|
||||
{
|
||||
foreach (const QUuid &client, clients)
|
||||
sendData(client, data);
|
||||
}
|
||||
|
||||
void BluetoothServer::onClientConnected()
|
||||
{
|
||||
// Got a new client connected
|
||||
QBluetoothSocket *client = m_server->nextPendingConnection();
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
qCDebug(dcConnection) << "Bluetooth server: new client connected:" << client->localName() << client->localAddress().toString();
|
||||
|
||||
QUuid clientId = QUuid::createUuid();
|
||||
m_clientList.insert(clientId, client);
|
||||
|
||||
connect(client, SIGNAL(readyRead()), this, SLOT(readData()));
|
||||
connect(client, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(onError(QBluetoothSocket::SocketError)));
|
||||
connect(client, SIGNAL(disconnected()), this, SLOT(onClientDisconnected()));
|
||||
|
||||
emit clientConnected(clientId);
|
||||
}
|
||||
|
||||
void BluetoothServer::onClientDisconnected()
|
||||
{
|
||||
QBluetoothSocket *client = qobject_cast<QBluetoothSocket *>(sender());
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
qCDebug(dcConnection) << "Bluetooth server: client disconnected:" << client->localName() << client->localAddress().toString();
|
||||
QUuid clientId = m_clientList.key(client);
|
||||
m_clientList.take(clientId)->deleteLater();
|
||||
}
|
||||
|
||||
void BluetoothServer::onError(QBluetoothSocket::SocketError error)
|
||||
{
|
||||
qCWarning(dcConnection) << "Bluetooth server error:" << error;
|
||||
}
|
||||
|
||||
void BluetoothServer::readData()
|
||||
{
|
||||
QBluetoothSocket *client = qobject_cast<QBluetoothSocket *>(sender());
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
while (client->canReadLine()) {
|
||||
QByteArray line = client->readLine().trimmed();
|
||||
qCDebug(dcConnection()) << "Bluetooth server: line in:" << QString::fromUtf8(line.constData(), line.length());
|
||||
}
|
||||
}
|
||||
|
||||
bool BluetoothServer::startServer()
|
||||
{
|
||||
if (m_server)
|
||||
return true;
|
||||
|
||||
// Check if Bluetooth is available on this device
|
||||
QBluetoothLocalDevice localDevice;
|
||||
if (localDevice.isValid()) {
|
||||
// Turn Bluetooth on
|
||||
localDevice.powerOn();
|
||||
// Make it visible to others
|
||||
localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
|
||||
} else {
|
||||
qCWarning(dcConnection()) << "Bluetooth server: could find any bluetooth hardware";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_server = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this);
|
||||
connect(m_server, SIGNAL(newConnection()), this, SLOT(onClientConnected()));
|
||||
if (!m_server->listen(localDevice.address())) {
|
||||
qCWarning(dcConnection()) << "Bluetooth server: could not listen on local device." << localDevice.name();
|
||||
return false;
|
||||
}
|
||||
|
||||
qCDebug(dcConnection) << "Started bluetooth server" << m_server->serverAddress().toString();
|
||||
|
||||
QBluetoothServiceInfo::Sequence classId;
|
||||
classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
|
||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, classId);
|
||||
|
||||
classId.prepend(QVariant::fromValue(QBluetoothUuid(serviceUuid)));
|
||||
|
||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
|
||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList,classId);
|
||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, tr("guhIO JSON-RPC"));
|
||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription, tr("The JSON-RPC interface for guhIO."));
|
||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, "guh.io");
|
||||
m_serviceInfo.setServiceUuid(QBluetoothUuid(serviceUuid));
|
||||
|
||||
QBluetoothServiceInfo::Sequence publicBrowse;
|
||||
publicBrowse << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
|
||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, publicBrowse);
|
||||
|
||||
QBluetoothServiceInfo::Sequence protocolDescriptorList;
|
||||
QBluetoothServiceInfo::Sequence protocol;
|
||||
protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap));
|
||||
protocolDescriptorList.append(QVariant::fromValue(protocol));
|
||||
protocol.clear();
|
||||
protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
|
||||
<< QVariant::fromValue(quint8(m_server->serverPort()));
|
||||
protocolDescriptorList.append(QVariant::fromValue(protocol));
|
||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList);
|
||||
m_serviceInfo.registerService(localDevice.address());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BluetoothServer::stopServer()
|
||||
{
|
||||
foreach (QBluetoothSocket *client, m_clientList.values()) {
|
||||
client->close();
|
||||
}
|
||||
|
||||
m_server->close();
|
||||
m_server->deleteLater();
|
||||
m_server = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
43
server/bluetoothserver.h
Normal file
43
server/bluetoothserver.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef BLUETOOTHSERVER_H
|
||||
#define BLUETOOTHSERVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QBluetoothSocket>
|
||||
#include <QBluetoothServer>
|
||||
|
||||
#include "transportinterface.h"
|
||||
|
||||
namespace guhserver {
|
||||
|
||||
class BluetoothServer : public TransportInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BluetoothServer(QObject *parent = 0);
|
||||
~BluetoothServer();
|
||||
|
||||
static bool hardwareAvailable();
|
||||
|
||||
void sendData(const QUuid &clientId, const QVariantMap &data) override;
|
||||
void sendData(const QList<QUuid> &clients, const QVariantMap &data) override;
|
||||
|
||||
private:
|
||||
QBluetoothServer *m_server;
|
||||
QBluetoothServiceInfo m_serviceInfo;
|
||||
QHash<QUuid, QBluetoothSocket *> m_clientList;
|
||||
|
||||
private slots:
|
||||
void onClientConnected();
|
||||
void onClientDisconnected();
|
||||
void onError(QBluetoothSocket::SocketError error);
|
||||
void readData();
|
||||
|
||||
public slots:
|
||||
bool startServer() override;
|
||||
bool stopServer() override;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // BLUETOOTHSERVER_H
|
||||
@ -381,6 +381,11 @@ ServerManager *GuhCore::serverManager() const
|
||||
return m_serverManager;
|
||||
}
|
||||
|
||||
BluetoothServer *GuhCore::bluetoothServer() const
|
||||
{
|
||||
return m_bluetoothServer;
|
||||
}
|
||||
|
||||
#ifdef TESTING_ENABLED
|
||||
MockTcpServer *GuhCore::tcpServer() const
|
||||
{
|
||||
@ -427,10 +432,13 @@ GuhCore::GuhCore(QObject *parent) :
|
||||
|
||||
m_webSocketServer = new WebSocketServer(m_configuration->webSocketAddress(), m_configuration->webSocketPort(), m_configuration->sslEnabled(), this);
|
||||
|
||||
m_bluetoothServer = new BluetoothServer(this);
|
||||
|
||||
// Register transport interface in the JSON RPC server
|
||||
m_serverManager->jsonServer()->registerTransportInterface(m_tcpServer);
|
||||
m_serverManager->jsonServer()->registerTransportInterface(m_webSocketServer);
|
||||
m_serverManager->jsonServer()->registerTransportInterface(m_cloudManager);
|
||||
m_serverManager->jsonServer()->registerTransportInterface(m_bluetoothServer);
|
||||
|
||||
m_webServer = new WebServer(m_configuration->webServerAddress(), m_configuration->webServerPort(), m_configuration->webServerPublicFolder(), this);
|
||||
m_serverManager->restServer()->registerWebserver(m_webServer);
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#include "ruleengine.h"
|
||||
#include "servermanager.h"
|
||||
#include "websocketserver.h"
|
||||
#include "bluetoothserver.h"
|
||||
|
||||
#include "cloud/cloudmanager.h"
|
||||
#include "time/timemanager.h"
|
||||
@ -84,6 +85,7 @@ public:
|
||||
WebSocketServer *webSocketServer() const;
|
||||
CloudManager *cloudManager() const;
|
||||
ServerManager *serverManager() const;
|
||||
BluetoothServer *bluetoothServer() const;
|
||||
|
||||
|
||||
#ifdef TESTING_ENABLED
|
||||
@ -126,6 +128,8 @@ private:
|
||||
#endif
|
||||
WebSocketServer *m_webSocketServer;
|
||||
WebServer *m_webServer;
|
||||
BluetoothServer *m_bluetoothServer;
|
||||
|
||||
CloudManager *m_cloudManager;
|
||||
|
||||
QHash<ActionId, Action> m_pendingActions;
|
||||
|
||||
@ -5,6 +5,15 @@ HEADERS += $$top_srcdir/server/guhcore.h \
|
||||
$$top_srcdir/server/tcpserver.h \
|
||||
$$top_srcdir/server/ruleengine.h \
|
||||
$$top_srcdir/server/rule.h \
|
||||
$$top_srcdir/server/stateevaluator.h \
|
||||
$$top_srcdir/server/webserver.h \
|
||||
$$top_srcdir/server/transportinterface.h \
|
||||
$$top_srcdir/server/servermanager.h \
|
||||
$$top_srcdir/server/httprequest.h \
|
||||
$$top_srcdir/server/websocketserver.h \
|
||||
$$top_srcdir/server/httpreply.h \
|
||||
$$top_srcdir/server/guhconfiguration.h \
|
||||
$$top_srcdir/server/bluetoothserver.h \
|
||||
$$top_srcdir/server/jsonrpc/jsonrpcserver.h \
|
||||
$$top_srcdir/server/jsonrpc/jsonhandler.h \
|
||||
$$top_srcdir/server/jsonrpc/devicehandler.h \
|
||||
@ -53,6 +62,15 @@ SOURCES += $$top_srcdir/server/guhcore.cpp \
|
||||
$$top_srcdir/server/tcpserver.cpp \
|
||||
$$top_srcdir/server/ruleengine.cpp \
|
||||
$$top_srcdir/server/rule.cpp \
|
||||
$$top_srcdir/server/stateevaluator.cpp \
|
||||
$$top_srcdir/server/webserver.cpp \
|
||||
$$top_srcdir/server/transportinterface.cpp \
|
||||
$$top_srcdir/server/servermanager.cpp \
|
||||
$$top_srcdir/server/httprequest.cpp \
|
||||
$$top_srcdir/server/websocketserver.cpp \
|
||||
$$top_srcdir/server/httpreply.cpp \
|
||||
$$top_srcdir/server/guhconfiguration.cpp \
|
||||
$$top_srcdir/server/bluetoothserver.cpp \
|
||||
$$top_srcdir/server/jsonrpc/jsonrpcserver.cpp \
|
||||
$$top_srcdir/server/jsonrpc/jsonhandler.cpp \
|
||||
$$top_srcdir/server/jsonrpc/devicehandler.cpp \
|
||||
|
||||
@ -8,7 +8,7 @@ INCLUDEPATH += ../libguh jsonrpc
|
||||
target.path = /usr/bin
|
||||
INSTALLS += target
|
||||
|
||||
QT += sql xml websockets
|
||||
QT += sql xml websockets bluetooth
|
||||
|
||||
LIBS += -L$$top_builddir/libguh/ -lguh
|
||||
|
||||
|
||||
Reference in New Issue
Block a user