a lot of cleanup

This commit is contained in:
Michael Zanetti 2018-08-05 16:03:26 +02:00
parent d5839a5229
commit 383eb2f682
36 changed files with 485 additions and 424 deletions

3
.gitmodules vendored
View File

@ -4,3 +4,6 @@
[submodule "aws-sdk-qt"] [submodule "aws-sdk-qt"]
path = aws-sdk-qt path = aws-sdk-qt
url = https://github.com/pcolby/aws-sdk-qt.git url = https://github.com/pcolby/aws-sdk-qt.git
[submodule "qmqtt"]
path = qmqtt
url = https://github.com/emqtt/qmqtt.git

View File

@ -93,7 +93,7 @@ void AWSClient::initiateAuthReply()
qDebug() << "AWS login successful"; qDebug() << "AWS login successful";
emit isLoggedInChanged(); emit isLoggedInChanged();
return; // Why should we call GetId? Ask Luca // return; // Why should we call GetId? Ask Luca
QUrl url("https://cognito-identity.eu-west-1.amazonaws.com/"); QUrl url("https://cognito-identity.eu-west-1.amazonaws.com/");
@ -131,6 +131,7 @@ void AWSClient::getIdReply()
void AWSClient::fetchDevices() void AWSClient::fetchDevices()
{ {
qDebug() << "Fetching cloud devices";
QUrl url("https://z6368zhf2m.execute-api.eu-west-1.amazonaws.com/dev/devices"); QUrl url("https://z6368zhf2m.execute-api.eu-west-1.amazonaws.com/dev/devices");
QNetworkRequest request(url); QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
@ -162,3 +163,8 @@ void AWSClient::fetchDevices()
}); });
} }
QByteArray AWSClient::accessToken() const
{
return m_accessToken;
}

View File

@ -28,6 +28,8 @@ public:
Q_INVOKABLE void fetchDevices(); Q_INVOKABLE void fetchDevices();
QByteArray accessToken() const;
signals: signals:
void isLoggedInChanged(); void isLoggedInChanged();

View File

