Qt实现树莓派管理程序,对树莓派性能进行监控。在树莓派上运行TCP服务程序,发送已开机时间、系统负载、内存使用情况、CPU温度、网速、当前登录用户等数据,管理程序显示数据。
raspberrypi.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define TEMP_PATH "/sys/class/thermal/thermal_zone0/temp"
#define TOTAL_SLEEP 10
#define CPU_SLEEP 5
#define SERVER_PORT 9930
#define LISTEN_NUM 10
struct cpu_stat
{
long us;
long ni;
long sy;
long id;
long usage;
long total;
};
void init_tcp_server(int *sockfd);
int get_raspberrypi_stat(char *raspberrypi_stat);
void get_cpu_stat(struct cpu_stat* cpu_stat);
float get_cpu_utilization(struct cpu_stat old_stat, struct cpu_stat cur_stat);
void get_net_rate(long long *recv_rate, long long *send_rate);
void logging(char *cli, char *log);
int main()
{
int sockfd;
int connfd;
struct sockaddr_in cli_addr;
socklen_t cli_len = sizeof(struct sockaddr_in);
int nbytes;
pid_t pid;
char recv_buf[32];
memset(recv_buf, '\0', sizeof(recv_buf));
char cli_buf[INET_ADDRSTRLEN + 7];
memset(cli_buf, '\0', sizeof(cli_buf));
init_tcp_server(&sockfd);
while (1)
{
connfd = accept(sockfd, (struct sockaddr*)&cli_addr, &cli_len);
if (connfd < 0)
{
perror("accept");
exit(-1);
}
memset(cli_buf, '\0', sizeof(cli_buf));
sprintf(cli_buf, "%s:%d", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
logging(cli_buf, (char*)"connected");
pid = fork();
if (pid < 0)
{
perror("fork");
exit(-1);
}
else if (pid == 0)
{
close(sockfd);
while (1)
{
memset(recv_buf, '\0', sizeof(recv_buf));
nbytes = recv(connfd, recv_buf, sizeof(recv_buf), 0);
if (nbytes < 0)
{
close(connfd);
perror("recv");
exit(-1);
}
else if (nbytes == 0)
{
close(connfd);
logging(cli_buf, (char*)"disconnected");
return 0;
}
if (strncmp(recv_buf, "hello", 5) == 0)
{
sleep(TOTAL_SLEEP - CPU_SLEEP);
char raspberrypi_stat[128];
if (get_raspberrypi_stat(raspberrypi_stat) == 0)
{
if ((nbytes = send(connfd, raspberrypi_stat, strlen(raspberrypi_stat), 0)) < 0)
{
close(connfd);
perror("send");
exit(-1);
}
logging(cli_buf, raspberrypi_stat);
}
else
{
char no_data[] = "no_data";
if ((nbytes = send(connfd, no_data, strlen(no_data), 0)) < 0)
{
close(connfd);
perror("send");
exit(-1);
}
logging(cli_buf, no_data);
}
}
}
}
else
{
close(connfd);
}
}
return 0;
}
void init_tcp_server(int *sockfd)
{
*sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (*sockfd < 0)
{
perror("socket");
exit(-1);
}
int optval = 1;
if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0)
{
perror("setsockopt");
exit(-1);
}
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(struct sockaddr_in));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERVER_PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(*sockfd, (struct sockaddr*)&serv_addr, sizeof(struct sockaddr_in)) < 0)
{
perror("bind");
exit(-1);
}
if (listen(*sockfd, LISTEN_NUM) < 0)
{
perror("listen");
exit(-1);
}
}
int get_raspberrypi_stat(char *raspberrypi_stat)
{
// get recv rate and send rate
struct timeval tv_1;
gettimeofday(&tv_1, NULL);
long long recv_rate_1, send_rate_1;
get_net_rate(&recv_rate_1, &send_rate_1);
// get recv rate and send rate
struct cpu_stat old_stat, cur_stat;
memset(&old_stat, 0, sizeof(struct cpu_stat));
memset(&cur_stat, 0, sizeof(struct cpu_stat));
get_cpu_stat(&old_stat);
sleep(CPU_SLEEP);
get_cpu_stat(&cur_stat);
// cpu utilization
float cpu_utilization = get_cpu_utilization(old_stat, cur_stat);
int fd = open(TEMP_PATH, O_RDONLY);
if (fd < 0)
{
perror("open");
return -1;
}
char buf[10];
if (read(fd, buf, sizeof(buf)) < 0)
{
perror("read");
return -1;
}
close(fd);
// cpu temp
float cpu_temp = atoi(buf) / 1000.0;
struct sysinfo sys_info;
if (sysinfo(&sys_info) != 0)
{
perror("sysinfo");
return -1;
}
// uptime
unsigned long uptime = sys_info.uptime;
// sys load
char sys_load_1_min[10];
char sys_load_5_min[10];
char sys_load_15_min[10];
memset(sys_load_1_min, '\0', sizeof(sys_load_1_min));
memset(sys_load_5_min, '\0', sizeof(sys_load_5_min));
memset(sys_load_15_min, '\0', sizeof(sys_load_15_min));
char load_buf[128];
memset(load_buf, '\0', sizeof(load_buf));
char tmp_buf[128];
memset(tmp_buf, '\0', sizeof(tmp_buf));
int tmp_index = 0;
int index = 0;
FILE *fp_load = NULL;
fp_load = popen("cat /proc/loadavg | awk {'print $1, $2, $3'}", "r");
if (fp_load == NULL)
{
sprintf(sys_load_1_min, "no_data");
sprintf(sys_load_5_min, "no_data");
sprintf(sys_load_15_min, "no_data");
}
else
{
fread(load_buf, sizeof(load_buf), 1, fp_load);
for (int i = 0; i < (int)strlen(load_buf); ++i)
{
if ((load_buf[i] == ' ') || (load_buf[i] == '\n'))
{
switch (index)
{
case 0:
strcpy(sys_load_1_min, tmp_buf);
break;
case 1:
strcpy(sys_load_5_min, tmp_buf);
break;
case 2:
strcpy(sys_load_15_min, tmp_buf);
break;
default:
break;
}
memset(tmp_buf, '\0', sizeof(tmp_buf));
tmp_index = 0;
++index;
}
else
{
tmp_buf[tmp_index++] = load_buf[i];
}
}
}
pclose(fp_load);
// free ram, total ram
unsigned long free_ram = (sys_info.freeram * sys_info.mem_unit) / 1024 / 1024;
unsigned long total_ram = (sys_info.totalram * sys_info.mem_unit) / 1024 / 1024;
// free swap, total swap
unsigned long free_swap = (sys_info.freeswap * sys_info.mem_unit) / 1024 / 1024;
unsigned long total_swap = (sys_info.totalswap * sys_info.mem_unit) / 1024 / 1024;
struct ifaddrs *if_addrs = NULL;
getifaddrs(&if_addrs);
// ip address
char ip_addrs[INET_ADDRSTRLEN];
memset(ip_addrs, '\0', sizeof(ip_addrs));
while (if_addrs != NULL)
{
if (if_addrs->ifa_addr->sa_family == AF_INET)
{
if ((strcmp(if_addrs->ifa_name, "eth0") == 0) || (strcmp(if_addrs->ifa_name, "wlan0") == 0))
{
inet_ntop(AF_INET, &((struct sockaddr_in*)if_addrs->ifa_addr)->sin_addr, ip_addrs, sizeof(ip_addrs));
}
}
if_addrs = if_addrs->ifa_next;
}
// hostname
char hostname[128];
memset(hostname, '\0', sizeof(hostname));
gethostname(hostname, sizeof(hostname));
// who
char who[128];
char who_buf[128];
int who_index = 0;
FILE *fp = NULL;
memset(who, '\0', sizeof(who));
memset(who_buf, '\0', sizeof(who_buf));
fp = popen("who | awk {'print $1, $2'}", "r");
if (fp == NULL)
{
sprintf(who, "no_data");
}
else
{
fread(who_buf, sizeof(who_buf), 1, fp);
for (int i = 0; i < (int)strlen(who_buf); ++i)
{
if (who_buf[i] == '\n')
{
who[who_index++] = ';';
}
else
{
who[who_index++] = who_buf[i];
}
}
}
pclose(fp);
// recv rate, send rate
struct timeval tv_2;
gettimeofday(&tv_2, NULL);
long long recv_rate_2, send_rate_2;
get_net_rate(&recv_rate_2, &send_rate_2);
float recv_rate = (recv_rate_2 - recv_rate_1) / (1024 * ((tv_2.tv_sec + tv_2.tv_usec * 0.000001) - (tv_1.tv_sec + tv_1.tv_usec * 0.000001)));
float send_rate = (send_rate_2 - send_rate_1) / (1024 * ((tv_2.tv_sec + tv_2.tv_usec * 0.000001) - (tv_1.tv_sec + tv_1.tv_usec * 0.000001)));
//printf("Uptime: %ld s\nSys Load: %s %s %s\nRam: %ld MB/%ld MB\nSwap: %ld MB/%ld MB\nIp: %s %s\nCpu Temp: %3.2f\nCpu Utilization: %3.2f%%\nWho: %s\nRecv Rate: %.2f KB/s\nSend Rate: %.2f KB/s\n", uptime, sys_load_1_min, sys_load_5_min, sys_load_15_min, free_ram, total_ram, free_swap, total_swap, ip_addrs, hostname, cpu_temp, cpu_utilization, who, recv_rate, send_rate);
sprintf(raspberrypi_stat, "%ld, %s, %s, %s, %ld, %ld, %ld, %ld, %s, %s, %3.2f, %3.2f, %s, %.2f, %.2f", uptime, sys_load_1_min, sys_load_5_min, sys_load_15_min, free_ram, total_ram, free_swap, total_swap, ip_addrs, hostname, cpu_temp, cpu_utilization, who, recv_rate, send_rate);
return 0;
}
void get_cpu_stat(struct cpu_stat* cpu_stat)
{
int fd = open("/proc/stat", O_RDONLY);
if (fd < 0)
{
perror("open");
exit(-1);
}
char buf[1024];
char tmp[32];
int tmp_index = 0;
int index = 0;
memset(buf, '\0', sizeof(buf));
memset(tmp, '\0', sizeof(tmp));
if (read(fd, buf, sizeof(buf)) < 0)
{
perror("read");
exit(-1);
}
close(fd);
for (int i = 0; i < (int)strlen(buf); ++i)
{
if (buf[i] == '\n')
{
break;
}
else if (buf[i] == ' ')
{
switch (index)
{
case 2:
cpu_stat->us = atoi(tmp);
break;
case 3:
cpu_stat->ni = atoi(tmp);
break;
case 4:
cpu_stat->sy = atoi(tmp);
break;
case 5:
cpu_stat->id = atoi(tmp);
break;
default:
break;
}
memset(tmp, '\0', sizeof(tmp));
tmp_index = 0;
++index;
}
else
{
tmp[tmp_index++] = buf[i];
}
}
cpu_stat->usage = cpu_stat->us + cpu_stat->ni + cpu_stat->sy;
cpu_stat->total = cpu_stat->us + cpu_stat->ni + cpu_stat->sy + cpu_stat->id;
}
float get_cpu_utilization(struct cpu_stat old_stat, struct cpu_stat cur_stat)
{
float cpu_utilization = ((float)(cur_stat.usage - old_stat.usage) / (cur_stat.total - old_stat.total)) * 100;
return cpu_utilization;
}
void get_net_rate(long long *recv_rate, long long *send_rate)
{
char rate_buf[64];
memset(rate_buf, '\0', sizeof(rate_buf));
char tmp_buf[64];
memset(tmp_buf, '\0', sizeof(tmp_buf));
int tmp_index = 0;
int index = 0;
FILE *fp = NULL;
fp = popen("cat /proc/net/dev | grep eth0 | awk {'print $2, $10'}", "r");
if (fp == NULL)
{
*recv_rate = 0;
*send_rate = 0;
}
else
{
fread(rate_buf, sizeof(rate_buf), 1, fp);
for (int i = 0; i < (int)strlen(rate_buf); ++i)
{
if ((rate_buf[i] == ' ') || (rate_buf[i] == '\n'))
{
switch (index)
{
case 0:
*recv_rate = atoll(tmp_buf);
break;
case 1:
*send_rate = atoll(tmp_buf);
break;
default:
break;
}
memset(tmp_buf, '\0', sizeof(tmp_buf));
tmp_index = 0;
++index;
}
else
{
tmp_buf[tmp_index++] = rate_buf[i];
}
}
}
pclose(fp);
}
void logging(char *cli, char *log)
{
time_t now;
struct tm* time_now;
time(&now);
time_now = localtime(&now);
char week[7][5] = {
"Sun.", "Mon.", "Tue.", "Wed.", "Thu.", "Fri.", "Sat."
};
char dir[] = "/home/pi/raspberrypi-logs/";
if (access(dir, F_OK) != 0)
{
if (mkdir(dir, 0755) < 0)
{
perror("mkdir");
exit(-1);
}
}
char file_name[64];
memset(file_name, '\0', sizeof(file_name));
sprintf(file_name, "%s%4d%02d%02draspberrypi.log", dir, time_now->tm_year + 1900, time_now->tm_mon + 1, time_now->tm_mday);
char buf[256];
memset(buf, '\0', sizeof(buf));
sprintf(buf, "[%4d-%02d-%02d %s %02d:%02d:%02d]: %s %s\n", time_now->tm_year + 1900, time_now->tm_mon + 1, time_now->tm_mday, week[time_now->tm_wday], time_now->tm_hour, time_now->tm_min, time_now->tm_sec, cli, log);
int fd = open(file_name, O_RDWR | O_CREAT | O_APPEND, 0666);
if (fd < 0)
{
perror("open");
exit(-1);
}
if (write(fd, buf, strlen(buf)) < 0)
{
perror("write");
exit(-1);
}
close(fd);
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "addrpigroup.h"
#include "addrpi.h"
#include
#include
#include
#include
#include
#include
#include
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QFont font;
font.setPixelSize(14);
setFont(font);
mTitle = QStringLiteral("树莓派管理");
setWindowTitle(mTitle);
mTcpSendStr = "hello";
mTreeViewModel = new QStandardItemModel(0, 1, this);
mTreeViewModel->setHeaderData(0, Qt::Horizontal, QStringLiteral("树莓派列表"));
ui->treeView->setModel(mTreeViewModel);
ui->treeView->setMaximumWidth(200);
ui->treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
mTimer = new QTimer(this);
connect(mTimer, SIGNAL(timeout()), this, SLOT(timerOut()));
mTimer->start(5000);
mQueueTimer = new QTimer(this);
connect(mQueueTimer, SIGNAL(timeout()), this, SLOT(queueTimerOut()));
mQueueTimer->start(5000);
initRPiLst();
}
MainWindow::~MainWindow()
{
foreach (QTcpSocket* tcpSocket, mRPiTcpSocketLst)
{
if (tcpSocket->state() == QAbstractSocket::ConnectedState)
{
closeConnection(tcpSocket);
}
delete tcpSocket;
}
mRPiMap.clear();
delete mTreeViewModel;
delete ui;
}
void MainWindow::connectedRPi()
{
QTcpSocket* tcpSocket = static_cast(sender());
for (int i = 0; i < mTreeViewModel->rowCount(); ++i)
{
QModelIndex parent = mTreeViewModel->index(i, 0);
QStandardItem *parentItem = mTreeViewModel->itemFromIndex(parent);
for (int j = 0; j < mTreeViewModel->rowCount(parent); ++j)
{
QModelIndex child = mTreeViewModel->index(j, 0, parent);
QStandardItem *childItem = mTreeViewModel->itemFromIndex(child);
QString rpi = QStringLiteral("%1:%2#%3").arg(parentItem->text()).arg(childItem->text()).arg(childItem->data().toString());
if (rpi == tcpSocket->objectName())
{
childItem->setForeground(Qt::green);
tcpSocket->write(mTcpSendStr.toStdString().c_str());
break;
}
}
}
}
void MainWindow::disConnectedRPi()
{
QTcpSocket* tcpSocket = static_cast(sender());
closeConnection(tcpSocket);
}
void MainWindow::readyReadRPi()
{
QTcpSocket* tcpSocket = static_cast(sender());
mRPiMap[tcpSocket->objectName()] = tcpSocket->readAll();
QString data = mRPiMap.value(tcpSocket->objectName());
if (data != "no_data")
{
mMsgQueue.enqueue(QStringLiteral("%1+%2").arg(tcpSocket->objectName().split("#")[0].replace(":", " ")).arg(data));
}
if (tcpSocket->state() == QAbstractSocket::ConnectedState)
{
tcpSocket->write(mTcpSendStr.toStdString().c_str());
}
}
void MainWindow::errorRPi()
{
QTcpSocket* tcpSocket = static_cast(sender());
for (int i = 0; i < mTreeViewModel->rowCount(); ++i)
{
QModelIndex parent = mTreeViewModel->index(i, 0);
QStandardItem *parentItem = mTreeViewModel->itemFromIndex(parent);
for (int j = 0; j < mTreeViewModel->rowCount(parent); ++j)
{
QModelIndex child = mTreeViewModel->index(j, 0, parent);
QStandardItem *childItem = mTreeViewModel->itemFromIndex(child);
QString rpi = QStringLiteral("%1:%2#%3").arg(parentItem->text()).arg(childItem->text()).arg(childItem->data().toString());
if (rpi == tcpSocket->objectName())
{
childItem->setForeground(Qt::red);
closeConnection(tcpSocket);
break;
}
}
}
}
void MainWindow::addRPiGroup()
{
AddRPiGroup *dialog = new AddRPiGroup();
int r = dialog->exec();
if (r == QDialog::Accepted)
{
QString group = dialog->getRPiGroup();
for (int i = 0; i < mTreeViewModel->rowCount(); ++i)
{
QModelIndex parent = mTreeViewModel->index(i, 0);
QStandardItem *parentItem = mTreeViewModel->itemFromIndex(parent);
if (group == parentItem->text())
{
informationMessageBox(mTitle, QStringLiteral("\"%1\"分组已存在。").arg(group), true);
return;
}
}
QStandardItem *item = new QStandardItem(group);
item->setData("root");
mTreeViewModel->appendRow(item);
}
delete dialog;
}
void MainWindow::deleteRPiGroup()
{
QModelIndex parent = ui->treeView->currentIndex();
QStandardItem *parentItem = mTreeViewModel->itemFromIndex(parent);
QString group = parentItem->text();
QStringList rpiLst = readTreeViewItem(parent.row());
QString rpi;
foreach (QString str, rpiLst)
{
rpi.append(QStringLiteral("\n%1 %2").arg(str.split("#")[0].split(":")[1]).arg(str.split("#")[1]));
}
if (informationMessageBox(QStringLiteral("删除分组"), QStringLiteral("确认删除分组及分组下的树莓派?\n%1%2").arg(group).arg(rpi)))
{
mTreeViewModel->removeRow(parent.row(), QModelIndex());
foreach (QString str, rpiLst)
{
deleteRPiFromData(str);
}
}
}
void MainWindow::closeConnection(QTcpSocket* tcpSocket)
{
tcpSocket->disconnectFromHost();
}
void MainWindow::initRPiLst()
{
QFile file(QStringLiteral("%1.txt").arg(mTitle));
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
return;
}
QTextStream in(&file);
in.setCodec("UTF-8");
QStringList groupLst;
QStringList rpiLst;
while (!in.atEnd())
{
QString str = in.readLine();
if (str.isEmpty() || str.startsWith("$$") || (!str.contains("#")))
{
continue;
}
QString group = str.split("#")[0].split(":")[0];
if (!groupLst.contains(group))
{
groupLst.append(group);
}
rpiLst.append(str);
}
file.close();
foreach (QString group, groupLst)
{
QStandardItem *item = new QStandardItem(group);
item->setData("root");
QList childItems;
foreach (QString rpi, rpiLst)
{
if (rpi.split("#")[0].split(":")[0] == group)
{
QString name = rpi.split("#")[0].split(":")[1];
QString ipaddressAndPort = rpi.split("#")[1];
QStandardItem *childItem = new QStandardItem(name);
childItem->setData(ipaddressAndPort);
childItem->setToolTip(childItem->data().toString());
childItems.append(childItem);
addRPiToData(rpi);
}
}
item->appendRows(childItems);
mTreeViewModel->appendRow(item);
}
}
void MainWindow::closeEvent(QCloseEvent *event)
{
Q_UNUSED(event);
saveRPilst();
}
void MainWindow::saveRPilst()
{
QFile file(QStringLiteral("%1.txt").arg(mTitle));
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
return;
}
QTextStream out(&file);
out.setCodec("UTF-8");
QStringList rpiLst = readTreeView();
foreach (QString rpi, rpiLst)
{
out << rpi << endl;
}
file.close();
}
QStringList MainWindow::readTreeView()
{
QStringList rpiLst;
for (int i = 0; i < mTreeViewModel->rowCount(); ++i)
{
QStringList itemLst = readTreeViewItem(i);
rpiLst.append(itemLst);
}
return rpiLst;
}
QStringList MainWindow::readTreeViewItem(int indexRow)
{
QStringList itemLst;
QModelIndex parent = mTreeViewModel->index(indexRow, 0);
QStandardItem *parentItem = mTreeViewModel->itemFromIndex(parent);
QString group = parentItem->text();
for (int i = 0; i < mTreeViewModel->rowCount(parent); ++i)
{
QModelIndex child = mTreeViewModel->index(i, 0, parent);
QStandardItem *childItem = mTreeViewModel->itemFromIndex(child);
QString item = QStringLiteral("%1:%2#%3").arg(group).arg(childItem->text()).arg(childItem->data().toString());
itemLst.append(item);
}
return itemLst;
}
int MainWindow::informationMessageBox(const QString& title, const QString& text, bool isOnlyOk)
{
QMessageBox msgBox(this);
msgBox.setFont(this->font());
msgBox.setIcon(QMessageBox::Information);
msgBox.setWindowTitle(title);
msgBox.setText(text);
if (isOnlyOk)
{
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setButtonText(QMessageBox::Ok, QStringLiteral("确定"));
}
else
{
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msgBox.setButtonText(QMessageBox::Ok, QStringLiteral("确定"));
msgBox.setButtonText(QMessageBox::Cancel, QStringLiteral("取消"));
}
return (msgBox.exec() == QMessageBox::Ok);
}
void MainWindow::deleteRPiFromData(const QString &rpi)
{
foreach (QTcpSocket* tcpSocket, mRPiTcpSocketLst)
{
if (tcpSocket->objectName() == rpi)
{
mRPiTcpSocketLst.removeOne(tcpSocket);
if (tcpSocket->state() == QAbstractSocket::ConnectedState)
{
closeConnection(tcpSocket);
}
delete tcpSocket;
}
}
QMap::iterator it;
for (it = mRPiMap.begin(); it != mRPiMap.end();)
{
if (it.key() == rpi)
{
mRPiMap.erase(it++);
}
else
{
it++;
}
}
}
void MainWindow::addRPiToData(const QString &rpi)
{
QTcpSocket *tcpSocket = new QTcpSocket(this);
tcpSocket->setObjectName(rpi);
connect(tcpSocket, SIGNAL(connected()), this, SLOT(connectedRPi()));
connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(disConnectedRPi()));
connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyReadRPi()));
connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(errorRPi()));
mRPiTcpSocketLst.append(tcpSocket);
mRPiMap.insert(rpi, "");
}
void MainWindow::showRPiData(const QString &rpi, const QString &data)
{
QStringList dataLst = data.split((", "));
int time = dataLst[0].toInt();
int h = time / 3600;
int m = (time % 3600) / 60;
int s = time % 60;
QString uptime = QStringLiteral("%1:%2:%3").arg(h, 2, 10, QChar('0')).arg(m, 2, 10, QChar('0')).arg(s, 2, 10, QChar('0'));
QString cpu_load_1 = dataLst[1];
QString cpu_load_5 = dataLst[2];
QString cpu_load_15 = dataLst[3];
QString free_ram = dataLst[4];
QString total_ram = dataLst[5];
QString free_swap = dataLst[6];
QString total_swap = dataLst[7];
QString ipaddress = dataLst[8];
QString hostname = dataLst[9];
QString cpu_temp = dataLst[10];
QString cpu_utilization = dataLst[11];
QStringList whoLst = dataLst[12].split(";");
QString who;
foreach (QString str, whoLst)
{
if (!str.isEmpty())
{
if (!who.isEmpty())
{
who.append("\n");
}
who.append(str);
}
}
QString recvRate = dataLst[13];
QString sendRate = dataLst[14];
ui->label_rpi->setText(rpi);
ui->label_uptime->setText(uptime);
ui->label_sysload->setText(QStringLiteral("%1 %2 %3").arg(cpu_load_1).arg(cpu_load_5).arg(cpu_load_15));
ui->label_cpuutilization->setText(QStringLiteral("%1 %").arg(cpu_utilization));
ui->label_cputemp->setText(QStringLiteral("%1 ℃").arg(cpu_temp));
ui->label_ram->setText(QStringLiteral("%1 MB/%2 MB").arg(free_ram).arg(total_ram));
ui->label_swap->setText(QStringLiteral("%1 MB/%2 MB").arg(free_swap).arg(total_swap));
ui->label_ipaddress->setText(ipaddress);
ui->label_hostname->setText(hostname);
ui->label_who->setText(who);
ui->label_recvrate->setText(QStringLiteral("%1 KB/s").arg(recvRate));
ui->label_sendrate->setText(QStringLiteral("%1 KB/s").arg(sendRate));
}
void MainWindow::addRPi()
{
AddRPi *dialog = new AddRPi();
int r = dialog->exec();
if (r == QDialog::Accepted)
{
QString rpi = dialog->getRPi();
QString name = rpi.split("#")[0];
QString ipaddressAndPort = rpi.split("#")[1];
QModelIndex parent = ui->treeView->currentIndex();
QStandardItem *parentItem = mTreeViewModel->itemFromIndex(parent);
for (int i = 0; i < mTreeViewModel->rowCount(parent); ++i)
{
QModelIndex child = mTreeViewModel->index(i, 0, parent);
QStandardItem *childItem = mTreeViewModel->itemFromIndex(child);
if (name == childItem->text())
{
informationMessageBox(mTitle, QStringLiteral("\"%1\"树莓派在当前分组已存在。").arg(name), true);
return;
}
}
QStandardItem *childItem = new QStandardItem(name);
childItem->setData(ipaddressAndPort);
childItem->setToolTip(childItem->data().toString());
QList childItems;
childItems.append(childItem);
parentItem->appendRows(childItems);
addRPiToData(QStringLiteral("%1:%2").arg(parentItem->text()).arg(rpi));
}
delete dialog;
}
void MainWindow::updateRPi()
{
QStandardItem *item = mTreeViewModel->itemFromIndex(ui->treeView->currentIndex());
QString name = item->text();
QString itemData = item->data().toString();
QString ipAddress = itemData.split(":")[0];
QString port = itemData.split(":")[1];
AddRPi *dialog = new AddRPi(name, ipAddress, port, QStringLiteral("修改树莓派"));
int r = dialog->exec();
if (r == QDialog::Accepted)
{
deleteRPiFromData(QStringLiteral("%1:%2#%3").arg(item->parent()->text()).arg(name).arg(itemData));
QString rpi = dialog->getRPi();
item->setText(rpi.split("#")[0]);
item->setData(rpi.split("#")[1]);
item->setToolTip(item->data().toString());
addRPiToData(QStringLiteral("%1:%2").arg(item->parent()->text()).arg(rpi));
}
delete dialog;
}
void MainWindow::deleteRPi()
{
QStandardItem *item = mTreeViewModel->itemFromIndex(ui->treeView->currentIndex());
QString name = item->text();
QString itemData = item->data().toString();
if (informationMessageBox(QStringLiteral("删除树莓派"), QStringLiteral("确认删除树莓派?\n%1 %2").arg(name).arg(itemData)))
{
QStandardItem *parent = item->parent();
mTreeViewModel->removeRow(ui->treeView->currentIndex().row(), mTreeViewModel->indexFromItem(parent));
deleteRPiFromData(QStringLiteral("%1:%2#%3").arg(parent->text()).arg(name).arg(itemData));
}
}
void MainWindow::on_treeView_customContextMenuRequested(const QPoint &pos)
{
Q_UNUSED(pos);
QModelIndex index = ui->treeView->indexAt(pos);
if (!index.isValid())
{
QMenu *menu = new QMenu(this);
QAction *addRPiGroup = new QAction(QStringLiteral("添加分组"), this);
QAction *expandAll = new QAction(QStringLiteral("展开全部"), this);
QAction *collapseAll = new QAction(QStringLiteral("折叠全部"), this);
menu->addAction(addRPiGroup);
menu->addSeparator();
menu->addAction(expandAll);
menu->addAction(collapseAll);
connect(addRPiGroup, SIGNAL(triggered(bool)), this, SLOT(addRPiGroup()));
connect(expandAll, SIGNAL(triggered(bool)), ui->treeView, SLOT(expandAll()));
connect(collapseAll, SIGNAL(triggered(bool)), ui->treeView, SLOT(collapseAll()));
menu->exec(QCursor::pos());
delete addRPiGroup;
delete expandAll;
delete collapseAll;
delete menu;
}
else
{
QStandardItem *item = mTreeViewModel->itemFromIndex(index);
QStandardItem *parent = item->parent();
if (parent == nullptr)
{
QMenu *menu = new QMenu(this);
QAction *addRPi = new QAction(QStringLiteral("添加树莓派"), this);
QAction *deleteRPiGroup = new QAction(QStringLiteral("删除分组"), this);
menu->addAction(addRPi);
menu->addSeparator();
menu->addAction(deleteRPiGroup);
connect(addRPi, SIGNAL(triggered(bool)), this, SLOT(addRPi()));
connect(deleteRPiGroup, SIGNAL(triggered(bool)), this, SLOT(deleteRPiGroup()));
menu->exec(QCursor::pos());
delete addRPi;
delete deleteRPiGroup;
delete menu;
}
else
{
QMenu *menu = new QMenu(this);
QAction *updateRPi = new QAction(QStringLiteral("修改树莓派"), this);
QAction *deleteRPi = new QAction(QStringLiteral("删除树莓派"), this);
menu->addAction(updateRPi);
menu->addSeparator();
menu->addAction(deleteRPi);
connect(updateRPi, SIGNAL(triggered(bool)), this, SLOT(updateRPi()));
connect(deleteRPi, SIGNAL(triggered(bool)), this, SLOT(deleteRPi()));
menu->exec(QCursor::pos());
delete updateRPi;
delete deleteRPi;
delete menu;
}
}
}
void MainWindow::on_treeView_clicked(const QModelIndex &index)
{
QStandardItem *item = mTreeViewModel->itemFromIndex(index);
QString itemData = item->data().toString();
if (itemData == "root")
{
return;
}
QString rpi = QStringLiteral("%1:%2#%3").arg(item->parent()->text()).arg(item->text()).arg(itemData);
QString data = mRPiMap.value(rpi);
if (data.isEmpty() || (data == "no_data"))
{
return;
}
else
{
showRPiData(rpi.split("#")[0].replace(":", " "), data);
}
}
void MainWindow::timerOut()
{
foreach (QTcpSocket* tcpSocket, mRPiTcpSocketLst)
{
QString rpi = tcpSocket->objectName();
QString ipaddressAndPort = rpi.split("#")[1];
if ((tcpSocket->state() != QAbstractSocket::ConnectedState) && (tcpSocket->state() != QAbstractSocket::ConnectingState))
{
tcpSocket->connectToHost(QHostAddress(ipaddressAndPort.split(":")[0]), ipaddressAndPort.split(":")[1].toInt());
}
}
}
void MainWindow::queueTimerOut()
{
if (!mMsgQueue.isEmpty())
{
QString str = mMsgQueue.dequeue();
QString rpi = str.split("+")[0];
QString data = str.split("+")[1];
showRPiData(rpi, data);
}
}