Qt 树莓派管理程序

Qt实现树莓派管理程序,对树莓派性能进行监控。在树莓派上运行TCP服务程序,发送已开机时间、系统负载、内存使用情况、CPU温度、网速、当前登录用户等数据,管理程序显示数据。

raspberrypi.c

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h> 
#include <sys/time.h>

#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 <QtNetwork>
#include <QTcpSocket>
#include <QFile>
#include <QMenu>
#include <QStandardItemModel>
#include <QMessageBox>
#include <QTimer>

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<QTcpSocket*>(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<QTcpSocket*>(sender());
    closeConnection(tcpSocket);
}

void MainWindow::readyReadRPi()
{
    QTcpSocket* tcpSocket = static_cast<QTcpSocket*>(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<QTcpSocket*>(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<QStandardItem*> 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<QString, QString>::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<QStandardItem*> 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);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值