bluegrassiot/mqttprobe
GitHub: bluegrassiot/mqttprobe
MQTTProbe 是一款专为工业物联网设计的开源 MQTT 诊断工具,支持实时 topic 浏览、payload 检查、JSON 遥测数据图表可视化以及原生 Sparkplug B 解码与 EoN 节点模拟。
Stars: 2 | Forks: 0
# MQTTProbe
**专为 IIoT 打造的 MQTT 诊断工具。**
[](https://github.com/bluegrassiot/mqttprobe/actions/workflows/ci.yml)
[](LICENSE)
[](https://dotnet.microsoft.com/download/dotnet/10.0)

## 功能

- **Topic 浏览器** — 实时树状视图,展示从 broker 接收到的所有 topic,支持递归层级导航
- **Payload 浏览器** — 结构化的 JSON 查看器,用于查看消息 payload,支持将 topic/payload 复制到剪贴板
- **订阅** — 在 runtime 添加和删除 MQTT topic 订阅(包括通配符);订阅按连接持久化,并在重连时自动重新订阅(可配置)
- **发布** — 向任何 topic 发送消息,支持可配置的 QoS 级别
- **MQTT/Sparkplug B 模拟器** — 模拟多个 Edge Node 以可配置的速率发布 metrics 数据,支持使用或不使用 Sparkplug B
- **Sparkplug B EoN 仪表盘** — 实时查看所有 Edge of Network 节点、设备和 metrics;自动为新发现的节点请求 Birth certificate
- **多重连接** — 保存并在多个 broker 配置之间切换
- **TLS / MQTTS** — 通过 TLS(端口 8883)或普通 MQTT(端口 1883)连接到 broker,支持可选的非受信证书覆盖
- **WebSocket 支持** — 除了原生 TCP 外,还支持通过 `ws://` 或 `wss://` 连接
- **图表** — JSON payload 字段的实时时间序列可视化,支持可配置的字段选择;图表配置按连接跨会话保存
- **身份验证** — 基于cookie的登录,使用 PBKDF2-SHA256 哈希密码;首次运行设置向导,应用内修改密码
- **安全凭证存储** — MQTT broker 密码存储在平台原生安全存储中(iOS Keychain / Android Keystore / ASP.NET Data Protection);绝不以明文形式写入
## 快速开始 — Docker
最快的启动方式:
```
git clone https://github.com/bluegrassiot/mqttprobe
cd mqttprobe
docker compose up -d
```
在浏览器中打开 **http://localhost:8080**。首次启动时,您将进入一个设置页面来创建您的管理员密码。
### 从其他机器访问
快速启动 compose(`docker-compose.yml`)在端口 8080 上提供普通 HTTP 服务 — 这对于运行 Docker 的机器来说没问题,但其他机器上的浏览器会拒绝在普通 HTTP 上使用 `Secure` 身份验证cookie。
如果要从其他机器进行局域网访问,请使用生产环境的 compose,它添加了一个 Caddy TLS 代理:
```
cp .env.example .env
# 编辑 .env:将 MQTTPROBE_HOST 设置为其他机器将使用的 IP 或主机名
docker compose -f docker-compose.prod.yml up -d
```
然后从网络上的任何机器浏览 **https://\**。Caddy 会从其自己的本地 CA 签发一张自签名证书 — 浏览器在首次访问时会发出警告。要消除此警告,请在客户端机器上信任 Caddy 的根 CA:
```
docker compose -f docker-compose.prod.yml cp caddy:/data/caddy/pki/authorities/local/root.crt caddy-root.crt
# Windows:certutil -addstore -user Root caddy-root.crt
```
### 连接到局域网 broker
如果您使用 MQTTS(TLS,端口 8883)并在 Docker Desktop for Windows 上遇到连接失败,这是一个已知的 WSL2 MTU 问题 — `docker-compose.prod.yml` 已经设置了 `com.docker.network.driver.mtu: 1400` 来解决此问题。
## 快速开始 — Blazor Server (Windows / Linux / macOS)
**前置条件:** [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0)
```
cd src/MqttProbe.Web
dotnet run
```
应用在 `https://localhost:5001` 上启动。首次启动时,它会重定向到 `/Setup` 以创建您的密码。
## 快速开始 — MAUI (iOS / Android / Windows)
**前置条件:** .NET 10 SDK + MAUI workload
```
dotnet workload install maui
```
在 **Visual Studio 2026** (v18.0+) 中打开 `MqttProbe.slnx` 并选择您的目标平台。
## 配置
首次运行时,应用会创建 `config/appsettings.json`(被 gitignore,永远不会提交)。所有设置 — 连接、身份验证、图表、模拟器和 UI 首选项 — 都位于此单个文件中:
```
{
"Connections": [
{
"Name": "My Broker",
"Host": "192.168.1.100",
"Port": 1883,
"User": "mqttuser",
"Protocol": 0,
"ClientId": "mqttprobe_my-device",
"WebsocketBasePath": "mqtt",
"UseTls": false,
"AllowUntrustedCertificate": false,
"SubscribedTopics": []
}
],
"Auth": {
"Username": "admin",
"PasswordHash": ""
},
"Performance": {
"MaxStoredMessages": 10000,
"MaxMessagesPerSecond": 50000
},
"Ui": {
"FontAccessible": false,
"Theme": "dark",
"FontFamily": "Inter",
"AutoResubscribe": true,
"DismissedHints": []
},
"ChartsByConnection": {},
"EmulatorsByConnection": {}
}
```
图表和模拟器配置按连接存储,以连接的 GUID 作为键。
### 协议值
| 值 | 协议 |
|---|---|
| `0` | MQTT (TCP) |
| `1` | WebSocket |
## 架构
```
MqttProbe.slnx
├── src/
│ ├── MqttProbe.Shared # Blazor components, models, services (shared by all hosts)
│ ├── MqttProbe.Web # ASP.NET Core web host (web + Docker)
│ └── MqttProbe.Maui # .NET MAUI host (iOS, Android, Windows)
└── tests/
└── MqttProbe.Tests # NUnit + bUnit unit & component tests
```
**核心库:**
- [MQTTnet](https://github.com/dotnet/MQTTnet) v4 — MQTT 客户端 *(锁定至 v4;见下文说明)*
- [MudBlazor](https://mudblazor.com) — UI 组件库
- [Blazor-ApexCharts](https://apexcharts.github.io/Blazor-ApexCharts/) — 实时图表
- [Blazor.Lucide](https://github.com/mrpmorris/blazor-lucide) — 图标库
- [SparkplugNet](https://github.com/SeppPenner/SparkplugNet) — Sparkplug B 模拟器
- [Google.Protobuf](https://github.com/protocolbuffers/protobuf) + [Grpc.Tools](https://www.nuget.org/packages/Grpc.Tools) — Sparkplug B payload 解码;C# 类型在构建时通过 `protoc` 从 `src/MqttProbe.Shared/Protos/sparkplug_b.proto` 生成(已打包在 `Grpc.Tools` 中,无需单独安装)
- [MessagePack-CSharp](https://github.com/MessagePack-CSharp/MessagePack-CSharp) — MessagePack payload 检测和解码
- [FluentValidation](https://docs.fluentvalidation.net/) — 连接表单验证
- [ASP.NET Core Data Protection](https://learn.microsoft.com/aspnet/core/security/data-protection/introduction) — 服务端密钥加密
## 安全
- 密码使用 **PBKDF2-SHA256** 进行哈希处理(100,000 次迭代,随机盐,常数时间验证)
- 在 Linux/macOS 上,`config/appsettings.json` 被限制为 **仅所有者可读写**(模式 600)
- MQTT broker 密码存储在 **平台原生安全存储** 中 — 绝不在配置文件中
- 身份验证cookie是 `HttpOnly`、`SameSite=Strict` 的,并在 8 小时后过期,支持滑动续期
- 绝不会将任何凭证提交到代码库中
## Docker 参考
```
# 启动(快速入门 — 仅 localhost)
docker compose up -d
# 启动(生产环境 — 通过 Caddy 使用 TLS,支持 LAN 访问)
docker compose -f docker-compose.prod.yml up -d
# 查看日志
docker compose logs -f
# 停止
docker compose down
# 代码更改后重新构建
docker compose up --build -d
```
该容器以 **非 root 用户** 身份在端口 `8080` 上运行,使用 `mcr.microsoft.com/dotnet/aspnet:10.0-alpine` 基础镜像(约 130 MB)。
### 使用您自己的反向代理
从 `docker-compose.prod.yml` 中移除 `caddy` 服务,将您的代理(nginx、Traefik 等)指向端口 `8080`,并在应用容器上设置 `AllowedHosts` 环境变量以匹配您的公共主机名,从而避免主机过滤产生的 400 响应。
## 开发
```
# 运行单元 + 组件测试
dotnet test tests/MqttProbe.Tests
# 通过 hot reload 运行 web host
dotnet watch --project src/MqttProbe.Web
# 生成本地 HTML 覆盖率报告(自动打开)
python scripts/coverage.py -open
# 检查代码格式化(CI 会强制执行此操作)
python scripts/format-check.py
# 自动修复格式化违规
python scripts/format-check.py --fix
```
## 许可证
Apache License 2.0 — 详见 [LICENSE](LICENSE)。
第三方组件及其许可证记录在 [NOTICES](NOTICES) 中。
标签:IIoT, Sparkplug B, 云安全, 物联网, 诊断工具, 请求拦截