@ -20,29 +20,29 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "bluetoothinterface.h" #include "bluetoothtransport.h"
#include <QUrl> #include <QUrl>
#include <QDebug> #include <QDebug>
#include <QUrlQuery> #include <QUrlQuery>
BluetoothInterface::BluetoothInterface(QObject *parent) : BluetoothTransport::BluetoothTransport(QObject *parent) :
NymeaInterface(parent) NymeaTransportInterface(parent)
{ {
m_socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); m_socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
QObject::connect(m_socket, &QBluetoothSocket::connected, this, &BluetoothInterface::onConnected); QObject::connect(m_socket, &QBluetoothSocket::connected, this, &BluetoothTransport::onConnected);
QObject::connect(m_socket, &QBluetoothSocket::disconnected, this, &BluetoothInterface::onDisconnected); QObject::connect(m_socket, &QBluetoothSocket::disconnected, this, &BluetoothTransport::onDisconnected);
QObject::connect(m_socket, &QBluetoothSocket::readyRead, this, &BluetoothInterface::onDataReady); QObject::connect(m_socket, &QBluetoothSocket::readyRead, this, &BluetoothTransport::onDataReady);
QObject::connect(m_socket, &QBluetoothSocket::stateChanged, this, &BluetoothInterface::onDataReady); QObject::connect(m_socket, &QBluetoothSocket::stateChanged, this, &BluetoothTransport::onDataReady);
} }
QStringList BluetoothInterface::supportedSchemes() const QStringList BluetoothTransport::supportedSchemes() const
{ {
return {"rfcom"}; return {"rfcom"};
} }
void BluetoothInterface::connect(const QUrl &url) void BluetoothTransport::connect(const QUrl &url)
{ {
if (url.scheme() != "rfcom") { if (url.scheme() != "rfcom") {
qWarning() << "BluetoothInterface: Cannot connect. Invalid scheme in url" << url.toString(); qWarning() << "BluetoothInterface: Cannot connect. Invalid scheme in url" << url.toString();
@ -58,31 +58,31 @@ void BluetoothInterface::connect(const QUrl &url)
m_socket->connectToService(macAddress, QBluetoothUuid(QUuid("997936b5-d2cd-4c57-b41b-c6048320cd2b"))); m_socket->connectToService(macAddress, QBluetoothUuid(QUuid("997936b5-d2cd-4c57-b41b-c6048320cd2b")));
} }
void BluetoothInterface::disconnect() void BluetoothTransport::disconnect()
{ {
m_socket->close(); m_socket->close();
} }
NymeaInterface::ConnectionState BluetoothInterface::connectionState() const NymeaTransportInterface::ConnectionState BluetoothTransport::connectionState() const
{ {
switch (m_socket->state()) { switch (m_socket->state()) {
case QBluetoothSocket::ConnectedState: case QBluetoothSocket::ConnectedState:
return NymeaInterface::ConnectionStateConnected; return NymeaTransportInterface::ConnectionStateConnected;
case QBluetoothSocket::ConnectingState: case QBluetoothSocket::ConnectingState:
case QBluetoothSocket::ServiceLookupState: case QBluetoothSocket::ServiceLookupState:
return NymeaInterface::ConnectionStateConnecting; return NymeaTransportInterface::ConnectionStateConnecting;
default: default:
return NymeaInterface::ConnectionStateDisconnected; return NymeaTransportInterface::ConnectionStateDisconnected;
} }
} }
void BluetoothInterface::sendData(const QByteArray &data) void BluetoothTransport::sendData(const QByteArray &data)
{ {
qDebug() << "BluetoothInterface: send data:" << qUtf8Printable(data); qDebug() << "BluetoothInterface: send data:" << qUtf8Printable(data);
m_socket->write(data); m_socket->write(data);
} }
void BluetoothInterface::onServiceFound(const QBluetoothServiceInfo &service) void BluetoothTransport::onServiceFound(const QBluetoothServiceInfo &service)
{ {
m_service = service; m_service = service;
if (m_socket->isOpen()) if (m_socket->isOpen())
@ -92,24 +92,24 @@ void BluetoothInterface::onServiceFound(const QBluetoothServiceInfo &service)
m_socket->connectToService(m_service); m_socket->connectToService(m_service);
} }
void BluetoothInterface::onConnected() void BluetoothTransport::onConnected()
{ {
qDebug() << "BluetoothInterface: connected" << m_socket->peerName() << m_socket->peerAddress(); qDebug() << "BluetoothInterface: connected" << m_socket->peerName() << m_socket->peerAddress();
emit connected(); emit connected();
} }
void BluetoothInterface::onDisconnected() void BluetoothTransport::onDisconnected()
{ {
qDebug() << "BluetoothInterface: disconnected" << m_socket->peerName() << m_socket->peerAddress(); qDebug() << "BluetoothInterface: disconnected" << m_socket->peerName() << m_socket->peerAddress();
emit disconnected(); emit disconnected();
} }
void BluetoothInterface::onStateChanged(const QBluetoothSocket::SocketState &state) void BluetoothTransport::onStateChanged(const QBluetoothSocket::SocketState &state)
{ {
qDebug() << "BluetoothInterface" << state; qDebug() << "BluetoothInterface" << state;
} }
void BluetoothInterface::onDataReady() void BluetoothTransport::onDataReady()
{ {
QByteArray data = m_socket->readAll(); QByteArray data = m_socket->readAll();
qDebug() << "BluetoothInterface: recived data:" << qUtf8Printable(data); qDebug() << "BluetoothInterface: recived data:" << qUtf8Printable(data);

View File

@ -20,19 +20,19 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef BLUETOOTHINTERFACE_H #ifndef BLUETOOTHTRANSPORT_H
#define BLUETOOTHINTERFACE_H #define BLUETOOTHTRANSPORT_H
#include <QObject> #include <QObject>
#include <QBluetoothSocket> #include <QBluetoothSocket>
#include "nymeainterface.h" #include "nymeatransportinterface.h"
class BluetoothInterface : public NymeaInterface class BluetoothTransport: public NymeaTransportInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit BluetoothInterface(QObject *parent = nullptr); explicit BluetoothTransport(QObject *parent = nullptr);
QStringList supportedSchemes() const override; QStringList supportedSchemes() const override;
@ -53,4 +53,4 @@ private slots:
void onDataReady(); void onDataReady();
}; };
#endif // BLUETOOTHINTERFACE_H #endif // BLUETOOTHTRANSPROT_H

View File

@ -0,0 +1,63 @@
#include "cloudtransport.h"
#include "qmqtt.h"
CloudTransport::CloudTransport(AWSClient *awsClient, QObject *parent):
NymeaTransportInterface(parent),
m_awsClient(awsClient)
{
}
QStringList CloudTransport::supportedSchemes() const
{
return {"cloud"};
}
void CloudTransport::connect(const QUrl &url)
{
qDebug() << "should connect to" << url;
QString date = QDateTime::currentDateTime().toString("yyyyMMddThhmmssZ");
QString region = "eu-west-1";
QString service = "iotdevicegateway";
QString credentialScope = date + '/' + region + '/' + service + '/' + "aws4_request";
QString algorithm = "AWS4-HMAC-SHA256";
QString canonicalQuerystring = "X-Amz-Algorithm=" + algorithm;
// canonicalQuerystring += "&X-Amz-Credential=" + QByteArray(credentials.accessKeyId + '/' + credentialScope).toPercentageEncoded();
// '&X-Amz-Security-Token=' + encodeURIComponent(credentials.sessionToken);
QString requestUrl = "wss://a2addxakg5juii.iot.eu-west-1.amazonaws.com/mqtt?" + canonicalQuerystring;
m_mqttClient = new QMQTT::Client(requestUrl, 443, QWebSocketProtocol::VersionLatest, true, this);
QObject::connect(m_mqttClient, &QMQTT::Client::connected, this, [](){
qDebug() << "MQTT connected";
});
QObject::connect(m_mqttClient, &QMQTT::Client::disconnected, this, []() {
qDebug() << "MQTT disconnected";
});
QObject::connect(m_mqttClient, &QMQTT::Client::error, this, [](QMQTT::ClientError error) {
qDebug() << "MQTT error" << error << QMQTT::ClientError::SocketHostNotFoundError;
});
m_mqttClient->setUsername("michael.zanetti@guh.io");
m_mqttClient->setPassword("H22*gemmmmm");
m_mqttClient->setClientId("8rjhfdlf9jf1suok2jcrltd6v");
m_mqttClient->connectToHost();
}
void CloudTransport::disconnect()
{
qDebug() << "should disconnect";
}
NymeaTransportInterface::ConnectionState CloudTransport::connectionState() const
{
return ConnectionStateDisconnected;
}
void CloudTransport::sendData(const QByteArray &data)
{
qDebug() << "should send" << data;
}

View File

@ -0,0 +1,31 @@
#ifndef CLOUDTRANSPORT_H
#define CLOUDTRANSPORT_H
#include "nymeatransportinterface.h"
#include <QObject>
namespace QMQTT {
class Client;
}
class AWSClient;
class CloudTransport : public NymeaTransportInterface
{
Q_OBJECT
public:
explicit CloudTransport(AWSClient *awsClient, QObject *parent = nullptr);
QStringList supportedSchemes() const override;
void connect(const QUrl &url) override;
void disconnect() override;
ConnectionState connectionState() const override;
void sendData(const QByteArray &data) override;
private:
QMQTT::Client *m_mqttClient = nullptr;
AWSClient *m_awsClient = nullptr;
};
#endif // CLOUDTRANSPORT_H

View File

@ -7,21 +7,10 @@
#include <QSettings> #include <QSettings>
#include <QMetaEnum> #include <QMetaEnum>
#include "nymeainterface.h" #include "nymeatransportinterface.h"
#include "tcpsocketinterface.h"
#include "websocketinterface.h"
#include "bluetoothinterface.h"
NymeaConnection::NymeaConnection(QObject *parent) : QObject(parent) NymeaConnection::NymeaConnection(QObject *parent) : QObject(parent)
{ {
NymeaInterface *iface = new TcpSocketInterface(this);
registerInterface(iface);
iface = new WebsocketInterface(this);
registerInterface(iface);
iface = new BluetoothInterface(this);
registerInterface(iface);
} }
void NymeaConnection::connect(const QString &url) void NymeaConnection::connect(const QString &url)
@ -32,23 +21,23 @@ void NymeaConnection::connect(const QString &url)
} }
m_currentUrl = QUrl(url); m_currentUrl = QUrl(url);
m_currentInterface = m_interfaces.value(m_currentUrl.scheme()); m_currentTransport = m_transports.value(m_currentUrl.scheme());
if (!m_currentInterface) { if (!m_currentTransport) {
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_transports.keys();
return; return;
} }
qDebug() << "Should connect to url" << m_currentUrl; qDebug() << "Should connect to url" << m_currentUrl;
m_currentInterface->connect(m_currentUrl); m_currentTransport->connect(m_currentUrl);
} }
void NymeaConnection::disconnect() void NymeaConnection::disconnect()
{ {
if (!m_currentInterface || m_currentInterface->connectionState() == NymeaInterface::ConnectionStateDisconnected) { if (!m_currentTransport || m_currentTransport->connectionState() == NymeaTransportInterface::ConnectionStateDisconnected) {
qWarning() << "not connected, cannot disconnect"; qWarning() << "not connected, cannot disconnect";
return; return;
} }
m_currentInterface->disconnect(); m_currentTransport->disconnect();
} }
void NymeaConnection::acceptCertificate(const QString &url, const QByteArray &fingerprint) void NymeaConnection::acceptCertificate(const QString &url, const QByteArray &fingerprint)
@ -68,7 +57,7 @@ bool NymeaConnection::isTrusted(const QString &url)
bool NymeaConnection::connected() bool NymeaConnection::connected()
{ {
return m_currentInterface && m_currentInterface->connectionState() == NymeaInterface::ConnectionStateConnected; return m_currentTransport && m_currentTransport->connectionState() == NymeaTransportInterface::ConnectionStateConnected;
} }
QString NymeaConnection::url() const QString NymeaConnection::url() const
@ -91,7 +80,7 @@ void NymeaConnection::sendData(const QByteArray &data)
{ {
if (connected()) { if (connected()) {
// qDebug() << "sending data:" << data; // qDebug() << "sending data:" << data;
m_currentInterface->sendData(data); m_currentTransport->sendData(data);
} else { } else {
qWarning() << "Connection: Not connected. Cannot send."; qWarning() << "Connection: Not connected. Cannot send.";
} }
@ -142,7 +131,7 @@ void NymeaConnection::onSslErrors(const QList<QSslError> &errors)
qDebug() << "SSL Error:" << error.errorString() << error.certificate(); qDebug() << "SSL Error:" << error.errorString() << error.certificate();
} }
} }
m_currentInterface->ignoreSslErrors(ignoredErrors); m_currentTransport->ignoreSslErrors(ignoredErrors);
} }
void NymeaConnection::onError(QAbstractSocket::SocketError error) void NymeaConnection::onError(QAbstractSocket::SocketError error)
@ -153,8 +142,8 @@ void NymeaConnection::onError(QAbstractSocket::SocketError error)
void NymeaConnection::onConnected() void NymeaConnection::onConnected()
{ {
if (m_currentInterface != sender()) { if (m_currentTransport != sender()) {
qWarning() << "An inactive interface is emitting signals... ignoring."; qWarning() << "NymeaConnection: An inactive transport is emitting signals... ignoring.";
return; return;
} }
qDebug() << "NymeaConnection: connected."; qDebug() << "NymeaConnection: connected.";
@ -163,26 +152,26 @@ void NymeaConnection::onConnected()
void NymeaConnection::onDisconnected() void NymeaConnection::onDisconnected()
{ {
if (m_currentInterface != sender()) { if (m_currentTransport != sender()) {
qWarning() << "An inactive interface is emitting signals... ignoring."; qWarning() << "NymeaConnection: An inactive transport is emitting signals... ignoring.";
return; return;
} }
m_currentInterface = nullptr; m_currentTransport = nullptr;
qDebug() << "NymeaConnection: disconnected."; qDebug() << "NymeaConnection: disconnected.";
emit connectedChanged(false); emit connectedChanged(false);
} }
void NymeaConnection::registerInterface(NymeaInterface *iface) void NymeaConnection::registerTransport(NymeaTransportInterface *transport)
{ {
QObject::connect(iface, &NymeaInterface::sslErrors, this, &NymeaConnection::onSslErrors); QObject::connect(transport, &NymeaTransportInterface::sslErrors, this, &NymeaConnection::onSslErrors);
QObject::connect(iface, &NymeaInterface::error, this, &NymeaConnection::onError); QObject::connect(transport, &NymeaTransportInterface::error, this, &NymeaConnection::onError);
QObject::connect(iface, &NymeaInterface::connected, this, &NymeaConnection::onConnected); QObject::connect(transport, &NymeaTransportInterface::connected, this, &NymeaConnection::onConnected);
QObject::connect(iface, &NymeaInterface::disconnected, this, &NymeaConnection::onDisconnected); QObject::connect(transport, &NymeaTransportInterface::disconnected, this, &NymeaConnection::onDisconnected);
// signal forwarding // signal forwarding
QObject::connect(iface, &NymeaInterface::dataReady, this, &NymeaConnection::dataAvailable); QObject::connect(transport, &NymeaTransportInterface::dataReady, this, &NymeaConnection::dataAvailable);
foreach (const QString &scheme, iface->supportedSchemes()) { foreach (const QString &scheme, transport->supportedSchemes()) {
m_interfaces[scheme] = iface; m_transports[scheme] = transport;
} }
} }

View File

@ -7,7 +7,7 @@
#include <QAbstractSocket> #include <QAbstractSocket>
#include <QUrl> #include <QUrl>
class NymeaInterface; class NymeaTransportInterface;
class NymeaConnection : public QObject class NymeaConnection : public QObject
{ {
@ -20,6 +20,8 @@ class NymeaConnection : public QObject
public: public:
explicit NymeaConnection(QObject *parent = nullptr); explicit NymeaConnection(QObject *parent = nullptr);
void registerTransport(NymeaTransportInterface *transport);
Q_INVOKABLE void connect(const QString &url); Q_INVOKABLE void connect(const QString &url);
Q_INVOKABLE void disconnect(); Q_INVOKABLE void disconnect();
Q_INVOKABLE void acceptCertificate(const QString &url, const QByteArray &fingerprint); Q_INVOKABLE void acceptCertificate(const QString &url, const QByteArray &fingerprint);
@ -46,11 +48,10 @@ private slots:
void onDisconnected(); void onDisconnected();
private: private:
void registerInterface(NymeaInterface *iface);
private: private:
QHash<QString, NymeaInterface*> m_interfaces; QHash<QString, NymeaTransportInterface*> m_transports;
NymeaInterface *m_currentInterface = nullptr; NymeaTransportInterface *m_currentTransport = nullptr;
QUrl m_currentUrl; QUrl m_currentUrl;
}; };

View File

@ -20,10 +20,10 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "nymeainterface.h" #include "nymeatransportinterface.h"
#include <QSettings> #include <QSettings>
NymeaInterface::NymeaInterface(QObject *parent) : NymeaTransportInterface::NymeaTransportInterface(QObject *parent) :
QObject(parent) QObject(parent)
{ {

View File

@ -20,14 +20,14 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef NYMEAINTERFACE_H #ifndef NYMEATRANSPORTINTERFACE_H
#define NYMEAINTERFACE_H #define NYMEATRANSPORTINTERFACE_H
#include <QObject> #include <QObject>
#include <QSslCertificate> #include <QSslCertificate>
#include <QHostAddress> #include <QHostAddress>
class NymeaInterface : public QObject class NymeaTransportInterface : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -38,7 +38,8 @@ public:
}; };
Q_ENUM(ConnectionState) Q_ENUM(ConnectionState)
explicit NymeaInterface(QObject *parent = 0); explicit NymeaTransportInterface(QObject *parent = nullptr);
virtual ~NymeaTransportInterface() = default;
virtual QStringList supportedSchemes() const = 0; virtual QStringList supportedSchemes() const = 0;
@ -56,4 +57,4 @@ signals:
void dataReady(const QByteArray &data); void dataReady(const QByteArray &data);
}; };
#endif // NYMEAINTERFACE_H #endif // NYMEATRANSPORTINTERFACE_H

View File

@ -1,27 +1,27 @@
#include "tcpsocketinterface.h" #include "tcpsockettransport.h"
#include <QUrl> #include <QUrl>
TcpSocketInterface::TcpSocketInterface(QObject *parent) : NymeaInterface(parent) TcpSocketTransport::TcpSocketTransport(QObject *parent) : NymeaTransportInterface(parent)
{ {
QObject::connect(&m_socket, &QSslSocket::connected, this, &TcpSocketInterface::onConnected); QObject::connect(&m_socket, &QSslSocket::connected, this, &TcpSocketTransport::onConnected);
QObject::connect(&m_socket, &QSslSocket::disconnected, this, &TcpSocketInterface::disconnected); QObject::connect(&m_socket, &QSslSocket::disconnected, this, &TcpSocketTransport::disconnected);
QObject::connect(&m_socket, &QSslSocket::encrypted, this, &TcpSocketInterface::onEncrypted); QObject::connect(&m_socket, &QSslSocket::encrypted, this, &TcpSocketTransport::onEncrypted);
typedef void (QSslSocket:: *sslErrorsSignal)(const QList<QSslError> &); typedef void (QSslSocket:: *sslErrorsSignal)(const QList<QSslError> &);
QObject::connect(&m_socket, static_cast<sslErrorsSignal>(&QSslSocket::sslErrors), this, &TcpSocketInterface::sslErrors); QObject::connect(&m_socket, static_cast<sslErrorsSignal>(&QSslSocket::sslErrors), this, &TcpSocketTransport::sslErrors);
QObject::connect(&m_socket, &QSslSocket::readyRead, this, &TcpSocketInterface::socketReadyRead); QObject::connect(&m_socket, &QSslSocket::readyRead, this, &TcpSocketTransport::socketReadyRead);
typedef void (QSslSocket:: *errorSignal)(QAbstractSocket::SocketError); typedef void (QSslSocket:: *errorSignal)(QAbstractSocket::SocketError);
QObject::connect(&m_socket, static_cast<errorSignal>(&QSslSocket::error), this, &TcpSocketInterface::error); QObject::connect(&m_socket, static_cast<errorSignal>(&QSslSocket::error), this, &TcpSocketTransport::error);
QObject::connect(&m_socket, &QSslSocket::stateChanged, this, &TcpSocketInterface::onSocketStateChanged); QObject::connect(&m_socket, &QSslSocket::stateChanged, this, &TcpSocketTransport::onSocketStateChanged);
} }
QStringList TcpSocketInterface::supportedSchemes() const QStringList TcpSocketTransport::supportedSchemes() const
{ {
return {"nymea", "nymeas"}; return {"nymea", "nymeas"};
} }
void TcpSocketInterface::sendData(const QByteArray &data) void TcpSocketTransport::sendData(const QByteArray &data)
{ {
qint64 ret = m_socket.write(data); qint64 ret = m_socket.write(data);
if (ret != data.length()) { if (ret != data.length()) {
@ -29,12 +29,12 @@ void TcpSocketInterface::sendData(const QByteArray &data)
} }
} }
void TcpSocketInterface::ignoreSslErrors(const QList<QSslError> &errors) void TcpSocketTransport::ignoreSslErrors(const QList<QSslError> &errors)
{ {
m_socket.ignoreSslErrors(errors); m_socket.ignoreSslErrors(errors);
} }
void TcpSocketInterface::onConnected() void TcpSocketTransport::onConnected()
{ {
if (m_url.scheme() == "nymea") { if (m_url.scheme() == "nymea") {
qDebug() << "TCP socket connected"; qDebug() << "TCP socket connected";
@ -42,13 +42,13 @@ void TcpSocketInterface::onConnected()
} }
} }
void TcpSocketInterface::onEncrypted() void TcpSocketTransport::onEncrypted()
{ {
qDebug() << "TCP socket encrypted"; qDebug() << "TCP socket encrypted";
emit connected(); emit connected();
} }
void TcpSocketInterface::connect(const QUrl &url) void TcpSocketTransport::connect(const QUrl &url)
{ {
m_url = url; m_url = url;
if (url.scheme() == "nymeas") { if (url.scheme() == "nymeas") {
@ -61,20 +61,20 @@ void TcpSocketInterface::connect(const QUrl &url)
} }
} }
NymeaInterface::ConnectionState TcpSocketInterface::connectionState() const NymeaTransportInterface::ConnectionState TcpSocketTransport::connectionState() const
{ {
switch (m_socket.state()) { switch (m_socket.state()) {
case QAbstractSocket::ConnectedState: case QAbstractSocket::ConnectedState:
return NymeaInterface::ConnectionStateConnected; return NymeaTransportInterface::ConnectionStateConnected;
case QAbstractSocket::ConnectingState: case QAbstractSocket::ConnectingState:
case QAbstractSocket::HostLookupState: case QAbstractSocket::HostLookupState:
return NymeaInterface::ConnectionStateConnecting; return NymeaTransportInterface::ConnectionStateConnecting;
default: default:
return NymeaInterface::ConnectionStateDisconnected; return NymeaTransportInterface::ConnectionStateDisconnected;
} }
} }
void TcpSocketInterface::disconnect() void TcpSocketTransport::disconnect()
{ {
qDebug() << "closing socket"; qDebug() << "closing socket";
m_socket.disconnectFromHost(); m_socket.disconnectFromHost();
@ -85,13 +85,13 @@ void TcpSocketInterface::disconnect()
m_socket.abort(); m_socket.abort();
} }
void TcpSocketInterface::socketReadyRead() void TcpSocketTransport::socketReadyRead()
{ {
QByteArray data = m_socket.readAll(); QByteArray data = m_socket.readAll();
emit dataReady(data); emit dataReady(data);
} }
void TcpSocketInterface::onSocketStateChanged(const QAbstractSocket::SocketState &state) void TcpSocketTransport::onSocketStateChanged(const QAbstractSocket::SocketState &state)
{ {
qDebug() << "Socket state changed -->" << state; qDebug() << "Socket state changed -->" << state;
} }

View File

@ -1,17 +1,17 @@
#ifndef TCPSOCKETINTERFACE_H #ifndef TCPSOCKETTRANSPORT_H
#define TCPSOCKETINTERFACE_H #define TCPSOCKETTRANSPORT_H
#include "nymeainterface.h" #include "nymeatransportinterface.h"
#include <QObject> #include <QObject>
#include <QSslSocket> #include <QSslSocket>
#include <QUrl> #include <QUrl>
class TcpSocketInterface : public NymeaInterface class TcpSocketTransport: public NymeaTransportInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit TcpSocketInterface(QObject *parent = nullptr); explicit TcpSocketTransport(QObject *parent = nullptr);
QStringList supportedSchemes() const override; QStringList supportedSchemes() const override;
@ -32,4 +32,4 @@ private:
QUrl m_url; QUrl m_url;
}; };
#endif // TCPSOCKETINTERFACE_H #endif // TCPSOCKETTRANSPROT_H

View File

@ -18,70 +18,69 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "websocketinterface.h" #include "websockettransport.h"
#include "engine.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonParseError> #include <QJsonParseError>
#include <QSettings> #include <QSettings>
WebsocketInterface::WebsocketInterface(QObject *parent) : WebsocketTransport::WebsocketTransport(QObject *parent) :
NymeaInterface(parent) NymeaTransportInterface(parent)
{ {
m_socket = new QWebSocket(QCoreApplication::applicationName(), QWebSocketProtocol::Version13, this); m_socket = new QWebSocket(QCoreApplication::applicationName(), QWebSocketProtocol::Version13, this);
QObject::connect(m_socket, &QWebSocket::connected, this, &WebsocketInterface::connected); QObject::connect(m_socket, &QWebSocket::connected, this, &WebsocketTransport::connected);
QObject::connect(m_socket, &QWebSocket::disconnected, this, &WebsocketInterface::disconnected); QObject::connect(m_socket, &QWebSocket::disconnected, this, &WebsocketTransport::disconnected);
typedef void (QWebSocket:: *errorSignal)(QAbstractSocket::SocketError); typedef void (QWebSocket:: *errorSignal)(QAbstractSocket::SocketError);
QObject::connect(m_socket, static_cast<errorSignal>(&QWebSocket::error), this, &WebsocketInterface::error); QObject::connect(m_socket, static_cast<errorSignal>(&QWebSocket::error), this, &WebsocketTransport::error);
QObject::connect(m_socket, &QWebSocket::textMessageReceived, this, &WebsocketInterface::onTextMessageReceived); QObject::connect(m_socket, &QWebSocket::textMessageReceived, this, &WebsocketTransport::onTextMessageReceived);
typedef void (QWebSocket:: *sslErrorsSignal)(const QList<QSslError> &); typedef void (QWebSocket:: *sslErrorsSignal)(const QList<QSslError> &);
QObject::connect(m_socket, static_cast<sslErrorsSignal>(&QWebSocket::sslErrors),this, &WebsocketInterface::sslErrors); QObject::connect(m_socket, static_cast<sslErrorsSignal>(&QWebSocket::sslErrors),this, &WebsocketTransport::sslErrors);
} }
QStringList WebsocketInterface::supportedSchemes() const QStringList WebsocketTransport::supportedSchemes() const
{ {
return {"ws", "wss"}; return {"ws", "wss"};
} }
void WebsocketInterface::connect(const QUrl &url) void WebsocketTransport::connect(const QUrl &url)
{ {
m_socket->open(QUrl(url)); m_socket->open(QUrl(url));
} }
NymeaInterface::ConnectionState WebsocketInterface::connectionState() const NymeaTransportInterface::ConnectionState WebsocketTransport::connectionState() const
{ {
switch (m_socket->state()) { switch (m_socket->state()) {
case QAbstractSocket::ConnectedState: case QAbstractSocket::ConnectedState:
return NymeaInterface::ConnectionStateConnected; return NymeaTransportInterface::ConnectionStateConnected;
case QAbstractSocket::ConnectingState: case QAbstractSocket::ConnectingState:
case QAbstractSocket::HostLookupState: case QAbstractSocket::HostLookupState:
return NymeaInterface::ConnectionStateConnecting; return NymeaTransportInterface::ConnectionStateConnecting;
default: default:
return NymeaInterface::ConnectionStateDisconnected; return NymeaTransportInterface::ConnectionStateDisconnected;
} }
} }
void WebsocketInterface::disconnect() void WebsocketTransport::disconnect()
{ {
m_socket->close(); m_socket->close();
m_socket->abort(); m_socket->abort();
} }
void WebsocketInterface::sendData(const QByteArray &data) void WebsocketTransport::sendData(const QByteArray &data)
{ {
m_socket->sendTextMessage(QString::fromUtf8(data)); m_socket->sendTextMessage(QString::fromUtf8(data));
} }
void WebsocketInterface::ignoreSslErrors(const QList<QSslError> &errors) void WebsocketTransport::ignoreSslErrors(const QList<QSslError> &errors)
{ {
m_socket->ignoreSslErrors(errors); m_socket->ignoreSslErrors(errors);
} }
void WebsocketInterface::onTextMessageReceived(const QString &data) void WebsocketTransport::onTextMessageReceived(const QString &data)
{ {
emit dataReady(data.toUtf8()); emit dataReady(data.toUtf8());
} }

