4105浏览
查看: 4105|回复: 7

[ESP8266/ESP32] TinyMonitor - 小巧的服务器状态监视器

[复制链接]
本帖最后由 linyuxuanlin 于 2023-5-26 18:31 编辑

TinyMonitor - 小巧的服务器状态监视器图2

TinyMonitor 是一个小巧极简的服务器状态监视终端,它仅由一个 ESP32 主控加上 OLED 显示屏,就可以将服务器的实时状态参数展示出来,方便观察调试。

前期准备

本项目用到的硬件物料非常简单,一个自带 Wi-Fi 蓝牙的 Beetle ESP32-C3,还有一块 128x64 的 OLED 屏。

TinyMonitor - 小巧的服务器状态监视器图4

Beetle ESP32-C3 的引脚定义如下。

TinyMonitor - 小巧的服务器状态监视器图1

因为可以使用软件 I2C 的方式(即自定义 I2C 引脚)驱动 OLED 屏,所以我将 Beetle ESP32-C3 的 0/1 引脚定义为 SCL/SDA 功能。这样一来,接线十分简单,相互贴着把 4 个引脚焊上就完成了。

TinyMonitor - 小巧的服务器状态监视器图3

注:给 Beetle ESP32-C3 烧录程序前,需要先添加 ESP32 的包,以正常识别板子型号。详见其 Wiki 页面

点亮屏幕

可以使用这个简单的程序,测试能否在 OLED 上正常显示信息:

#include <U8g2lib.h>

#define OLED_SDA 1
#define OLED_SCL 0

U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R2,  OLED_SCL, OLED_SDA, U8X8_PIN_NONE);

void setup(void) {
  u8g2.begin();
}

void loop(void) {
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.drawStr(0,10,"Hello World!");
  u8g2.sendBuffer();
  delay(1000);
}

MQTT 代理服务

MQTT 是一种基于客户端 - 服务器的消息发布 / 订阅传输协议。在本项目中,MQTT 是服务器与 ESP32 通信的桥梁,为了方便,我将 MQTT 服务部署在需要监控的服务器上;如果有需要,你也可以部署在其他的机器上。

部署 Mosquitto 服务

Mosquitto 是一款实现了消息推送协议 MQTT v3.1 的开源消息代理软件,在这里我用的是 Docker 方式部署的 eclipse-mosquitto 作为 MQTT 代理服务器。如果不熟悉 Docker 部署的方式,可以参考文章 Docker 简易指南Docker Compose - 更优雅的打开方式

根据官方的说明,首先需要创建以下目录和文件供 Mosquitto 使用,并赋予足够的权限:(请将 ${STACK_DIR} 修改为本地存放数据的路径,例如 /DATA/AppData/mosquitto,下文同)

mkdir -vp ${STACK_DIR}/{config,data,log} \
&& touch ${STACK_DIR}/config/mosquitto.conf \
&& chmod -R 755 ${STACK_DIR} \
&& chmod -R 777 ${STACK_DIR}/log \

随后,在 mosquitto.conf 文件中写入以下内容:

persistence true
persistence_location /mosquitto/data
log_dest file /mosquitto/log/mosquitto.log

# 关闭匿名模式
allow_anonymous false
# 指定密码文件
password_file /mosquitto/config/pwfile.conf

使用 docker-compose 方式部署容器:

version: "3"
services:
  mosquitto:
    container_name: mosquitto_app
    image: eclipse-mosquitto:1.6.14 # 2.x 版本可能兼容性不佳
    ports:
      - "1883:1883"
      - "9001:9001"
    volumes:
      - ${STACK_DIR}/config/mosquitto.conf:/mosquitto/config/mosquitto.conf
      - ${STACK_DIR}/data:/mosquitto/data
      - ${STACK_DIR}/log:/mosquitto/log
    #privileged: true
    restart: always

进入容器并修改密码:

cd 存放docker-compose.yml的路径
docker compose up

docker compose ps # 找到运行的容器的ID
docker exec -it 容器ID sh # 进入容器 shell

touch /mosquitto/config/pwfile.conf
chmod -R 755 /mosquitto/config/pwfile.conf

# 创建用户与密码,用户名:test,密码:123
mosquitto_passwd -b /mosquitto/config/pwfile.conf test 123

exit # 退出容器 shell
docker restart 容器ID # 重启容器生效

测试 MQTT 服务器的可用性

正常启动了 mosquitto 服务后,我们可以使用 MQTTBox 测试 MQTT 代理服务器的可用性。

安装软件后,点击 Create MQTT Client 新建连接,按照下图填写相关参数:

TinyMonitor - 小巧的服务器状态监视器图6

其中,HOST 为 MQTT 服务所在的服务器的地址(例如,我的服务器在局域网内的地址是 192.168.1.2);用户名和密码需要与上文配置 Mosquitto 时设置的值对应。

点击 Save 保存后,如果在顶部状态栏看到绿色的 Connected,则表示已经连接上服务器。

服务端监控脚本

我们可通过在服务端运行以下 Python 程序,实现对设备实时信息的抓取,并推送到 MQTT 服务器的相应主题上。首先需要安装以下依赖包:

pip install paho-mqtt psutil

创建并运行 Python 程序:

import paho.mqtt.client as mqtt
import psutil
import time

# 连接到 MQTT 代理服务器
client = mqtt.Client()
client.username_pw_set("MQTT用户名", "MQTT密码")
client.connect("MQTT服务器地址", 端口号)
# 例:client.connect("192.168.1.2", 1883)

