xuqiang 4 месяцев назад
Родитель
Сommit
e57853702f
9 измененных файлов с 281 добавлено и 0 удалено
  1. 3 0
      include/appcontext.h
  2. 30 0
      include/broadcast.h
  3. 14 0
      include/defs.h
  4. 7 0
      include/mainwindow.h
  5. 32 0
      include/sysstate.h
  6. 5 0
      src/appcontext.cpp
  7. 56 0
      src/broadcast.cpp
  8. 11 0
      src/mainwindow.cpp
  9. 123 0
      src/sysstate.cpp

+ 3 - 0
include/appcontext.h

@@ -11,6 +11,7 @@
 #include "netparseprocess.h"
 #include "calprocess.h"
 #include "datadict.h"
+#include "sysstate.h"
 
 class AppContext : public QObject
 {
@@ -30,6 +31,7 @@ public:
     NetParseProcess &netParseProcess();
     CalProcess &calProcess();
     DataDict &dataDict();
+    SysState &sysState();
 
 private:
     PluginManager m_pluginMgr;
@@ -41,6 +43,7 @@ private:
     NetParseProcess m_netParseProcess;
     CalProcess m_calProcess;
     DataDict m_dataDict;
+    SysState m_sysState;
 };
 
 #endif  // APPCONTEXT_H

+ 30 - 0
include/broadcast.h

@@ -0,0 +1,30 @@
+#ifndef __BROADCAST_H__
+#define __BROADCAST_H__
+
+#include <QObject>
+#include <QJsonObject>
+
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+class Broadcast : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit Broadcast(const int port, QObject *parent = nullptr);
+    ~Broadcast();
+    int write(const QJsonObject &json);
+
+protected:
+    bool init(const int port);
+
+private:
+    int sockfd;
+    struct sockaddr_in broadcast_addr;
+    int broadcast_enable = 1;
+
+};
+
+#endif  // BROADCAST_H

+ 14 - 0
include/defs.h

@@ -6,4 +6,18 @@
 #define NETPARSE_FIFO_PATH      "/tmp/netparsefifo"
 #define CALCULATE_FIFO_PATH     "/tmp/calculatefifo"
 
+#define BROADCAST_PORT 60999
+
+// cpu temperature
+#define BIG_CORE0   "/sys/class/thermal/thermal_zone1"  // bigcore0
+#define BIG_CORE1   "/sys/class/thermal/thermal_zone2"  // bigcore1
+#define LITTLE_CORE "/sys/class/thermal/thermal_zone3"  // littlecore
+
+// meminfo
+#define MEMINFO "/proc/meminfo"
+
+// diskinfo
+#define MOUNT_ROOTFS    "/"
+#define MOUNT_USERDATA  "/userdata"
+
 #endif

+ 7 - 0
include/mainwindow.h

@@ -6,6 +6,8 @@
 #include <QTimer>
 #include <QLabel>
 
+#include "broadcast.h"
+
 #define MAX_CANVAS_COUNT 12
 
 class MainWindow : public QMainWindow
@@ -28,12 +30,17 @@ private:
     QTimer m_updateScreenTimer;     // 更新画面显示定时器
     int m_frequency;                // 更新频率
     QLabel *m_pErrStrLabel;
+    Broadcast m_broadcast;
+    QTimer m_reportTimer;
 
 public slots:
     void onUpdateScreen(const QJsonObject &obj);
     void onPageSwitdh(int state);
     void onConfigureUpdate(const QString &filename);
     void onReloadCanvas();
+
+private slots:
+    void onReport();
     
 };
 

+ 32 - 0
include/sysstate.h

@@ -0,0 +1,32 @@
+#ifndef __SYSSTATE_H__
+#define __SYSSTATE_H__
+
+#include <QObject>
+#include <QTimer>
+#include "broadcast.h"
+
+class SysState : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit SysState(QObject *parent = nullptr);
+    QJsonObject sysStateInfo();
+
+protected:
+    float cpuTemperature();
+    float meminfo();
+    float diskinfo();
+
+private:
+    QTimer m_detectTimer;
+    int m_cputemp;
+    int m_meminfo;
+    int m_diskinfo;
+
+private slots:
+    void onDetectSysState();
+
+};
+
+#endif  // SYSSTATE_H

+ 5 - 0
src/appcontext.cpp

@@ -71,3 +71,8 @@ DataDict &AppContext::dataDict()
 {
     return m_dataDict;
 }
+
+SysState &AppContext::sysState()
+{
+    return m_sysState;
+}

+ 56 - 0
src/broadcast.cpp

@@ -0,0 +1,56 @@
+#include "broadcast.h"
+#include "utils.h"
+#include <QJsonDocument>
+
+Broadcast::Broadcast(const int port, QObject *parent)
+    : QObject{parent}
+{
+    init(port);
+}
+Broadcast::~Broadcast()
+{
+    close(sockfd);
+}
+
+int Broadcast::write(const QJsonObject &json)
+{
+    QJsonDocument doc(json);
+    QByteArray byteArray = doc.toJson(QJsonDocument::Compact);
+    return sendto(sockfd, byteArray.data(), byteArray.size(), 0, (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr));
+}
+
+bool Broadcast::init(const int port)
+{
+    // 1. 创建 UDP 套接字
+    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+        perror("socket failed");
+        exit(EXIT_FAILURE);
+    }
+
+    // 2. 设置广播权限
+    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)) < 0) {
+        perror("setsockopt(SO_BROADCAST) failed");
+        close(sockfd);
+        exit(EXIT_FAILURE);
+    }
+
+    char *ip = NULL;
+    char *mask = NULL;
+    bool result = Utils::ipv4("eth0", &ip, &mask);
+    if(!result) {
+        close(sockfd);
+        exit(EXIT_FAILURE);
+    }
+
+    QString addr = Utils::broadcast(ip, mask);
+    free(ip);
+    free(mask);
+
+    // 3. 配置广播地址
+    memset(&broadcast_addr, 0, sizeof(broadcast_addr));
+    broadcast_addr.sin_family = AF_INET;
+    broadcast_addr.sin_port = htons(port);
+    broadcast_addr.sin_addr.s_addr = inet_addr(addr.toUtf8().data());  // 广播地址
+
+    return true;
+}

+ 11 - 0
src/mainwindow.cpp

@@ -10,11 +10,13 @@
 #include <QSettings>
 #include <QDateTime>
 #include <time.h>
+#include "defs.h"
 
 MainWindow::MainWindow(const int &frequency, QWidget *parent)
     : QMainWindow(parent)
     , m_pStackedWidget(nullptr)
     , m_pErrStrLabel(nullptr)
+    , m_broadcast(Broadcast(BROADCAST_PORT))
     , m_frequency(frequency)
 {
     setWindowFlags(Qt::FramelessWindowHint | Qt::Window);
@@ -33,6 +35,9 @@ MainWindow::MainWindow(const int &frequency, QWidget *parent)
     DataFifo &dataFifo = AppContext::instance().dataFifo();
     connect(&dataFifo, &DataFifo::updateScreen, this, &MainWindow::onUpdateScreen);
 
+    connect(&m_reportTimer, &QTimer::timeout, this, &MainWindow::onReport);
+    m_reportTimer.start(1000);
+
     connect(&m_timer, &QTimer::timeout, this, [this](){
         DataFifo &dataFifo = AppContext::instance().dataFifo();
         qint64 recvTimestamp = dataFifo.recvTimestamp();
@@ -325,3 +330,9 @@ void MainWindow::onReloadCanvas()
     reload();
     setCurrentCanvas();
 }
+
+void MainWindow::onReport()
+{
+    QJsonObject obj = AppContext::instance().sysState().sysStateInfo();
+    m_broadcast.write(obj);
+}

+ 123 - 0
src/sysstate.cpp

@@ -0,0 +1,123 @@
+#include "sysstate.h"
+#include "utils.h"
+#include "logger.h"
+#include "defs.h"
+
+#include <QFile>
+#include <QTextStream>
+
+#include <sys/statvfs.h>
+#include <math.h>
+
+SysState::SysState(QObject *parent)
+    : QObject{parent}
+    , m_cputemp(0)
+    , m_meminfo(0)
+    , m_diskinfo(0)
+{
+    connect(&m_detectTimer, &QTimer::timeout, this, &SysState::onDetectSysState);
+
+    QTimer::singleShot(0, this, &SysState::onDetectSysState);
+    m_detectTimer.start(10000);
+}
+
+QJsonObject SysState::sysStateInfo()
+{
+    QJsonObject obj;
+    obj["cputemp"]= (int)floor(m_cputemp);
+    obj["meminfo"]= (int)floor(m_meminfo);
+    obj["diskinfo"] = (int)floor(m_diskinfo);
+    return obj;
+}
+
+float SysState::cpuTemperature()
+{
+    QStringList cpuZones = {
+        BIG_CORE0,
+        BIG_CORE1,
+        LITTLE_CORE
+    };
+
+    float maxTemp = 0;
+    for (const QString &zone : cpuZones) {
+        QFile file(zone + "/temp");
+        if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+            return -1;
+        QTextStream in(&file);
+        in.setCodec("UTF-8");
+        float temp = in.readLine().toInt() / 1000.0; // 毫摄氏度转 °C
+
+        if (temp > maxTemp) 
+            maxTemp = temp; // 也可以取平均值
+    }
+    return maxTemp;
+}
+
+float SysState::meminfo()
+{
+    FILE *fp = fopen(MEMINFO, "r");
+    if (fp == NULL) {
+        LOG_ERROR("get meminfo error");
+        return -1;
+    }
+
+    char line[256];
+    long memTotal = 0;
+    long memAvailable = 0;
+
+    while (fgets(line, sizeof(line), fp)) {
+        if (sscanf(line, "MemTotal: %ld kB", &memTotal) == 1) {
+            continue;
+        }
+        if (sscanf(line, "MemAvailable: %ld kB", &memAvailable) == 1) {
+            break; // 找到 MemAvailable 后就可以退出
+        }
+    }
+
+    fclose(fp);
+
+    if (memTotal == 0) {
+        LOG_ERROR("cannot read MemTotal");
+        return -1;
+    }
+
+    long memUsed = memTotal - memAvailable;
+    float usagePercent = 1.0 * memUsed / memTotal * 100;
+    return usagePercent;
+}
+
+float SysState::diskinfo()
+{
+    const char *mounts[] = {MOUNT_ROOTFS, MOUNT_USERDATA};
+    unsigned long long total_all = 0;
+    unsigned long long free_all = 0;
+
+    for (int i = 0; i < 2; i++) {
+        struct statvfs stat;
+        if (statvfs(mounts[i], &stat) != 0) {
+            perror(mounts[i]);
+            continue;
+        }
+
+        unsigned long long total = (unsigned long long)stat.f_blocks * stat.f_frsize;
+        unsigned long long free = (unsigned long long)stat.f_bfree * stat.f_frsize;
+
+        total_all += total;
+        free_all += free;
+    }
+
+    unsigned long long used_all = total_all - free_all;
+    float usagePercent = (total_all == 0) ? 0.0 : 1.0 * used_all / total_all * 100;
+    return usagePercent;
+}
+
+void SysState::onDetectSysState()
+{
+    float cputemp  = cpuTemperature();
+    float sysmeminfo = meminfo();
+    float sysdiskinfo = diskinfo();
+
+    m_cputemp = (int)floor(cputemp);
+    m_meminfo = (int)floor(sysmeminfo);
+    m_diskinfo = (int)floor(sysdiskinfo);
+}