工业设备预测性维护系统,本科生生产实习版本。项目覆盖数据模拟、Kafka 实时队列、Spark Structured Streaming 窗口处理、InfluxDB 时序存储、PyTorch 模型推理、Spring Boot 报警工单和 Vue 可视化看板。
- Python:设备模拟器、备用流处理 worker、FastAPI 模型服务。
- Java + Spring Boot:设备、报警、工单和预测结果管理。
- Vue 3 + Vue Router + Vite + Axios + ECharts:前端看板。
- Kafka:实时消息队列。
- Spark Structured Streaming:实时窗口特征计算。
- InfluxDB:时序数据和窗口特征。
- PyTorch:LSTM AutoEncoder、CNN-LSTM VAE 异常检测。
- sklearn:IsolationForest 传统异常检测。
- MySQL:业务数据存储。
flowchart LR
A[Python 设备模拟器] --> B[Kafka: pdm.raw.telemetry.v1]
B --> C[实时处理: simple_worker 或 Spark]
C --> D[InfluxDB: raw_sensor / feature_window]
C -- predict request --> E[FastAPI model-service]
C --> F[Kafka: pdm.feature.window.v1 / pdm.anomaly.score.v1]
C --> G[Spring Boot: /api/internal/predictions]
E -- predict result --> C
G --> H[MySQL]
H --> I[Vue Dashboard]
模拟器每秒生成 5 台设备数据,发送到 pdm.raw.telemetry.v1。演示默认使用 simple_worker.py,它按设备维护最近 30 条数据缓存,约等于 30 秒窗口,每 5 秒计算窗口特征;可选 Spark 版本使用 30 秒窗口、5 秒滑动步长。流处理会写入 InfluxDB、调用模型服务、把结果写入 Kafka,并同步 POST 到 Spring Boot。模型服务返回异常分数、健康度、RUL 和维修建议。后端保存预测结果,WARNING/CRITICAL 生成报警,只有 CRITICAL 自动生成 P1 工单。
建议先启动 MySQL、Kafka、InfluxDB 这些基础组件,再用多个终端分别启动模型服务、后端、前端、模拟器和实时处理 worker。演示时优先使用 simple_worker.py,它不依赖本机 Spark 环境,能跑通“模拟数据 -> Kafka -> 模型服务 -> 后端 -> 前端看板”的完整闭环。
需要提前安装:
- JDK 17+、Maven。
- Node.js、npm。
- Python 3.10+,推荐使用 Conda 虚拟环境
MLtest1。 - MySQL、Kafka、InfluxDB。可以用 Docker Compose,也可以用 Homebrew 本机服务。
先进入项目根目录:
cd /Users/ZeroneRY/Desktop/project/工业检测/industrial-pdm-system第一次按后面的 2A. Homebrew 启动基础组件 完成依赖安装和初始化后,后续日常启动可以直接执行:
bash scripts/start-all.sh脚本会自动完成这些事情:
- 启动 MySQL、Kafka、InfluxDB。
- 初始化 MySQL 数据库、InfluxDB bucket 和 Kafka topics,已存在时会自动跳过。
- 启动
model-service、backend-java、frontend-vue、simulator、simple_worker.py。 - 将日志写入
logs/,将进程号写入pids/。 - 默认使用 Conda 环境
MLtest1,默认模拟器异常率ANOMALY_RATE=0.015。当前规则模型会结合窗口均值和峰值判断异常,默认值适合演示报警和工单。
启动完成后打开:
http://127.0.0.1:5173
查看日志:
tail -f logs/model-service.log logs/backend-java.log logs/frontend-vue.log logs/simulator.log logs/simple-worker.log停止全部脚本启动的服务:
cd /Users/ZeroneRY/Desktop/project/工业检测/industrial-pdm-system
bash scripts/stop-all.sh如果是通过后台 screen 会话启动的一键脚本,还可以顺手关闭该会话:
screen -S industrial-pdm-start -X quit如果要更快触发报警和工单:
ANOMALY_RATE=0.3 bash scripts/start-all.sh如果要长时间观察看板且不希望报警增长太快:
ANOMALY_RATE=0.005 bash scripts/start-all.sh如果 Conda 环境名不是 MLtest1:
CONDA_ENV=你的环境名 bash scripts/start-all.sh下面的手动启动步骤主要用于第一次初始化、排错或单独调试某个模块。
当前这台 macOS 机器推荐使用 Homebrew 启动 MySQL、Kafka、InfluxDB,因为 Docker Hub 拉取镜像可能超时。
安装依赖,第一次安装过以后不用重复执行:
brew install mysql@8.4 kafka influxdb@2 maven启动 MySQL:
/opt/homebrew/opt/mysql@8.4/bin/mysqld_safe --datadir=/opt/homebrew/var/mysql新开一个终端启动 Kafka:
/opt/homebrew/opt/kafka/bin/kafka-server-start /opt/homebrew/etc/kafka/server.properties新开一个终端启动 InfluxDB:
INFLUXD_CONFIG_PATH=/opt/homebrew/etc/influxdb2/config.yml \
/opt/homebrew/opt/influxdb@2/bin/influxdHomebrew 方式需要手动初始化 MySQL、InfluxDB 和 Kafka。
下面的初始化命令只需要第一次执行。以后日常启动只需要启动 MySQL、Kafka、InfluxDB 三个进程,不需要重复建库、建 bucket 或建 topic。
MySQL 初始化:
/opt/homebrew/opt/mysql@8.4/bin/mysql -u root -e "CREATE DATABASE IF NOT EXISTS pdm CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER IF NOT EXISTS 'pdm'@'localhost' IDENTIFIED BY 'pdm123456'; CREATE USER IF NOT EXISTS 'pdm'@'%' IDENTIFIED BY 'pdm123456'; GRANT ALL PRIVILEGES ON pdm.* TO 'pdm'@'localhost'; GRANT ALL PRIVILEGES ON pdm.* TO 'pdm'@'%'; FLUSH PRIVILEGES;"
/opt/homebrew/opt/mysql@8.4/bin/mysql -u pdm -ppdm123456 pdm < sql/schema.sql
/opt/homebrew/opt/mysql@8.4/bin/mysql -u pdm -ppdm123456 pdm < sql/seed.sqlInfluxDB 初始化:
curl -X POST http://localhost:8086/api/v2/setup \
-H "Content-Type: application/json" \
-d '{"username":"pdm","password":"pdm123456","org":"pdm","bucket":"pdm","token":"pdm-token"}'如果提示已经初始化,可以忽略。
Kafka Topic 初始化:
for t in pdm.raw.telemetry.v1 pdm.feature.window.v1 pdm.anomaly.score.v1 pdm.alarm.event.v1; do
/opt/homebrew/opt/kafka/bin/kafka-topics \
--bootstrap-server localhost:9092 \
--create \
--if-not-exists \
--topic "$t" \
--partitions 3 \
--replication-factor 1
done其中 pdm.alarm.event.v1 是预留报警事件 topic,当前报警闭环由流处理模块同步调用 Spring Boot 完成,后端还没有直接生产或消费该 topic。
如果 Docker Hub 网络正常,也可以用 Docker Compose 启动 MySQL、Kafka、InfluxDB:
docker compose version
docker compose up -d
docker compose psdocker compose up -d 必须在包含 docker-compose.yml 的项目根目录执行。如果在上一级 工业检测 目录执行,会出现 no configuration file provided: not found。也可以不切目录,直接指定配置文件:
docker compose -f /Users/ZeroneRY/Desktop/project/工业检测/industrial-pdm-system/docker-compose.yml up -dDocker Compose 会自动完成 MySQL、InfluxDB 和 Kafka 初始化,不需要再手动执行上面的 Homebrew 初始化命令。
如果出现下面这种错误,说明 Docker Hub 拉镜像超时,不是项目配置错误:
failed to resolve reference "docker.io/..."
i/o timeout
这种情况下直接改用 3A. Homebrew 启动基础组件。
如果执行 docker compose up -d 出现 unknown command: docker compose 或 unknown shorthand flag: 'd' in -d,说明当前 Docker CLI 没有安装 Compose 插件,也直接改用 Homebrew 方式。
如果本机已经用 Homebrew 启动过 MySQL、Kafka 或 InfluxDB,可能会占用 3306、9092、8086 端口。此时 Docker Compose 和 Homebrew 二选一,不要同时启动。
cd model-service
conda activate MLtest1
pip install -r requirements.txt
uvicorn app.main:app --host 127.0.0.1 --port 8000验证:
curl http://127.0.0.1:8000/api/health
curl http://127.0.0.1:8000/api/modelscd backend-java
mvn spring-boot:run验证:
curl http://127.0.0.1:8080/api/equipmentscd frontend-vue
npm install
npm run dev -- --host 127.0.0.1浏览器打开:
http://127.0.0.1:5173
前端页面每 5 秒自动轮询后端,实时刷新设备状态、报警、工单和趋势图。
cd simulator
conda activate MLtest1
pip install -r requirements.txt
ANOMALY_RATE=0.015 python main.py模拟器默认异常率为 0.015,和一键启动脚本一致。如果希望长时间观察实时看板且不让报警增长过快,建议显式使用 ANOMALY_RATE=0.005。如果需要快速演示报警和工单生成,可临时使用:
ANOMALY_RATE=0.3 python main.pycd stream-spark
conda activate MLtest1
pip install -r requirements.txt
python simple_worker.pysimple_worker.py 会消费 Kafka 原始数据,计算窗口均值、标准差和峰值特征,写入 InfluxDB,调用模型服务,并把预测结果同步写入 Spring Boot 后端。模型服务返回 WARNING 时后端生成报警,返回 CRITICAL 时后端生成报警并自动创建 P1 工单。
前端 Dashboard 页面有“重置演示数据”按钮,会清空预测结果、报警和工单,并恢复 5 台设备初始状态。
也可以用命令重置:
curl -X POST http://127.0.0.1:8080/api/demo/reset训练模型:
cd model-service
conda activate MLtest1
python train/train_lstm_ae.py
python train/train_cnn_lstm_vae.py
python train/train_iforest.py
curl -X POST http://127.0.0.1:8000/api/models/reload切换模型:
curl -X POST http://127.0.0.1:8000/api/models/switch \
-H "Content-Type: application/json" \
-d '{"model_name":"ensemble"}'可选模型包括 rule、lstm_ae、cnn_lstm_vae、iforest、ensemble。没有训练权重时,深度学习和 IsolationForest 会返回保守默认分数,规则模型仍会根据窗口均值和峰值识别明显异常,保证项目既能跑通,也能在演示数据中触发报警和工单。
本科生演示建议先用 simple_worker.py。如果本机 Spark 环境完整,可以改用 Spark Structured Streaming:
cd stream-spark
spark-submit --packages org.apache.spark:spark-sql-kafka-0-10_2.12:3.5.1 spark_streaming_job.py一键脚本启动的服务推荐使用:
cd /Users/ZeroneRY/Desktop/project/工业检测/industrial-pdm-system
bash scripts/stop-all.sh
screen -S industrial-pdm-start -X quit如果是手动分别启动的业务服务,可以在对应终端按 Ctrl+C 停止。也可以使用:
pkill -f 'uvicorn app.main:app'
pkill -f 'spring-boot:run'
pkill -f 'vite'
pkill -f 'simulator/main.py'
pkill -f 'simple_worker.py'Homebrew 基础组件停止:
pkill -f kafka.Kafka
pkill -f influxd
/opt/homebrew/opt/mysql@8.4/bin/mysqladmin -u root shutdownDocker Compose 基础组件停止:
cd /Users/ZeroneRY/Desktop/project/工业检测/industrial-pdm-system
docker compose stop如果要删除 Docker 容器并重新走初始化流程:
docker compose down
docker compose up -dsimulator:模拟 pump、motor 的温度、振动、电流、转速、压力,支持 temperature_high、vibration_high、current_high、drift、spike。stream-spark:Spark 实时窗口处理;simple_worker.py是本科生演示推荐方案,不依赖本机 Spark。model-service:统一模型接口,包含 LSTM AutoEncoder、CNN-LSTM VAE、IsolationForest 和 RuleModel;RuleModel 会结合均值和峰值特征输出异常类型。backend-java:Spring Boot 三层结构,管理设备、报警、工单和预测结果;工单开始处理会确认关联报警,工单完成会关闭关联报警。frontend-vue:Dashboard、设备地图、设备详情、报警列表、工单列表;页面每 5 秒自动轮询后端刷新数据。sql:MySQL 建表和初始化数据。
更详细的逐文件说明和完整数据流见 docs/project-structure-and-flow.md。
模型服务提供 /api/health、/api/models、/api/models/switch、/api/models/reload、/api/predict。后端提供 /api/equipments、/api/alarms、/api/work-orders、/api/internal/predictions 等接口。演示环境还提供 /api/demo/reset,用于清空预测结果、报警、工单并恢复 5 台设备初始状态。
完整请求体和返回字段见 docs/api.md。
当前已内置 cnn_lstm_vae 模型,流程是:
设备时序数据
-> 普通 CNN + 膨胀 CNN 并行提取多尺度特征
-> LSTM 编码时间依赖
-> 输出 mu/logvar
-> 采样 z
-> Decoder 重构序列
-> 重构误差 + KL 散度
-> 异常分数
如果要把 LSTM AutoEncoder 换成其他 CNN-LSTM 模型,只需要:
- 在
model-service/app/models/下新增模型文件,例如cnn_lstm.py。 - 继承
BasePredictiveModel。 - 实现
load和predict。 - 在
ModelManager注册模型。 - 修改
active_model_name或调用/api/models/switch。 - Spark、Spring Boot、Vue 不需要修改,因为它们只依赖
/api/predict的统一返回。
切换到 CNN-LSTM VAE:
curl -X POST http://127.0.0.1:8000/api/models/switch \
-H "Content-Type: application/json" \
-d '{"model_name":"cnn_lstm_vae"}'详见 docs/demo-flow.md。建议先使用 simple_worker.py 演示闭环,再展示 Spark 版本代码。
本项目定位为本科生产实习和答辩演示版本,重点是跑通预测性维护的完整业务闭环。以下能力已经保留工程接口或演示实现,但不是工业生产级完整实现:
- MQTT / Modbus:当前通过
simulator/protocol_adapters.py保留统一采集源接口,演示时使用 Python 模拟数据;后续接真实设备时,可用paho-mqtt订阅设备 topic,或用pymodbus读取 PLC/网关寄存器,再转换为当前统一 telemetry 格式写入 Kafka。 - RUL / PHM:当前
rul.py根据健康度和异常分数进行规则估算,能够支撑看板和工单演示;严格 PHM 需要真实故障历史、寿命标签或退化过程数据,再训练剩余寿命预测模型。 - 模型权重:项目提供 LSTM AutoEncoder、CNN-LSTM VAE、IsolationForest 的训练脚本和加载机制;没有训练权重时,深度学习模型和 IsolationForest 会返回保守默认分数,RuleModel 负责保证演示数据能触发可解释的报警和工单。
- Kafka 报警 topic:
pdm.alarm.event.v1当前是预留 topic,报警和工单闭环由流处理模块同步调用 Spring Boot 完成;后续可改为后端 Kafka Consumer 或报警事件异步订阅。
- 数据采集、实时处理、模型推理、报警、工单、可视化形成完整闭环。
- 前端看板支持 5 秒自动刷新,便于观察实时数据流带来的状态变化。
- Dashboard 提供“重置演示数据”按钮,便于重复演示报警和工单生成流程。
- 后端会对同设备未关闭报警、未完成工单做去重,避免持续异常时工单无限暴涨。
- 模型层可替换,已包含 CNN-LSTM VAE 示例,便于后续替换 Transformer 或 TCN。
- 使用 InfluxDB 保存时序特征,MySQL 保存业务数据,职责清晰。
- 代码结构简单,适合本科生答辩讲解。
- 没有实现登录鉴权和多租户。
- MQTT / Modbus 当前是扩展接口,尚未接入真实 broker、PLC 或工业网关。
- RUL 当前是规则估算,尚未基于真实寿命标签训练严格 PHM 模型。
- LSTM AutoEncoder、CNN-LSTM VAE 和 IsolationForest 提供训练脚本与加载机制,真实项目需要工业现场历史数据重新训练和验证。
- Spring Boot 趋势图暂用 MySQL 预测结果,后续可接入 InfluxDB 查询。
- Kafka 到后端的消费目前由流处理代码同步 POST,后续可增加后端 Kafka Consumer。