View File

@ -18,19 +18,19 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef WEBSOCKETINTERFACE_H #ifndef WEBSOCKETTRANSPORT_H
#define WEBSOCKETINTERFACE_H #define WEBSOCKETTRANSPORT_H
#include <QObject> #include <QObject>
#include <QWebSocket> #include <QWebSocket>
#include "nymeainterface.h" #include "nymeatransportinterface.h"
class WebsocketInterface : public NymeaInterface class WebsocketTransport: public NymeaTransportInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit WebsocketInterface(QObject *parent = 0); explicit WebsocketTransport(QObject *parent = nullptr);
QStringList supportedSchemes() const override; QStringList supportedSchemes() const override;
@ -47,4 +47,4 @@ private slots:
void onTextMessageReceived(const QString &data); void onTextMessageReceived(const QString &data);
}; };
#endif // WEBSOCKETINTERFACE_H #endif // WEBSOCKETTRANSPORT_H

View File

@ -36,7 +36,7 @@ void BluetoothServiceDiscovery::discover()
{ {
m_enabed = true; m_enabed = true;
if (!m_localDevice->isValid() || m_localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff) { if (!m_localDevice->isValid() || m_localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff) {
qWarning() << "BluetoothServiceDiscovery: Not restart discovery, the bluetooth device is not available"; qWarning() << "BluetoothServiceDiscovery: Bluetooth device not available. Not starting discovery.";
return; return;
} }
@ -45,7 +45,7 @@ void BluetoothServiceDiscovery::discover()
if (m_discovering) if (m_discovering)
return; return;
qDebug() << "BluetoothServiceDiscovery: Start scanning for service" << m_nymeaServiceUuid.toString(); qDebug() << "BluetoothServiceDiscovery: Service scan started for service: " << m_nymeaServiceUuid.toString();
setDiscovering(true); setDiscovering(true);
m_serviceDiscovery->setUuidFilter(m_nymeaServiceUuid); m_serviceDiscovery->setUuidFilter(m_nymeaServiceUuid);
@ -73,15 +73,13 @@ void BluetoothServiceDiscovery::setDiscovering(const bool &discovering)
void BluetoothServiceDiscovery::onHostModeChanged(const QBluetoothLocalDevice::HostMode &mode) void BluetoothServiceDiscovery::onHostModeChanged(const QBluetoothLocalDevice::HostMode &mode)
{ {
qDebug() << "BluetoothServiceDiscovery: Host mode changed" << mode;
if (mode != QBluetoothLocalDevice::HostPoweredOff && m_enabed) { if (mode != QBluetoothLocalDevice::HostPoweredOff && m_enabed) {
qDebug() << "Bluetooth available again, continue discovery"; qDebug() << "BluetoothServiceDiscovery: Bluetooth device available. Starting discovery.";
discover(); discover();
} }
if (mode == QBluetoothLocalDevice::HostPoweredOff) { if (mode == QBluetoothLocalDevice::HostPoweredOff) {
qDebug() << "BluetoothServiceDiscovery: Bluetooth adapter disabled. Stop discovering"; qDebug() << "BluetoothServiceDiscovery: Bluetooth adapter disabled. Stopping discovering";
m_serviceDiscovery->stop(); m_serviceDiscovery->stop();
} }
} }

View File

@ -23,9 +23,9 @@
#include <QUrl> #include <QUrl>
DiscoveryDevice::DiscoveryDevice(QObject *parent): DiscoveryDevice::DiscoveryDevice(QObject *parent):
QObject(parent) QObject(parent),
m_connections(new Connections(this))
{ {
m_portConfigs = new PortConfigs(this);
} }
QUuid DiscoveryDevice::uuid() const QUuid DiscoveryDevice::uuid() const
@ -64,143 +64,101 @@ void DiscoveryDevice::setVersion(const QString &version)
} }
} }
PortConfigs* DiscoveryDevice::portConfigs() const Connections* DiscoveryDevice::connections() const
{ {
return m_portConfigs; return m_connections;
} }
QString DiscoveryDevice::toUrl(int portConfigIndex) Connections::Connections(QObject *parent):
{ QAbstractListModel(parent)
PortConfig *pc = m_portConfigs->get(portConfigIndex);
if (!pc) {
qWarning() << "No portconfig for index" << portConfigIndex;
return QString();
}
QString ret = pc->protocol() == PortConfig::ProtocolNymeaRpc ? "nymea" : "ws";
ret += pc->sslEnabled() ? "s" : "";
ret += "://";
if (pc->hostAddress().protocol() == QAbstractSocket::IPv4Protocol) {
ret += pc->hostAddress().toString();
} else if (pc->hostAddress().protocol() == QAbstractSocket::IPv6Protocol){
ret += "[" + pc->hostAddress().toString() + "]";
}
ret += ":";
ret += QString::number(pc->port());
return ret;
}
PortConfigs::PortConfigs(QObject *parent): QAbstractListModel(parent)
{ {
} }
int PortConfigs::rowCount(const QModelIndex &parent) const int Connections::rowCount(const QModelIndex &parent) const
{ {
Q_UNUSED(parent) Q_UNUSED(parent)
return m_portConfigs.count(); return m_connections.count();
} }
QVariant PortConfigs::data(const QModelIndex &index, int role) const QVariant Connections::data(const QModelIndex &index, int role) const
{ {
switch (role) { switch (role) {
case RoleAddress: case RoleUrl:
return m_portConfigs.at(index.row())->hostAddressString(); return m_connections.at(index.row())->url();
case RolePort: case RoleName:
return m_portConfigs.at(index.row())->port(); return m_connections.at(index.row())->displayName();
case RoleProtocol: case RoleBearerType:
return m_portConfigs.at(index.row())->protocol(); return m_connections.at(index.row())->bearerType();
case RoleSSLEnabled: case RoleSecure:
return m_portConfigs.at(index.row())->sslEnabled(); return m_connections.at(index.row())->secure();
} }
return QVariant(); return QVariant();
} }
PortConfig *PortConfigs::find(int port) Connection* Connections::find(const QUrl &url) const
{ {
foreach (PortConfig* pc, m_portConfigs) { foreach (Connection *conn, m_connections) {
if (pc->port() == port) { if (conn->url() == url) {
return pc; return conn;
} }
} }
return nullptr; return nullptr;
} }
void PortConfigs::insert(PortConfig *portConfig) void Connections::addConnection(Connection *connection)
{ {
portConfig->setParent(this); connection->setParent(this);
beginInsertRows(QModelIndex(), m_portConfigs.count(), m_portConfigs.count()); beginInsertRows(QModelIndex(), m_connections.count(), m_connections.count());
m_portConfigs.append(portConfig); m_connections.append(connection);
endInsertRows(); endInsertRows();
emit countChanged(); emit countChanged();
} }
PortConfig* PortConfigs::get(int index) const Connection* Connections::get(int index) const
{ {
if (index < 0 || index >= m_portConfigs.count()) if (index >= 0 && index < m_connections.count()) {
return nullptr; return m_connections.at(index);
}
return m_portConfigs.at(index); return nullptr;
} }
QHash<int, QByteArray> PortConfigs::roleNames() const QHash<int, QByteArray> Connections::roleNames() const
{ {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles.insert(RoleAddress, "address"); roles.insert(RoleUrl, "url");
roles.insert(RolePort, "port"); roles.insert(RoleBearerType, "bearerType");
roles.insert(RoleProtocol, "protocol"); roles.insert(RoleName, "name");
roles.insert(RoleSSLEnabled, "sslEnabled"); roles.insert(RoleSecure, "secure");
return roles; return roles;
} }
PortConfig::PortConfig(const QHostAddress &hostAddress, int port, QObject *parent): Connection::Connection(const QUrl &url, Connection::BearerType bearerType, bool secure, const QString &displayName, QObject *parent):
QObject(parent), QObject(parent),
m_port(port), m_url(url),
m_hostAddress(hostAddress) m_bearerType(bearerType),
m_secure(secure),
m_displayName(displayName)
{ {
} }
int PortConfig::port() const QUrl Connection::url() const
{ {
return m_port; return m_url;
} }
PortConfig::Protocol PortConfig::protocol() const Connection::BearerType Connection::bearerType() const
{ {
return m_protocol; return m_bearerType;
} }
void PortConfig::setProtocol(PortConfig::Protocol protocol) bool Connection::secure() const
{ {
if (m_protocol != protocol) { return m_secure;
m_protocol = protocol;
emit protocolChanged();
}
} }
QHostAddress PortConfig::hostAddress() const QString Connection::displayName() const
{ {
return m_hostAddress; return m_displayName;
}
QString PortConfig::hostAddressString() const
{
if (m_hostAddress.protocol() == QAbstractSocket::IPv6Protocol){
return "[" + m_hostAddress.toString() + "]";
}
return m_hostAddress.toString();
}
bool PortConfig::sslEnabled() const
{
return m_sslEnabled;
}
void PortConfig::setSslEnabled(bool sslEnabled)
{
if (m_sslEnabled != sslEnabled) {
m_sslEnabled = sslEnabled;
emit sslEnabledChanged();
}
} }

View File

