
做工业设备监测这个项目最直接的动机是我在车间里见过太多设备坏了才知道、修好全靠老师傅的场景。传统中小工厂的设备管理基本是三表一账点检表、维修表、保养表加一本纸质台账设备状态靠人眼盯、靠耳朵听数据上报靠下班后补Excel。而一套基于Django的工业物联网设备监测与维护系统要解决的就是把设备从离线哑设备变成在线数字设备的过程——实时采集运行参数、自动识别异常工况、把维护任务从口头安排变成系统化的工单流转。这篇文章我把整个项目从需求拆解、技术选型、设备接入、监测预警、维护工单到论文答辩资料整理的完整链条都捋一遍既适合正在做毕业设计的同学参考也适合想用Django做工业场景项目的开发者抄作业。1. 设备监测系统的需求拆解与整体架构设计1.1 车间现场的真实痛点我在项目前期调研时蹲过一家机械加工车间的生产现场观察了整整三天。车间里有三十多台数控机床和注塑机每台设备的控制器都在持续产生大量有价值的数据包括主轴转速、温升、振动频率、电流负载率、液压油压、运行时长等等。但现场的操作方式却是设备报警灯亮了操作工先用对讲机喊电工电工来了靠万用表和经验排查排查完在纸质维修单上签字月底再由文员把维修单录入Excel。这个流程最大的问题不是某一个环节出错而是整个链条没有数据沉淀。设备运行参数没有任何历史记录昨天和今天的电流曲线有什么差异根本无从对比维护保养靠日历提醒而不是设备状态驱动很多隐患都是在设备已经出现明显故障征兆之后才被发现。所以这个系统的核心需求定义得很清晰一是采集把分散设备的运行数据实时汇聚到统一平台二是监测以曲线、报表、大屏的方式让设备状态可视化三是预警当运行参数越限时自动产生报警并通知责任人四是维护闭环报警之后能够创建维修工单、指派人员、跟踪进度、记录结果形成完整的维护档案。这四个需求不是并列关系而是层层递进采集是底座监测是展示预警是判断维护工单是动作。没有采集后面全是空中楼阁只有采集没有维护闭环那也就是个展示用的花瓶系统。1.2 技术选型Django在工业物联网场景里的位置说实话工业物联网平台用Java或者Go做后端是业界的主流特别是大型企业级项目往往用Spring Cloud那套微服务体系。但Django在这个场景里完全有自己不可替代的位置尤其是对于中小型工厂、实训基地、高校实验室这类规模的项目。Django最大的优势是开发效率。设备的监测和维护系统本质上是数据采集 业务管理两类功能的复合体Django的ORM、Admin后台、Form校验、自带的权限系统几乎把业务管理这部分的工作量砍掉了一半。设备台账管理、用户角色分配、工单流转、报警记录查询这些用Django写起来非常顺手模型一定义完增删改查和后台管理界面就自动出来了。第二个优势是Python的生态衔接。工业设备的数据采集层几乎离不开PythonModbus通信有pymodbus库PLC串口有pyserialMQTT有paho-mqtt数据解析用struct或者numpy都方便。如果后端用Java采集端还得单独写一个Python服务两边用HTTP或者消息队列对接架构复杂度上去了。用Django可以做到采集服务和Web业务共用一套模型定义和数据库配置开发调试都轻松很多。当然Django也有短板最大的问题是阻塞模型在处理大量长连接时的弱势。这个我在后面的部署章节会专门讲解决方案通常是把采集进程独立出去不占用Django的请求进程这个设计思路要在架构阶段就定下来不然后期会很被动。1.3 四层架构设备层、采集层、业务层、展示层整个系统我最终采用的是四层架构每层之间职责边界很清楚设备层车间现场的PLC、传感器、仪器仪表通过Modbus TCP/RTU、MQTT等协议对外提供数据。采集层部署在工厂侧的采集服务定时轮询或订阅设备数据解析后上报到中心数据库。这一层我选择了独立于Django主进程的Python采集程序。业务层Django应用本身负责设备台账、实时监测、报警规则、维护工单、用户权限、报表统计等业务逻辑。展示层基于Django模板BootstrapECharts的数字大屏和Web管理界面移动端通过响应式页面适配。这个架构的核心决策在于采集层必须独立部署。很多初学Django的同学会试图把数据采集逻辑直接写进views里用HTTP请求触发采集动作这完全是错的。工业生产要求的是持续、稳定的数据流不是用户点一下才采一次。所以采集层的定位是常驻运行的守护进程它只管把设备数据搬进数据库不关心Web请求Django业务层只负责把数据呈现给用户以及处理人的操作。两者通过数据库和消息队列解耦这样即使Web服务重启采集也不会中断。2. 设备接入与数据采集从PLC到Django的数据链路2.1 通信协议选型Modbus TCP为主兼顾MQTT设备接入是整个项目里技术含量最高也最容易踩坑的部分。我在系统里主要适配了两种协议Modbus TCP和MQTT。Modbus是工业领域最普及的通信协议几乎所有PLC和仪器仪表都原生支持。Modbus TCP的用法很简单设备作为服务端监听502端口采集端作为客户端去读寄存器。一个典型的读操作流程是建立TCP连接、发送读请求帧包含设备地址、功能码、寄存器起始地址、寄存器数量、接收响应帧、按字节解析出数值。例如读取一台变频器的输出频率可能在40001寄存器地址功能码03表示读保持寄存器协议栈会帮你处理事务ID和CRC校验Python的pymodbus库封装得已经很成熟了。MQTT则主要针对那些不具备传统工业总线接口、通过网关或者4G DTU上云的设备。它的优势是发布/订阅模型天然适合大规模的遥测数据上行Broker负责转发消息设备端只管发布服务端只管订阅。我在采集层里同时开了Modbus TCP接入模块和MQTT订阅模块这样既覆盖了车间现有的老设备也兼容了新的物联网网关设备。2.2 Django模型设计设备台账与采集点位的建模设备接入要落到Django模型上这里有两个关键模型设备Device和采集点位Point。设备模型管理的是「这台设备是谁」字段包括设备编号、设备名称、设备类型、所在车间、PLC型号、IP地址、通信端口、Modbus从站地址、设备状态在线/离线/维修、投产日期、保养周期等基础信息。采集点位模型管理的是「设备上有哪些可采的数据」字段包括所属设备外键、点位名称比如主轴电流、寄存器地址、数据类型16位整数/32位浮点/布尔量、倍率转换系数、单位、报警阈值上下限、是否启用等。点位为什么要单独建一张表而不是直接把字段写死在代码里因为不同设备的寄存器映射表完全不同把点位配置化之后新增一台设备只需要在数据库里录入点位信息采集服务和监测页面都会自动适配不需要改一行代码。这个设计是整套系统灵活性的关键我在论文里也重点讲了这一点。2.3 采集服务独立进程 批量写入采集服务我没有放在Django项目里而是作为独立的Python服务运行通过环境变量读取Django的数据库配置。采集循环的逻辑大致是这样import time from pymodbus.client import ModbusTcpClient def read_device_points(device, points): client ModbusTcpClient(device.ip, portdevice.port, timeout5) if not client.connect(): return None results {} for point in points: data client.read_holding_registers( addresspoint.register_addr, countpoint.register_count, slavedevice.slave_id ) if data.isError(): continue raw data.registers[0] results[point.id] raw * point.scale_factor client.close() return results这段是简化后的逻辑实际项目里还涉及Modbus的功能码选择、字节序处理、32位数据的两个寄存器拼接等细节。采集到的数据不会一条条立即写库而是先攒在内存里每5秒批量INSERT一次。批量写入的原因很简单——如果一台设备有20个采集点采集周期3秒50台设备每秒产生的数据接近300条逐条写入数据库会带来极大的写入压力。批量写入配合数据库连接的事务管理能轻松把写入次数降低一到两个数量级。2.4 时序数据存哪MySQL的轻量方案与优化工业监测数据本质上是时序数据理想的选择是TimescaleDB、InfluxDB这类时序数据库。但考虑到毕设项目和中小规模系统的部署便利性我用了MySQL并在表设计上做了时序化的处理。核心的采集记录表结构大致是自增主键、设备外键、点位外键、采集时间、数值。这张表增长很快必须做两个优化。第一是联合索引按(device_id, point_id, collect_time)建索引所有查询都是某台设备某个点位在某段时间内的数据这个索引能保证查询效率。第二是数据归档策略原始明细数据只保留三个月三个月前的数据聚合成每小时均值表存到历史库既控制存储成本又不丢统计趋势。有一点要特别注意读取设备的实时状态和查询历史曲线是两个完全不同的逻辑。实时状态永远只查设备点位表的当前值由采集服务每次写入后同步更新历史曲线才需要去查流水表。把这两个概念分开系统的性能瓶颈就清晰多了。3. 监测预警与维护工单核心业务功能的落地细节3.1 实时监控页面轮询、图表与在线状态判定监测大屏是所有非技术用户最直观感受系统价值的入口也是答辩演示时最能出效果的模块。大屏页面我做了三个区域车间总览卡片区展示设备总数、在线数、报警数、待处理工单数设备状态列表区用红黄绿三色标识每台设备当前状态核心设备曲线区展示选中设备的关键参数实时曲线。实时数据的前端获取方案我最终选择了轻量的轮询而非WebSocket。每3秒发一次AJAX请求查询设备点位表和最近几十条流水数据用ECharts的setOption更新曲线。在设备数量不大、请求不频繁的情况下这个方案完全够用开发成本远低于WebSocket也不需要考虑连接保持和重连问题。代码也很简单setInterval配合一个公共的Ajax函数就能完成。设备在线状态的判定很容易忽略。我的做法是不依赖Web应用去判断而是由采集服务每轮采集后更新设备表的last_seen字段。展示层判断在线状态时只要看last_seen和当前时间之差是否超过设定的阀值比如90秒即可。这样避免了一个经典问题Web服务器重启后所有设备都显示离线因为采集还在跑设备其实活得好好的。3.2 预警规则引擎阈值判断不能只做一次比较报警功能看起来很直接——点位值超上限就报警。但实际设计时必须考虑几个工程细节否则做出来会被车间用户骂。首先是死区设置。设备的正常运行参数会有波动比如主轴电流偶发超过报警阈值0.5秒又回落。如果阈值一超就报警系统会变成报警轰炸机。所以我在每个点位模型里增加了报警死区字段只有当数值超过阈值且持续超过设定的时长比如连续3个采集周期才判定为报警。这个延时确认机制能过滤掉大量毛刺和瞬时干扰。然后是报警恢复与去重。同一个设备同一个点位在报警未消除之前不应该重复产生报警记录。我给活跃报警表设计了唯一约束设备点位状态每次采集时检查只在状态从正常变为异常时插入一条报警记录异常变为正常时把记录状态更新为已恢复。这样既保留了完整的事故时间线又避免重复报警。报警通知我做了两级Web站内消息推送到维护中心首页同时通过企业微信机器人Webhook和短信接口把报警概要推送给当班工程师。短信真的会产生费用实际部署时一般只对最高级别的报警开短信其他级别走消息中心就够了。3.3 维护工单从报警到修复的闭环流程维护工单模块是整个系统里业务逻辑最重的一块也是区别于大多数只监测不处理的物联网Demo的核心。工单模型包含工单编号自动生成、关联设备、报警记录外键、工单类型故障维修/计划保养、紧急程度普通/加急/紧急、标题、描述、指派人、当前状态、计划完成时间、实际完成时间、维修内容记录、工时、更换配件、处理结果等字段。工单状态我设计成五个节点待指派、处理中、待验收、已完成、已关闭。流转规则是这样的报警确认后维护中心可以一键从报警记录创建工单默认状态待指派指派给维修工程师后变成处理中工程师处理完填写维修详情状态变成待验收车间负责人确认故障消除状态变成已完成如果维修不彻底设备再次报警可以从已完成状态重新开出工单并关联同一个设备的历史故障记录。这个闭环的价值是可以输出两张报表设备MTBF平均故障间隔时间和MTTR平均修复时间。这两张表不是摆设它们直接反映整个车间的设备管理水平也是论文里很好的分析素材。我把报表导出做成了CSV和Excel双格式用户点下载按钮就能拿到数据这个功能的使用频率比很多人预想的要高得多。4. 系统设计之外论文、答辩PPT和源码规范的配套实操4.1 论文如何写出工程性而不是流水账很多同学做毕设技术做得不错论文却写成软件使用说明书这是最可惜的。工业物联网系统的论文一定要体现需求—设计—实现—验证的闭环而且每一步都要有层次。我写论文时采用的是这样的结构框架第一章绪论讲背景和国内外工业物联网的研究现状重点引用几篇近五年的文献把监测技术从传统人工巡检到工业互联网平台的发展脉络梳理清楚第二章需求分析把前面讲的四个痛点一一对应到功能性需求和非功能性需求不要写“系统需要界面友好”这种废话要写具体的指标比如数据采集周期不超过3秒同时支持不少于50台设备接入第三章系统设计给出四层架构图和数据库E-R图说明每一层为什么这么划分第四章系统实现按采集模块、监测模块、报警模块、工单模块分别写实现思路和关键代码片段这段避免大段贴代码要贴的是有设计思想的代码比如批量写入逻辑、预警死区判断逻辑、工单状态机转换逻辑第五章系统测试分功能测试和性能测试性能测试要有实际数据比如模拟50台设备、5000个点位并发上报时平均响应时间是多少。论文最忌讳的是把系统设计写成了功能罗列每一个模块都是首先设计了表结构、然后实现了增删改查页面。要把每个功能模块背后的判断写出来为什么采集要独立进程为什么预警要加死区为什么工单要有验收环节这些为什么才是工程论文的价值所在。4.2 答辩PPT怎么组织逻辑答辩PPT我用的是场景引入—技术亮点—效果展示—总结展望四段式整个过程控制在15分钟以内。场景引入部分放两张车间的实拍照片加一张开篇页讲清楚现状痛点30秒内把评委拉进你的语境里。技术亮点部分是最重要的挑3到4个最能体现你工作量的点展开第一个是设备接入层完整演示Modbus的采集链路第二个是四层架构设计的合理性第三个是预警规则引擎和工单闭环的联动第四个是性能优化比如批量写入和数据库索引。效果展示环节千万不要只截静态页面截图要录一段3到5分钟的系统演示视频打开大屏页面、选择一台设备、展示实时曲线、故意触发一次报警可以用测试数据把电流值推高、演示报警生成和工单流转的完整过程。视频的冲击力比页面截图强十倍同时也是应对答辩当天突发网络故障的安全措施。4.3 源码整理规范给评分的人和看代码的人留条路项目源码的整理直接反映一个学生的工程素养。我习惯按这个结构组织仓库src/ ├── collect/ # 采集服务独立Python进程 ├── web/ # Django项目主目录 │ ├── apps/ │ │ ├── devices/ # 设备管理模块 │ │ ├── monitor/ # 监测与图表模块 │ │ ├── alarm/ # 报警模块 │ │ └── workorder # 维护工单模块 │ ├── config/ # 项目配置 │ └── static/ # 前端静态资源 ├── docs/ # 数据库设计文档、接口文档 └── deploy/ # 部署脚本、requirements.txt每个模块的README里写清楚这块是干什么的、怎么运行、主要文件入口在哪。最关键的是在项目根目录放一份部署说明保证一个没见过这个项目的人按着文档能在半小时内把系统跑起来。我见过太多毕设项目代码写得还可以但没有部署文档评阅老师根本没法复现最后的评价自然打折扣。5. 部署实测中的坑与优化复盘5.1 长连接的噩梦Django的进程模型handle不了持续采集我第一次把采集逻辑直接写在Django的App里用起了uWSGI的定时器结果发现uWSGI的worker会周期性重启每30秒就会中断一次采集任务日志里全是connection reset。后来我明白了Django的Web进程是按处理请求、返回响应、结束进程的模型设计的任何需要长期占用进程的任务——长连接、轮询采集、消息订阅——都不应该在Web进程里做。最终解决方案是把采集服务独立成一个单独的Python进程用daemon方式常驻运行它自己管理TCP连接和MQTT会话数据库连接独立配置完全不经过Django的请求生命周期。这个改动之后系统运行稳定多了Web服务随便重启采集端不受影响。5.2 数据库不要让慢查询毁掉大屏体验系统上线后我测了一下大屏接口的响应时间发现设备列表和数据曲线的接口都在300到500毫秒这在演示时已经能感觉到明显的卡顿。排查过程是这样的先用Django的connection.queries开了SQL日志发现设备列表接口N1查询问题严重查询每台设备都要额外执行一次点位表的子查询。解决方案是调整ORM查询方式用select_related把设备的外键关联一次性查出来或者干脆在设备表里冗余一个关联点位数量字段列表页直接读这个字段。然后是曲线接口每次都在几十万行的流水表里做范围查询第一次查很慢。加了组合索引后同样查询从400毫秒降到了30毫秒以内这个差距是肉眼可见的。另一个经验是给高频查询加缓存。设备在线状态和报警未读数这两个数据其实是同一个值可以用Django的cache框架配上RedisTTL设成2秒展示层读缓存采集层写库后主动清除缓存。大屏的响应时间稳定在了50毫秒以内演示效果提升明显。5.3 权限体系不要让每个用户都能看到所有设备的隐藏数据系统的用户角色我划分成了四类系统管理员、维护中心工程师、车间操作工、车间负责人。Django自带的auth框架和permission机制完全够用不需要引入额外的权限库。管理员管设备和用户工程师能看所有设备状态、处理工单操作工只能看到自己所在车间的设备可以上报问题但不能改工单内容负责人除了工程师的权限之外还能看统计报表和维护分析数据。权限控制不仅在视图层做在模板层也要配合导航菜单根据用户角色动态显示不该看的按钮不要渲染出来。我吃过一个亏是初期权限没控制好测试时所有账号都能进后台Admin直接在Admin里把报警记录删了导致演示数据缺失。后来我把Admin的访问权限收敛给了管理员业务用户一律走业务页面这个教训值得写进开发计划里。5.4 几个容易被忽略的小坑部署方面有几个坑虽然小但踩一次就够难受的时区问题采集时间如果混用本地时间和UTC时间曲线会整体偏移8小时。统一设定TIME_ZONE Asia/Shanghai、USE_TZ False并且所有采集服务写入的时间都用到当前系统时间保持全链路一致。静态文件DEBUG关闭后静态文件404是Django老生常谈的问题务必配好STATIC_ROOT并执行collectstatic线上用WhiteNoise或者Nginx直接serve。Excel导出中文乱码用openpyxl导出时文件流要指定UTF-8 BOM编码不然Excel打开中文全是乱码这个坑我已经遇到不止三次。报警通知偶尔发重复分布式环境下同一个报警可能被多个worker各自判断一次。解决办法除了数据库唯一约束还要在通知逻辑里加一层分布式锁我用Redis的setnx实现的成本很低。关于这套系统后续还能怎么扩展我自己有几个明确的方向。一是接入OPC UA协议Django配合asyncua库可以让系统覆盖更多西门子和罗克韦尔等高端PLC设备。二是引入机器学习做异常检测传统的阈值报警只能抓量变异常检测模型可以抓质变——比如轴承的振动频谱特征在故障前几周就会逐步偏移这种趋势靠人工阈值是发现不了的。三是把移动端升级成微信小程序车间主任在办公室就能通过手机看到全车间设备状态比盯着电脑大屏方便得多。从最早在车间蹲点观察人工巡检流程到最后系统稳定跑起来、论文送审答辩这一路踩过的坑和积累的经验都写在上面了。如果你也在做Django相关的工业物联网项目我的建议是先把数据采集链路打通让数据真正流动起来后面所有的监测、预警、工单逻辑都只是水到渠成的事情。设备数据本身才是这个系统最值钱的东西。