Skip to content

Repository files navigation

MqttMonitor

基于 Qt + Paho MQTT C++ 的通用 MQTT 设备监控客户端。


项目定位

MqttMonitor 是一个运行在 Windows 桌面端的 MQTT 客户端上位机,面向需要监控多台 IoT 设备的调试/运维人员。

它不绑定任何特定设备类型或 Topic 格式,用户可以自由配置订阅规则,程序负责收集消息、展示状态、下发指令。


核心功能

配置管理

  • 填写 Broker 地址、端口、用户名/密码、ClientID、KeepAlive 等连接参数
  • 配置全局订阅 Topic(支持通配符,如 devices/#
  • 配置持久化,支持多套环境切换(如测试环境 / 生产环境)

设备管理

设备有两种来源:

来源 说明
手动添加 用户填写设备名称及其关注的 Topic 列表
自动发现 程序监听全局订阅 Topic,有新消息来源时自动创建设备卡片

自动发现的设备以消息来源 Topic 作为初始名称,用户可后续重命名。

设备卡片视图

右侧主区域以卡片网格展示所有设备,每张卡片显示:

  • 设备名称
  • 在线状态(在线 🟢 / 离线 🔴 / 未知 🟡)
  • 最后一条消息的首个字段预览
  • 最后消息时间戳

点击工具栏"卡片规则"按钮可自定义 JSON 字段名映射及在线/离线状态值,配置本地持久化。

消息查看与通信

  • 点击单个设备卡片 → 查看该设备的消息详情(原始 Payload + JSON 自动解析展开)
  • 多选设备 → 向所选设备批量下发指令(群发)
  • 指令下发:选择目标 Topic、填写 Payload、选择 QoS,发送

消息展示策略

  • 原始层:始终保留原始 Payload,便于调试
  • 解析层:若 Payload 为合法 JSON,自动展开为键值对
  • 非 JSON 格式(纯文本、十六进制)同样支持展示,不强制约定格式

界面结构

┌──────────┬──────────────────────────────────────────┐
│          │                                          │
│  配置     │   [设备A 🟢]  [设备B 🔴]  [设备C 🟢]     │
│          │                                          │
│          │   [设备D 🟢]  [设备E 🟡]  [未知设备 🟢]   │
│  设备     │                                          │
│          │   [设备G 🔴]  [设备H 🟢]  [...]           │
│          │                                          │
└──────────┴──────────────────────────────────────────┘

左侧导航:配置 / 设备两个页面入口
右侧内容区:当前页面的主体内容


技术栈

技术
UI 框架 Qt 5(Widgets,Fusion 风格 + 自定义 QSS 暗黑主题)
MQTT 通信 Eclipse Paho MQTT C++
构建系统 CMake + vcpkg
平台 Windows 11

架构分层

UI 层
  MainWindow / ConfigPanel / DeviceGridView / DeviceDetailView
       ↕ Qt 信号槽(QueuedConnection)
Bridge 层
  MqttBridge(QObject,负责线程安全的消息转发)
       ↕ 回调注册
Core 层
  MqttClient(封装 Paho,管理连接/订阅/发布)
  MessageBuffer(线程安全消息队列,批量推送给 UI)

Paho 的消息回调运行在子线程,Bridge 层通过 Qt::QueuedConnection 将消息安全投递至主线程,避免直接操作 UI。


设备断联检测设计

断联判断条件(三选一触发)

设备被标记为"断联"的条件:

条件 来源 说明
时间超时 本地计时 设备超过 30 秒未收到消息
MQTT 连接断开 MqttBridge.connectionLost 信号 Broker 连接丢失时,所有设备标记断联
status 字段 消息 JSON 设备主动上报 status: "offline"

判定逻辑: 只要满足上述任意一个条件,设备即刻被标记为断联(无需多条件同时满足)。

UI 样式标记

断联状态在 DeviceCard 上以样式标记显示(不覆盖原有 status 显示):

  • 保留原 status 字段显示:卡片继续展示消息中的 status 值
  • 应用断联视觉标记:边框/背景改为灰化或红色提示样式(如 border: 2px solid #ff6b6b
  • QSS 实现:使用选择器 DeviceCard[disconnected="true"] 精确定位样式

检测实现(懒惰轮询)

为支持大量设备的高效检测,采用懒惰轮询策略:

  1. 轮询定时器:QTimer,每 1 秒触发一次检查
  2. 待检查队列:维护 QSet<QString> checkQueue_,仅包含"距上次消息已 > 20 秒"的设备
    • 新消息到达:若该设备距离上次消息时间已 > 20 秒,自动加入待检查队列
    • 轮询时:仅检查队列中的设备,计算 当前时间 - lastMessageTime,若 > 30 秒则标记断联
  3. 性能特性:即使有 1000+ 设备,也仅检查活跃设备的小规模子集,性能开销恒定

恢复逻辑

  • 立即恢复:设备一旦收到新消息、或 MQTT 重连、或 status ≠ offline,立即取消断联标记
  • 无需延迟确认:消息本身已代表设备活着,无抖动风险

数据结构

DeviceView 维护每个设备的状态:

struct DeviceState {
    QString   deviceId;
    qint64    lastMessageTime;  // 最后收消息的时间戳(毫秒)
    bool      isDisconnected;   // 当前是否已标记为断联
};

开发阶段规划

Phase 1 — 核心连通 ✅ 完成

  • CMakeLists.txt 集成 Paho MQTT C++
  • MqttClient 封装:连接、订阅、发布
  • MessageBuffer 线程安全消息队列
  • CMakePresets.json(VS Code CMake Tools 集成)

Phase 2 — 基础 UI ✅ 完成

  • ConfigPanel:Broker 参数填写,内置 QSplitter(左配置表单 + 右消息列表)
  • MqttBridge:Paho 回调 → Qt 信号跨线程安全传递
  • MainWindow:navBar(配置/设备)+ QStackedWidget 双页结构
  • DeviceView 占位类(待 Phase 3 实现)

Phase 3 — 设备管理 ✅ 完成

  • 设备消息 JSON 结构确定(device_id / name / status / timestamp / data)
  • DeviceView 实现(QScrollArea + QGridLayout 卡片网格)
  • DeviceCard 类(展示 name / status / data KV)
  • JSON 解析(Qt5 QJsonDocument)
  • 手动添加/删除设备(对话框填写 ID + 名称;右键菜单删除)
  • 自动发现:收到新 device_id 消息时自动生成卡片(配合通配符订阅如 devices/#
  • 多选设备 + 指令群发(左键点击卡片选中/取消;底部面板填写 Topic / Payload / QoS 批量发送;Topic 支持 {device_id} 占位符)

UI 风格优化 ✅ 完成

  • Catppuccin Mocha 暗黑主题(全局 QSS)
  • Win11 原生标题栏暗色(DWM API)
  • 导航按钮互斥高亮

Phase 4 — 扩展模块

  • 多套 Broker 配置切换:命名配置存档,启动自动恢复,JSON 持久化至 %APPDATA%\MqttMonitor\profiles.json
  • 卡片规则配置:JSON 字段名(device_id / name / status / data)及状态值(online / offline)均可自定义,规则持久化至 %APPDATA%\MqttMonitor\card_rules.json,修改仅对新消息生效
  • 指令预设:群发面板支持保存命名预设(以 topic 命名,重名加 -2/-3 后缀),持久化至 %APPDATA%\MqttMonitor\cmd_presets.json;上次使用的 topic/payload/QoS 跨重启自动恢复
  • 设备断联检测(设计阶段):自动检测设备离线状态,基于组合判断(见下方详述)
  • 日志模块:消息历史记录到本地文件
  • 数据库模块:SQLite 持久化 + 历史消息查询

目录结构

MqttMonitor/
├── CMakeLists.txt
├── CMakePresets.json
├── README.md
├── PROGRESS.md
├── main.cpp
├── mainwindow.h / .cpp / .ui
└── src/
    ├── core/
    │   ├── MqttClient.h / .cpp        # Paho 封装
    │   ├── MessageBuffer.h / .cpp     # 线程安全消息队列
    │   ├── ConfigStore.h / .cpp       # MQTT 配置持久化
    │   ├── CardRuleConfig.h           # 卡片规则数据结构
    │   ├── CardRuleStore.h / .cpp     # 卡片规则持久化
    │   ├── CmdPreset.h                # 指令预设数据结构
    │   └── CmdPresetStore.h / .cpp    # 指令预设持久化
    ├── bridge/
    │   └── MqttBridge.h / .cpp        # Paho 回调 → Qt 信号
    └── ui/
        ├── ConfigPanel.h / .cpp / .ui  # 配置页(含消息列表)
        ├── DeviceView.h / .cpp         # 设备页(卡片网格 + 指令面板 + 预设)
        ├── DeviceCard.h / .cpp         # 设备卡片(状态展示 + 多选)
        ├── AddDeviceDialog.h / .cpp    # 手动添加设备对话框
        └── CardRuleDialog.h / .cpp     # 卡片规则配置对话框

消息格式约定

Topic 格式

devices/<device_id>/status

device_id 同时冗余在 payload JSON 中,便于解析。

Payload JSON 结构

{
  "device_id":  "device001",
  "name":       "温控器-1号",
  "status":     "online",
  "timestamp":  1712750000,
  "data": {
    "temperature": 25.3,
    "humidity":    60
  }
}
字段 类型 说明
device_id string 设备唯一标识
name string 可读名称,卡片标题显示
status string online / offline / error
timestamp number Unix 时间戳(秒)
data object 业务 KV,value 为 number 或 string
  • 设备离线时主动发送 status: offline 消息,不依赖心跳超时
  • data 字段结构自由,程序以 KV 列表形式展示在卡片下方

调试工具

MQTTX 定时发送脚本

在 MQTTX 的定时发送功能中使用以下脚本,可模拟设备持续上报温湿度数据:

function handlePayload(value) {
  let msg = typeof value === 'string' ? JSON.parse(value) : value;

  msg.timestamp = Date.now();
  msg.data = {
    temperature: +(20 + Math.random() * 15).toFixed(1), // 模拟 20-35 度
    humidity: Math.floor(40 + Math.random() * 30)       // 模拟 40-70% 湿度
  };

  return JSON.stringify(msg, null, 2);
}

execute(handlePayload);

使用方式:

  1. 在 MQTTX 新建连接,Topic 填写 <device_id>/status
  2. Payload 填写包含完整字段的初始 JSON(device_idnamestatus 等固定字段在此填写)
  3. 开启定时发送,选择上方脚本,脚本会自动覆盖 timestampdata 字段

About

A Qt-based generic MQTT device monitor client

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages