Update monitor behaviour

This commit is contained in:
Simon Stürz 2018-08-23 10:02:08 +02:00
parent 545a145605
commit d308be58b3
8 changed files with 139 additions and 38 deletions

View File

@ -20,6 +20,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <QUrl> #include <QUrl>
#include <QFileInfo>
#include <QCoreApplication> #include <QCoreApplication>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QCommandLineParser> #include <QCommandLineParser>
@ -50,9 +51,20 @@ int main(int argc, char *argv[])
QCommandLineOption socketOption(QStringList() << "s" << "socket", "The socket descriptor for the nymea-remoteproxy monitor socket. Default is /tmp/nymea-remoteproxy-monitor.sock", "socket"); 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"); socketOption.setDefaultValue("/tmp/nymea-remoteproxy-monitor.sock");
parser.addOption(socketOption); parser.addOption(socketOption);
parser.process(application); parser.process(application);
// Check socket file
QFileInfo fileInfo(parser.value(socketOption));
if (!fileInfo.exists()) {
qWarning() << "Could not find socket descriptor" << fileInfo.canonicalFilePath();
exit(1);
}
if (!fileInfo.isReadable()) {
qWarning() << "Could not open socket descriptor" << fileInfo.canonicalFilePath();
exit(1);
}
Monitor monitor(parser.value(socketOption)); Monitor monitor(parser.value(socketOption));
return application.exec(); return application.exec();

View File

@ -23,10 +23,24 @@
Monitor::Monitor(const QString &serverName, QObject *parent) : QObject(parent) Monitor::Monitor(const QString &serverName, QObject *parent) : QObject(parent)
{ {
m_terminal = new TerminalWindow(this);
m_monitorClient = new MonitorClient(serverName, this); m_monitorClient = new MonitorClient(serverName, this);
connect(m_monitorClient, &MonitorClient::connected, this, &Monitor::onConnected);
connect(m_monitorClient, &MonitorClient::dataReady, m_terminal, &TerminalWindow::refreshWindow); connect(m_monitorClient, &MonitorClient::disconnected, this, &Monitor::onDisconnected);
m_monitorClient->connectMonitor(); m_monitorClient->connectMonitor();
} }
void Monitor::onConnected()
{
m_terminal = new TerminalWindow(this);
connect(m_monitorClient, &MonitorClient::dataReady, m_terminal, &TerminalWindow::refreshWindow);
}
void Monitor::onDisconnected()
{
if (!m_terminal)
return;
m_terminal->deleteLater();
m_terminal = nullptr;
}

View File

@ -37,6 +37,10 @@ private:
TerminalWindow *m_terminal = nullptr; TerminalWindow *m_terminal = nullptr;
MonitorClient *m_monitorClient = nullptr; MonitorClient *m_monitorClient = nullptr;
private slots:
void onConnected();
void onDisconnected();
}; };
#endif // MONITOR_H #endif // MONITOR_H

View File

@ -32,16 +32,19 @@ MonitorClient::MonitorClient(const QString &serverName, QObject *parent) :
connect(m_socket, &QLocalSocket::connected, this, &MonitorClient::onConnected); connect(m_socket, &QLocalSocket::connected, this, &MonitorClient::onConnected);
connect(m_socket, &QLocalSocket::disconnected, this, &MonitorClient::onDisconnected); connect(m_socket, &QLocalSocket::disconnected, this, &MonitorClient::onDisconnected);
connect(m_socket, &QLocalSocket::readyRead, this, &MonitorClient::onReadyRead); connect(m_socket, &QLocalSocket::readyRead, this, &MonitorClient::onReadyRead);
connect(m_socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(onErrorOccured(QLocalSocket::LocalSocketError)));
} }
void MonitorClient::onConnected() void MonitorClient::onConnected()
{ {
qDebug() << "Monitor connected to" << m_serverName; qDebug() << "Monitor connected to" << m_serverName;
emit connected();
} }
void MonitorClient::onDisconnected() void MonitorClient::onDisconnected()
{ {
qDebug() << "Monitor disconnected from" << m_serverName; qDebug() << "Monitor disconnected from" << m_serverName;
emit disconnected();
} }
void MonitorClient::onReadyRead() void MonitorClient::onReadyRead()
@ -62,6 +65,13 @@ void MonitorClient::onReadyRead()
emit dataReady(dataMap); emit dataReady(dataMap);
} }
void MonitorClient::onErrorOccured(QLocalSocket::LocalSocketError socketError)
{
Q_UNUSED(socketError)
qWarning() << "Local socket error occured" << m_socket->errorString();
exit(1);
}
void MonitorClient::connectMonitor() void MonitorClient::connectMonitor()
{ {
m_socket->connectToServer(m_serverName, QLocalSocket::ReadOnly); m_socket->connectToServer(m_serverName, QLocalSocket::ReadOnly);

View File

@ -36,13 +36,17 @@ public:
private: private:
QString m_serverName; QString m_serverName;
QLocalSocket *m_socket = nullptr; QLocalSocket *m_socket = nullptr;
signals: signals:
void connected();
void disconnected();
void dataReady(const QVariantMap &data); void dataReady(const QVariantMap &data);
private slots: private slots:
void onConnected(); void onConnected();
void onDisconnected(); void onDisconnected();
void onReadyRead(); void onReadyRead();
void onErrorOccured(QLocalSocket::LocalSocketError socketError);
public slots: public slots:
void connectMonitor(); void connectMonitor();

View File

@ -21,6 +21,7 @@
#include "terminalwindow.h" #include "terminalwindow.h"
#include <QTime>
#include <QDebug> #include <QDebug>
#include <QDateTime> #include <QDateTime>
#include <QMetaObject> #include <QMetaObject>
@ -30,40 +31,48 @@ TerminalWindow::TerminalWindow(QObject *parent) :
{ {
// Create main window // Create main window
m_mainWindow = initscr(); m_mainWindow = initscr();
start_color();
init_pair(1, COLOR_BLACK, COLOR_GREEN); // Enable colors if available
init_pair(2, COLOR_BLACK, COLOR_RED); if (has_colors()) {
start_color();
init_pair(1, COLOR_BLACK, COLOR_GREEN);
init_pair(2, COLOR_BLACK, COLOR_RED);
}
// Configure behaviour // Configure behaviour
cbreak(); cbreak();
noecho(); noecho();
nonl();;
nodelay(stdscr, TRUE);
curs_set(FALSE); curs_set(FALSE);
//clear(); clear();
keypad(m_mainWindow, true); keypad(m_mainWindow, true);
nodelay(m_mainWindow, true); nodelay(m_mainWindow, true);
getmaxyx(stdscr, m_terminalSizeY, m_terminalSizeX); getmaxyx(m_mainWindow, m_terminalSizeY, m_terminalSizeX);
wrefresh(m_mainWindow);
// Create header and content window // Create header and content window
m_headerWindow = newwin(m_headerHeight, m_terminalSizeX, 0, 0); m_headerWindow = newwin(m_headerHeight, m_terminalSizeX, 0, 0);
m_contentWindow = newwin(m_terminalSizeY - m_headerHeight, m_terminalSizeX, m_headerHeight, 0); m_contentWindow = newwin(m_terminalSizeY - m_headerHeight, m_terminalSizeX, m_headerHeight, 0);
// Draw borders // Draw borders
wclear(m_headerWindow); werase(m_headerWindow);
wclear(m_contentWindow); werase(m_contentWindow);
drawWindowBorder(m_headerWindow);
drawWindowBorder(m_contentWindow);
mvwprintw(m_headerWindow, 1, 2, convertString("Connecting...")); //box(m_headerWindow, 0 , 0);
//box(m_contentWindow, 0 , 0);
box(m_headerWindow, 0 , 0);
box(m_contentWindow, 0 , 0);
// Refresh windows // Refresh windows
wrefresh(m_headerWindow); wrefresh(m_headerWindow);
wrefresh(m_contentWindow); wrefresh(m_contentWindow);
refresh(); refresh();
eventLoop();
} }
TerminalWindow::~TerminalWindow() TerminalWindow::~TerminalWindow()
@ -80,6 +89,18 @@ const char *TerminalWindow::convertString(const QString &string)
return reinterpret_cast<const char *>(string.toLatin1().data()); return reinterpret_cast<const char *>(string.toLatin1().data());
} }
QString TerminalWindow::getDurationString(uint timestamp)
{
uint duration = QDateTime::currentDateTime().toTime_t() - timestamp;
QString res;
int seconds = static_cast<int>(duration % 60);
duration /= 60;
int minutes = static_cast<int>(duration % 60);
duration /= 60;
int hours = static_cast<int>(duration % 24);
return res.sprintf("%02d:%02d:%02d", hours, minutes, seconds);
}
void TerminalWindow::resizeWindow() void TerminalWindow::resizeWindow()
{ {
int terminalSizeX; int terminalSizeX;
@ -93,30 +114,61 @@ void TerminalWindow::resizeWindow()
} }
} }
void TerminalWindow::drawWindowBorder(WINDOW *window)
{
int x, y, i;
getmaxyx(window, y, x);
// corners
mvwprintw(window, 0, 0, "+");
mvwprintw(window, y - 1, 0, "+");
mvwprintw(window, 0, x - 1, "+");
mvwprintw(window, y - 1, x - 1, "+");
// sides
for (i = 1; i < (y - 1); i++) {
mvwprintw(window, i, 0, "|");
mvwprintw(window, i, x - 1, "|");
}
// top and bottom
for (i = 1; i < (x - 1); i++) {
mvwprintw(window, 0, i, "-");
mvwprintw(window, y - 1, i, "-");
}
}
void TerminalWindow::paintHeader() void TerminalWindow::paintHeader()
{ {
QString headerString = QString(" Server: %1 %2 | API version %3 | Clients: %4 | Tunnels %5 | %6 %7") QString headerString = QString(" Server: %1 %2 | API version %3 | Clients: %4 | Tunnels %5 | %6 ")
.arg(m_dataMap.value("serverName").toString()) .arg(m_dataMap.value("serverName", "-").toString())
.arg(m_dataMap.value("serverVersion").toString()) .arg(m_dataMap.value("serverVersion", "-").toString())
.arg(m_dataMap.value("apiVersion").toString()) .arg(m_dataMap.value("apiVersion", "-").toString())
.arg(m_dataMap.value("proxyStatistic").toMap().value("clientCount").toInt()) .arg(m_dataMap.value("proxyStatistic").toMap().value("clientCount", 0).toInt())
.arg(m_dataMap.value("proxyStatistic").toMap().value("tunnelCount").toInt()) .arg(m_dataMap.value("proxyStatistic").toMap().value("tunnelCount", 0).toInt())
.arg((m_view == ViewClients ? "Clients" : "Tunnels")) .arg((m_view == ViewClients ? "-- Clients --" : "-- Tunnels --"));
.arg("", m_terminalSizeX, ' ');
int delta = m_terminalSizeX - headerString.count();
// Fill string for background color
for (int i = 0; i < delta; i++)
headerString.append(" ");
wclear(m_headerWindow); wclear(m_headerWindow);
wattron(m_headerWindow, A_BOLD | COLOR_PAIR(1)); wattron(m_headerWindow, A_BOLD | COLOR_PAIR(1));
mvwprintw(m_headerWindow, 1, 2, convertString(headerString)); mvwprintw(m_headerWindow, 1, 2, convertString(headerString));
wattroff(m_headerWindow, A_BOLD | COLOR_PAIR(1)); wattroff(m_headerWindow, A_BOLD | COLOR_PAIR(1));
box(m_headerWindow, 0 , 0); drawWindowBorder(m_headerWindow);
wrefresh(m_headerWindow); wrefresh(m_headerWindow);
} }
void TerminalWindow::paintContentClients() void TerminalWindow::paintContentClients()
{ {
int i = 1; if (m_clientHash.isEmpty())
return;
int i = 1;
wclear(m_contentWindow); wclear(m_contentWindow);
foreach (const QVariant &clientVariant, m_clientHash.values()) { foreach (const QVariant &clientVariant, m_clientHash.values()) {
QVariantMap clientMap = clientVariant.toMap(); QVariantMap clientMap = clientVariant.toMap();
@ -124,20 +176,21 @@ void TerminalWindow::paintContentClients()
uint timeStamp = clientMap.value("timestamp").toUInt(); uint timeStamp = clientMap.value("timestamp").toUInt();
QString clientConnectionTime = QDateTime::fromTime_t(timeStamp).toString("dd.MM.yyyy hh:mm:ss"); QString clientConnectionTime = QDateTime::fromTime_t(timeStamp).toString("dd.MM.yyyy hh:mm:ss");
QString clientPrint = QString("%1 | %2 | %3 | %4 | %5 | %6 |") QString clientPrint = QString("%1 | %2 | %3 | %4 | %5 | %6 | %7")
.arg(clientConnectionTime) .arg(clientConnectionTime)
.arg(clientMap.value("duration").toString())
.arg(clientMap.value("address").toString()) .arg(clientMap.value("address").toString())
.arg(clientMap.value("uuid").toString()) .arg(clientMap.value("uuid").toString())
.arg(clientMap.value("name").toString(), -30) .arg((clientMap.value("authenticated").toBool() ? "A" : "-"))
.arg((clientMap.value("authenticated").toBool() ? "auth" : "no auth"), -9) .arg((clientMap.value("tunnelConnected").toBool() ? "T" : "-"))
.arg((clientMap.value("tunnelConnected").toBool() ? "<--->" : " | ")); .arg(clientMap.value("name").toString(), -30);
mvwprintw(m_contentWindow, i, 2, convertString(clientPrint)); mvwprintw(m_contentWindow, i, 2, convertString(clientPrint.trimmed()));
i++; i++;
} }
// Draw borders // Draw borders
box(m_contentWindow, 0 , 0); drawWindowBorder(m_contentWindow);
wrefresh(m_contentWindow); wrefresh(m_contentWindow);
} }
@ -159,7 +212,7 @@ void TerminalWindow::paintContentTunnels()
.arg(tunnelConnectionTime) .arg(tunnelConnectionTime)
.arg(clientOne.value("address").toString()) .arg(clientOne.value("address").toString())
.arg(clientOne.value("name").toString()) .arg(clientOne.value("name").toString())
.arg("<--->", 10) .arg(" <---> ")
.arg(clientTwo.value("address").toString()) .arg(clientTwo.value("address").toString())
.arg(clientTwo.value("name").toString()) .arg(clientTwo.value("name").toString())
; ;
@ -169,7 +222,7 @@ void TerminalWindow::paintContentTunnels()
} }
// Draw borders // Draw borders
box(m_contentWindow, 0 , 0); drawWindowBorder(m_contentWindow);
wrefresh(m_contentWindow); wrefresh(m_contentWindow);
} }
@ -191,6 +244,7 @@ void TerminalWindow::eventLoop()
delwin(m_contentWindow); delwin(m_contentWindow);
delwin(m_mainWindow); delwin(m_mainWindow);
endwin(); endwin();
qDebug() << "Closing window monitor. Have a nice day!";
exit(0); exit(0);
break; break;
default: default:
@ -213,10 +267,10 @@ void TerminalWindow::eventLoop()
refresh(); refresh();
// Reinvoke the method for the next event loop run // Reinvoke the method for the next event loop run
QMetaObject::invokeMethod(this, "eventLoop", Qt::QueuedConnection); //QMetaObject::invokeMethod(this, "eventLoop", Qt::QueuedConnection);
QTimer::singleShot(50, this, &TerminalWindow::eventLoop);
} }
void TerminalWindow::refreshWindow(const QVariantMap &dataMap) void TerminalWindow::refreshWindow(const QVariantMap &dataMap)
{ {
m_dataMap = dataMap; m_dataMap = dataMap;
@ -224,11 +278,11 @@ void TerminalWindow::refreshWindow(const QVariantMap &dataMap)
QVariantMap statisticMap = m_dataMap.value("proxyStatistic").toMap(); QVariantMap statisticMap = m_dataMap.value("proxyStatistic").toMap();
m_clientHash.clear(); m_clientHash.clear();
foreach (const QVariant &clientVariant, statisticMap.value("clients").toList()) { foreach (const QVariant &clientVariant, statisticMap.value("clients").toList()) {
QVariantMap clientMap = clientVariant.toMap(); QVariantMap clientMap = clientVariant.toMap();
clientMap.insert("duration", getDurationString(clientMap.value("timestamp").toUInt()));
m_clientHash.insert(clientMap.value("id").toString(), clientMap); m_clientHash.insert(clientMap.value("id").toString(), clientMap);
} }
eventLoop();
} }

View File

@ -23,6 +23,7 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <QTimer>
#include <QVariantMap> #include <QVariantMap>
#include <ncurses.h> #include <ncurses.h>
@ -56,9 +57,11 @@ private:
QHash<QString, QVariantMap> m_clientHash; QHash<QString, QVariantMap> m_clientHash;
const char *convertString(const QString &string); const char *convertString(const QString &string);
QString getDurationString(uint timestamp);
// content paint methods // content paint methods
void resizeWindow(); void resizeWindow();
void drawWindowBorder(WINDOW *window);
void paintHeader(); void paintHeader();
void paintContentClients(); void paintContentClients();
void paintContentTunnels(); void paintContentTunnels();

View File

@ -23,7 +23,7 @@ ccache {
QMAKE_CXX = ccache g++ QMAKE_CXX = ccache g++
} }
coverage { coverage {<
# Note: this works only if you build in the source dir # Note: this works only if you build in the source dir
OBJECTS_DIR = OBJECTS_DIR =
MOC_DIR = MOC_DIR =