First working version containing rfcom connectivity

This commit is contained in:
Simon Stürz 2018-07-06 09:29:26 +02:00
parent 0e50c481fb
commit e84ff331fa
11 changed files with 61 additions and 37 deletions

View File

@ -34,6 +34,7 @@ BluetoothInterface::BluetoothInterface(QObject *parent) :
QObject::connect(m_socket, &QBluetoothSocket::connected, this, &BluetoothInterface::onConnected); QObject::connect(m_socket, &QBluetoothSocket::connected, this, &BluetoothInterface::onConnected);
QObject::connect(m_socket, &QBluetoothSocket::disconnected, this, &BluetoothInterface::onDisconnected); QObject::connect(m_socket, &QBluetoothSocket::disconnected, this, &BluetoothInterface::onDisconnected);
QObject::connect(m_socket, &QBluetoothSocket::readyRead, this, &BluetoothInterface::onDataReady); QObject::connect(m_socket, &QBluetoothSocket::readyRead, this, &BluetoothInterface::onDataReady);
QObject::connect(m_socket, &QBluetoothSocket::stateChanged, this, &BluetoothInterface::onDataReady);
} }
QStringList BluetoothInterface::supportedSchemes() const QStringList BluetoothInterface::supportedSchemes() const
@ -50,9 +51,10 @@ void BluetoothInterface::connect(const QUrl &url)
QUrlQuery query(url); QUrlQuery query(url);
QString macAddressString = query.queryItemValue("mac"); QString macAddressString = query.queryItemValue("mac");
QString name = query.queryItemValue("name");
QBluetoothAddress macAddress = QBluetoothAddress(macAddressString); QBluetoothAddress macAddress = QBluetoothAddress(macAddressString);
qDebug() << "Connecting to bluetooth server" << macAddressString << macAddress.toString(); qDebug() << "Connecting to bluetooth server" << name << macAddress.toString();
m_socket->connectToService(macAddress, QBluetoothUuid(QUuid("997936b5-d2cd-4c57-b41b-c6048320cd2b"))); m_socket->connectToService(macAddress, QBluetoothUuid(QUuid("997936b5-d2cd-4c57-b41b-c6048320cd2b")));
} }
@ -76,7 +78,8 @@ NymeaInterface::ConnectionState BluetoothInterface::connectionState() const
void BluetoothInterface::sendData(const QByteArray &data) void BluetoothInterface::sendData(const QByteArray &data)
{ {
m_socket->write(data + '\n'); qDebug() << "BluetoothInterface: send data:" << qUtf8Printable(data);
m_socket->write(data);
} }
void BluetoothInterface::onServiceFound(const QBluetoothServiceInfo &service) void BluetoothInterface::onServiceFound(const QBluetoothServiceInfo &service)
@ -101,8 +104,14 @@ void BluetoothInterface::onDisconnected()
emit disconnected(); emit disconnected();
} }
void BluetoothInterface::onStateChanged(const QBluetoothSocket::SocketState &state)
{
qDebug() << "BluetoothInterface" << state;
}
void BluetoothInterface::onDataReady() void BluetoothInterface::onDataReady()
{ {
QByteArray data = m_socket->readAll(); QByteArray data = m_socket->readAll();
qDebug() << "BluetoothInterface: recived data:" << qUtf8Printable(data);
emit dataReady(data); emit dataReady(data);
} }

View File

@ -49,6 +49,7 @@ private slots:
void onServiceFound(const QBluetoothServiceInfo &service); void onServiceFound(const QBluetoothServiceInfo &service);
void onConnected(); void onConnected();
void onDisconnected(); void onDisconnected();
void onStateChanged(const QBluetoothSocket::SocketState &state);
void onDataReady(); void onDataReady();
}; };

View File

@ -71,25 +71,24 @@ void BluetoothServiceDiscovery::onHostModeChanged(const QBluetoothLocalDevice::H
if (mode != QBluetoothLocalDevice::HostPoweredOff && m_enabed) { if (mode != QBluetoothLocalDevice::HostPoweredOff && m_enabed) {
qDebug() << "Bluetooth available again, continue discovery"; qDebug() << "Bluetooth available again, continue discovery";
m_serviceDiscovery->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); discover();
}
if (mode == QBluetoothLocalDevice::HostPoweredOff) {
qDebug() << "BluetoothServiceDiscovery: Bluetooth adapter disabled. Stop discovering";
m_serviceDiscovery->stop();
} }
} }
void BluetoothServiceDiscovery::onServiceDiscovered(const QBluetoothServiceInfo &serviceInfo) void BluetoothServiceDiscovery::onServiceDiscovered(const QBluetoothServiceInfo &serviceInfo)
{ {
qDebug() << "BluetoothServiceDiscovery: Service [+]" << serviceInfo.device().name() << serviceInfo.serviceName() << serviceInfo.serviceProvider(); qDebug() << "BluetoothServiceDiscovery: Discovered service on" << serviceInfo.device().name() << serviceInfo.device().address().toString();
qDebug() << "\tDevive name:" << serviceInfo.device().name();
qDebug() << "Discovered service on"
<< serviceInfo.device().name() << serviceInfo.device().address().toString();
qDebug() << "\tService name:" << serviceInfo.serviceName(); qDebug() << "\tService name:" << serviceInfo.serviceName();
qDebug() << "\tDescription:" qDebug() << "\tDescription:" << serviceInfo.attribute(QBluetoothServiceInfo::ServiceDescription).toString();
<< serviceInfo.attribute(QBluetoothServiceInfo::ServiceDescription).toString(); qDebug() << "\tProvider:" << serviceInfo.attribute(QBluetoothServiceInfo::ServiceProvider).toString();
qDebug() << "\tProvider:" qDebug() << "\tDocumentation:" << serviceInfo.attribute(QBluetoothServiceInfo::DocumentationUrl).toString();
<< serviceInfo.attribute(QBluetoothServiceInfo::ServiceProvider).toString(); qDebug() << "\tL2CAP protocol service multiplexer:" << serviceInfo.protocolServiceMultiplexer();
qDebug() << "\Documentation:"
<< serviceInfo.attribute(QBluetoothServiceInfo::DocumentationUrl).toString();
qDebug() << "\tL2CAP protocol service multiplexer:"
<< serviceInfo.protocolServiceMultiplexer();
qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel(); qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel();
if (serviceInfo.serviceClassUuids().isEmpty()) if (serviceInfo.serviceClassUuids().isEmpty())

View File

@ -128,11 +128,6 @@ QString DiscoveryDevice::toUrl(int portConfigIndex)
return ret; return ret;
} }
QString DiscoveryDevice::toUrl(const QString &hostAddress)
{
return QString("rfcom://%1").arg(hostAddress);
}
PortConfigs::PortConfigs(QObject *parent): QAbstractListModel(parent) PortConfigs::PortConfigs(QObject *parent): QAbstractListModel(parent)
{ {

View File

@ -134,7 +134,6 @@ public:
PortConfigs *portConfigs() const; PortConfigs *portConfigs() const;
Q_INVOKABLE QString toUrl(int portConfigIndex); Q_INVOKABLE QString toUrl(int portConfigIndex);
Q_INVOKABLE QString toUrl(const QString &hostAddress);
signals: signals:
void nameChanged(); void nameChanged();

View File

@ -38,7 +38,7 @@ QVariant DiscoveryModel::data(const QModelIndex &index, int role) const
DiscoveryDevice *device = m_devices.at(index.row()); DiscoveryDevice *device = m_devices.at(index.row());
switch (role) { switch (role) {
case TypeRole: case DeviceTypeRole:
return device->deviceType(); return device->deviceType();
case UuidRole: case UuidRole:
return device->uuid(); return device->uuid();
@ -112,7 +112,7 @@ void DiscoveryModel::clearModel()
QHash<int, QByteArray> DiscoveryModel::roleNames() const QHash<int, QByteArray> DiscoveryModel::roleNames() const
{ {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[TypeRole] = "type"; roles[DeviceTypeRole] = "deviceType";
roles[UuidRole] = "uuid"; roles[UuidRole] = "uuid";
roles[NameRole] = "name"; roles[NameRole] = "name";
roles[HostAddressRole] = "hostAddress"; roles[HostAddressRole] = "hostAddress";

View File

@ -32,7 +32,7 @@ class DiscoveryModel : public QAbstractListModel
Q_PROPERTY(int count READ rowCount NOTIFY countChanged) Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
public: public:
enum DeviceRole { enum DeviceRole {
TypeRole, DeviceTypeRole,
UuidRole, UuidRole,
NameRole, NameRole,
HostAddressRole, HostAddressRole,

View File

@ -267,6 +267,7 @@ void JsonRpcClient::onInterfaceConnectedChanged(bool connected)
void JsonRpcClient::dataReceived(const QByteArray &data) void JsonRpcClient::dataReceived(const QByteArray &data)
{ {
qDebug() << "JsonRpcClient: received data:" << qUtf8Printable(data);
m_receiveBuffer.append(data); m_receiveBuffer.append(data);
int splitIndex = m_receiveBuffer.indexOf("}\n{") + 1; int splitIndex = m_receiveBuffer.indexOf("}\n{") + 1;

View File

@ -37,6 +37,7 @@ void NymeaConnection::connect(const QString &url)
qWarning() << "Cannot connect to urls of scheme" << m_currentUrl.scheme() << "Supported schemes are" << m_interfaces.keys(); qWarning() << "Cannot connect to urls of scheme" << m_currentUrl.scheme() << "Supported schemes are" << m_interfaces.keys();
return; return;
} }
qDebug() << "Should connect to url" << m_currentUrl; qDebug() << "Should connect to url" << m_currentUrl;
m_currentInterface->connect(m_currentUrl); m_currentInterface->connect(m_currentUrl);
} }
@ -80,13 +81,19 @@ QString NymeaConnection::hostAddress() const
return m_currentUrl.host(); return m_currentUrl.host();
} }
QString NymeaConnection::bluetoothAddress() const
{
QUrlQuery query(m_currentUrl);
return query.queryItemValue("mac");
}
void NymeaConnection::sendData(const QByteArray &data) void NymeaConnection::sendData(const QByteArray &data)
{ {
if (connected()) { if (connected()) {
// qDebug() << "sending data:" << data; // qDebug() << "sending data:" << data;
m_currentInterface->sendData(data); m_currentInterface->sendData(data);
} else { } else {
qWarning() << "Not connected. Cannot send."; qWarning() << "Connection: Not connected. Cannot send.";
} }
} }
@ -150,7 +157,7 @@ void NymeaConnection::onConnected()
qWarning() << "An inactive interface is emitting signals... ignoring."; qWarning() << "An inactive interface is emitting signals... ignoring.";
return; return;
} }
qDebug() << "connected"; qDebug() << "NymeaConnection: connected.";
emit connectedChanged(true); emit connectedChanged(true);
} }
@ -161,7 +168,7 @@ void NymeaConnection::onDisconnected()
return; return;
} }
m_currentInterface = nullptr; m_currentInterface = nullptr;
qDebug() << "disconnected"; qDebug() << "NymeaConnection: disconnected.";
emit connectedChanged(false); emit connectedChanged(false);
} }