@ -29,65 +29,56 @@
#include <QObject> #include <QObject>
#include <QAbstractListModel> #include <QAbstractListModel>
class PortConfig: public QObject class Connection: public QObject {
{
Q_OBJECT Q_OBJECT
Q_PROPERTY(int port READ port CONSTANT) Q_PROPERTY(QUrl url READ url CONSTANT)
Q_PROPERTY(Protocol protocol READ protocol NOTIFY protocolChanged) Q_PROPERTY(BearerType bearerType READ bearerType CONSTANT)
Q_PROPERTY(QString hostAddress READ hostAddressString NOTIFY hostAddressChanged) Q_PROPERTY(bool secure READ secure CONSTANT)
Q_PROPERTY(bool sslEnabled READ sslEnabled NOTIFY sslEnabledChanged) Q_PROPERTY(QString displayName READ displayName CONSTANT)
public: public:
enum Protocol { enum BearerType {
ProtocolNymeaRpc, BearerTypeUnknown,
ProtocolWebSocket BearerTypeWifi,
BearerTypeEthernet,
BearerTypeBluetooth,
BearerTypeCloud
}; };
Q_ENUM(Protocol) Q_ENUM(BearerType)
PortConfig(const QHostAddress &hostAddress, int port, QObject *parent = nullptr);
int port() const; Connection(const QUrl &url, BearerType bearerType, bool secure, const QString &displayName, QObject *parent = nullptr);
Protocol protocol() const; QUrl url() const;
void setProtocol(Protocol protocol); BearerType bearerType() const;
bool secure() const;
QHostAddress hostAddress() const; QString displayName() const;
QString hostAddressString() const;
void setHostAddress(const QString &hostAddress);
bool sslEnabled() const;
void setSslEnabled(bool sslEnabled);
signals:
void protocolChanged();
void hostAddressChanged();
void sslEnabledChanged();
private: private:
int m_port = -1; QUrl m_url;
QHostAddress m_hostAddress; BearerType m_bearerType = BearerTypeUnknown;
Protocol m_protocol = ProtocolNymeaRpc; bool m_secure = false;
bool m_sslEnabled = false; QString m_displayName;
}; };
class PortConfigs: public QAbstractListModel class Connections: public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int count READ rowCount NOTIFY countChanged) Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
public: public:
enum Roles { enum Roles {
RoleAddress, RoleUrl,
RolePort, RoleName,
RoleProtocol, RoleBearerType,
RoleSSLEnabled RoleSecure
}; };
Q_ENUM(Roles) Q_ENUM(Roles)
PortConfigs(QObject* parent = nullptr); Connections(QObject* parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
PortConfig* find(int port); void addConnection(Connection *connection);
void insert(PortConfig* portConfig);
Q_INVOKABLE PortConfig *get(int index) const; Q_INVOKABLE Connection* find(const QUrl &url) const;
Q_INVOKABLE Connection* get(int index) const;
signals: signals:
void countChanged(); void countChanged();
@ -96,7 +87,7 @@ protected:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
private: private:
QList<PortConfig*> m_portConfigs; QList<Connection*> m_connections;
}; };
@ -106,7 +97,7 @@ class DiscoveryDevice: public QObject
Q_PROPERTY(QUuid uuid READ uuid CONSTANT) Q_PROPERTY(QUuid uuid READ uuid CONSTANT)
Q_PROPERTY(QString name READ name NOTIFY nameChanged) Q_PROPERTY(QString name READ name NOTIFY nameChanged)
Q_PROPERTY(QString version READ version NOTIFY versionChanged) Q_PROPERTY(QString version READ version NOTIFY versionChanged)
Q_PROPERTY(PortConfigs* portConfigs READ portConfigs CONSTANT) Q_PROPERTY(Connections* connections READ connections CONSTANT)
public: public:
explicit DiscoveryDevice(QObject *parent = nullptr); explicit DiscoveryDevice(QObject *parent = nullptr);
@ -120,9 +111,7 @@ public:
QString version() const; QString version() const;
void setVersion(const QString &version); void setVersion(const QString &version);
PortConfigs *portConfigs() const; Connections *connections() const;
Q_INVOKABLE QString toUrl(int portConfigIndex);
signals: signals:
void nameChanged(); void nameChanged();
@ -132,7 +121,7 @@ private:
QUuid m_uuid; QUuid m_uuid;
QString m_name; QString m_name;
QString m_version; QString m_version;
PortConfigs *m_portConfigs = nullptr; Connections *m_connections = nullptr;
}; };
#endif // DISCOVERYDEVICE_H #endif // DISCOVERYDEVICE_H

View File

@ -3,7 +3,7 @@
#include "upnpdiscovery.h" #include "upnpdiscovery.h"
#include "zeroconfdiscovery.h" #include "zeroconfdiscovery.h"
#include "bluetoothservicediscovery.h" #include "bluetoothservicediscovery.h"
#include "awsclient.h" #include "connection/awsclient.h"
#include <QUuid> #include <QUuid>
#include <QBluetoothUuid> #include <QBluetoothUuid>
@ -59,10 +59,21 @@ DiscoveryModel *NymeaDiscovery::discoveryModel() const
void NymeaDiscovery::cloudDevicesFetched(const QList<AWSDevice> &devices) void NymeaDiscovery::cloudDevicesFetched(const QList<AWSDevice> &devices)
{ {
qDebug() << "Cloud devices fetched";
foreach (const AWSDevice &d, devices) { foreach (const AWSDevice &d, devices) {
DiscoveryDevice *device = m_discoveryModel->find(d.id); DiscoveryDevice *device = m_discoveryModel->find(d.id);
if (!device) { if (!device) {
device = new DiscoveryDevice();
device->setUuid(d.id);
device->setName(d.name);
m_discoveryModel->addDevice(device);
}
QUrl url;
url.setScheme("cloud");
url.setHost(d.id);
if (!device->connections()->find(url)) {
Connection *conn = new Connection(url, Connection::BearerTypeCloud, true, d.id);
device->connections()->addConnection(conn);
} }
} }
} }

View File

@ -3,7 +3,7 @@
#include <QObject> #include <QObject>
#include "awsclient.h" #include "connection/awsclient.h"
class DiscoveryModel; class DiscoveryModel;
class UpnpDiscovery; class UpnpDiscovery;

View File

@ -51,10 +51,10 @@ UpnpDiscovery::UpnpDiscovery(DiscoveryModel *discoveryModel, QObject *parent) :
} }
if (port == 65535 || socket->state() != QUdpSocket::BoundState) { if (port == 65535 || socket->state() != QUdpSocket::BoundState) {
socket->deleteLater(); socket->deleteLater();
qWarning() << "UPnP discovery could not bind to interface" << netAddressEntry.ip(); qWarning() << "UPnP: Discovery could not bind to interface" << netAddressEntry.ip();
continue; continue;
} }
qDebug() << "Discovering on" << netAddressEntry.ip() << port; qDebug() << "UPnP: Discovering on" << netAddressEntry.ip() << port;
m_sockets.append(socket); m_sockets.append(socket);
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError))); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
connect(socket, &QUdpSocket::readyRead, this, &UpnpDiscovery::readData); connect(socket, &QUdpSocket::readyRead, this, &UpnpDiscovery::readData);
@ -76,11 +76,11 @@ bool UpnpDiscovery::available() const
void UpnpDiscovery::discover() void UpnpDiscovery::discover()
{ {
if (!available()) { if (!available()) {
qWarning() << "Could not discover. UPnP not available."; qWarning() << "UPnP: UPnP not available. Discovery not started.";
return; return;
} }
qDebug() << "start discovering..."; qDebug() << "UPNP: Discovery started...";
m_repeatTimer.start(); m_repeatTimer.start();
m_foundDevices.clear(); m_foundDevices.clear();
writeDiscoveryPacket(); writeDiscoveryPacket();
@ -89,7 +89,7 @@ void UpnpDiscovery::discover()
void UpnpDiscovery::stopDiscovery() void UpnpDiscovery::stopDiscovery()
{ {
qDebug() << "stop discovering"; qDebug() << "UPNP: Discovery stopped.";
m_repeatTimer.stop(); m_repeatTimer.stop();
emit discoveringChanged(); emit discoveringChanged();
} }
@ -106,7 +106,7 @@ void UpnpDiscovery::writeDiscoveryPacket()
foreach (QUdpSocket* socket, m_sockets) { foreach (QUdpSocket* socket, m_sockets) {
qint64 ret = socket->writeDatagram(ssdpSearchMessage, QHostAddress("239.255.255.250"), 1900); qint64 ret = socket->writeDatagram(ssdpSearchMessage, QHostAddress("239.255.255.250"), 1900);
if (ret != ssdpSearchMessage.length()) { if (ret != ssdpSearchMessage.length()) {
qWarning() << "Error sending SSDP query on socket" << socket->localAddress(); qWarning() << "UPnP: Error sending SSDP query on socket" << socket->localAddress();
} }
} }
@ -115,7 +115,7 @@ void UpnpDiscovery::writeDiscoveryPacket()
void UpnpDiscovery::error(QAbstractSocket::SocketError error) void UpnpDiscovery::error(QAbstractSocket::SocketError error)
{ {
QUdpSocket* socket = static_cast<QUdpSocket*>(sender()); QUdpSocket* socket = static_cast<QUdpSocket*>(sender());
qWarning() << "UPnP socket error:" << error << socket->errorString(); qWarning() << "UPnP: Socket error:" << error << socket->errorString();
} }
void UpnpDiscovery::readData() void UpnpDiscovery::readData()
@ -180,7 +180,7 @@ void UpnpDiscovery::networkReplyFinished(QNetworkReply *reply)
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (reply->error() != QNetworkReply::NoError || status != 200) { if (reply->error() != QNetworkReply::NoError || status != 200) {
qWarning() << "Error fetching UPnP discovery data:" << status << reply->error() << reply->errorString(); qWarning() << "UPnP: Error fetching discovery data:" << status << reply->error() << reply->errorString();
return; return;
} }
@ -189,7 +189,7 @@ void UpnpDiscovery::networkReplyFinished(QNetworkReply *reply)
QString name; QString name;
QString version; QString version;
QUuid uuid; QUuid uuid;
QList<PortConfig*> portConfigList; QList<QUrl> connections;
// parse XML data // parse XML data
QXmlStreamReader xml(data); QXmlStreamReader xml(data);
@ -203,30 +203,11 @@ void UpnpDiscovery::networkReplyFinished(QNetworkReply *reply)
if (xml.isStartElement()) { if (xml.isStartElement()) {
// Check for old style websocketURL and nymeaRpcURL // Check for old style websocketURL and nymeaRpcURL
if (xml.name().toString() == "websocketURL") { if (xml.name().toString() == "websocketURL" ||
xml.name().toString() == "nymeaRpcURL" ||
xml.name().toString() == "guhRpcURL") {
QUrl u(xml.readElementText()); QUrl u(xml.readElementText());
PortConfig *pc = new PortConfig(discoveredAddress, u.port()); connections.append(u);
pc->setProtocol(PortConfig::ProtocolWebSocket);
pc->setSslEnabled(u.scheme() == "wss");
portConfigList.append(pc);
}
if (xml.name().toString() == "nymeaRpcURL") {
QUrl u(xml.readElementText());
qDebug() << "have url" << u << u.scheme();
PortConfig *pc = new PortConfig(discoveredAddress, u.port());
pc->setProtocol(PortConfig::ProtocolNymeaRpc);
pc->setSslEnabled(u.scheme() == "nymeas");
portConfigList.append(pc);
}
if (xml.name().toString() == "guhRpcURL") {
QUrl u(xml.readElementText());
qDebug() << "have url" << u << u.scheme();
PortConfig *pc = new PortConfig(discoveredAddress, u.port());
pc->setProtocol(PortConfig::ProtocolNymeaRpc);
pc->setSslEnabled(u.scheme() == "guhs");
portConfigList.append(pc);
} }
// But also for new style serviceList // But also for new style serviceList
@ -238,10 +219,7 @@ void UpnpDiscovery::networkReplyFinished(QNetworkReply *reply)
xml.readNext(); xml.readNext();
if (xml.name().toString() == "SCPDURL") { if (xml.name().toString() == "SCPDURL") {
QUrl u(xml.readElementText()); QUrl u(xml.readElementText());
PortConfig *pc = new PortConfig(discoveredAddress, u.port()); connections.append(u);
pc->setProtocol(u.scheme().startsWith("nymea") ? PortConfig::ProtocolNymeaRpc : PortConfig::ProtocolWebSocket);
pc->setSslEnabled(u.scheme() == "nymeas" || u.scheme() == "wss");
portConfigList.append(pc);
} }
} }
} }
@ -260,27 +238,24 @@ void UpnpDiscovery::networkReplyFinished(QNetworkReply *reply)
} }
} }
qDebug() << "discovered device" << uuid << name << discoveredAddress << version; // qDebug() << "discovered device" << uuid << name << discoveredAddress << version << connections << data;
DiscoveryDevice* device = m_discoveryModel->find(uuid); DiscoveryDevice* device = m_discoveryModel->find(uuid);
if (!device) { if (!device) {
device = new DiscoveryDevice(m_discoveryModel); device = new DiscoveryDevice(m_discoveryModel);
device->setUuid(uuid); device->setUuid(uuid);
qDebug() << "Adding new host to model"; qDebug() << "UPnP: Adding new host to model";
m_discoveryModel->addDevice(device); m_discoveryModel->addDevice(device);
} }
device->setName(name); device->setName(name);
device->setVersion(version); device->setVersion(version);
foreach (PortConfig *pc, portConfigList) { foreach (const QUrl &url, connections) {
PortConfig *portConfig = device->portConfigs()->find(pc->port()); if (!device->connections()->find(url)) {
if (portConfig) { qDebug() << "UPnP: Adding new connection to host:" << device->name() << url;
qDebug() << "Updating port config" << portConfig->port() << portConfig->sslEnabled() << portConfig->protocol(); bool sslEnabled = url.scheme() == "nymeas" || url.scheme() == "wss";
portConfig->setProtocol(pc->protocol()); QString displayName = QString("%1:%2").arg(url.host()).arg(url.port());
portConfig->setSslEnabled(pc->sslEnabled()); Connection *conn = new Connection(url, Connection::BearerTypeWifi, sslEnabled, displayName);
pc->deleteLater(); device->connections()->addConnection(conn);
} else {
qDebug() << "adding new port config" << pc->port() << pc->sslEnabled() << pc->protocol();
device->portConfigs()->insert(pc);
} }
} }
} }

