diff --git a/debian/control b/debian/control index 696e14f..1afd2c2 100644 --- a/debian/control +++ b/debian/control @@ -5,6 +5,7 @@ Maintainer: Simon Stürz Build-depends: debhelper (>= 0.0.0), dh-systemd, libqt5websockets5-dev, + libncurses5-dev, Standards-Version: 3.9.3 Package: nymea-remoteproxy @@ -13,10 +14,10 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, awscli, libnymea-remoteproxy (= ${binary:Version}), +Suggests: nymea-remoteproxy-monitor (= ${binary:Version}) Description: The nymea remote proxy server The nymea remote proxy server - Package: libnymea-remoteproxy Architecture: any Section: libs @@ -85,3 +86,11 @@ Depends: ${shlibs:Depends}, libnymea-remoteproxy (= ${binary:Version}), Description: The nymea remote proxy server tests The nymea remote proxy server tests + +Package: nymea-remoteproxy-monitor +Architecture: any +Depends: ${shlibs:Depends}, + ${misc:Depends}, + libncurses5, +Description: The nymea remote proxy monitor tool + The nymea remote proxy server tests diff --git a/debian/nymea-remoteproxy-monitor.install b/debian/nymea-remoteproxy-monitor.install new file mode 100644 index 0000000..a8cb356 --- /dev/null +++ b/debian/nymea-remoteproxy-monitor.install @@ -0,0 +1 @@ +usr/bin/nymea-remoteproxy-monitor diff --git a/libnymea-remoteproxy/proxyconfiguration.cpp b/libnymea-remoteproxy/proxyconfiguration.cpp index fb10c5a..1286178 100644 --- a/libnymea-remoteproxy/proxyconfiguration.cpp +++ b/libnymea-remoteproxy/proxyconfiguration.cpp @@ -53,9 +53,9 @@ bool ProxyConfiguration::loadConfiguration(const QString &fileName) setMonitorSocketFileName(settings.value("monitorSocket", "/tmp/nymea-remoteproxy.monitor").toString()); setJsonRpcTimeout(settings.value("jsonRpcTimeout", 10000).toInt()); - setAuthenticationTimeout(settings.value("authenticationTimeout", 5000).toInt()); - setInactiveTimeout(settings.value("inactiveTimeout", 5000).toInt()); - setAloneTimeout(settings.value("aloneTimeout", 5000).toInt()); + setAuthenticationTimeout(settings.value("authenticationTimeout", 8000).toInt()); + setInactiveTimeout(settings.value("inactiveTimeout", 8000).toInt()); + setAloneTimeout(settings.value("aloneTimeout", 8000).toInt()); settings.endGroup(); diff --git a/libnymea-remoteproxy/proxyserver.cpp b/libnymea-remoteproxy/proxyserver.cpp index 8b39ec6..0d454a0 100644 --- a/libnymea-remoteproxy/proxyserver.cpp +++ b/libnymea-remoteproxy/proxyserver.cpp @@ -23,6 +23,7 @@ #include "loggingcategories.h" #include +#include #include namespace remoteproxy { @@ -64,6 +65,33 @@ QVariantMap ProxyServer::currentStatistics() QVariantMap statisticsMap; statisticsMap.insert("clientCount", m_proxyClients.count()); statisticsMap.insert("tunnelCount", m_tunnels.count()); + + // Create client list + QVariantList clientList; + foreach (ProxyClient *client, m_proxyClients) { + QVariantMap clientMap; + clientMap.insert("id", client->clientId().toString()); + clientMap.insert("address", client->peerAddress().toString()); + clientMap.insert("timestamp", client->creationTime()); + clientMap.insert("authenticated", client->isAuthenticated()); + clientMap.insert("tunnelConnected", client->isTunnelConnected()); + clientMap.insert("name", client->name()); + clientMap.insert("uuid", client->uuid()); + clientList.append(clientMap); + } + statisticsMap.insert("clients", clientList); + + // Create tunnel list + QVariantList tunnelList; + foreach (const TunnelConnection &tunnel, m_tunnels) { + QVariantMap tunnelMap; + tunnelMap.insert("clientOne", tunnel.clientOne()->clientId().toString()); + tunnelMap.insert("clientTwo", tunnel.clientTwo()->clientId().toString()); + tunnelMap.insert("timestamp", tunnel.creationTime()); + tunnelList.append(tunnelMap); + } + statisticsMap.insert("tunnels", tunnelList); + return statisticsMap; } diff --git a/libnymea-remoteproxy/tunnelconnection.cpp b/libnymea-remoteproxy/tunnelconnection.cpp index 3aa3bd2..1ea6340 100644 --- a/libnymea-remoteproxy/tunnelconnection.cpp +++ b/libnymea-remoteproxy/tunnelconnection.cpp @@ -21,13 +21,15 @@ #include "tunnelconnection.h" +#include + namespace remoteproxy { TunnelConnection::TunnelConnection(ProxyClient *clientOne, ProxyClient *clientTwo): m_clientOne(clientOne), m_clientTwo(clientTwo) { - + m_creationTimeStamp = QDateTime::currentDateTime().toTime_t(); } QString TunnelConnection::token() const @@ -38,6 +40,16 @@ QString TunnelConnection::token() const return m_clientOne->token(); } +uint TunnelConnection::creationTime() const +{ + return m_creationTimeStamp; +} + +QString TunnelConnection::creationTimeString() const +{ + return QDateTime::fromTime_t(creationTime()).toString("dd.MM.yyyy hh:mm:ss"); +} + ProxyClient *TunnelConnection::clientOne() const { return m_clientOne; @@ -65,4 +77,12 @@ bool TunnelConnection::isValid() const return true; } +QDebug operator<<(QDebug debug, const TunnelConnection &tunnel) +{ + debug.nospace() << "TunnelConnection(" << tunnel.creationTimeString() << ")" << endl; + debug.nospace() << " client:" << tunnel.clientOne() << endl; + debug.nospace() << " client:" << tunnel.clientTwo() << endl; + return debug; +} + } diff --git a/libnymea-remoteproxy/tunnelconnection.h b/libnymea-remoteproxy/tunnelconnection.h index 386dd80..f8c376a 100644 --- a/libnymea-remoteproxy/tunnelconnection.h +++ b/libnymea-remoteproxy/tunnelconnection.h @@ -33,17 +33,24 @@ public: QString token() const; + uint creationTime() const; + QString creationTimeString() const; + ProxyClient *clientOne() const; ProxyClient *clientTwo() const; bool isValid() const; private: + uint m_creationTimeStamp = 0; + ProxyClient *m_clientOne = nullptr; ProxyClient *m_clientTwo = nullptr; }; +QDebug operator<< (QDebug debug, const TunnelConnection &tunnel); + } #endif // TUNNELCONNECTION_H diff --git a/monitor/main.cpp b/monitor/main.cpp index a77d37b..80e95c8 100644 --- a/monitor/main.cpp +++ b/monitor/main.cpp @@ -25,6 +25,8 @@ #include #include +#include "monitor.h" + int main(int argc, char *argv[]) { @@ -36,8 +38,7 @@ int main(int argc, char *argv[]) QCommandLineParser parser; parser.addHelpOption(); parser.addVersionOption(); - parser.setApplicationDescription(QString("\nThe nymea remote proxy server client application. This client allowes to test " - "a server application as client perspective.\n\n" + parser.setApplicationDescription(QString("\nThe nymea remote proxy monitor allowes to monitor the live server activity on the a local instance.\n\n" "Server version: %1\n" "API version: %2\n\n" "Copyright %3 2018 Simon Stürz \n") @@ -46,10 +47,13 @@ int main(int argc, char *argv[]) .arg(QChar(0xA9))); - QCommandLineOption tokenOption(QStringList() << "s" << "socket", "The AWS token for authentication. Default /tmp/", "socket"); - parser.addOption(tokenOption); + QCommandLineOption socketOption(QStringList() << "s" << "socket", "The socket descriptor for the nymea-remoteproxy monitor socket. Default is /tmp/nymea-remoteproxy-monitor.sock", "socket"); + socketOption.setDefaultValue("/tmp/nymea-remoteproxy-monitor.sock"); + parser.addOption(socketOption); parser.process(application); + Monitor monitor(parser.value(socketOption)); + return application.exec(); } diff --git a/monitor/monitor.cpp b/monitor/monitor.cpp new file mode 100644 index 0000000..1b48168 --- /dev/null +++ b/monitor/monitor.cpp @@ -0,0 +1,11 @@ +#include "monitor.h" + +Monitor::Monitor(const QString &serverName, QObject *parent) : QObject(parent) +{ + m_terminal = new TerminalWindow(this); + m_monitorClient = new MonitorClient(serverName, this); + + connect(m_monitorClient, &MonitorClient::dataReady, m_terminal, &TerminalWindow::refreshWindow); + + m_monitorClient->connectMonitor(); +} diff --git a/monitor/monitor.h b/monitor/monitor.h new file mode 100644 index 0000000..ae93ff1 --- /dev/null +++ b/monitor/monitor.h @@ -0,0 +1,42 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2018 Simon Stürz * + * * + * This file is part of nymea-remoteproxy. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef MONITOR_H +#define MONITOR_H + +#include + +#include "monitorclient.h" +#include "terminalwindow.h" + +class Monitor : public QObject +{ + Q_OBJECT +public: + explicit Monitor(const QString &serverName, QObject *parent = nullptr); + +private: + TerminalWindow *m_terminal = nullptr; + MonitorClient *m_monitorClient = nullptr; + +}; + +#endif // MONITOR_H diff --git a/monitor/monitor.pro b/monitor/monitor.pro index 53236c6..49dbf05 100644 --- a/monitor/monitor.pro +++ b/monitor/monitor.pro @@ -3,9 +3,17 @@ include(../nymea-remoteproxy.pri) TARGET = nymea-remoteproxy-monitor TEMPLATE = app -SOURCES += main.cpp +SOURCES += main.cpp \ + monitorclient.cpp \ + terminalwindow.cpp \ + monitor.cpp + +LIBS += -lncurses target.path = /usr/bin INSTALLS += target HEADERS += \ + monitorclient.h \ + terminalwindow.h \ + monitor.h diff --git a/monitor/monitorclient.cpp b/monitor/monitorclient.cpp new file mode 100644 index 0000000..8da8313 --- /dev/null +++ b/monitor/monitorclient.cpp @@ -0,0 +1,73 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2018 Simon Stürz * + * * + * This file is part of nymea-remoteproxy. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "monitorclient.h" + +#include + +MonitorClient::MonitorClient(const QString &serverName, QObject *parent) : + QObject(parent), + m_serverName(serverName) +{ + m_socket = new QLocalSocket(this); + + connect(m_socket, &QLocalSocket::connected, this, &MonitorClient::onConnected); + connect(m_socket, &QLocalSocket::disconnected, this, &MonitorClient::onDisconnected); + connect(m_socket, &QLocalSocket::readyRead, this, &MonitorClient::onReadyRead); +} + +void MonitorClient::onConnected() +{ + qDebug() << "Monitor connected to" << m_serverName; +} + +void MonitorClient::onDisconnected() +{ + qDebug() << "Monitor disconnected from" << m_serverName; +} + +void MonitorClient::onReadyRead() +{ + QByteArray data = m_socket->readAll(); + + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + + if(error.error != QJsonParseError::NoError) { + qWarning() << "Failed to parse JSON data" << data << ":" << error.errorString(); + return; + } + + //qDebug() << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented)); + + QVariantMap dataMap = jsonDoc.toVariant().toMap(); + emit dataReady(dataMap); +} + +void MonitorClient::connectMonitor() +{ + m_socket->connectToServer(m_serverName, QLocalSocket::ReadOnly); +} + +void MonitorClient::disconnectMonitor() +{ + m_socket->close(); +} diff --git a/monitor/monitorclient.h b/monitor/monitorclient.h new file mode 100644 index 0000000..ac8aede --- /dev/null +++ b/monitor/monitorclient.h @@ -0,0 +1,53 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2018 Simon Stürz * + * * + * This file is part of nymea-remoteproxy. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef MONITORCLIENT_H +#define MONITORCLIENT_H + +#include +#include + +#include "terminalwindow.h" + +class MonitorClient : public QObject +{ + Q_OBJECT +public: + explicit MonitorClient(const QString &serverName, QObject *parent = nullptr); + +private: + QString m_serverName; + QLocalSocket *m_socket = nullptr; +signals: + void dataReady(const QVariantMap &data); + +private slots: + void onConnected(); + void onDisconnected(); + void onReadyRead(); + +public slots: + void connectMonitor(); + void disconnectMonitor(); + +}; + +#endif // MONITORCLIENT_H diff --git a/monitor/terminalwindow.cpp b/monitor/terminalwindow.cpp new file mode 100644 index 0000000..d5ac489 --- /dev/null +++ b/monitor/terminalwindow.cpp @@ -0,0 +1,234 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2018 Simon Stürz * + * * + * This file is part of nymea-remoteproxy. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "terminalwindow.h" + +#include +#include +#include + +TerminalWindow::TerminalWindow(QObject *parent) : + QObject(parent) +{ + // Create main window + m_mainWindow = initscr(); + start_color(); + + init_pair(1, COLOR_BLACK, COLOR_GREEN); + init_pair(2, COLOR_BLACK, COLOR_RED); + + // Configure behaviour + cbreak(); + noecho(); + curs_set(FALSE); + + //clear(); + + keypad(m_mainWindow, true); + nodelay(m_mainWindow, true); + getmaxyx(stdscr, m_terminalSizeY, m_terminalSizeX); + + // Create header and content window + m_headerWindow = newwin(m_headerHeight, m_terminalSizeX, 0, 0); + m_contentWindow = newwin(m_terminalSizeY - m_headerHeight, m_terminalSizeX, m_headerHeight, 0); + + // Draw borders + wclear(m_headerWindow); + wclear(m_contentWindow); + + mvwprintw(m_headerWindow, 1, 2, convertString("Connecting...")); + + box(m_headerWindow, 0 , 0); + box(m_contentWindow, 0 , 0); + + // Refresh windows + wrefresh(m_headerWindow); + wrefresh(m_contentWindow); + + refresh(); +} + +TerminalWindow::~TerminalWindow() +{ + clear(); + delwin(m_headerWindow); + delwin(m_contentWindow); + delwin(m_mainWindow); + endwin(); +} + +const char *TerminalWindow::convertString(const QString &string) +{ + return reinterpret_cast(string.toLatin1().data()); +} + +void TerminalWindow::resizeWindow() +{ + int terminalSizeX; + int terminalSizeY; + getmaxyx(stdscr, terminalSizeY, terminalSizeX); + if (m_terminalSizeX != terminalSizeX || m_terminalSizeY != terminalSizeY) { + m_terminalSizeX = terminalSizeX; + m_terminalSizeY = terminalSizeY; + wresize(m_headerWindow, m_headerHeight, m_terminalSizeX); + wresize(m_contentWindow, m_terminalSizeY - m_headerHeight, m_terminalSizeX); + } +} + +void TerminalWindow::paintHeader() +{ + QString headerString = QString(" Server: %1 %2 | API version %3 | Clients: %4 | Tunnels %5 | %6 %7") + .arg(m_dataMap.value("serverName").toString()) + .arg(m_dataMap.value("serverVersion").toString()) + .arg(m_dataMap.value("apiVersion").toString()) + .arg(m_dataMap.value("proxyStatistic").toMap().value("clientCount").toInt()) + .arg(m_dataMap.value("proxyStatistic").toMap().value("tunnelCount").toInt()) + .arg((m_view == ViewClients ? "Clients" : "Tunnels")) + .arg("", m_terminalSizeX, ' '); + + + wclear(m_headerWindow); + wattron(m_headerWindow, A_BOLD | COLOR_PAIR(1)); + mvwprintw(m_headerWindow, 1, 2, convertString(headerString)); + wattroff(m_headerWindow, A_BOLD | COLOR_PAIR(1)); + box(m_headerWindow, 0 , 0); + wrefresh(m_headerWindow); +} + +void TerminalWindow::paintContentClients() +{ + int i = 1; + + wclear(m_contentWindow); + foreach (const QVariant &clientVariant, m_clientHash.values()) { + QVariantMap clientMap = clientVariant.toMap(); + + uint timeStamp = clientMap.value("timestamp").toUInt(); + QString clientConnectionTime = QDateTime::fromTime_t(timeStamp).toString("dd.MM.yyyy hh:mm:ss"); + + QString clientPrint = QString("%1 | %2 | %3 | %4 | %5 | %6 |") + .arg(clientConnectionTime) + .arg(clientMap.value("address").toString()) + .arg(clientMap.value("uuid").toString()) + .arg(clientMap.value("name").toString(), -30) + .arg((clientMap.value("authenticated").toBool() ? "auth" : "no auth"), -9) + .arg((clientMap.value("tunnelConnected").toBool() ? "<--->" : " | ")); + + mvwprintw(m_contentWindow, i, 2, convertString(clientPrint)); + i++; + } + + // Draw borders + box(m_contentWindow, 0 , 0); + wrefresh(m_contentWindow); +} + +void TerminalWindow::paintContentTunnels() +{ + int i = 1; + + wclear(m_contentWindow); + foreach (const QVariant &tunnelVaiant, m_dataMap.value("proxyStatistic").toMap().value("tunnels").toList()) { + QVariantMap tunnelMap = tunnelVaiant.toMap(); + QVariantMap clientOne = m_clientHash.value(tunnelMap.value("clientOne").toString()); + QVariantMap clientTwo = m_clientHash.value(tunnelMap.value("clientTwo").toString()); + + // Tunnel time + uint timeStamp = tunnelMap.value("timestamp").toUInt(); + QString tunnelConnectionTime = QDateTime::fromTime_t(timeStamp).toString("dd.MM.yyyy hh:mm:ss"); + + QString tunnelPrint = QString("%1 | %2 %3 %4 %5 %6") + .arg(tunnelConnectionTime) + .arg(clientOne.value("address").toString()) + .arg(clientOne.value("name").toString()) + .arg("<--->", 10) + .arg(clientTwo.value("address").toString()) + .arg(clientTwo.value("name").toString()) + ; + + mvwprintw(m_contentWindow, i, 2, convertString(tunnelPrint)); + i++; + } + + // Draw borders + box(m_contentWindow, 0 , 0); + wrefresh(m_contentWindow); +} + +void TerminalWindow::eventLoop() +{ + resizeWindow(); + + int keyInteger = getch(); + switch (keyInteger) { + case KEY_LEFT: + m_view = ViewClients; + break; + case KEY_RIGHT: + m_view = ViewTunnels; + break; + case 27: // Esc + clear(); + delwin(m_headerWindow); + delwin(m_contentWindow); + delwin(m_mainWindow); + endwin(); + exit(0); + break; + default: + break; + } + + // Refresh header window + paintHeader(); + + // Refresh content window + switch (m_view) { + case ViewClients: + paintContentClients(); + break; + case ViewTunnels: + paintContentTunnels(); + break; + } + + refresh(); + + // Reinvoke the method for the next event loop run + QMetaObject::invokeMethod(this, "eventLoop", Qt::QueuedConnection); +} + + +void TerminalWindow::refreshWindow(const QVariantMap &dataMap) +{ + m_dataMap = dataMap; + + QVariantMap statisticMap = m_dataMap.value("proxyStatistic").toMap(); + + m_clientHash.clear(); + foreach (const QVariant &clientVariant, statisticMap.value("clients").toList()) { + QVariantMap clientMap = clientVariant.toMap(); + m_clientHash.insert(clientMap.value("id").toString(), clientMap); + } + + eventLoop(); +} + diff --git a/monitor/terminalwindow.h b/monitor/terminalwindow.h new file mode 100644 index 0000000..fe59c54 --- /dev/null +++ b/monitor/terminalwindow.h @@ -0,0 +1,76 @@ +#ifndef TERMINALWINDOW_H +#define TERMINALWINDOW_H + +#include +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2018 Simon Stürz * + * * + * This file is part of nymea-remoteproxy. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include + +#include + +class TerminalWindow : public QObject +{ + Q_OBJECT +public: + + enum View { + ViewClients, + ViewTunnels + }; + Q_ENUM(View) + + explicit TerminalWindow(QObject *parent = nullptr); + ~TerminalWindow(); + +private: + WINDOW *m_mainWindow = nullptr; + WINDOW *m_headerWindow = nullptr; + WINDOW *m_contentWindow = nullptr; + + int m_headerHeight = 3; + int m_terminalSizeX = 0; + int m_terminalSizeY = 0; + + View m_view = ViewClients; + + QVariantMap m_dataMap; + QHash m_clientHash; + + const char *convertString(const QString &string); + + // content paint methods + void resizeWindow(); + void paintHeader(); + void paintContentClients(); + void paintContentTunnels(); + +signals: + +private slots: + void eventLoop(); + +public slots: + void refreshWindow(const QVariantMap &dataMap); + +}; + +#endif // TERMINALWINDOW_H diff --git a/nymea-remoteproxy.pro b/nymea-remoteproxy.pro index 4a98a89..aeb7020 100644 --- a/nymea-remoteproxy.pro +++ b/nymea-remoteproxy.pro @@ -12,5 +12,6 @@ message("Building nymea-remoteproxy $${SERVER_VERSION}") message("----------------------------------------------------------") message("JSON-RPC API version $${API_VERSION_MAJOR}.$${API_VERSION_MINOR}") message("Qt version:" $$[QT_VERSION]) + coverage { message("Building with coverage report") } ccache { message("Building with ccache support") }