View File

@ -15,6 +15,7 @@ class NymeaConnection : public QObject
Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged) Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
Q_PROPERTY(QString url READ url NOTIFY connectedChanged) Q_PROPERTY(QString url READ url NOTIFY connectedChanged)
Q_PROPERTY(QString hostAddress READ hostAddress NOTIFY connectedChanged) Q_PROPERTY(QString hostAddress READ hostAddress NOTIFY connectedChanged)
Q_PROPERTY(QString bluetoothAddress READ bluetoothAddress NOTIFY connectedChanged)
public: public:
explicit NymeaConnection(QObject *parent = nullptr); explicit NymeaConnection(QObject *parent = nullptr);
@ -28,6 +29,7 @@ public:
QString url() const; QString url() const;
QString hostAddress() const; QString hostAddress() const;
QString bluetoothAddress() const;
void sendData(const QByteArray &data); void sendData(const QByteArray &data);

View File

@ -150,6 +150,11 @@ Page {
objectName: "discoveryDelegate" + index objectName: "discoveryDelegate" + index
property var discoveryDevice: discovery.discoveryModel.get(index) property var discoveryDevice: discovery.discoveryModel.get(index)
property string defaultPortConfigIndex: { property string defaultPortConfigIndex: {
if (model.deviceType !== DiscoveryDevice.DeviceTypeNetwork) {
return -1
}
var usedConfigIndex = 0; var usedConfigIndex = 0;
for (var i = 1; i < discoveryDevice.portConfigs.count; i++) { for (var i = 1; i < discoveryDevice.portConfigs.count; i++) {
var oldConfig = discoveryDevice.portConfigs.get(usedConfigIndex); var oldConfig = discoveryDevice.portConfigs.get(usedConfigIndex);
@ -172,18 +177,18 @@ Page {
return usedConfigIndex return usedConfigIndex
} }
iconName: model.type === DiscoveryDevice.DeviceTypeNetwork ? "../images/network-wifi-symbolic.svg" : "../images/bluetooth.svg" iconName: model.deviceType === DiscoveryDevice.DeviceTypeNetwork ? "../images/network-wifi-symbolic.svg" : "../images/bluetooth.svg"
text: model.name text: model.name
subText: model.type === DiscoveryDevice.DeviceTypeNetwork ? model.hostAddress : model.bluetoothAddress subText: model.deviceType === DiscoveryDevice.DeviceTypeNetwork ? discoveryDevice.hostAddress : discoveryDevice.bluetoothAddress
property bool hasSecurePort: { property bool hasSecurePort: {
if (model.type === DiscoveryDevice.DeviceTypeNetwork) { if (discoveryDevice.deviceType === DiscoveryDevice.DeviceTypeNetwork) {
return discoveryDeviceDelegate.discoveryDevice.portConfigs.get(discoveryDeviceDelegate.defaultPortConfigIndex).sslEnabled return discoveryDeviceDelegate.discoveryDevice.portConfigs.get(discoveryDeviceDelegate.defaultPortConfigIndex).sslEnabled
} else { } else {
return false return false
} }
} }
property bool isTrusted: { property bool isTrusted: {
if (model.type === DiscoveryDevice.DeviceTypeNetwork) { if (discoveryDeviceDelegate.discoveryDevice.deviceType === DiscoveryDevice.DeviceTypeNetwork) {
Engine.connection.isTrusted(discoveryDeviceDelegate.discoveryDevice.toUrl(discoveryDeviceDelegate.defaultPortConfigIndex)) Engine.connection.isTrusted(discoveryDeviceDelegate.discoveryDevice.toUrl(discoveryDeviceDelegate.defaultPortConfigIndex))
} else { } else {
return false return false
@ -192,13 +197,19 @@ Page {
progressive: hasSecurePort progressive: hasSecurePort
secondaryIconName: "../images/network-secure.svg" secondaryIconName: "../images/network-secure.svg"
secondaryIconColor: isTrusted ? app.guhAccent : Material.foreground secondaryIconColor: isTrusted ? app.guhAccent : Material.foreground
swipe.enabled: model.type === DiscoveryDevice.DeviceTypeNetwork swipe.enabled: discoveryDeviceDelegate.discoveryDevice.deviceType === DiscoveryDevice.DeviceTypeNetwork
onClicked: { onClicked: {
if (model.type === DiscoveryDevice.DeviceTypeNetwork) { switch (discoveryDeviceDelegate.discoveryDevice.deviceType) {
Engine.connection.connect(discoveryDevice.toUrl(defaultPortConfigIndex)) case DiscoveryDevice.DeviceTypeNetwork:
} else if (model.type === DiscoveryDevice.DeviceTypeBluetooth) { Engine.connection.connect(discoveryDeviceDelegate.discoveryDevice.toUrl(discoveryDeviceDelegate.defaultPortConfigIndex))
Engine.connection.connect("rfcom://bluetooth.local?mac=" + model.bluetoothAddress) break;
case DiscoveryDevice.DeviceTypeBluetooth:
Engine.connection.connect("rfcom://bluetooth.local?mac=" + model.bluetoothAddress + "&name=" + model.name)
break;
default:
console.warn("Could not connect, unknown type")
break;
} }
pageStack.push(connectingPage) pageStack.push(connectingPage)
@ -214,7 +225,7 @@ Page {
name: "../images/info.svg" name: "../images/info.svg"
} }
onClicked: { onClicked: {
if (model.type === DiscoveryDevice.DeviceTypeNetwork) { if (model.deviceType === DiscoveryDevice.DeviceTypeNetwork) {
swipe.close() swipe.close()
var popup = infoDialog.createObject(app,{discoveryDevice: discovery.discoveryModel.get(index)}) var popup = infoDialog.createObject(app,{discoveryDevice: discovery.discoveryModel.get(index)})
popup.open() popup.open()