View File

@ -13,13 +13,13 @@ ZeroconfDiscovery::ZeroconfDiscovery(DiscoveryModel *discoveryModel, QObject *pa
connect(m_zeroconfJsonRPC, &QZeroConf::serviceAdded, this, &ZeroconfDiscovery::serviceEntryAdded); connect(m_zeroconfJsonRPC, &QZeroConf::serviceAdded, this, &ZeroconfDiscovery::serviceEntryAdded);
connect(m_zeroconfJsonRPC, &QZeroConf::serviceUpdated, this, &ZeroconfDiscovery::serviceEntryAdded); connect(m_zeroconfJsonRPC, &QZeroConf::serviceUpdated, this, &ZeroconfDiscovery::serviceEntryAdded);
m_zeroconfJsonRPC->startBrowser("_jsonrpc._tcp", QAbstractSocket::AnyIPProtocol); m_zeroconfJsonRPC->startBrowser("_jsonrpc._tcp", QAbstractSocket::AnyIPProtocol);
qDebug() << "created service browser for _jsonrpc._tcp:" << m_zeroconfJsonRPC->browserExists(); qDebug() << "ZeroConf: Created service browser for _jsonrpc._tcp:" << m_zeroconfJsonRPC->browserExists();
m_zeroconfWebSocket = new QZeroConf(this); m_zeroconfWebSocket = new QZeroConf(this);
connect(m_zeroconfWebSocket, &QZeroConf::serviceAdded, this, &ZeroconfDiscovery::serviceEntryAdded); connect(m_zeroconfWebSocket, &QZeroConf::serviceAdded, this, &ZeroconfDiscovery::serviceEntryAdded);
connect(m_zeroconfWebSocket, &QZeroConf::serviceUpdated, this, &ZeroconfDiscovery::serviceEntryAdded); connect(m_zeroconfWebSocket, &QZeroConf::serviceUpdated, this, &ZeroconfDiscovery::serviceEntryAdded);
m_zeroconfWebSocket->startBrowser("_ws._tcp", QAbstractSocket::AnyIPProtocol); m_zeroconfWebSocket->startBrowser("_ws._tcp", QAbstractSocket::AnyIPProtocol);
qDebug() << "created service browser for _ws._tcp:" << m_zeroconfWebSocket->browserExists(); qDebug() << "TeroConf: Created service browser for _ws._tcp:" << m_zeroconfWebSocket->browserExists();
#else #else
qDebug() << "Zeroconf support not compiled in. Zeroconf will not be available."; qDebug() << "Zeroconf support not compiled in. Zeroconf will not be available.";
#endif #endif
@ -73,18 +73,25 @@ void ZeroconfDiscovery::serviceEntryAdded(const QZeroConfService &entry)
if (!device) { if (!device) {
device = new DiscoveryDevice(m_discoveryModel); device = new DiscoveryDevice(m_discoveryModel);
device->setUuid(uuid); device->setUuid(uuid);
qDebug() << "ZeroConf: Adding new host to model"; qDebug() << "ZeroConf: Adding new host:" << serverName << uuid;
m_discoveryModel->addDevice(device); m_discoveryModel->addDevice(device);
} }
device->setName(serverName); device->setName(serverName);
device->setVersion(version); device->setVersion(version);
PortConfig *portConfig = device->portConfigs()->find(entry.port()); QUrl url;
if (!portConfig) { if (entry.type() == "_jsonrpc._tcp") {
qDebug() << "ZeroConf: Adding new port config"; url.setScheme(sslEnabled ? "nymeas" : "nymea");
portConfig = new PortConfig(!entry.ip().isNull() ? entry.ip() : entry.ipv6(), entry.port()); } else {
device->portConfigs()->insert(portConfig); url.setScheme(sslEnabled ? "wss" : "ws");
}
// entry
url.setHost(!entry.ip().isNull() ? entry.ip().toString() : entry.ipv6().toString());
url.setPort(entry.port());
if (!device->connections()->find(url)){
qDebug() << "Zeroconf: Adding new connection to host:" << device->name() << url.toString();
QString displayName = QString("%1:%2").arg(url.host()).arg(url.port());
Connection *connection = new Connection(url, Connection::BearerTypeWifi, sslEnabled, displayName);
device->connections()->addConnection(connection);
} }
portConfig->setProtocol(entry.type() == "_ws._tcp" ? PortConfig::ProtocolWebSocket : PortConfig::ProtocolNymeaRpc);
portConfig->setSslEnabled(sslEnabled);
} }
#endif #endif

View File

@ -20,12 +20,16 @@
#include "engine.h" #include "engine.h"
#include "tcpsocketinterface.h"
#include "rulemanager.h" #include "rulemanager.h"
#include "logmanager.h" #include "logmanager.h"
#include "tagsmanager.h" #include "tagsmanager.h"
#include "basicconfiguration.h" #include "basicconfiguration.h"
#include "awsclient.h" #include "connection/awsclient.h"
#include "connection/tcpsockettransport.h"
#include "connection/websockettransport.h"
#include "connection/bluetoothtransport.h"
#include "connection/cloudtransport.h"
Engine* Engine::s_instance = nullptr; Engine* Engine::s_instance = nullptr;
@ -94,6 +98,11 @@ Engine::Engine(QObject *parent) :
m_bluetoothDiscovery(new BluetoothDiscovery(this)), m_bluetoothDiscovery(new BluetoothDiscovery(this)),
m_aws(new AWSClient(this)) m_aws(new AWSClient(this))
{ {
m_connection->registerTransport(new TcpSocketTransport(this));
m_connection->registerTransport(new WebsocketTransport(this));
m_connection->registerTransport(new BluetoothTransport(this));
m_connection->registerTransport(new CloudTransport(m_aws, this));
connect(m_jsonRpcClient, &JsonRpcClient::connectedChanged, this, &Engine::onConnectedChanged); connect(m_jsonRpcClient, &JsonRpcClient::connectedChanged, this, &Engine::onConnectedChanged);
connect(m_jsonRpcClient, &JsonRpcClient::authenticationRequiredChanged, this, &Engine::onConnectedChanged); connect(m_jsonRpcClient, &JsonRpcClient::authenticationRequiredChanged, this, &Engine::onConnectedChanged);

View File

@ -24,7 +24,7 @@
#include <QObject> #include <QObject>
#include "devicemanager.h" #include "devicemanager.h"
#include "nymeainterface.h" #include "connection/nymeatransportinterface.h"
#include "jsonrpc/jsonrpcclient.h" #include "jsonrpc/jsonrpcclient.h"
#include "wifisetup/bluetoothdiscovery.h" #include "wifisetup/bluetoothdiscovery.h"

View File

@ -19,7 +19,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "jsonrpcclient.h" #include "jsonrpcclient.h"
#include "nymeaconnection.h" #include "connection/nymeaconnection.h"
#include "types/param.h" #include "types/param.h"
#include "types/params.h" #include "types/params.h"

View File

@ -26,7 +26,7 @@
#include <QPointer> #include <QPointer>
#include <QVersionNumber> #include <QVersionNumber>
#include "nymeaconnection.h" #include "connection/nymeaconnection.h"
#include "jsonhandler.h" #include "jsonhandler.h"
class JsonRpcReply; class JsonRpcReply;

View File

@ -50,7 +50,7 @@
#include "ruletemplates/stateevaluatortemplate.h" #include "ruletemplates/stateevaluatortemplate.h"
#include "ruletemplates/statedescriptortemplate.h" #include "ruletemplates/statedescriptortemplate.h"
#include "ruletemplates/ruleactiontemplate.h" #include "ruletemplates/ruleactiontemplate.h"
#include "awsclient.h" #include "connection/awsclient.h"
#include <QtQml/qqml.h> #include <QtQml/qqml.h>
@ -150,8 +150,7 @@ void registerQmlTypes() {
qmlRegisterType<NymeaDiscovery>(uri, 1, 0, "NymeaDiscovery"); qmlRegisterType<NymeaDiscovery>(uri, 1, 0, "NymeaDiscovery");
qmlRegisterUncreatableType<DiscoveryModel>(uri, 1, 0, "DiscoveryModel", "Get it from NymeaDiscovery"); qmlRegisterUncreatableType<DiscoveryModel>(uri, 1, 0, "DiscoveryModel", "Get it from NymeaDiscovery");
qmlRegisterUncreatableType<DiscoveryDevice>(uri, 1, 0, "DiscoveryDevice", "Get it from DiscoveryModel"); qmlRegisterUncreatableType<DiscoveryDevice>(uri, 1, 0, "DiscoveryDevice", "Get it from DiscoveryModel");
qmlRegisterUncreatableType<PortConfigs>(uri, 1, 0, "PortConfigs", "Get it from DiscoveryDevice"); qmlRegisterUncreatableType<Connection>(uri, 1, 0, "Connection", "Get it from DiscoveryDevice");
qmlRegisterUncreatableType<PortConfig>(uri, 1, 0, "PortConfig", "Get it from DiscoveryDevice");
qmlRegisterType<EventDescriptorParamsFilterModel>(uri, 1, 0, "EventDescriptorParamsFilterModel"); qmlRegisterType<EventDescriptorParamsFilterModel>(uri, 1, 0, "EventDescriptorParamsFilterModel");

View File

@ -10,19 +10,28 @@ include(../config.pri)
DEFINES += WITH_ZEROCONF DEFINES += WITH_ZEROCONF
include(../QtZeroConf/qtzeroconf.pri) include(../QtZeroConf/qtzeroconf.pri)
} }
DEFINES += QT_STATIC
include(../qmqtt/src/mqtt/mqtt.pri)
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
QT -= gui QT -= gui
QT += network websockets bluetooth QT += network websockets bluetooth
LIBS += -lssl -lcrypto LIBS += -lssl -lcrypto
INCLUDEPATH += $$top_srcdir/libnymea-common $$top_srcdir/QtZeroConf INCLUDEPATH += $$top_srcdir/libnymea-common \
$$top_srcdir/QtZeroConf \
$$top_srcdir/qmqtt/src/mqtt/
SOURCES += \ SOURCES += \
engine.cpp \ engine.cpp \
nymeainterface.cpp \ connection/nymeaconnection.cpp \
connection/nymeatransportinterface.cpp \
connection/websockettransport.cpp \
connection/tcpsockettransport.cpp \
connection/bluetoothtransport.cpp \
connection/awsclient.cpp \
devicemanager.cpp \ devicemanager.cpp \
websocketinterface.cpp \
jsonrpc/jsontypes.cpp \ jsonrpc/jsontypes.cpp \
jsonrpc/jsonrpcclient.cpp \ jsonrpc/jsonrpcclient.cpp \
jsonrpc/jsonhandler.cpp \ jsonrpc/jsonhandler.cpp \
@ -36,8 +45,6 @@ SOURCES += \
devicediscovery.cpp \ devicediscovery.cpp \
vendorsproxy.cpp \ vendorsproxy.cpp \
pluginsproxy.cpp \ pluginsproxy.cpp \
tcpsocketinterface.cpp \
nymeaconnection.cpp \
interfacesmodel.cpp \ interfacesmodel.cpp \
discovery/zeroconfdiscovery.cpp \ discovery/zeroconfdiscovery.cpp \
discovery/discoverydevice.cpp \ discovery/discoverydevice.cpp \
@ -69,16 +76,18 @@ SOURCES += \
ruletemplates/ruleactiontemplate.cpp \ ruletemplates/ruleactiontemplate.cpp \
ruletemplates/stateevaluatortemplate.cpp \ ruletemplates/stateevaluatortemplate.cpp \
ruletemplates/statedescriptortemplate.cpp \ ruletemplates/statedescriptortemplate.cpp \
bluetoothinterface.cpp \
discovery/bluetoothservicediscovery.cpp \ discovery/bluetoothservicediscovery.cpp \
awsclient.cpp \ connection/cloudtransport.cpp
connection/srp.c
HEADERS += \ HEADERS += \
engine.h \ engine.h \
nymeainterface.h \ connection/nymeaconnection.h \
connection/nymeatransportinterface.h \
connection/websockettransport.h \
connection/tcpsockettransport.h \
connection/bluetoothtransport.h \
connection/awsclient.h \
devicemanager.h \ devicemanager.h \
websocketinterface.h \
jsonrpc/jsontypes.h \ jsonrpc/jsontypes.h \
jsonrpc/jsonrpcclient.h \ jsonrpc/jsonrpcclient.h \
jsonrpc/jsonhandler.h \ jsonrpc/jsonhandler.h \
@ -92,8 +101,6 @@ HEADERS += \
devicediscovery.h \ devicediscovery.h \
vendorsproxy.h \ vendorsproxy.h \
pluginsproxy.h \ pluginsproxy.h \
tcpsocketinterface.h \
nymeaconnection.h \
interfacesmodel.h \ interfacesmodel.h \
discovery/zeroconfdiscovery.h \ discovery/zeroconfdiscovery.h \
discovery/discoverydevice.h \ discovery/discoverydevice.h \
@ -126,9 +133,8 @@ HEADERS += \
ruletemplates/ruleactiontemplate.h \ ruletemplates/ruleactiontemplate.h \
ruletemplates/stateevaluatortemplate.h \ ruletemplates/stateevaluatortemplate.h \
ruletemplates/statedescriptortemplate.h \ ruletemplates/statedescriptortemplate.h \
bluetoothinterface.h \
discovery/bluetoothservicediscovery.h \ discovery/bluetoothservicediscovery.h \
awsclient.h connection/cloudtransport.h
unix { unix {
target.path = /usr/lib target.path = /usr/lib

View File

@ -49,6 +49,7 @@ void WirelessAccessPointsProxy::setAccessPoints(WirelessAccessPoints *accessPoin
bool WirelessAccessPointsProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const bool WirelessAccessPointsProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{ {
Q_UNUSED(source_parent) Q_UNUSED(source_parent)
Q_UNUSED(source_row)
// Filter out the current selected network // Filter out the current selected network
// WirelessAccessPoint *accessPoint = m_accessPoints->get(source_row); // WirelessAccessPoint *accessPoint = m_accessPoints->get(source_row);

View File

@ -43,7 +43,7 @@ int main(int argc, char *argv[])
foreach (const QFileInfo &fi, QDir(":/ui/fonts/").entryInfoList()) { foreach (const QFileInfo &fi, QDir(":/ui/fonts/").entryInfoList()) {
int id = QFontDatabase::addApplicationFont(fi.absoluteFilePath()); int id = QFontDatabase::addApplicationFont(fi.absoluteFilePath());
qDebug() << "Added font" << fi.absoluteFilePath() << QFontDatabase::applicationFontFamilies(id); // qDebug() << "Added font" << fi.absoluteFilePath() << QFontDatabase::applicationFontFamilies(id);
} }
QFont applicationFont; QFont applicationFont;

View File

@ -7,7 +7,8 @@ QT += network qml quick quickcontrols2 svg websockets bluetooth
INCLUDEPATH += $$top_srcdir/libnymea-common \ INCLUDEPATH += $$top_srcdir/libnymea-common \
$$top_srcdir/libnymea-app-core $$top_srcdir/libnymea-app-core
LIBS += -L$$top_builddir/libnymea-app-core/ -lnymea-app-core \ LIBS += -L$$top_builddir/libnymea-app-core/ -lnymea-app-core \
-L$$top_builddir/libnymea-common/ -lnymea-common -L$$top_builddir/libnymea-common/ -lnymea-common \
LIBS += -lssl -lcrypto LIBS += -lssl -lcrypto
win32:Debug:LIBS += -L$$top_builddir/libnymea-app-core/debug \ win32:Debug:LIBS += -L$$top_builddir/libnymea-app-core/debug \
@ -93,6 +94,3 @@ BR=$$BRANDING
target.path = /usr/bin target.path = /usr/bin
INSTALLS += target INSTALLS += target
DISTFILES += \
ui/magic/NewThingMagicPage.qml

View File

@ -40,6 +40,6 @@ void StyleController::setCurrentStyle(const QString &currentStyle)
QStringList StyleController::allStyles() const QStringList StyleController::allStyles() const
{ {
QDir dir(":/styles/"); QDir dir(":/styles/");
qDebug() << "styles:" << dir.entryList(); // qDebug() << "styles:" << dir.entryList();
return dir.entryList(QDir::Dirs); return dir.entryList(QDir::Dirs);
} }

View File

@ -116,9 +116,9 @@ ApplicationWindow {
objectName: "pageStack" objectName: "pageStack"
anchors.fill: parent anchors.fill: parent
initialItem: Page {} initialItem: Page {}
onDepthChanged: { // onDepthChanged: {
print("stackview depth changed", pageStack.depth) // print("stackview depth changed", pageStack.depth)
} // }
} }
onClosing: { onClosing: {

View File

@ -1,6 +1,7 @@
import QtQuick 2.9 import QtQuick 2.9
import QtQuick.Controls 2.2 import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.2
SwipeDelegate { SwipeDelegate {
id: root id: root
@ -9,6 +10,9 @@ SwipeDelegate {
property bool progressive: true property bool progressive: true
property bool canDelete: false property bool canDelete: false
property bool wrapTexts: true
property bool prominentSubText: true
property string iconName property string iconName
property int iconSize: app.iconSize property int iconSize: app.iconSize
property color iconColor: app.accentColor property color iconColor: app.accentColor
@ -37,8 +41,8 @@ SwipeDelegate {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
text: root.text text: root.text
wrapMode: Text.WordWrap wrapMode: root.wrapTexts ? Text.WordWrap : Text.NoWrap
maximumLineCount: 2 maximumLineCount: root.wrapTexts ? 2 : 1
elide: Text.ElideRight elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
@ -46,9 +50,10 @@ SwipeDelegate {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
text: root.subText text: root.subText
font.pixelSize: app.smallFont font.pixelSize: root.prominentSubText ? app.smallFont : app.extraSmallFont
wrapMode: Text.WordWrap color: root.prominentSubText ? Material.foreground : Material.color(Material.Grey)
maximumLineCount: 2 wrapMode: root.wrapTexts ? Text.WordWrap : Text.NoWrap
maximumLineCount: root.wrapTexts ? 2 : 1
elide: Text.ElideRight elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
visible: root.subText.length > 0 visible: root.subText.length > 0

View File

@ -85,9 +85,9 @@ Page {
header: FancyHeader { header: FancyHeader {
title: qsTr("Connect %1").arg(app.systemName) title: qsTr("Connect %1").arg(app.systemName)
model: ListModel { model: ListModel {
ListElement { iconSource: "../images/network-vpn.svg"; text: qsTr("Manual connection"); page: "connection/ManualConnectPage.qml" } ListElement { iconSource: "../images/network-vpn.svg"; text: qsTr("Manual connection"); page: "ManualConnectPage.qml" }
ListElement { iconSource: "../images/bluetooth.svg"; text: qsTr("Wireless setup"); page: "connection/BluetoothDiscoveryPage.qml"; } ListElement { iconSource: "../images/bluetooth.svg"; text: qsTr("Wireless setup"); page: "BluetoothDiscoveryPage.qml"; }
ListElement { iconSource: "../images/cloud.svg"; text: qsTr("Cloud login"); page: "connection/CloudLoginPage.qml" } ListElement { iconSource: "../images/cloud.svg"; text: qsTr("Cloud login"); page: "CloudLoginPage.qml" }
ListElement { iconSource: "../images/stock_application.svg"; text: qsTr("App settings"); page: "AppSettingsPage.qml" } ListElement { iconSource: "../images/stock_application.svg"; text: qsTr("App settings"); page: "AppSettingsPage.qml" }
} }
onClicked: { onClicked: {
@ -145,58 +145,68 @@ Page {
height: app.delegateHeight height: app.delegateHeight
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 defaultConnectionIndex: {
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.connections.count; i++) {
var oldConfig = discoveryDevice.portConfigs.get(usedConfigIndex); var oldConfig = discoveryDevice.connections.get(usedConfigIndex);
var newConfig = discoveryDevice.portConfigs.get(i); var newConfig = discoveryDevice.connections.get(i);
// prefer secure over insecure // Preference of bearerType
if (!oldConfig.sslEnabled && newConfig.sslEnabled) { var bearerPreference = [Connection.BearerTypeEthernet, Connection.BearerTypeWifi, Connection.BearerTypeBluetooth, Connection.BearerTypeCloud]
var oldBearerPriority = bearerPreference.indexOf(oldConfig.bearerType);
var newBearerPriority = bearerPreference.indexOf(newConfig.bearerType);
if (newBearerPriority > oldBearerPriority) {
usedConfigIndex = i; usedConfigIndex = i;
continue; continue;
} }
if (oldConfig.sslEnabled && !newConfig.sslEnabled) { if (oldBearerPriority > newBearerPriority) {
continue; // discard new one the one we have is on a better bearer type
}
// prefer secure over insecure
if (!oldConfig.secure && newConfig.secure) {
usedConfigIndex = i;
continue;
}
if (oldConfig.secure && !newConfig.secure) {
continue; // discard new one as the one we already have is more secure continue; // discard new one as the one we already have is more secure
} }
// both options are new either secure or insecure, prefer nymearpc over websocket for less overhead // both options are now on the same bearer and either secure or insecure, prefer nymearpc over websocket for less overhead
if (oldConfig.protocol === PortConfig.ProtocolWebSocket && newConfig.protocol === PortConfig.ProtocolNymeaRpc) { if (oldConfig.url.toString().startsWith("ws") && newConfig.url.toString().startsWith("nymea")) {
usedConfigIndex = i; usedConfigIndex = i;
} }
} }
return usedConfigIndex return usedConfigIndex
} }
iconName: model.deviceType === DiscoveryDevice.DeviceTypeNetwork ? "../images/network-wifi-symbolic.svg" : "../images/bluetooth.svg" iconName: {
switch (discoveryDevice.connections.get(defaultConnectionIndex).bearerType) {
case Connection.BearerTypeWifi:
return "../images/network-wifi-symbolic.svg";
case Connection.BearerTypeEthernet:
return "../images/network-wired-symbolic.svg"
case Connection.BearerTypeBluetooth:
return "../images/bluetooth.svg";
case Connection.BearerTypeCloud:
return "../images/cloud.svg"
}
return ""
}
text: model.name text: model.name
subText: model.deviceType === DiscoveryDevice.DeviceTypeNetwork ? discoveryDevice.hostAddress : discoveryDevice.bluetoothAddress subText: discoveryDevice.connections.get(defaultConnectionIndex).url
property bool hasSecurePort: { wrapTexts: false
if (discoveryDevice.deviceType === DiscoveryDevice.DeviceTypeNetwork) { prominentSubText: false
return discoveryDeviceDelegate.discoveryDevice.portConfigs.get(discoveryDeviceDelegate.defaultPortConfigIndex).sslEnabled progressive: false
} else { property bool isSecure: discoveryDevice.connections.get(defaultConnectionIndex).secure
return false property bool isTrusted: Engine.connection.isTrusted(discoveryDeviceDelegate.discoveryDevice.connections.get(defaultConnectionIndex).url)
} secondaryIconName: isSecure ? "../images/network-secure.svg" : ""
}
property bool isTrusted: {
if (discoveryDeviceDelegate.discoveryDevice.deviceType === DiscoveryDevice.DeviceTypeNetwork) {
Engine.connection.isTrusted(discoveryDeviceDelegate.discoveryDevice.toUrl(discoveryDeviceDelegate.defaultPortConfigIndex))
} else {
return false
}
}
progressive: true
secondaryIconName: "../images/network-secure.svg"
secondaryIconColor: isTrusted ? app.accentColor : Material.foreground secondaryIconColor: isTrusted ? app.accentColor : Material.foreground
swipe.enabled: discoveryDeviceDelegate.discoveryDevice.deviceType === DiscoveryDevice.DeviceTypeNetwork swipe.enabled: discoveryDeviceDelegate.discoveryDevice.deviceType === DiscoveryDevice.DeviceTypeNetwork
onClicked: { onClicked: {
Engine.connection.connect(discoveryDeviceDelegate.discoveryDevice.toUrl(discoveryDeviceDelegate.defaultPortConfigIndex)) Engine.connection.connect(discoveryDeviceDelegate.discoveryDevice.connections.get(defaultConnectionIndex).url)
var page = pageStack.push(Qt.resolvedUrl("ConnectingPage.qml")) var page = pageStack.push(Qt.resolvedUrl("ConnectingPage.qml"))
page.cancel.connect(function() { page.cancel.connect(function() {
Engine.connection.disconnect() Engine.connection.disconnect()
@ -484,35 +494,34 @@ Page {
id: contentColumn id: contentColumn
width: parent.width width: parent.width
Repeater { Repeater {
model: dialog.discoveryDevice.portConfigs model: dialog.discoveryDevice.connections
ItemDelegate { delegate: MeaListItemDelegate {
Layout.fillWidth: true Layout.fillWidth: true
contentItem: RowLayout { wrapTexts: false
ColumnLayout { progressive: false
Layout.fillWidth: true text: model.name
Label { subText: model.url
Layout.fillWidth: true prominentSubText: false
elide: Text.ElideMiddle iconName: {
text: "%1:%2".arg(model.address).arg(model.port) switch (model.bearerType) {
} case Connection.BearerTypeWifi:
Label { return "../images/network-wifi-symbolic.svg";
text: model.protocol === PortConfig.ProtocolNymeaRpc ? "nymea-rpc" : "websocket" case Connection.BearerTypeEthernet:
Layout.fillWidth: true return "../images/network-wired-symbolic.svg"
font.pixelSize: app.smallFont case Connection.BearerTypeBluetooth:
} return "../images/bluetooth.svg";
} case Connection.BearerTypeCloud:
return "../images/cloud.svg"
ColorIcon {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: height
visible: model.sslEnabled
name: "../images/network-secure.svg"
property bool isTrusted: Engine.connection.isTrusted(dialog.discoveryDevice.toUrl(index))
color: isTrusted ? app.accentColor : keyColor
} }
return ""
} }
secondaryIconName: model.secure ? "../images/network-secure.svg" : ""
secondaryIconColor: isTrusted ? app.accentColor : "gray"
readonly property bool isTrusted: Engine.connection.isTrusted(url)
onClicked: { onClicked: {
Engine.connection.connect(dialog.discoveryDevice.toUrl(index)) Engine.connection.connect(dialog.discoveryDevice.connections.get(index).url)
dialog.close() dialog.close()
} }
} }

1
qmqtt Submodule

@ -0,0 +1 @@
Subproject commit 0defd80f002a4bcb7b92605393708d4c68c89988