Add monitor
parent
2e15b840e9
commit
faff3e9074
|
|
@ -5,6 +5,7 @@ Maintainer: Simon Stürz <simon.stürz@guh.io>
|
||||||
Build-depends: debhelper (>= 0.0.0),
|
Build-depends: debhelper (>= 0.0.0),
|
||||||
dh-systemd,
|
dh-systemd,
|
||||||
libqt5websockets5-dev,
|
libqt5websockets5-dev,
|
||||||
|
libncurses5-dev,
|
||||||
Standards-Version: 3.9.3
|
Standards-Version: 3.9.3
|
||||||
|
|
||||||
Package: nymea-remoteproxy
|
Package: nymea-remoteproxy
|
||||||
|
|
@ -13,10 +14,10 @@ Depends: ${shlibs:Depends},
|
||||||
${misc:Depends},
|
${misc:Depends},
|
||||||
awscli,
|
awscli,
|
||||||
libnymea-remoteproxy (= ${binary:Version}),
|
libnymea-remoteproxy (= ${binary:Version}),
|
||||||
|
Suggests: nymea-remoteproxy-monitor (= ${binary:Version})
|
||||||
Description: The nymea remote proxy server
|
Description: The nymea remote proxy server
|
||||||
The nymea remote proxy server
|
The nymea remote proxy server
|
||||||
|
|
||||||
|
|
||||||
Package: libnymea-remoteproxy
|
Package: libnymea-remoteproxy
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Section: libs
|
Section: libs
|
||||||
|
|
@ -85,3 +86,11 @@ Depends: ${shlibs:Depends},
|
||||||
libnymea-remoteproxy (= ${binary:Version}),
|
libnymea-remoteproxy (= ${binary:Version}),
|
||||||
Description: The nymea remote proxy server tests
|
Description: The nymea remote proxy server tests
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
usr/bin/nymea-remoteproxy-monitor
|
||||||
|
|
@ -53,9 +53,9 @@ bool ProxyConfiguration::loadConfiguration(const QString &fileName)
|
||||||
setMonitorSocketFileName(settings.value("monitorSocket", "/tmp/nymea-remoteproxy.monitor").toString());
|
setMonitorSocketFileName(settings.value("monitorSocket", "/tmp/nymea-remoteproxy.monitor").toString());
|
||||||
|
|
||||||
setJsonRpcTimeout(settings.value("jsonRpcTimeout", 10000).toInt());
|
setJsonRpcTimeout(settings.value("jsonRpcTimeout", 10000).toInt());
|
||||||
setAuthenticationTimeout(settings.value("authenticationTimeout", 5000).toInt());
|
setAuthenticationTimeout(settings.value("authenticationTimeout", 8000).toInt());
|
||||||
setInactiveTimeout(settings.value("inactiveTimeout", 5000).toInt());
|
setInactiveTimeout(settings.value("inactiveTimeout", 8000).toInt());
|
||||||
setAloneTimeout(settings.value("aloneTimeout", 5000).toInt());
|
setAloneTimeout(settings.value("aloneTimeout", 8000).toInt());
|
||||||
|
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include "loggingcategories.h"
|
#include "loggingcategories.h"
|
||||||
|
|
||||||
#include <QMetaObject>
|
#include <QMetaObject>
|
||||||
|
#include <QVariantList>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|
||||||
namespace remoteproxy {
|
namespace remoteproxy {
|
||||||
|
|
@ -64,6 +65,33 @@ QVariantMap ProxyServer::currentStatistics()
|
||||||
QVariantMap statisticsMap;
|
QVariantMap statisticsMap;
|
||||||
statisticsMap.insert("clientCount", m_proxyClients.count());
|
statisticsMap.insert("clientCount", m_proxyClients.count());
|
||||||
statisticsMap.insert("tunnelCount", m_tunnels.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;
|
return statisticsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,15 @@
|
||||||
|
|
||||||
#include "tunnelconnection.h"
|
#include "tunnelconnection.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
namespace remoteproxy {
|
namespace remoteproxy {
|
||||||
|
|
||||||
TunnelConnection::TunnelConnection(ProxyClient *clientOne, ProxyClient *clientTwo):
|
TunnelConnection::TunnelConnection(ProxyClient *clientOne, ProxyClient *clientTwo):
|
||||||
m_clientOne(clientOne),
|
m_clientOne(clientOne),
|
||||||
m_clientTwo(clientTwo)
|
m_clientTwo(clientTwo)
|
||||||
{
|
{
|
||||||
|
m_creationTimeStamp = QDateTime::currentDateTime().toTime_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TunnelConnection::token() const
|
QString TunnelConnection::token() const
|
||||||
|
|
@ -38,6 +40,16 @@ QString TunnelConnection::token() const
|
||||||
return m_clientOne->token();
|
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
|
ProxyClient *TunnelConnection::clientOne() const
|
||||||
{
|
{
|
||||||
return m_clientOne;
|
return m_clientOne;
|
||||||
|
|
@ -65,4 +77,12 @@ bool TunnelConnection::isValid() const
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,17 +33,24 @@ public:
|
||||||
|
|
||||||
QString token() const;
|
QString token() const;
|
||||||
|
|
||||||
|
uint creationTime() const;
|
||||||
|
QString creationTimeString() const;
|
||||||
|
|
||||||
ProxyClient *clientOne() const;
|
ProxyClient *clientOne() const;
|
||||||
ProxyClient *clientTwo() const;
|
ProxyClient *clientTwo() const;
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint m_creationTimeStamp = 0;
|
||||||
|
|
||||||
ProxyClient *m_clientOne = nullptr;
|
ProxyClient *m_clientOne = nullptr;
|
||||||
ProxyClient *m_clientTwo = nullptr;
|
ProxyClient *m_clientTwo = nullptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QDebug operator<< (QDebug debug, const TunnelConnection &tunnel);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TUNNELCONNECTION_H
|
#endif // TUNNELCONNECTION_H
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
#include <QCommandLineOption>
|
#include <QCommandLineOption>
|
||||||
|
|
||||||
|
#include "monitor.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -36,8 +38,7 @@ int main(int argc, char *argv[])
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
parser.addVersionOption();
|
parser.addVersionOption();
|
||||||
parser.setApplicationDescription(QString("\nThe nymea remote proxy server client application. This client allowes to test "
|
parser.setApplicationDescription(QString("\nThe nymea remote proxy monitor allowes to monitor the live server activity on the a local instance.\n\n"
|
||||||
"a server application as client perspective.\n\n"
|
|
||||||
"Server version: %1\n"
|
"Server version: %1\n"
|
||||||
"API version: %2\n\n"
|
"API version: %2\n\n"
|
||||||
"Copyright %3 2018 Simon Stürz <simon.stuerz@guh.io>\n")
|
"Copyright %3 2018 Simon Stürz <simon.stuerz@guh.io>\n")
|
||||||
|
|
@ -46,10 +47,13 @@ int main(int argc, char *argv[])
|
||||||
.arg(QChar(0xA9)));
|
.arg(QChar(0xA9)));
|
||||||
|
|
||||||
|
|
||||||
QCommandLineOption tokenOption(QStringList() << "s" << "socket", "The AWS token for authentication. Default /tmp/", "socket");
|
QCommandLineOption socketOption(QStringList() << "s" << "socket", "The socket descriptor for the nymea-remoteproxy monitor socket. Default is /tmp/nymea-remoteproxy-monitor.sock", "socket");
|
||||||
parser.addOption(tokenOption);
|
socketOption.setDefaultValue("/tmp/nymea-remoteproxy-monitor.sock");
|
||||||
|
parser.addOption(socketOption);
|
||||||
|
|
||||||
parser.process(application);
|
parser.process(application);
|
||||||
|
|
||||||
|
Monitor monitor(parser.value(socketOption));
|
||||||
|
|
||||||
return application.exec();
|
return application.exec();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef MONITOR_H
|
||||||
|
#define MONITOR_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
@ -3,9 +3,17 @@ include(../nymea-remoteproxy.pri)
|
||||||
TARGET = nymea-remoteproxy-monitor
|
TARGET = nymea-remoteproxy-monitor
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
|
|
||||||
SOURCES += main.cpp
|
SOURCES += main.cpp \
|
||||||
|
monitorclient.cpp \
|
||||||
|
terminalwindow.cpp \
|
||||||
|
monitor.cpp
|
||||||
|
|
||||||
|
LIBS += -lncurses
|
||||||
|
|
||||||
target.path = /usr/bin
|
target.path = /usr/bin
|
||||||
INSTALLS += target
|
INSTALLS += target
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
monitorclient.h \
|
||||||
|
terminalwindow.h \
|
||||||
|
monitor.h
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "monitorclient.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef MONITORCLIENT_H
|
||||||
|
#define MONITORCLIENT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
@ -0,0 +1,234 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "terminalwindow.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QMetaObject>
|
||||||
|
|
||||||
|
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<const char *>(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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
#ifndef TERMINALWINDOW_H
|
||||||
|
#define TERMINALWINDOW_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
#include <ncurses.h>
|
||||||
|
|
||||||
|
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<QString, QVariantMap> 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
|
||||||
|
|
@ -12,5 +12,6 @@ message("Building nymea-remoteproxy $${SERVER_VERSION}")
|
||||||
message("----------------------------------------------------------")
|
message("----------------------------------------------------------")
|
||||||
message("JSON-RPC API version $${API_VERSION_MAJOR}.$${API_VERSION_MINOR}")
|
message("JSON-RPC API version $${API_VERSION_MAJOR}.$${API_VERSION_MINOR}")
|
||||||
message("Qt version:" $$[QT_VERSION])
|
message("Qt version:" $$[QT_VERSION])
|
||||||
|
|
||||||
coverage { message("Building with coverage report") }
|
coverage { message("Building with coverage report") }
|
||||||
ccache { message("Building with ccache support") }
|
ccache { message("Building with ccache support") }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue