1. 项目背景与整体设计思路
1.1 为什么工厂车间需要可视化电子看板
我在汽车零部件行业做过好几个车间的数字化改造项目,上海这边的制造工厂有个很普遍的特点:产线密度高、设备品牌杂、班组交接频繁。车间主任最头疼的事情就是——数据散落在各个角落。A线的产量在PLC里,B线的良率在MES里,C线的设备状态在SCADA里,每次开早会要三个人分别报数,报完还要对一遍,对完发现口径不一致。
可视化电子看板要解决的核心问题就一个:把分散的数据源汇聚到统一的大屏上,让车间里所有人看到同一份实时数据。听起来简单,但落地的时候坑非常多。多块大屏同步显示就是其中最典型的难点——你不可能给每块屏单独配一台工控机跑一套程序,成本扛不住,维护也扛不住。
这个项目的目标很明确:在上海某汽车零部件工厂的冲压和装配两个车间,部署6块55寸工业大屏,分别挂在车间入口、两条产线中段、质检区、设备维修间和车间办公室。所有屏幕显示同一套数据,包括实时产量、节拍、良率、设备OEE、异常报警。数据来源涉及MES系统、PLC采集网关和一个独立的Andon报警系统。
1.2 整体架构选型与背后的考量
架构设计上我走过弯路,第一版方案是每块屏配一台迷你主机,各自跑浏览器全屏打开看板页面。这个方案的问题在调试阶段就暴露了:6台机器要分别配置网络、分别设置开机自启、分别处理浏览器缓存问题。更致命的是,当看板页面需要更新时,你要逐台远程操作,万一某台机器离线了,那块屏就挂着旧版本跑。
第二版方案改成了中心渲染+多屏同步的架构。具体来说:
- 一台性能足够的工控机作为渲染主机,负责运行看板前端程序
- 通过HDMI分配器或者视频矩阵把画面分发到多块大屏
- 数据层由后端服务统一从MES、PLC网关拉取,通过WebSocket推送给前端
这个架构的好处是:只需要维护一套渲染逻辑,屏幕数量增加时只需要加分配器端口。缺点是HDMI线缆传输距离有限,超过15米就需要用光纤HDMI或者走网络方案。
最终我们采用的是混合方案:车间办公室和入口的两块屏用HDMI分配器直连,距离渲染主机不超过10米;产线中段和质检区的四块屏走网络推流方案,每块屏配一个支持RTSP或者HTTP流的网络播放盒,渲染主机把画面编码后推给播放盒。这样既控制了成本,又解决了远距离传输问题。
注意:网络推流方案的延迟比HDMI直连高,实测在200ms到500ms之间。对于产量看板这种秒级更新的场景完全够用,但如果是设备急停报警这种要求实时性的场景,建议还是走HDMI直连或者单独的Andon灯系统。
1.3 数据链路的关键设计决策
数据链路这块,我重点说一下为什么选择NTP时间同步作为整个系统的基础设施。多块大屏显示同一份数据,如果各屏幕的时间不一致,会出现一个很尴尬的情况:A屏显示"10:30:15 产量120",B屏显示"10:30:12 产量118"。操作工看到会质疑数据准确性,班组长会怀疑系统有bug。
NTP同步在这个项目里做了两层:
第一层是渲染主机和所有数据源服务器(MES应用服务器、PLC网关、Andon服务器)都指向同一个NTP源。上海工厂这边我们用的是华为云NTP服务器地址,延迟低、稳定性好。具体配置后面会详细说。
第二层是网络播放盒和渲染主机之间的时间同步。播放盒本身不产生数据,但它渲染的画面里如果有时间戳组件,就需要和渲染主机保持一致。我们通过播放盒的NTP客户端配置,让它也指向同一个NTP源。
这个设计决策看起来简单,但在实际调试中,NTP同步没做好导致的"灵异问题"占了总调试时间的30%以上。后面我会专门用一节来讲NTP调试的坑。
2. 核心硬件选型与现场部署实操
2.1 大屏与播放设备的选型要点
工业大屏和商用大屏是两回事。车间环境有粉尘、有震动、有电磁干扰,商用大屏用不了几个月就会出现色差、坏点甚至黑屏。我们选的是工业级液晶屏,亮度至少500cd/m²,对比度3000:1以上,支持7x24小时连续运行。尺寸上55寸是车间看板的黄金尺寸——太小了远处看不清,太大了安装支架成本飙升。
播放设备这块,HDMI直连的屏幕不需要额外设备,但网络推流的屏幕需要网络播放盒。市面上常见的方案有三种:
| 方案类型 | 典型延迟 | 成本 | 稳定性 | 适用场景 |
|---|---|---|---|---|
| 安卓播放盒 | 300-800ms | 低 | 一般 | 非实时看板 |
| 工控机+解码软件 | 200-500ms | 中 | 高 | 工业看板 |
| 专用解码器 | 100-300ms | 高 | 很高 | 安防监控 |
我们最终选了工控机+解码软件的方案。原因很简单:安卓播放盒在长时间运行后会出现内存泄漏,画面卡顿甚至黑屏,需要定期重启。工控机虽然贵一点,但跑Linux系统,稳定性有保障,而且可以通过SSH远程批量管理。
2.2 网络规划与布线实操
车间网络规划有个原则:看板网络和设备控制网络物理隔离。这不是小题大做,我见过因为看板网络广播风暴导致PLC通信中断的案例。具体做法是:
- 看板系统单独走一个VLAN,用独立的交换机
- 如果需要从MES取数据,通过防火墙策略只开放必要的端口
- 网络播放盒的IP地址用DHCP保留,不要用静态IP手动配置,后期维护会疯掉
布线方面,网线用超六类屏蔽线,车间里变频器、伺服驱动器一大堆,非屏蔽线跑千兆会丢包。走线槽要和动力线保持至少30cm距离,交叉时垂直交叉。这些细节看起来琐碎,但后期排查网络问题时,你会发现当初多花的那点线材钱太值了。
HDMI线缆超过10米一定要用光纤HDMI,普通铜缆HDMI在15米以上就会出现闪屏、无信号。光纤HDMI有方向性,Source端和Display端不能接反,接反了直接黑屏。我第一次用的时候没注意,排查了半天以为是大屏坏了。
2.3 渲染主机的配置与优化
渲染主机不需要顶级配置,但有几个关键点:
- CPU:至少4核,主频3.0GHz以上。看板前端如果有复杂动画,CPU占用会比较高
- 内存:16GB起步。浏览器全屏跑看板页面,加上WebSocket长连接,内存占用不小
- 显卡:支持多路输出,如果走HDMI分配器,显卡只需要一个输出口
- 硬盘:SSD,256GB足够。系统盘用SSD,日志和数据盘可以用机械盘
- 操作系统:Ubuntu Server 22.04 LTS。不要用Windows,自动更新和杀毒软件会打断看板运行
系统优化方面,我做了这几件事:
# 关闭不必要的系统服务 sudo systemctl disable bluetooth.service sudo systemctl disable cups.service # 设置看板程序开机自启 sudo systemctl enable kanban-renderer.service # 配置自动登录和自动启动浏览器全屏 # 在 ~/.config/autostart/ 下创建 desktop 文件浏览器用的是Chromium,启动参数很关键:
chromium-browser --kiosk --noerrdialogs --disable-infobars \ --disable-session-crashed-bubble --disable-translate \ --autoplay-policy=no-user-gesture-required \ --touch-events=disabled \ http://localhost:8080/kanban--kiosk参数让浏览器全屏且无地址栏,--noerrdialogs禁止错误弹窗,--disable-session-crashed-bubble防止崩溃恢复提示遮挡画面。这些参数少一个,现场就可能出问题。
3. 数据采集与MES对接的核心细节
3.1 MES数据接口的选型与调试
MES系统对接是看板项目里最耗时的环节,没有之一。上海这家工厂用的是某国产MES,接口方式有WebService和REST API两种。我们最终选了REST API,原因有三:
第一,WebService的SOAP协议解析起来太啰嗦,前端直接调用不方便,需要中间层转换。第二,REST API返回JSON格式,前端处理起来简单直接。第三,MES厂商的REST API文档更完整,调试工具也更好用。
调试MES接口的时候,网口调试助手和串口调试助手是我的左膀右臂。网口调试助手用来测试HTTP接口,串口调试助手用来调试PLC网关的串口通信。这里要提醒一句:网口调试助手选择支持HTTP和WebSocket的版本,普通的TCP/UDP调试工具不够用。
MES接口的典型调用流程是这样的:
import requests import json from datetime import datetime # MES接口配置 MES_BASE_URL = "http://mes-server:8080/api/v1" API_KEY = "your-api-key-here" def get_production_data(line_code): """获取指定产线的实时产量数据""" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } params = { "line": line_code, "shift": get_current_shift(), "date": datetime.now().strftime("%Y-%m-%d") } try: response = requests.get( f"{MES_BASE_URL}/production/realtime", headers=headers, params=params, timeout=5 ) response.raise_for_status() return response.json() except requests.exceptions.Timeout: # 超时处理:返回上一次缓存数据 return get_cached_data(line_code) except requests.exceptions.RequestException as e: log_error(f"MES接口调用失败: {e}") return None这段代码里有个关键设计:超时返回缓存数据。MES系统偶尔会重启或者响应慢,如果看板直接显示"数据获取失败",车间主任会打电话来问是不是系统坏了。返回上一次的缓存数据,同时在看板角落显示一个小提示"数据延迟",体验会好很多。
3.2 PLC数据采集与协议转换
PLC数据采集这块,工厂里常见的有西门子、三菱、欧姆龙几个品牌。上海这家工厂冲压线用的是西门子S7-1200,装配线用的是三菱FX系列。两种PLC的通信协议完全不同,需要分别处理。
西门子S7-1200支持S7协议,可以通过开源库python-snap7直接读取。三菱FX系列用的是MC协议,需要用到pymcprotocol这个库。如果PLC型号比较老,只有串口输出,那就需要串口转网口的网关设备。
串口调试助手在这里的作用是:先确认PLC的串口输出格式,再配置网关的转换规则。我遇到过一个问题:PLC输出的数据是十六进制字符串,但网关默认按ASCII解析,导致数据完全对不上。用串口调试助手抓包一看,发现是解析模式设错了,改成HEX模式就正常了。
PLC数据采集的频率不需要太高,1秒一次足够了。采集太频繁会给PLC增加负担,有些老型号PLC的通信模块处理不过来,会导致通信超时。
import snap7 from snap7.util import get_int, get_real def read_s7_plc(plc_ip, rack, slot): """读取西门子S7-1200 PLC数据""" client = snap7.client.Client() try: client.connect(plc_ip, rack, slot) # 读取DB块数据 # DB100.DBD0 存储产量,DB100.DBD4 存储节拍 data = client.db_read(100, 0, 8) production_count = get_int(data, 0) cycle_time = get_real(data, 4) return { "production": production_count, "cycle_time": cycle_time, "timestamp": datetime.now().isoformat() } except Exception as e: log_error(f"PLC读取失败: {e}") return None finally: client.disconnect()3.3 数据缓存与断线重连机制
工厂网络不是实验室网络,断线是常态。看板系统必须能扛住网络抖动。我的做法是在后端服务里加一层内存缓存+本地持久化:
- 每次从MES或PLC取到数据,先写入内存缓存
- 同时异步写入本地SQLite数据库,作为持久化备份
- 前端通过WebSocket订阅数据,后端每500ms推送一次最新缓存
- 如果数据源断线,后端继续推送缓存数据,同时标记数据状态为"延迟"
WebSocket的重连机制也很重要。前端要监听onclose事件,断开后自动重连,重连间隔采用指数退避策略:1秒、2秒、4秒、8秒,最大30秒。
let reconnectDelay = 1000; const MAX_DELAY = 30000; function connectWebSocket() { const ws = new WebSocket('ws://localhost:8080/ws/kanban'); ws.onopen = function() { console.log('WebSocket连接成功'); reconnectDelay = 1000; // 重置重连延迟 }; ws.onmessage = function(event) { const data = JSON.parse(event.data); updateKanbanDisplay(data); }; ws.onclose = function() { console.log(`连接断开,${reconnectDelay}ms后重连`); setTimeout(connectWebSocket, reconnectDelay); reconnectDelay = Math.min(reconnectDelay * 2, MAX_DELAY); }; ws.onerror = function(error) { console.error('WebSocket错误:', error); ws.close(); }; }这套机制上线后,即使MES系统半夜重启,看板也只是短暂显示"数据延迟",不会黑屏或者报错。
4. 多屏同步显示的核心技术与调试
4.1 NTP时间同步的配置与排错
NTP同步是整个多屏系统的基石。我前面说过,时间不一致会导致数据看起来"打架"。具体配置分三步:
第一步:确认渲染主机和所有数据源服务器都能访问NTP服务器。
# 测试NTP服务器连通性 ntpdate -q ntp.huaweicloud.com # 输出示例 # server 120.46.128.100, stratum 2, offset 0.003421, delay 0.02567 # offset 0.003421 表示本地时间比NTP服务器快3.4毫秒,这个精度完全够用第二步:配置chrony作为NTP客户端。Ubuntu 22.04默认用chrony而不是ntpd,配置文件在/etc/chrony/chrony.conf:
# 华为云NTP服务器 server ntp.huaweicloud.com iburst server ntp1.huaweicloud.com iburst server ntp2.huaweicloud.com iburst # 允许本地网络的其他设备同步 allow 192.168.1.0/24 # 即使无法访问外部NTP,也作为本地时间源提供服务 local stratum 10iburst参数让chrony在启动时快速发送多个NTP请求,加快同步速度。local stratum 10这行很关键——如果工厂外网断了,渲染主机还能作为本地NTP服务器给播放盒提供时间同步。
第三步:播放盒配置NTP客户端。播放盒的NTP配置通常在系统设置里,指向渲染主机的IP地址。配置完成后用chronyc sources命令检查同步状态。
NTP调试中最常见的坑:
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 时间偏差几小时 | 时区配置错误 | 检查/etc/timezone是否为Asia/Shanghai |
| 时间偏差几秒 | NTP未同步 | 检查防火墙是否放行UDP 123端口 |
| 时间忽快忽慢 | 硬件时钟问题 | 检查主板电池,更换CR2032电池 |
| 播放盒时间不同步 | NTP客户端未启用 | 在播放盒设置中手动启用NTP |
注意:NTP同步不是一劳永逸的。工厂电网波动会导致工控机硬件时钟漂移,建议每周检查一次
chronyc tracking的输出,确认时间偏差在可接受范围内。
4.2 画面同步的三种技术方案对比
多块大屏显示同一份数据,画面同步有三种技术路线:
方案一:HDMI分配器直连。渲染主机的HDMI输出接到分配器,分配器分出多路HDMI信号到各屏幕。优点是零延迟、零配置,插上就能用。缺点是传输距离受限,超过15米信号衰减严重,而且所有屏幕必须显示完全相同的内容,无法单独控制某块屏。
方案二:网络推流。渲染主机把画面编码成H.264或H.265流,通过网络推送给各播放盒。优点是传输距离不受限,可以跨楼层甚至跨厂区。缺点是延迟较高,而且编码解码会消耗CPU资源。
方案三:分布式渲染。每块屏配一台播放设备,各自从后端拉取数据并渲染。优点是灵活性最高,每块屏可以显示不同内容。缺点是维护成本高,而且如果各设备渲染逻辑有细微差异,会出现显示不一致。
我们最终采用的是方案一和方案二的混合:近距离的屏幕用HDMI分配器,远距离的屏幕用网络推流。这个决策的依据是:车间办公室和入口的屏幕距离渲染主机近,走HDMI最稳定;产线中段和质检区的屏幕距离远,走网络推流更实际。
网络推流的具体配置:
# 使用ffmpeg进行屏幕捕获和推流 ffmpeg -f x11grab -video_size 1920x1080 -framerate 30 -i :0.0 \ -c:v libx264 -preset ultrafast -tune zerolatency \ -b:v 4M -maxrate 4M -bufsize 8M \ -f rtsp rtsp://192.168.1.100:8554/kanban-preset ultrafast和-tune zerolatency这两个参数是降低延迟的关键。-b:v 4M设置码率为4Mbps,对于看板这种画面变化不大的场景,4Mbps足够清晰。
播放盒端用ffplay或者VLC接收RTSP流:
ffplay -fflags nobuffer -flags low_delay -framedrop \ rtsp://192.168.1.100:8554/kanban-fflags nobuffer禁用缓冲,-flags low_delay启用低延迟模式,-framedrop在解码跟不上时丢帧而不是卡顿。这三个参数组合下来,端到端延迟可以控制在300ms以内。
4.3 画面撕裂与不同步的排查实录
调试阶段遇到的最诡异问题是:两块相邻的大屏,一块显示"产量120",另一块显示"产量118",而且持续了好几秒。操作工看到后直接找班组长说系统有问题。
排查过程:
第一步,确认数据源是否一致。检查后端日志,发现同一时刻只推送了一次数据,所有WebSocket客户端收到的都是"120"。说明数据源没问题。
第二步,检查播放盒的接收时间。在两块屏对应的播放盒上分别抓包,发现一块播放盒在10:30:15收到数据,另一块在10:30:18才收到。差了3秒。
第三步,排查网络延迟。用ping测试渲染主机到两个播放盒的延迟,都在1ms以内。网络没问题。
第四步,检查播放盒的解码缓冲设置。发现其中一块播放盒的缓冲设置是默认的2000ms,另一块被之前调试时改成了500ms。缓冲设置不同导致画面更新时机不一致。
解决方法:统一所有播放盒的缓冲设置为500ms,并且在渲染主机端启用帧同步标记——每帧画面携带一个时间戳,播放盒根据时间戳对齐显示。
# 在ffmpeg推流时添加时间戳 ffmpeg -f x11grab -video_size 1920x1080 -framerate 30 -i :0.0 \ -c:v libx264 -preset ultrafast -tune zerolatency \ -b:v 4M -maxrate 4M -bufsize 8M \ -vf "drawtext=text='%{localtime}':fontsize=24:fontcolor=white:x=10:y=10" \ -f rtsp rtsp://192.168.1.100:8554/kanban这个drawtext滤镜在画面左上角叠加了本地时间,播放盒端如果发现时间戳不一致,可以自动调整缓冲。虽然增加了少量CPU开销,但解决了同步问题。
实操心得:多屏同步问题,80%出在缓冲设置不一致上。建议在项目初期就统一所有播放设备的缓冲参数,并且把这个参数写进设备配置文档,后期维护时不要随意改动。
5. 看板前端开发与性能优化
5.1 前端框架选型与页面布局
看板前端不需要复杂的框架,React或Vue都可以,关键是轻量和稳定。我选的是Vue 3 + Vite构建,原因是Vue的响应式系统对于数据频繁更新的场景更友好,而且打包体积比React小。
页面布局采用栅格系统,1920x1080的分辨率下划分成12列x8行。核心区域包括:
- 顶部状态栏:显示当前时间、班次、系统状态
- 左侧产量区:各产线实时产量、目标产量、完成率
- 中间设备状态区:设备OEE、运行状态、故障报警
- 右侧质量区:良率、缺陷类型分布、返修数量
- 底部滚动区:异常事件滚动播报
字体大小很关键。车间看板是给操作工在3-5米外看的,正文至少24px,关键数据至少48px,标题至少36px。颜色对比度要足够高,深色背景配浅色文字,避免使用相近色。
5.2 数据更新与渲染性能优化
看板页面需要长时间运行,内存泄漏和渲染性能是两大挑战。我做了这几件事:
第一,虚拟DOM的更新频率控制。数据每500ms推送一次,但并不是所有数据都需要每500ms更新。产量数据可以500ms更新,设备状态可以2秒更新,质量数据可以5秒更新。通过分组更新,减少不必要的DOM操作。
// 数据更新分组 const updateGroups = { production: { interval: 500, lastUpdate: 0 }, equipment: { interval: 2000, lastUpdate: 0 }, quality: { interval: 5000, lastUpdate: 0 } }; function handleWebSocketMessage(data) { const now = Date.now(); if (now - updateGroups.production.lastUpdate >= updateGroups.production.interval) { updateProductionDisplay(data.production); updateGroups.production.lastUpdate = now; } if (now - updateGroups.equipment.lastUpdate >= updateGroups.equipment.interval) { updateEquipmentDisplay(data.equipment); updateGroups.equipment.lastUpdate = now; } // 质量数据更新... }第二,使用Canvas绘制图表。ECharts这类图表库在数据频繁更新时会产生大量DOM操作,长时间运行后内存占用会持续上升。对于产量趋势图这种简单图表,直接用Canvas绘制,性能好很多。
第三,定期清理浏览器缓存。Chromium长时间运行后,缓存和GPU内存会累积。我配置了一个定时任务,每天凌晨3点自动重启浏览器:
# 在crontab中添加 0 3 * * * pkill chromium && sleep 5 && \ DISPLAY=:0 chromium-browser --kiosk http://localhost:8080/kanban &这个操作会导致看板短暂黑屏约10秒,但凌晨3点车间没有生产,影响可以忽略。
5.3 异常状态的可视化设计
看板不只是显示正常数据,更重要的是异常状态要醒目。我的设计原则是:
- 正常状态:绿色或白色文字,无背景色
- 警告状态:黄色文字,浅黄色背景
- 异常状态:红色文字,红色背景闪烁
- 离线状态:灰色文字,显示"数据延迟"标记
闪烁效果用CSS动画实现,频率控制在1Hz左右,太快了会让人眼疲劳:
@keyframes alarm-blink { 0%, 100% { background-color: #ff4444; } 50% { background-color: #ff8888; } } .alarm-active { animation: alarm-blink 1s infinite; color: white; font-weight: bold; }报警声音是可选项。车间噪音大,声音报警效果有限,而且多个报警同时触发时声音会重叠。我们最终没有启用声音报警,而是通过Andon灯系统做声音提示,看板只负责视觉显示。
6. 常见问题排查与调试技巧实录
6.1 网络与通信类问题速查
| 问题现象 | 排查步骤 | 常见原因 | 解决方法 |
|---|---|---|---|
| 看板显示"连接失败" | 1. ping渲染主机 2. 检查WebSocket端口 | 防火墙拦截 | 开放8080端口 |
| 数据更新延迟超过10秒 | 1. 检查MES接口响应时间 2. 查看后端日志 | MES接口超时 | 增加超时时间,启用缓存 |
| 播放盒黑屏 | 1. 检查RTSP流是否正常 2. 检查播放盒网络 | 推流中断 | 重启ffmpeg推流进程 |
| 画面卡顿 | 1. 检查CPU占用 2. 检查网络带宽 | 编码参数过高 | 降低码率或分辨率 |
| 时间显示不一致 | 1. 检查NTP同步状态 2. 检查时区设置 | NTP未同步 | 重新配置chrony |
6.2 显示与渲染类问题排查
问题一:大屏出现色差。两块相邻的屏幕,同一张图片显示出来的颜色不一样。这是工业大屏常见问题,原因是面板批次不同或者背光老化程度不同。解决方法:进入大屏的工厂菜单,调整RGB增益和偏移,尽量让两块屏的颜色接近。如果色差太大,只能更换同批次面板。
问题二:画面撕裂。快速移动的画面出现横向撕裂。这是垂直同步没开导致的。在渲染主机的显卡设置里启用"垂直同步",或者在ffmpeg推流时添加-vsync cfr参数强制恒定帧率。
问题三:文字模糊。看板上的文字边缘模糊,看不清。检查分辨率设置,确保渲染主机输出分辨率和屏幕物理分辨率一致。如果屏幕是4K但渲染主机输出1080P,文字会被拉伸导致模糊。
6.3 我踩过的三个大坑
第一个坑:NTP服务器地址写错。项目初期我随手填了一个NTP服务器地址,结果那个地址已经失效了。chrony一直同步不上,但系统没有报错,只是时间慢慢漂移。过了两周才发现看板时间和实际时间差了3分钟。教训:NTP配置完成后一定要用chronyc tracking验证同步状态,确认System time的偏差在1秒以内。
第二个坑:WebSocket心跳缺失。看板运行了几天后,发现有些屏幕的数据不更新了,但WebSocket连接显示还是"已连接"。原因是中间的网络设备(防火墙、负载均衡)会主动断开长时间没有数据传输的连接。解决方法:在前端和后端之间加心跳机制,每30秒发送一个ping消息。
// 前端心跳 setInterval(() => { if (ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ type: 'ping' })); } }, 30000); // 后端响应 ws.on('message', (message) => { const data = JSON.parse(message); if (data.type === 'ping') { ws.send(JSON.stringify({ type: 'pong' })); } });第三个坑:浏览器内存泄漏。Chromium连续运行一周后,内存占用从500MB涨到了4GB,页面开始卡顿。原因是看板页面里的某些JavaScript对象没有被正确回收。解决方法:除了每天定时重启浏览器外,还在页面里加了performance.memory监控,当内存超过1GB时自动刷新页面。
// 内存监控 setInterval(() => { if (performance.memory) { const usedMB = performance.memory.usedJSHeapSize / 1024 / 1024; if (usedMB > 1024) { console.warn(`内存占用过高: ${usedMB}MB,即将刷新页面`); location.reload(); } } }, 60000);6.4 调试工具与命令速查
调试这个项目用到的工具和命令,我整理了一份速查表:
# 检查NTP同步状态 chronyc tracking chronyc sources -v # 检查网络连通性 ping -c 4 192.168.1.100 traceroute 192.168.1.100 # 检查端口监听 netstat -tlnp | grep 8080 ss -tlnp | grep 8080 # 检查WebSocket连接 # 在浏览器控制台执行 ws.readyState // 1表示已连接 # 检查ffmpeg推流状态 ps aux | grep ffmpeg tail -f /var/log/ffmpeg.log # 检查系统资源 top -b -n 1 | head -20 free -h df -h网口调试助手在这个项目里主要用于测试MES接口和PLC网关的TCP通信。串口调试助手用于调试PLC的串口输出。这两个工具在Windows和Linux下都有替代品,Linux下可以用nc(netcat)和minicom。
# 用nc测试TCP端口 nc -zv 192.168.1.100 8080 # 用nc发送HTTP请求 echo -e "GET /api/v1/production HTTP/1.1\r\nHost: mes-server\r\n\r\n" | nc mes-server 8080 # 用minicom调试串口 minicom -D /dev/ttyUSB0 -b 96006.5 上线后的运维建议
看板系统上线后,运维比开发更重要。我的建议是:
第一,建立巡检制度。每天上班前检查所有屏幕是否正常显示,数据是否更新。发现异常及时处理,不要等到车间主任打电话来。
第二,保留回滚方案。每次更新看板程序前,先备份当前版本。如果新版本有问题,能在5分钟内回滚到旧版本。
第三,日志集中管理。渲染主机、播放盒、后端服务的日志统一收集到一个地方,方便排查问题。我们用的是一个简单的ELK栈,对于看板系统来说够用了。
第四,定期演练故障恢复。模拟MES宕机、网络中断、渲染主机故障等场景,验证备用方案是否有效。我见过太多项目,备用方案写在文档里,但从来没测试过,真出问题时发现备用方案根本跑不起来。
这个项目从进场调试到稳定运行,前后花了大约六周时间。其中硬件安装和布线一周,MES接口对接两周,多屏同步调试一周,前端开发和优化一周,试运行和问题修复一周。最大的体会是:多屏同步的难点不在技术,而在细节。NTP配置、缓冲设置、心跳机制,每一个细节没做好,都会导致现场出现问题。把这些细节做到位,系统就能稳定运行。