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"]
path = aws-sdk-qt
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";
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/");
@ -131,6 +131,7 @@ void AWSClient::getIdReply()
void AWSClient::fetchDevices()
{
qDebug() << "Fetching cloud devices";
QUrl url("https://z6368zhf2m.execute-api.eu-west-1.amazonaws.com/dev/devices");
QNetworkRequest request(url);
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();
QByteArray accessToken() const;
signals:
void isLoggedInChanged();

View File

@ -20,29 +20,29 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "bluetoothinterface.h"
#include "bluetoothtransport.h"
#include <QUrl>
#include <QDebug>
#include <QUrlQuery>
BluetoothInterface::BluetoothInterface(QObject *parent) :
NymeaInterface(parent)
BluetoothTransport::BluetoothTransport(QObject *parent) :
NymeaTransportInterface(parent)
{
m_socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
QObject::connect(m_socket, &QBluetoothSocket::connected, this, &BluetoothInterface::onConnected);
QObject::connect(m_socket, &QBluetoothSocket::disconnected, this, &BluetoothInterface::onDisconnected);
QObject::connect(m_socket, &QBluetoothSocket::readyRead, this, &BluetoothInterface::onDataReady);
QObject::connect(m_socket, &QBluetoothSocket::stateChanged, this, &BluetoothInterface::onDataReady);
QObject::connect(m_socket, &QBluetoothSocket::connected, this, &BluetoothTransport::onConnected);
QObject::connect(m_socket, &QBluetoothSocket::disconnected, this, &BluetoothTransport::onDisconnected);
QObject::connect(m_socket, &QBluetoothSocket::readyRead, this, &BluetoothTransport::onDataReady);
QObject::connect(m_socket, &QBluetoothSocket::stateChanged, this, &BluetoothTransport::onDataReady);
}
QStringList BluetoothInterface::supportedSchemes() const
QStringList BluetoothTransport::supportedSchemes() const
{
return {"rfcom"};
}
void BluetoothInterface::connect(const QUrl &url)
void BluetoothTransport::connect(const QUrl &url)
{
if (url.scheme() != "rfcom") {
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")));
}
void BluetoothInterface::disconnect()
void BluetoothTransport::disconnect()
{
m_socket->close();
}
NymeaInterface::ConnectionState BluetoothInterface::connectionState() const
NymeaTransportInterface::ConnectionState BluetoothTransport::connectionState() const
{
switch (m_socket->state()) {
case QBluetoothSocket::ConnectedState:
return NymeaInterface::ConnectionStateConnected;
return NymeaTransportInterface::ConnectionStateConnected;
case QBluetoothSocket::ConnectingState:
case QBluetoothSocket::ServiceLookupState:
return NymeaInterface::ConnectionStateConnecting;
return NymeaTransportInterface::ConnectionStateConnecting;
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);
m_socket->write(data);
}
void BluetoothInterface::onServiceFound(const QBluetoothServiceInfo &service)
void BluetoothTransport::onServiceFound(const QBluetoothServiceInfo &service)
{
m_service = service;
if (m_socket->isOpen())
@ -92,24 +92,24 @@ void BluetoothInterface::onServiceFound(const QBluetoothServiceInfo &service)
m_socket->connectToService(m_service);
}
void BluetoothInterface::onConnected()
void BluetoothTransport::onConnected()
{
qDebug() << "BluetoothInterface: connected" << m_socket->peerName() << m_socket->peerAddress();
emit connected();
}
void BluetoothInterface::onDisconnected()
void BluetoothTransport::onDisconnected()
{
qDebug() << "BluetoothInterface: disconnected" << m_socket->peerName() << m_socket->peerAddress();
emit disconnected();
}
void BluetoothInterface::onStateChanged(const QBluetoothSocket::SocketState &state)
void BluetoothTransport::onStateChanged(const QBluetoothSocket::SocketState &state)
{
qDebug() << "BluetoothInterface" << state;
}
void BluetoothInterface::onDataReady()
void BluetoothTransport::onDataReady()
{
QByteArray data = m_socket->readAll();
qDebug() << "BluetoothInterface: recived data:" << qUtf8Printable(data);

View File

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

View File

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

View File

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

View File

@ -20,14 +20,14 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef NYMEAINTERFACE_H
#define NYMEAINTERFACE_H
#ifndef NYMEATRANSPORTINTERFACE_H
#define NYMEATRANSPORTINTERFACE_H
#include <QObject>
#include <QSslCertificate>
#include <QHostAddress>
class NymeaInterface : public QObject
class NymeaTransportInterface : public QObject
{
Q_OBJECT
public:
@ -38,7 +38,8 @@ public:
};
Q_ENUM(ConnectionState)
explicit NymeaInterface(QObject *parent = 0);
explicit NymeaTransportInterface(QObject *parent = nullptr);
virtual ~NymeaTransportInterface() = default;
virtual QStringList supportedSchemes() const = 0;
@ -56,4 +57,4 @@ signals:
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>
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::disconnected, this, &TcpSocketInterface::disconnected);
QObject::connect(&m_socket, &QSslSocket::encrypted, this, &TcpSocketInterface::onEncrypted);
QObject::connect(&m_socket, &QSslSocket::connected, this, &TcpSocketTransport::onConnected);
QObject::connect(&m_socket, &QSslSocket::disconnected, this, &TcpSocketTransport::disconnected);
QObject::connect(&m_socket, &QSslSocket::encrypted, this, &TcpSocketTransport::onEncrypted);
typedef void (QSslSocket:: *sslErrorsSignal)(const QList<QSslError> &);
QObject::connect(&m_socket, static_cast<sslErrorsSignal>(&QSslSocket::sslErrors), this, &TcpSocketInterface::sslErrors);
QObject::connect(&m_socket, &QSslSocket::readyRead, this, &TcpSocketInterface::socketReadyRead);
QObject::connect(&m_socket, static_cast<sslErrorsSignal>(&QSslSocket::sslErrors), this, &TcpSocketTransport::sslErrors);
QObject::connect(&m_socket, &QSslSocket::readyRead, this, &TcpSocketTransport::socketReadyRead);
typedef void (QSslSocket:: *errorSignal)(QAbstractSocket::SocketError);
QObject::connect(&m_socket, static_cast<errorSignal>(&QSslSocket::error), this, &TcpSocketInterface::error);
QObject::connect(&m_socket, &QSslSocket::stateChanged, this, &TcpSocketInterface::onSocketStateChanged);
QObject::connect(&m_socket, static_cast<errorSignal>(&QSslSocket::error), this, &TcpSocketTransport::error);
QObject::connect(&m_socket, &QSslSocket::stateChanged, this, &TcpSocketTransport::onSocketStateChanged);
}
QStringList TcpSocketInterface::supportedSchemes() const
QStringList TcpSocketTransport::supportedSchemes() const
{
return {"nymea", "nymeas"};
}
void TcpSocketInterface::sendData(const QByteArray &data)
void TcpSocketTransport::sendData(const QByteArray &data)
{
qint64 ret = m_socket.write(data);
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);
}
void TcpSocketInterface::onConnected()
void TcpSocketTransport::onConnected()
{
if (m_url.scheme() == "nymea") {
qDebug() << "TCP socket connected";
@ -42,13 +42,13 @@ void TcpSocketInterface::onConnected()
}
}
void TcpSocketInterface::onEncrypted()
void TcpSocketTransport::onEncrypted()
{
qDebug() << "TCP socket encrypted";
emit connected();
}
void TcpSocketInterface::connect(const QUrl &url)
void TcpSocketTransport::connect(const QUrl &url)
{
m_url = url;
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()) {
case QAbstractSocket::ConnectedState:
return NymeaInterface::ConnectionStateConnected;
return NymeaTransportInterface::ConnectionStateConnected;
case QAbstractSocket::ConnectingState:
case QAbstractSocket::HostLookupState:
return NymeaInterface::ConnectionStateConnecting;
return NymeaTransportInterface::ConnectionStateConnecting;
default:
return NymeaInterface::ConnectionStateDisconnected;
return NymeaTransportInterface::ConnectionStateDisconnected;
}
}
void TcpSocketInterface::disconnect()
void TcpSocketTransport::disconnect()
{
qDebug() << "closing socket";
m_socket.disconnectFromHost();
@ -85,13 +85,13 @@ void TcpSocketInterface::disconnect()
m_socket.abort();
}
void TcpSocketInterface::socketReadyRead()
void TcpSocketTransport::socketReadyRead()
{
QByteArray data = m_socket.readAll();
emit dataReady(data);
}
void TcpSocketInterface::onSocketStateChanged(const QAbstractSocket::SocketState &state)
void TcpSocketTransport::onSocketStateChanged(const QAbstractSocket::SocketState &state)
{
qDebug() << "Socket state changed -->" << state;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -23,9 +23,9 @@
#include <QUrl>
DiscoveryDevice::DiscoveryDevice(QObject *parent):
QObject(parent)
QObject(parent),
m_connections(new Connections(this))
{
m_portConfigs = new PortConfigs(this);
}
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)
{
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)
Connections::Connections(QObject *parent):
QAbstractListModel(parent)
{
}
int PortConfigs::rowCount(const QModelIndex &parent) const
int Connections::rowCount(const QModelIndex &parent) const
{
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) {
case RoleAddress:
return m_portConfigs.at(index.row())->hostAddressString();
case RolePort:
return m_portConfigs.at(index.row())->port();
case RoleProtocol:
return m_portConfigs.at(index.row())->protocol();
case RoleSSLEnabled:
return m_portConfigs.at(index.row())->sslEnabled();
case RoleUrl:
return m_connections.at(index.row())->url();
case RoleName:
return m_connections.at(index.row())->displayName();
case RoleBearerType:
return m_connections.at(index.row())->bearerType();
case RoleSecure:
return m_connections.at(index.row())->secure();
}
return QVariant();
}
PortConfig *PortConfigs::find(int port)
Connection* Connections::find(const QUrl &url) const
{
foreach (PortConfig* pc, m_portConfigs) {
if (pc->port() == port) {
return pc;
foreach (Connection *conn, m_connections) {
if (conn->url() == url) {
return conn;
}
}
return nullptr;
}
void PortConfigs::insert(PortConfig *portConfig)
void Connections::addConnection(Connection *connection)
{
portConfig->setParent(this);
beginInsertRows(QModelIndex(), m_portConfigs.count(), m_portConfigs.count());
m_portConfigs.append(portConfig);
connection->setParent(this);
beginInsertRows(QModelIndex(), m_connections.count(), m_connections.count());
m_connections.append(connection);
endInsertRows();
emit countChanged();
}
PortConfig* PortConfigs::get(int index) const
Connection* Connections::get(int index) const
{
if (index < 0 || index >= m_portConfigs.count())
return nullptr;
return m_portConfigs.at(index);
if (index >= 0 && index < m_connections.count()) {
return m_connections.at(index);
}
return nullptr;
}
QHash<int, QByteArray> PortConfigs::roleNames() const
QHash<int, QByteArray> Connections::roleNames() const
{
QHash<int, QByteArray> roles;
roles.insert(RoleAddress, "address");
roles.insert(RolePort, "port");
roles.insert(RoleProtocol, "protocol");
roles.insert(RoleSSLEnabled, "sslEnabled");
roles.insert(RoleUrl, "url");
roles.insert(RoleBearerType, "bearerType");
roles.insert(RoleName, "name");
roles.insert(RoleSecure, "secure");
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),
m_port(port),
m_hostAddress(hostAddress)
m_url(url),
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) {
m_protocol = protocol;
emit protocolChanged();
}
return m_secure;
}
QHostAddress PortConfig::hostAddress() const
QString Connection::displayName() const
{
return m_hostAddress;
}
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();
}
return m_displayName;
}

