Update bluetooth server
This commit is contained in:
parent
681b306b1b
commit
2231fd8f94
@ -1,6 +1,6 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
* Copyright (C) 2016-2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
* *
|
* *
|
||||||
* This file is part of nymea. *
|
* This file is part of nymea. *
|
||||||
* *
|
* *
|
||||||
@ -38,15 +38,14 @@
|
|||||||
#include "loggingcategories.h"
|
#include "loggingcategories.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QBluetoothLocalDevice>
|
|
||||||
|
|
||||||
namespace nymeaserver {
|
namespace nymeaserver {
|
||||||
|
|
||||||
static const QBluetoothUuid serviceUuid(QUuid("997936b5-d2cd-4c57-b41b-c6048320cd2b"));
|
static const QBluetoothUuid nymeaServiceUuid(QUuid("997936b5-d2cd-4c57-b41b-c6048320cd2b"));
|
||||||
|
|
||||||
/*! Constructs a \l{BluetoothServer} with the given \a parent. */
|
/*! Constructs a \l{BluetoothServer} with the given \a parent. */
|
||||||
BluetoothServer::BluetoothServer(QObject *parent) :
|
BluetoothServer::BluetoothServer(QObject *parent) :
|
||||||
TransportInterface(ServerConfiguration(), parent),
|
TransportInterface(ServerConfiguration(), parent)
|
||||||
m_server(0)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -54,9 +53,6 @@ BluetoothServer::BluetoothServer(QObject *parent) :
|
|||||||
/*! Destructs this \l{BluetoothServer}. */
|
/*! Destructs this \l{BluetoothServer}. */
|
||||||
BluetoothServer::~BluetoothServer()
|
BluetoothServer::~BluetoothServer()
|
||||||
{
|
{
|
||||||
if (m_server && m_server->isListening())
|
|
||||||
qCDebug(dcApplication) << "Shutting down \"Bluetooth server\"";
|
|
||||||
|
|
||||||
stopServer();
|
stopServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,8 +68,10 @@ void BluetoothServer::sendData(const QUuid &clientId, const QByteArray &data)
|
|||||||
{
|
{
|
||||||
QBluetoothSocket *client = 0;
|
QBluetoothSocket *client = 0;
|
||||||
client = m_clientList.value(clientId);
|
client = m_clientList.value(clientId);
|
||||||
if (client)
|
if (!client)
|
||||||
client->write(QJsonDocument::fromVariant(data).toJson(QJsonDocument::Compact) + '\n');
|
return;
|
||||||
|
|
||||||
|
client->write(data + '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Send the given \a data to the \a clients. */
|
/*! Send the given \a data to the \a clients. */
|
||||||
@ -83,6 +81,17 @@ void BluetoothServer::sendData(const QList<QUuid> &clients, const QByteArray &da
|
|||||||
sendData(client, data);
|
sendData(client, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::onHostModeChanged(const QBluetoothLocalDevice::HostMode &mode)
|
||||||
|
{
|
||||||
|
if (!m_server || !m_localDevice)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mode != QBluetoothLocalDevice::HostDiscoverable || QBluetoothLocalDevice::HostDiscoverableLimitedInquiry) {
|
||||||
|
m_localDevice->powerOn();
|
||||||
|
m_localDevice->setHostMode(QBluetoothLocalDevice::HostDiscoverableLimitedInquiry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BluetoothServer::onClientConnected()
|
void BluetoothServer::onClientConnected()
|
||||||
{
|
{
|
||||||
// Got a new client connected
|
// Got a new client connected
|
||||||
@ -90,7 +99,7 @@ void BluetoothServer::onClientConnected()
|
|||||||
if (!client)
|
if (!client)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qCDebug(dcConnection) << "Bluetooth server: new client connected:" << client->localName() << client->localAddress().toString();
|
qCDebug(dcConnection) << "BluetoothServer: New client connected:" << client->localName() << client->localAddress().toString();
|
||||||
|
|
||||||
QUuid clientId = QUuid::createUuid();
|
QUuid clientId = QUuid::createUuid();
|
||||||
m_clientList.insert(clientId, client);
|
m_clientList.insert(clientId, client);
|
||||||
@ -108,14 +117,14 @@ void BluetoothServer::onClientDisconnected()
|
|||||||
if (!client)
|
if (!client)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qCDebug(dcConnection) << "Bluetooth server: client disconnected:" << client->localName() << client->localAddress().toString();
|
qCDebug(dcConnection) << "BluetoothServer: Client disconnected:" << client->localName() << client->localAddress().toString();
|
||||||
QUuid clientId = m_clientList.key(client);
|
QUuid clientId = m_clientList.key(client);
|
||||||
m_clientList.take(clientId)->deleteLater();
|
m_clientList.take(clientId)->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BluetoothServer::onError(QBluetoothSocket::SocketError error)
|
void BluetoothServer::onError(QBluetoothSocket::SocketError error)
|
||||||
{
|
{
|
||||||
qCWarning(dcConnection) << "Bluetooth server error:" << error;
|
qCWarning(dcConnection) << "BluetoothServer: Error occured:" << error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BluetoothServer::readData()
|
void BluetoothServer::readData()
|
||||||
@ -124,42 +133,51 @@ void BluetoothServer::readData()
|
|||||||
if (!client)
|
if (!client)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QByteArray message;
|
m_receiveBuffer.append(client->readAll());
|
||||||
while (client->canReadLine()) {
|
int splitIndex = m_receiveBuffer.indexOf("}\n{");
|
||||||
QByteArray dataLine = client->readLine();
|
while (splitIndex > -1) {
|
||||||
message.append(dataLine);
|
emit dataAvailable(m_clientList.key(client), m_receiveBuffer.left(splitIndex + 1));
|
||||||
if (dataLine.endsWith('\n')) {
|
m_receiveBuffer = m_receiveBuffer.right(m_receiveBuffer.length() - splitIndex - 2);
|
||||||
qCDebug(dcConnection()) << "Bluetooth data received:" << message;
|
splitIndex = m_receiveBuffer.indexOf("}\n{");
|
||||||
emit dataAvailable(m_clientList.key(client), message);
|
}
|
||||||
message.clear();
|
if (m_receiveBuffer.endsWith("}\n")) {
|
||||||
}
|
emit dataAvailable(m_clientList.key(client), m_receiveBuffer);
|
||||||
|
m_receiveBuffer.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BluetoothServer::startServer()
|
bool BluetoothServer::startServer()
|
||||||
{
|
{
|
||||||
if (m_server)
|
if (m_server && m_localDevice)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Check if Bluetooth is available on this device
|
m_localDevice = new QBluetoothLocalDevice(this);
|
||||||
QBluetoothLocalDevice localDevice;
|
if (!m_localDevice->isValid()) {
|
||||||
if (localDevice.isValid()) {
|
qCWarning(dcConnection()) << "BluetoothServer: could find any bluetooth hardware";
|
||||||
qCDebug(dcConnection()) << "Bluetooth: using adapter" << localDevice.name() << localDevice.address().toString();
|
delete m_localDevice;
|
||||||
localDevice.powerOn();
|
m_localDevice = nullptr;
|
||||||
localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
|
|
||||||
} else {
|
|
||||||
qCWarning(dcConnection()) << "Bluetooth server: could find any bluetooth hardware";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init adapter
|
||||||
|
qCDebug(dcConnection()) << "BluetoothServer: Using adapter" << m_localDevice->name() << m_localDevice->address().toString();
|
||||||
|
m_localDevice->powerOn();
|
||||||
|
m_localDevice->setHostMode(QBluetoothLocalDevice::HostDiscoverableLimitedInquiry);
|
||||||
|
connect(m_localDevice, &QBluetoothLocalDevice::hostModeStateChanged, this, &BluetoothServer::onHostModeChanged);
|
||||||
|
|
||||||
|
// Init bluetooth server
|
||||||
m_server = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this);
|
m_server = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this);
|
||||||
connect(m_server, SIGNAL(newConnection()), this, SLOT(onClientConnected()));
|
connect(m_server, SIGNAL(newConnection()), this, SLOT(onClientConnected()));
|
||||||
if (!m_server->listen(localDevice.address())) {
|
if (!m_server->listen(m_localDevice->address())) {
|
||||||
qCWarning(dcConnection()) << "Bluetooth server: could not listen on local device." << localDevice.name();
|
qCWarning(dcConnection()) << "BluetoothServer: Could not listen on local device." << m_localDevice->name();
|
||||||
|
delete m_localDevice;
|
||||||
|
delete m_server;
|
||||||
|
m_localDevice = nullptr;
|
||||||
|
m_server = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcConnection) << "Started bluetooth server" << m_server->serverAddress().toString();
|
qCDebug(dcConnection) << "BluetoothServer: Started bluetooth server" << m_server->serverAddress().toString();
|
||||||
|
|
||||||
// Set service attributes
|
// Set service attributes
|
||||||
QBluetoothServiceInfo::Sequence browseSequence;
|
QBluetoothServiceInfo::Sequence browseSequence;
|
||||||
@ -169,14 +187,14 @@ bool BluetoothServer::startServer()
|
|||||||
QBluetoothServiceInfo::Sequence classId;
|
QBluetoothServiceInfo::Sequence classId;
|
||||||
classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
|
classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
|
||||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, classId);
|
m_serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, classId);
|
||||||
classId.prepend(QVariant::fromValue(serviceUuid));
|
classId.prepend(QVariant::fromValue(nymeaServiceUuid));
|
||||||
|
|
||||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
|
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
|
||||||
|
m_serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, classId);
|
||||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList,classId);
|
|
||||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, QVariant("nymea"));
|
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, QVariant("nymea"));
|
||||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription, QVariant("The JSON-RPC interface for nymea."));
|
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription, QVariant("The JSON-RPC interface for nymea."));
|
||||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, QVariant("https://nymea.io"));
|
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, QVariant("https://nymea.io"));
|
||||||
|
m_serviceInfo.setAttribute(QBluetoothServiceInfo::DocumentationUrl, QVariant("https://doc.nymea.io/jsonrpc.html"));
|
||||||
|
|
||||||
// Define protocol
|
// Define protocol
|
||||||
QBluetoothServiceInfo::Sequence protocolDescriptorList;
|
QBluetoothServiceInfo::Sequence protocolDescriptorList;
|
||||||
@ -187,15 +205,19 @@ bool BluetoothServer::startServer()
|
|||||||
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList);
|
m_serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList);
|
||||||
|
|
||||||
// Set UUID
|
// Set UUID
|
||||||
m_serviceInfo.setServiceUuid(serviceUuid);
|
m_serviceInfo.setServiceUuid(nymeaServiceUuid);
|
||||||
|
|
||||||
// Register the service in the local device
|
// Register the service in the local device
|
||||||
if (!m_serviceInfo.registerService(localDevice.address())) {
|
if (!m_serviceInfo.registerService(m_localDevice->address())) {
|
||||||
qCWarning(dcConnection()) << "Bluetooth: Could not register service" << m_serviceInfo.serviceName() << serviceUuid.toString();
|
qCWarning(dcConnection()) << "BluetoothServer: Could not register service" << m_serviceInfo.serviceName() << nymeaServiceUuid.toString();
|
||||||
|
delete m_localDevice;
|
||||||
|
delete m_server;
|
||||||
|
m_localDevice = nullptr;
|
||||||
|
m_server = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcConnection()) << "Bluetooth: Registered successfully service" << m_serviceInfo.serviceName() << serviceUuid.toString();
|
qCDebug(dcConnection()) << "BluetoothServer: Registered successfully service" << m_serviceInfo.serviceName() << nymeaServiceUuid.toString();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,14 +227,20 @@ bool BluetoothServer::stopServer()
|
|||||||
client->close();
|
client->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_server)
|
if (m_server) {
|
||||||
return true;
|
qCDebug(dcBluetooth()) << "Shutting down \"Bluetooth server\"";
|
||||||
|
m_serviceInfo.unregisterService();
|
||||||
|
m_server->close();
|
||||||
|
m_server->deleteLater();
|
||||||
|
m_server = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
m_serviceInfo.unregisterService();
|
if (m_localDevice) {
|
||||||
|
m_localDevice->deleteLater();
|
||||||
|
m_localDevice = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
m_server->close();
|
m_receiveBuffer.clear();
|
||||||
m_server->deleteLater();
|
|
||||||
m_server = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
* Copyright (C) 2016-2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
* *
|
* *
|
||||||
* This file is part of nymea. *
|
* This file is part of nymea. *
|
||||||
* *
|
* *
|
||||||
@ -24,6 +24,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QBluetoothSocket>
|
#include <QBluetoothSocket>
|
||||||
#include <QBluetoothServer>
|
#include <QBluetoothServer>
|
||||||
|
#include <QBluetoothLocalDevice>
|
||||||
|
|
||||||
#include "transportinterface.h"
|
#include "transportinterface.h"
|
||||||
|
|
||||||
@ -42,11 +43,17 @@ public:
|
|||||||
void sendData(const QList<QUuid> &clients, const QByteArray &data) override;
|
void sendData(const QList<QUuid> &clients, const QByteArray &data) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QBluetoothServer *m_server;
|
QBluetoothServer *m_server = nullptr;
|
||||||
|
QBluetoothLocalDevice *m_localDevice = nullptr;
|
||||||
QBluetoothServiceInfo m_serviceInfo;
|
QBluetoothServiceInfo m_serviceInfo;
|
||||||
|
|
||||||
|
// Client storage
|
||||||
QHash<QUuid, QBluetoothSocket *> m_clientList;
|
QHash<QUuid, QBluetoothSocket *> m_clientList;
|
||||||
|
QByteArray m_receiveBuffer;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void onHostModeChanged(const QBluetoothLocalDevice::HostMode &mode);
|
||||||
|
|
||||||
void onClientConnected();
|
void onClientConnected();
|
||||||
void onClientDisconnected();
|
void onClientDisconnected();
|
||||||
void onError(QBluetoothSocket::SocketError error);
|
void onError(QBluetoothSocket::SocketError error);
|
||||||
|
|||||||
Reference in New Issue
Block a user