工业物联网智能人机界面后端服务 — 基于 Go + go-zero 框架构建的 IoT 数据采集、设备连接管理与实时数据推送平台。
IoT-iHMI (Industrial Human-Machine Interface) 是一个面向工业物联网场景的后端服务,提供:
- 多协议设备连接 — 支持 MQTT、Modbus TCP、IEC 61850、Kafka 等工业协议
- 数据源管理 — 项目 → 数据源 → 数据点 三级管理模型
- 实时数据推送 — 基于 WebSocket 的设备数据实时推送
- 消息队列 — Kafka 异步数据流处理
- Mock 模拟器 — 内置设备数据模拟器,无需真实设备即可开发调试
- 连接引擎 — 统一的设备连接池管理,支持自动重连和心跳检测
┌─────────────────────────────────────────────────────────────┐
│ Frontend (Next.js) │
│ WebSocket + REST API │
└───────────────────────────┬─────────────────────────────────┘
│
┌───────────────────────────▼─────────────────────────────────┐
│ IoT-iHMI Backend │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
│ │ REST │ │WebSocket │ │ Engine │ │ Mock │ │
│ │ API │ │ Hub │ │ (连接池) │ │ Simulator │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────────────┘ │
│ │ │ │ │
│ ┌────▼──────────────▼─────────────▼────────────────────┐ │
│ │ Service Context (svc) │ │
│ │ Model (MySQL) │ Redis Cache │ Kafka Producer │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
┌──────────────────┼──────────────────┐
▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌──────────┐
│ MySQL │ │ Redis │ │ Kafka │
└─────────┘ └──────────┘ └──────────┘
│
┌───────────────────────┼───────────────────────┐
▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌──────────┐
│ MQTT │ │ Modbus │ │ IEC61850 │
│ Broker │ │ Device │ │ Device │
└─────────┘ └──────────┘ └──────────┘
iot-ihmi/
├── cmd/
│ └── main.go # 应用入口
├── etc/
│ ├── iot-ihmi.yaml # 默认配置 (安全占位符)
│ ├── iot-ihmi-local.yaml # 本地开发配置 (.gitignore)
│ └── iot-ihmi-dev.yaml # 服务器容器内配置
├── internal/
│ ├── config/
│ │ └── config.go # 配置结构定义
│ ├── engine/
│ │ ├── engine.go # 连接引擎 (连接池管理)
│ │ ├── types.go # 适配器接口定义
│ │ ├── mqtt_adapter.go # MQTT 协议适配器
│ │ ├── modbus_adapter.go # Modbus TCP 适配器
│ │ ├── kafka_adapter.go # Kafka 适配器
│ │ └── iec61850_adapter.go # IEC 61850 适配器
│ ├── handler/
│ │ ├── routes.go # 路由注册
│ │ ├── projecthandler.go # 项目管理 Handler
│ │ ├── sourcehandler.go # 数据源管理 Handler
│ │ ├── sourceparamhandler.go# 数据点管理 Handler
│ │ ├── mockhandler.go # Mock 模拟器 Handler
│ │ └── systemhandler.go # 系统 Handler
│ ├── logic/
│ │ ├── project/ # 项目业务逻辑
│ │ ├── source/ # 数据源业务逻辑
│ │ ├── sourceparam/ # 数据点业务逻辑
│ │ └── mock/ # Mock 模拟器逻辑
│ ├── middleware/
│ │ ├── cors.go # CORS 跨域中间件
│ │ ├── log.go # 日志中间件
│ │ ├── recover.go # Panic 恢复中间件
│ │ └── requestid.go # 请求 ID 中间件
│ ├── mock/
│ │ └── manager.go # Mock 设备模拟器管理
│ ├── model/
│ │ ├── projectmodel.go # 项目数据模型
│ │ ├── sourcemodel.go # 数据源数据模型
│ │ ├── sourceparammodel.go # 数据点数据模型
│ │ └── vars.go # 模型公共变量
│ ├── mq/
│ │ └── producer.go # Kafka 生产者
│ ├── svc/
│ │ └── servicecontext.go # 服务上下文 (依赖注入)
│ ├── types/
│ │ └── types.go # 请求/响应类型定义
│ └── websocket/
│ ├── hub.go # WebSocket Hub (广播中心)
│ ├── client.go # WebSocket 客户端连接
│ └── message.go # WebSocket 消息定义
├── pkg/
│ ├── constant/ # 常量定义
│ ├── errcode/ # 错误码
│ ├── response/ # 统一响应封装
│ └── utils/ # 工具函数
├── sql/
│ ├── iot-ihmi.sql # 数据库建表脚本
│ └── test-data.sql # 测试数据
├── .github/
│ └── workflows/
│ └── deploy-dev.yml # GitHub Actions CI/CD
├── docker-compose.yaml # 本地开发环境 (全套依赖)
├── docker-compose.dev.yml # 服务器部署用
├── Dockerfile # 多阶段 Docker 构建
├── Makefile # 构建脚本
├── .env.example # 环境变量模板
├── .gitignore
└── .dockerignore
- Go 1.21+
- MySQL 8.0
- Redis 7+
- Apache Kafka (可选,Mock 模式不依赖)
# 1. 克隆项目
git clone https://github.com/samxie52/iot-ihmi.git
cd iot-ihmi
# 2. 启动 MySQL、Redis、Kafka、Zookeeper、Mosquitto
make docker-compose-up
# 3. 安装依赖
make tidy
# 4. 启动应用
make run
# 1. 复制环境变量模板
cp .env.example .env
# 2. 编辑 .env 填入真实值
vim .env
# 3. 创建本地开发配置
cp etc/iot-ihmi.yaml etc/iot-ihmi-local.yaml
# 编辑 iot-ihmi-local.yaml 填入远程服务器地址和密码
# 4. 启动
make run-dev
# 健康检查
curl http://localhost:8080/api/v1/system/health
# 系统信息
curl http://localhost:8080/api/v1/system/info
| 文件 |
用途 |
是否提交 Git |
etc/iot-ihmi.yaml |
默认配置 (localhost 安全占位符) |
✅ |
etc/iot-ihmi-local.yaml |
本地开发 (含真实密码) |
❌ |
etc/iot-ihmi-dev.yaml |
服务器容器内 (环境变量注入) |
✅ |
.env.example |
环境变量模板 |
✅ |
.env |
真实环境变量 |
❌ |
| 变量名 |
说明 |
默认值 |
MYSQL_USER |
MySQL 用户名 |
root |
MYSQL_PASSWORD |
MySQL 密码 |
password |
MYSQL_HOST |
MySQL 地址 |
localhost |
MYSQL_PORT |
MySQL 端口 |
3306 |
MYSQL_DATABASE |
MySQL 数据库名 |
iot_ihmi |
REDIS_HOST |
Redis 地址 |
localhost |
REDIS_PORT |
Redis 端口 |
6379 |
REDIS_PASS |
Redis 密码 |
(空) |
KAFKA_HOST |
Kafka 地址 |
localhost |
KAFKA_PORT |
Kafka 端口 |
9092 |
Base URL: http://localhost:8080
统一响应格式:
{
"code": 0,
"msg": "ok",
"data": {}
}
| 方法 |
路径 |
说明 |
| GET |
/api/v1/system/health |
健康检查 |
| GET |
/api/v1/system/info |
系统信息 |
| 方法 |
路径 |
说明 |
| POST |
/api/v1/project |
创建项目 |
| PUT |
/api/v1/project/:id |
更新项目 |
| DELETE |
/api/v1/project/:id |
删除项目 |
| GET |
/api/v1/project/:id |
获取项目详情 |
| GET |
/api/v1/project/list |
获取项目列表 |
curl -X POST http://localhost:8080/api/v1/project \
-H "Content-Type: application/json" \
-d '{"name": "智慧工厂", "description": "工厂设备监控系统"}'
curl "http://localhost:8080/api/v1/project/list?page=1&pageSize=10"
| 方法 |
路径 |
说明 |
| POST |
/api/v1/source |
创建数据源 |
| PUT |
/api/v1/source/:id |
更新数据源 |
| DELETE |
/api/v1/source/:id |
删除数据源 |
| GET |
/api/v1/source/:id |
获取数据源详情 |
| GET |
/api/v1/source/list |
获取数据源列表 |
| POST |
/api/v1/source/connect/:id |
连接数据源 |
| POST |
/api/v1/source/disconnect/:id |
断开数据源 |
| POST |
/api/v1/source/test |
测试数据源连接 |
curl -X POST http://localhost:8080/api/v1/source \
-H "Content-Type: application/json" \
-d '{
"projectId": 1,
"name": "MQTT 温湿度传感器",
"sourceType": "mqtt",
"config": "{\"broker\":\"192.168.1.100\",\"port\":1883,\"clientId\":\"sensor-01\",\"topic\":\"sensor/#\",\"qos\":1}"
}'
curl -X POST http://localhost:8080/api/v1/source \
-H "Content-Type: application/json" \
-d '{
"projectId": 1,
"name": "PLC 车间控制器",
"sourceType": "modbus",
"config": "{\"host\":\"192.168.1.200\",\"port\":502,\"slaveId\":1,\"timeout\":3000,\"pollInterval\":1000}"
}'
| 类型 |
说明 |
配置参数 |
mqtt |
MQTT 协议 |
broker, port, clientId, topic, qos, username, password |
modbus |
Modbus TCP |
host, port, slaveId, timeout, pollInterval |
iec61850 |
IEC 61850 |
host, port (预留) |
kafka |
Kafka 消费 |
brokers, topic, groupId |
| 方法 |
路径 |
说明 |
| POST |
/api/v1/source-param |
创建数据点 |
| PUT |
/api/v1/source-param/:id |
更新数据点 |
| DELETE |
/api/v1/source-param/:id |
删除数据点 |
| GET |
/api/v1/source-param/:id |
获取数据点详情 |
| GET |
/api/v1/source-param/list |
获取数据点列表 |
| POST |
/api/v1/source-param/batch |
批量创建数据点 |
curl -X POST http://localhost:8080/api/v1/source-param \
-H "Content-Type: application/json" \
-d '{
"sourceId": 1,
"pointId": "temperature",
"pointName": "车间温度",
"dataType": "float",
"unit": "℃",
"config": "{\"topic\":\"sensor/temperature\"}"
}'
curl -X POST http://localhost:8080/api/v1/source-param/batch \
-H "Content-Type: application/json" \
-d '{
"sourceId": 1,
"params": [
{"pointId": "temp", "pointName": "温度", "dataType": "float", "unit": "℃"},
{"pointId": "humidity", "pointName": "湿度", "dataType": "float", "unit": "%"}
]
}'
| 方法 |
路径 |
说明 |
| POST |
/api/v1/mock |
创建模拟器 |
| POST |
/api/v1/mock/start/:id |
启动模拟器 |
| POST |
/api/v1/mock/stop/:id |
停止模拟器 |
| DELETE |
/api/v1/mock/:id |
删除模拟器 |
| GET |
/api/v1/mock/:id |
获取模拟器详情 |
| GET |
/api/v1/mock/list |
获取模拟器列表 |
# 创建
curl -X POST http://localhost:8080/api/v1/mock \
-H "Content-Type: application/json" \
-d '{"name": "温度模拟器", "protocol": "mqtt", "interval": 1000, "pointCount": 5}'
# 启动 (用返回的 id)
curl -X POST http://localhost:8080/api/v1/mock/start/{id}
服务端推送的设备数据消息:
{
"type": "device_data",
"sourceId": 1,
"pointId": "temperature",
"value": 25.6,
"timestamp": "2026-02-28T12:00:00Z"
}
const ws = new WebSocket('ws://localhost:8080/ws');
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Device data:', data);
};
ws.onclose = () => {
console.log('WebSocket disconnected');
// 实现自动重连逻辑
};
Push to dev → GitHub Actions → Test → Build (GHCR) → SSH Deploy → Server
项目使用 GitHub Actions 自动部署,流程:
- Push to
dev 分支 — 触发 deploy-dev.yml
- Test —
go vet + gofmt 代码检查
- Build — 多阶段 Docker 构建,推送镜像到 GHCR
- Deploy — SSH 到服务器,
docker compose pull && up -d
在仓库 Settings → Secrets and variables → Actions 中添加:
| Secret |
说明 |
SERVER_HOST |
服务器 IP |
SERVER_USER |
SSH 用户名 |
SSH_PRIVATE_KEY |
SSH 私钥 |
SSH_PORT |
SSH 端口 |
MYSQL_USER |
MySQL 用户名 |
MYSQL_PASSWORD |
MySQL 密码 |
MYSQL_DATABASE |
MySQL 数据库名 |
IOT_IHMI_SERVER_PORT |
应用端口 (默认 8082) |
# 1. 构建 Docker 镜像
make docker
# 2. 或直接在服务器上
docker compose -f docker-compose.dev.yml up -d
| 服务 |
容器名 |
端口 |
| IoT-iHMI API |
iot-ihmi-dev |
8082 |
| MySQL |
mysql |
23306 |
| Redis |
redis |
26379 |
| Kafka |
kafka |
29092 |
| Zookeeper |
zookeeper |
22181 |
make build # 构建应用
make run # 运行 (默认配置)
make run-dev # 运行 (本地开发配置,连接远程服务器)
make test # 运行测试
make cover # 测试覆盖率
make lint # 代码检查 (需安装 golangci-lint)
make fmt # 代码格式化
make tidy # 依赖管理
make docker # Docker 构建
make docker-compose-up # 启动本地开发环境依赖
make docker-compose-down# 停止本地开发环境依赖
make sql-import # 导入 SQL 到远程服务器
make sql-test-data # 导入测试数据到远程服务器
# 初始化数据库
mysql -h <host> -P <port> -u <user> -p<password> iot_ihmi < sql/iot-ihmi.sql
# 导入测试数据
mysql -h <host> -P <port> -u <user> -p<password> iot_ihmi < sql/test-data.sql
project (项目)
└── source (数据源: mqtt / modbus / iec61850 / kafka)
└── source_param (数据点)
| 表 |
说明 |
project |
项目表 — 顶层管理单元 |
source |
数据源表 — 设备连接配置 |
source_param |
数据点表 — 具体采集的数据项 |
每个 API 请求经过以下中间件(从外到内):
RequestID → CORS → Recover → Log → Handler
- 在
internal/engine/ 创建 xxx_adapter.go
- 实现
Adapter 接口:
type Adapter interface {
Connect(config string) error
Disconnect() error
IsConnected() bool
Subscribe(handler DataHandler) error
GetStatus() AdapterStatus
}
- 在
engine.go 中注册新的适配器类型
MIT License
Copyright (c) 2026 Sam Xie