View File

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

View File

@ -3,7 +3,7 @@
#include "upnpdiscovery.h"
#include "zeroconfdiscovery.h"
#include "bluetoothservicediscovery.h"
#include "awsclient.h"
#include "connection/awsclient.h"
#include <QUuid>
#include <QBluetoothUuid>
@ -59,10 +59,21 @@ DiscoveryModel *NymeaDiscovery::discoveryModel() const
void NymeaDiscovery::cloudDevicesFetched(const QList<AWSDevice> &devices)
{
qDebug() << "Cloud devices fetched";
foreach (const AWSDevice &d, devices) {
DiscoveryDevice *device = m_discoveryModel->find(d.id);
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 "awsclient.h"
#include "connection/awsclient.h"
class DiscoveryModel;
class UpnpDiscovery;

View File

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

View File

@ -13,13 +13,13 @@ ZeroconfDiscovery::ZeroconfDiscovery(DiscoveryModel *discoveryModel, QObject *pa
connect(m_zeroconfJsonRPC, &QZeroConf::serviceAdded, this, &ZeroconfDiscovery::serviceEntryAdded);
connect(m_zeroconfJsonRPC, &QZeroConf::serviceUpdated, this, &ZeroconfDiscovery::serviceEntryAdded);
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);
connect(m_zeroconfWebSocket, &QZeroConf::serviceAdded, this, &ZeroconfDiscovery::serviceEntryAdded);
connect(m_zeroconfWebSocket, &QZeroConf::serviceUpdated, this, &ZeroconfDiscovery::serviceEntryAdded);
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
qDebug() << "Zeroconf support not compiled in. Zeroconf will not be available.";
#endif
@ -73,18 +73,25 @@ void ZeroconfDiscovery::serviceEntryAdded(const QZeroConfService &entry)
if (!device) {
device = new DiscoveryDevice(m_discoveryModel);
device->setUuid(uuid);
qDebug() << "ZeroConf: Adding new host to model";
qDebug() << "ZeroConf: Adding new host:" << serverName << uuid;
m_discoveryModel->addDevice(device);
}
device->setName(serverName);
device->setVersion(version);
PortConfig *portConfig = device->portConfigs()->find(entry.port());
if (!portConfig) {
qDebug() << "ZeroConf: Adding new port config";
portConfig = new PortConfig(!entry.ip().isNull() ? entry.ip() : entry.ipv6(), entry.port());
device->portConfigs()->insert(portConfig);
QUrl url;
if (entry.type() == "_jsonrpc._tcp") {
url.setScheme(sslEnabled ? "nymeas" : "nymea");
} else {
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

View File

@ -20,12 +20,16 @@
#include "engine.h"
#include "tcpsocketinterface.h"
#include "rulemanager.h"
#include "logmanager.h"
#include "tagsmanager.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;
@ -94,6 +98,11 @@ Engine::Engine(QObject *parent) :
m_bluetoothDiscovery(new BluetoothDiscovery(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::authenticationRequiredChanged, this, &Engine::onConnectedChanged);

View File

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

View File

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

View File

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

View File

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

View File

@ -10,19 +10,28 @@ include(../config.pri)
DEFINES += WITH_ZEROCONF
include(../QtZeroConf/qtzeroconf.pri)
}
DEFINES += QT_STATIC
include(../qmqtt/src/mqtt/mqtt.pri)
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
QT -= gui
QT += network websockets bluetooth
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 += \
engine.cpp \
nymeainterface.cpp \
connection/nymeaconnection.cpp \
connection/nymeatransportinterface.cpp \
connection/websockettransport.cpp \
connection/tcpsockettransport.cpp \
connection/bluetoothtransport.cpp \
connection/awsclient.cpp \
devicemanager.cpp \
websocketinterface.cpp \
jsonrpc/jsontypes.cpp \
jsonrpc/jsonrpcclient.cpp \
jsonrpc/jsonhandler.cpp \
@ -36,8 +45,6 @@ SOURCES += \
devicediscovery.cpp \
vendorsproxy.cpp \
pluginsproxy.cpp \
tcpsocketinterface.cpp \
nymeaconnection.cpp \
interfacesmodel.cpp \
discovery/zeroconfdiscovery.cpp \
discovery/discoverydevice.cpp \
@ -69,16 +76,18 @@ SOURCES += \
ruletemplates/ruleactiontemplate.cpp \
ruletemplates/stateevaluatortemplate.cpp \
ruletemplates/statedescriptortemplate.cpp \
bluetoothinterface.cpp \
discovery/bluetoothservicediscovery.cpp \
awsclient.cpp \
connection/srp.c
connection/cloudtransport.cpp
HEADERS += \
engine.h \
nymeainterface.h \
connection/nymeaconnection.h \
connection/nymeatransportinterface.h \
connection/websockettransport.h \
connection/tcpsockettransport.h \
connection/bluetoothtransport.h \
connection/awsclient.h \
devicemanager.h \
websocketinterface.h \
jsonrpc/jsontypes.h \
jsonrpc/jsonrpcclient.h \
jsonrpc/jsonhandler.h \
@ -92,8 +101,6 @@ HEADERS += \
devicediscovery.h \
vendorsproxy.h \
pluginsproxy.h \
tcpsocketinterface.h \
nymeaconnection.h \
interfacesmodel.h \
discovery/zeroconfdiscovery.h \
discovery/discoverydevice.h \
@ -126,9 +133,8 @@ HEADERS += \
ruletemplates/ruleactiontemplate.h \
ruletemplates/stateevaluatortemplate.h \
ruletemplates/statedescriptortemplate.h \
bluetoothinterface.h \
discovery/bluetoothservicediscovery.h \
awsclient.h
connection/cloudtransport.h
unix {
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
{
Q_UNUSED(source_parent)
Q_UNUSED(source_row)
// Filter out the current selected network
// 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()) {
int id = QFontDatabase::addApplicationFont(fi.absoluteFilePath());
qDebug() << "Added font" << fi.absoluteFilePath() << QFontDatabase::applicationFontFamilies(id);
// qDebug() << "Added font" << fi.absoluteFilePath() << QFontDatabase::applicationFontFamilies(id);
}
QFont applicationFont;

View File

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

View File

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

View File

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

View File

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

View File

@ -85,9 +85,9 @@ Page {
header: FancyHeader {
title: qsTr("Connect %1").arg(app.systemName)
model: ListModel {
ListElement { iconSource: "../images/network-vpn.svg"; text: qsTr("Manual connection"); page: "connection/ManualConnectPage.qml" }
ListElement { iconSource: "../images/bluetooth.svg"; text: qsTr("Wireless setup"); page: "connection/BluetoothDiscoveryPage.qml"; }
ListElement { iconSource: "../images/cloud.svg"; text: qsTr("Cloud login"); page: "connection/CloudLoginPage.qml" }
ListElement { iconSource: "../images/network-vpn.svg"; text: qsTr("Manual connection"); page: "ManualConnectPage.qml" }
ListElement { iconSource: "../images/bluetooth.svg"; text: qsTr("Wireless setup"); page: "BluetoothDiscoveryPage.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" }
}
onClicked: {
@ -145,58 +145,68 @@ Page {
height: app.delegateHeight
objectName: "discoveryDelegate" + index
property var discoveryDevice: discovery.discoveryModel.get(index)
property string defaultPortConfigIndex: {
if (model.deviceType !== DiscoveryDevice.DeviceTypeNetwork) {
return -1
}
property string defaultConnectionIndex: {
var usedConfigIndex = 0;
for (var i = 1; i < discoveryDevice.portConfigs.count; i++) {
var oldConfig = discoveryDevice.portConfigs.get(usedConfigIndex);
var newConfig = discoveryDevice.portConfigs.get(i);
for (var i = 1; i < discoveryDevice.connections.count; i++) {
var oldConfig = discoveryDevice.connections.get(usedConfigIndex);
var newConfig = discoveryDevice.connections.get(i);
// prefer secure over insecure
if (!oldConfig.sslEnabled && newConfig.sslEnabled) {
// Preference of bearerType
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;
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
}
// both options are new either secure or insecure, prefer nymearpc over websocket for less overhead
if (oldConfig.protocol === PortConfig.ProtocolWebSocket && newConfig.protocol === PortConfig.ProtocolNymeaRpc) {
// both options are now on the same bearer and either secure or insecure, prefer nymearpc over websocket for less overhead
if (oldConfig.url.toString().startsWith("ws") && newConfig.url.toString().startsWith("nymea")) {
usedConfigIndex = i;
}
}
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
subText: model.deviceType === DiscoveryDevice.DeviceTypeNetwork ? discoveryDevice.hostAddress : discoveryDevice.bluetoothAddress
property bool hasSecurePort: {
if (discoveryDevice.deviceType === DiscoveryDevice.DeviceTypeNetwork) {
return discoveryDeviceDelegate.discoveryDevice.portConfigs.get(discoveryDeviceDelegate.defaultPortConfigIndex).sslEnabled
} else {
return false
}
}
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"
subText: discoveryDevice.connections.get(defaultConnectionIndex).url
wrapTexts: false
prominentSubText: false
progressive: false
property bool isSecure: discoveryDevice.connections.get(defaultConnectionIndex).secure
property bool isTrusted: Engine.connection.isTrusted(discoveryDeviceDelegate.discoveryDevice.connections.get(defaultConnectionIndex).url)
secondaryIconName: isSecure ? "../images/network-secure.svg" : ""
secondaryIconColor: isTrusted ? app.accentColor : Material.foreground
swipe.enabled: discoveryDeviceDelegate.discoveryDevice.deviceType === DiscoveryDevice.DeviceTypeNetwork
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"))
page.cancel.connect(function() {
Engine.connection.disconnect()
@ -484,35 +494,34 @@ Page {
id: contentColumn
width: parent.width
Repeater {
model: dialog.discoveryDevice.portConfigs
ItemDelegate {
model: dialog.discoveryDevice.connections
delegate: MeaListItemDelegate {
Layout.fillWidth: true
contentItem: RowLayout {
ColumnLayout {
Layout.fillWidth: true
Label {
Layout.fillWidth: true
elide: Text.ElideMiddle
text: "%1:%2".arg(model.address).arg(model.port)
}
Label {
text: model.protocol === PortConfig.ProtocolNymeaRpc ? "nymea-rpc" : "websocket"
Layout.fillWidth: true
font.pixelSize: app.smallFont
}
}
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
wrapTexts: false
progressive: false
text: model.name
subText: model.url
prominentSubText: false
iconName: {
switch (model.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 ""
}
secondaryIconName: model.secure ? "../images/network-secure.svg" : ""
secondaryIconColor: isTrusted ? app.accentColor : "gray"
readonly property bool isTrusted: Engine.connection.isTrusted(url)
onClicked: {
Engine.connection.connect(dialog.discoveryDevice.toUrl(index))
Engine.connection.connect(dialog.discoveryDevice.connections.get(index).url)
dialog.close()
}
}

1
qmqtt Submodule

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