# 收集服务器状态并发送到 MQTT 主题
while True:
    client.publish("USAGE_CPU", psutil.cpu_percent())
    client.publish("USAGE_MEM", psutil.virtual_memory().percent)
    client.publish("USAGE_DISK", psutil.disk_usage('/').percent)
    time.sleep(1) # 每隔一秒发布一次

成功运行后,我们可以在 MQTTBox 顶部状态栏上点击 Add subscriber 添加对这三个主题的订阅,例如:

TinyMonitor - 小巧的服务器状态监视器图5

如果一切正常的话,应该可以在 MQTTBox 中看到不断回传的服务器的状态信息。

Beetle ESP32-C3 显示端

创建以下 Arduino 代码,修改其中的参数,并烧录进 ESP32。如果一切正常的话,应该可以看到不断更新的状态信息。

#include <Wire.h>
#include <U8g2lib.h>
#include <WiFi.h>
#include <PubSubClient.h>

// 使用软件 I2C 方式连接 OLED,重新定义引脚
#define OLED_SDA 1
#define OLED_SCL 0

// MQTT 定义
#define WIFI_SSID "Wi-Fi名称"
#define WIFI_PASSWORD "Wi-Fi密码"
#define MQTT_BROKER "MQTT服务器地址" // 例如 192.168.31.2
#define MQTT_PORT MQTT端口 //例如 1883
#define MQTT_USERNAME "MQTT用户名" //test,应与上文配置对应
#define MQTT_PASSWORD "MQTT密码" //123,应与上文配置对应
#define MQTT_TOPIC_CPU "USAGE_CPU" //订阅的主题
#define MQTT_TOPIC_MEM "USAGE_MEM"
#define MQTT_TOPIC_DISK "USAGE_DISK"

char msg_cpu_usage[10];
char msg_mem_usage[10];
char msg_disk_usage[10];

// 定义 OLED 屏幕对象
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R2, OLED_SCL, OLED_SDA, U8X8_PIN_NONE);

// WIFI 客户端对象
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

// MQTT 回调函数
void mqttCallback(char* topic, byte* payload, unsigned int length) {
  if (strcmp(topic, MQTT_TOPIC_CPU) == 0) {
    // 记录 CPU 使用率
    for (int i = 0; i < length; i++)
      msg_cpu_usage = (char)payload;
  } else if (strcmp(topic, MQTT_TOPIC_MEM) == 0) {
    // 记录内存使用率
    for (int i = 0; i < length; i++)
      msg_mem_usage = (char)payload;
  } else if (strcmp(topic, MQTT_TOPIC_DISK) == 0) {
    // 记录磁盘使用率
    for (int i = 0; i < length; i++)
      msg_disk_usage = (char)payload;
  }
}

void setup() {
  u8g2.begin();  // 初始化 OLED 屏幕
  Wire.begin();  // 开始 I2C 传输

  // 连接 WIFI
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
  }

  // 连接 MQTT 代理服务器
  mqttClient.setServer(MQTT_BROKER, MQTT_PORT);
  mqttClient.setCallback(mqttCallback);
  if (mqttClient.connect("ESP32", MQTT_USERNAME, MQTT_PASSWORD)) {
    mqttClient.subscribe(MQTT_TOPIC_CPU);
    mqttClient.subscribe(MQTT_TOPIC_MEM);
    mqttClient.subscribe(MQTT_TOPIC_DISK);
  }
}

void loop() {
  mqttClient.loop();  // 处理 MQTT 消息
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_9x15_tf);

    // 显示 CPU 使用率
    u8g2.setCursor(0, 12);
    u8g2.print("CPU: ");
    for (int i = 0; i < 9; i++)
      u8g2.print(msg_cpu_usage);
    u8g2.print(" %");

    // 显示内存使用率
    u8g2.setCursor(0, 35);
    u8g2.print("Mem: ");
    for (int i = 0; i < 9; i++)
      u8g2.print(msg_mem_usage);
    u8g2.print(" %");

    // 显示磁盘使用率
    u8g2.setCursor(0, 58);
    u8g2.print("Disk: ");
    for (int i = 0; i < 9; i++)
      u8g2.print(msg_disk_usage);
    u8g2.print(" %");

  } while (u8g2.nextPage());
}

更多扩展玩法

以下的想法有待实现:

  • 增加电池和 3D 打印的外壳,做成更精致的桌面小摆件
  • 增加内网穿透,打造为小挂件,不在家也可观察服务器状态
  • 将 Python 监测程序封装为 Docker 方式部署
  • 优化 UI 布局,实现更多参数监控
  • 增加多服务器状态监控功能
  • 增加某些参数超出阈值报警的功能

参考与致谢

Post by Power (wiki-power.com)




hnyzcj  版主

发表于 2023-5-27 06:54:40

漂亮,就是这个味道,哈哈哈哈哈哈
回复

使用道具 举报

腿毛利小五郎  初级技匠

发表于 2023-6-19 10:12:56

围观支持
回复

使用道具 举报

派大星ym  初级技匠

发表于 2023-8-20 11:39:04

酷酷酷     
回复

使用道具 举报

派大星ym  初级技匠

发表于 2023-8-20 11:47:18

555555555555
回复

使用道具 举报

花生编程  中级技匠

发表于 2023-8-22 13:39:55

厉害厉害
回复

使用道具 举报

花生编程  中级技匠

发表于 2023-8-22 13:41:03

赞赞赞赞赞
回复

使用道具 举报

txm派瑞深山锹  高级技师

发表于 2023-10-14 10:57:21

可以试试在一个mqtttopic里用json传输与解析消息
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail