ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

开源MES QCADOO实战:从技术栈拆解到生产工单部署避坑全记录

开源MES QCADOO实战:从技术栈拆解到生产工单部署避坑全记录 简介基于QCADOO的开源MES生产制造管理系统聚焦离散制造场景覆盖机加工、食品包装、制鞋、服装等行业面向制造业IT团队与工业软件开发者提供从生产计划、工序执行到质量追溯的一体化参考方案。压缩包共2000个文件整体大小37.7MB核心以1090个Java源码与595个XML配置为主辅以118个JS交互脚本、88个properties配置、54个JSP页面以及2个SQL初始化文件可清晰看出后端逻辑、页面模板与资源文件的组织脉络。目前已有150人学习下载。这套资源不仅包含可直接运行的业务模块还体现了QCADOO插件化扩展机制与模块解耦思路适合开发者在真实项目前先快速了解MES核心流程再结合自身工艺进行二次开发或重构是学习工业软件架构与开源MES落地的实用素材。1. 为什么车间里小厂也敢用开源 MESQCADOO 到底是什么搜索“基于 QCADOO 的开源 MES”这个词的人多半已经对商业系统的报价和交付周期失去耐心了。它是一套用 Java 生态写成的生产制造管理系统 Manufacturing Execution System从主数据维护、工艺路线、生产工单、排程、报工到批次追溯制造执行的骨干流程基本都能覆盖而且按 Apache 2.0 协议开放源码拿去做商业落地不需要先交一笔授权费。对中小企业来说这是少数能在预算内同时拿到“完整业务模型”和“可改源码”的开源 MES对做技术选型的开发团队来说它还自带一套可扩展的模块化框架适合作为从零搭 MES 的最短路径。前提是你要接受它的文档不算厚、社区不算大以及老派 Vaadin 界面带来的那股“复古味”。这篇笔记按我真实落地顺序来讲先拆技术栈再讲怎么跑通最后把主数据到工单的完整链路和 5 个必踩的坑说清楚。2. 技术栈与架构拆解从 Vaadin 单体和模块化设计看 QCADOO 为什么适合做 MES2.1 为什么是 Java Spring Boot Vaadin这套架构对 MES 到底意味着什么QCADOO 的底层是 Java Spring Boot持久层用 JPA/Hibernate前台界面由 Vaadin 负责渲染默认数据库在开发环境用 H2、生产环境换 PostgreSQL。这套技术栈和现在互联网圈流行的“Vue 前端 Spring Boot 后端 MyBatis”思路不是一回事但放在 MES 这个场景里反而合理。MES 和电商后台不一样界面大量是表单、表格、向导页、主从联动编辑交互复杂度高但并发量很低。Vaadin 的做法是让服务端直接维护 UI 状态浏览器端只是渲染通道车间工控机上的旧浏览器和低配终端基本不需要纠结前端框架版本。对我这种要兼顾后端逻辑和页面改动的工程师来说少维护一套 Node 前端工程等于少掉一半头发。尤其是工厂现场还要应对内网离线部署、老旧 Windows 工控机这时候前后端分离的现代化栈反而是包袱。拿国内热门的“基于若依框架的 MES”来对比会更直观。若依把菜单管理、用户权限、代码生成、操作日志做得很完善很多团队拿它当底座去填制造业务。但问题在于若依本身不提供制造域模型物料、工序、工艺路线、报工逻辑全都要自己设计表结构最后往往做成一个“挂着生产名字的进销存”。QCADOO 正好相反它的权限菜单和界面风格都比较朴素可物料怎么分类、订单怎么绑定工艺路线、完工怎么回写库存这套业务骨架是现成的。这决定了两种选型路径想快速做出一套内部管理系统就选若依系想把制造执行的模型先立住再慢慢强化QCADOO 的底子更厚。Spring Boot 在这套方案里的价值也值得多说一句。MES 项目生命周期普遍在五年以上中间要接 ERP、要接设备、要换数据库Spring Boot 的起步依赖管理、自带嵌入式 Web 容器、对 JVM 系监控探针的友好支持让这些变动大部分停留在配置层。我见过不少用非 Java 语言做 MES 做到后期被报表和集成接口拖垮的团队Java 生态在这些边角问题上的积累就是明摆着的筹码。2.2 核心数据模型物料、工艺路线、工单之间到底怎么串联QCADOO 的制造模型可以拆成四层主数据层、工艺层、计划层、执行层。理解这四层后面所有操作都不会走偏。业务对象QCADOO 中的常见叫法作用物料/产品Component原材料、半成品、成品的统一主数据工艺路线Technology定义产品按什么顺序经过哪些工序工序Operation工艺路线的基本节点可绑定工时和辅助材料生产线ProductionLine物理产线或工作中心生产工单Order包含数量、优先级、计划时间的生产指令作业计划Workplan按工单和工艺路线自动展开的工序级执行计划工人Worker操作工与班组信息一条成品从计划到入库在系统里的流转大致是先在主数据里建物料再为这个物料维护工艺路线工艺路线下挂若干工序每道工序可以指定需要的子物料、标准工时和设备。计划员创建生产工单时选择物料、数量、生产线和优先级系统按物料对应的工艺路线自动展开作业计划。工单下达后车间按作业计划的顺序逐道工序报工每道工序的合格数量回写库存最终成品入库同时保留可回溯的批次履历。这套模型最值钱的地方是“工艺路线独立存在”。很多自研 MES 把工序直接写在工单里每次排产都要重新录入QCADOO 则让产品与工艺分离同一个产品可以维护多套工艺版本工单创建时再选定这就给工艺改进留了操作空间。字段命名在不同版本里可能有差异但制造域的实体关系基本稳定吃透这一张表再去看源码里的 JPA 实体就很轻松。2.3 模块化与多组织开源 MES 搞二次开发的地基QCADOO 没有把自己做成一个铁板一块的单体应用核心是一个类平台的框架功能模块以“插件”方式挂上去。你可以只启用基础数据和生产执行模块也可以把成本核算、质量管理的模块一起跑起来自己开发的模块只要遵循已有的挂载方式就能被系统识别、进菜单、拿权限。扩展到多车间场景的时候这套模块化设计就更划算了。一个集团实例可以承载多个组织或工厂的数据不同工厂维护自己的物料、产线和工单互不串库。对开源项目来说这种边界清晰的分层也让社区贡献变得容易不熟悉制造业务的人可以改界面组件懂业务的人专心写领域服务彼此不踩脚。我一般会提醒团队接 QCADOO 之前先分清两层改动第一层是配置层面的东西比如写个显示字段、加一个查询条件完全可以在标准功能里完成第二层是真要写 Java 代码的业务扩展比如自定义排程算法、对接设备采集数据。把改动按这两层归类才能在后续升级上游版本的时候保住自己的代码。3. 本地与容器化跑通 QCADOO从源码构建到 PostgreSQL 的最小可复现路径3.1 本地最小复现源码构建加 H2 开发模式先把仓库克隆到本地。这里不写死某个仓库地址因为 QCADOO 的代码托管地址随社区维护情况会变动GitHub 上搜 qcadoo 或 qcadoo-mes 就能找到企业内网也可以自己镜像一份。克隆之后第一件事不是急着读源码而是先构建并启动起来。# 克隆源码 git clone qcadOO-mes 仓库地址 qcadoo-mes cd qcadoo-mes # 构建打包跳过测试以节省第一次构建的时间 mvn clean install -DskipTests第一次 Maven 构建会很慢大部分时间花在下载依赖上这很正常。注意-DskipTests只是跳过测试执行测试代码仍然会编译如果连测试代码都不想编译要用-Dmaven.test.skiptrue。对内部快速验证来说前者更稳妥至少能暴露编译问题。构建完成后进入启动环节。不同分支的启动方式会有差异常见做法是找到 Maven 模块里的启动类用 IDE 直接运行 main 方法或者把构建出的 jar 包用 java -jar 启动。开发阶段我会推荐用 H2 内存库省掉装数据库这一步java -jar target/qcadoo-mes-app.jar \ --spring.profiles.activedev \ --spring.datasource.urljdbc:h2:mem:mes;DB_CLOSE_DELAY-1;MODEPostgreSQL如果构建产物不是可执行 fat jar而是 war 包就扔进本机 Tomcat 的 webapps 目录再启动。启动成功后浏览器访问 8080 端口进入登录界面。首次登录需要的账号密码一般在项目文档的快速开始一节写明或者由启动时的初始化数据生成别在源码里翻“admin/admin123”这类默认口令很容易翻到废弃配置。这条路的优点是零外部依赖适合先验证业务功能缺点是 H2 内存库重启即清空所有建好的物料和工艺路线都会丢。所以它只适合功能演示不适合攒数据。3.2 Docker Compose 部署生产形态PostgreSQL 加 Nginx 反代真正要往车间走必须换 PostgreSQL。常见做法是先用 Docker Compose 把应用和数据库一起编排起来下面这份是我自己常用的简化模板镜像名和 jar 包名换成你实际构建出来的即可services: db: image: postgres:14 environment: POSTGRES_DB: mes POSTGRES_USER: qcadoo POSTGRES_PASSWORD: qcadoo volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U qcadoo] interval: 5s timeout: 3s retries: 10 app: build: context: . dockerfile: Dockerfile depends_on: db: condition: service_healthy environment: SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/mes SPRING_DATASOURCE_USERNAME: qcadoo SPRING_DATASOURCE_PASSWORD: qcadoo SPRING_PROFILES_ACTIVE: production ports: - 8080:8080 web: image: nginx:1.25 volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf ports: - 80:80 volumes: pgdata:几个关键点拆开讲。depends_on里的condition: service_healthy是让应用容器等数据库就绪再启动避免应用先启动连不上库而直接失败退出的反复重启生产数据库密码不要用弱口令也不要写在 Compose 文件里明文提交用环境变量文件的方式管理。应用镜像建议你在本地先构建出 jar 包再打包Dockerfile 写起来很简单FROM eclipse-temurin:11-jre WORKDIR /opt/mes COPY target/qcadoo-mes-app.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]Nginx 配置不需要复杂重点是把 8080 端口代理到 80同时带上 WebSocket 和超时参数。QCADOO 的 Vaadin 界面在操作频繁时有长连接交互代理超时设短了会出现“页面突然白屏、操作没反应”的假死现象。server { listen 80; server_name mes.example.internal; location / { proxy_pass http://app:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 120s; proxy_send_timeout 120s; } }如果车间网络强制要求 HTTPS就在 Nginx 上挂证书并把 80 端口重定向到 443应用本身不用改任何配置。3.3 数据库连接参数四个必调项把 H2 换成 PostgreSQL 不只是改一个 JDBC URL 那么简单我遇到最多的问题集中在四个参数上。参数开发环境建议生产环境建议设置不当的后果字符集utf8utf8中文乱码、报表导出崩溃连接池上限默认30 到 50并发报工时连接耗尽时区跟随系统明确指定 Asia/Shanghai生产日报统计前后对不上日志级别DEBUGINFO磁盘被日志灌满JDBC URL 里建议显式带上字符集参数jdbc:postgresql://db:5432/mes?characterEncodingutf8。连接池参数按 Spring Boot 的通用配置调不需要改代码。时区问题最容易翻车如果数据库服务器和应用服务器在不同时区排程界面显示的计划时间和实际执行时间会差几个钟头尤其做跨工厂部署的时候一上来就先统一时区能少吵很多架。4. 把 MES 真正用起来主数据、工艺路线、生产工单三步落地4.1 先把主数据建干净物料与计量单位的“地基工程”很多团队部署完第一周就开始急着建工单结果数据越报越乱最后回过来补主数据。正确顺序是先花两到三天把物料主数据整理完。在 QCADOO 的主数据菜单里新建物料时至少要把物料编号、名称、物料类型、计量单位四个字段填准确。物料编号建议按“原材料-半成品-成品”设计可识别的编码前缀比如RM-、SFG-、FG-。计量单位是重灾区。同样一批钢材采购按“吨”下单车间按“根”领料系统里如果只维护了一个单位库存数量就会变成一笔糊涂账。QCADOO 这类以单品主数据为核心的 MES单位体系通常在物料类型层级统一约束。我的习惯是强制所有物料使用最小计量单位入库吨换算成千克箱换算成件厂内统计口径一致后再谈换算关系。物料类型也要规划好层次不要上来就建几百个彼此孤立的明细类型。常见的做法是先设原材料、半成品、成品、辅料、工装这几大类后续再根据需要细分。这时候图省事后面所有报表和权限配置都会一起跟着难受。4.2 工艺路线与工序绑定注意工序顺序和辅助材料物料建好后进入工艺路线维护。先为成品创建一个工艺路线再按实际生产顺序挂工序比如“下料 - 焊接 - 打磨 - 检验”。每一道工序至少要定义清楚三件事工序编号、顺序号、标准工时。顺序号一定要留出富裕量这是血泪经验。如果第一版工序顺序是 10、20、30后续要在焊接和打磨之间插一道“去毛刺”按 35 插入即可如果你一开始就用 1、2、3 排号插入任何工序都意味着把所有后续工序全部重排一遍。标准工时先不用精确按车间老师傅的经验值填系统上线后再用实际报工数据校准远比一上来就搞秒表测时靠谱。工艺路线里还有一类容易被忽略的数据工序辅助材料。焊接工序要绑定焊丝检验工序要绑定标签纸这些消耗品不体现在成品 BOM 里但车间领料时又要按工序查询。QCADOO 的工序对象支持绑定子物料我建议把所有辅助材料都挂上去虽然录入会多花点时间但后续做物料齐套和成本核算时会省非常多事。维护完工艺路线后做一个验证动作随便建一张测试工单确认作业计划能按工艺路线自动展开工序顺序、物料绑定没有遗漏。这个动作只要一分钟能提前暴露一半以上的配置错误。4.3 生产工单的生成与下达排产、下达、报工的顺序主数据和工艺路线就位后业务才算真正流转起来。计划员在工单模块创建生产工单时需要填写物料、数量、生产线、计划开始时间和优先级。工单保存后系统依据物料对应的工艺路线自动生成作业计划。我对“工单下达”有明确的操作建议先检查物料库存和工序能力再点下达。如果原材料不足工单下达后车间要么停工待料要么被迫超领物料报工数据会立刻失真如果某道工序被多个工单同时占用先调整优先级比事后插单更稳妥。下达后的工单状态会从“已创建”变为“已释放”车间端才可以在执行界面看到任务并开始报工。车间执行时按工序报工每完成一道工序系统更新该工序的合格数量、不良数量和剩余量同时联动库存。全部工序完成后成品数量进入库存工单关闭。这个链路在界面上只是一系列点击但背后把工艺路线、工序、物料、仓库、批次全部串起来了。第一张工单不要急着追产量先走通全流程确认每一步状态变更都符合预期再逐步放开到多个产线并行。5. QCADOO 避坑排查从若依系迁移、Maven 构建到中文乱码的 5 个血泪经验5.1 从若依系 MES 迁移过来权限模型落差最大现象团队之前做的“基于若依框架的 MES”里用户权限可以精确到每个菜单按钮迁移到 QCADOO 后却发现系统菜单和权限入口完全对不上项目组觉得“权限不好使”。原因若依是中后台通用框架权限设计服务于“菜单-按钮-接口”的管理后台逻辑QCADOO 的权限围绕“模块用户组”来组织更贴近制造车间的角色划分而不是办公后台的页面可见性。解决放弃复刻原来的按钮级权限矩阵先按制造角色重建权限组。至少分出系统管理员、计划员、车间班组长、质量检验员、设备维护员这几类每个角色分配相应模块再让车间反馈实际使用中是否有越权或漏权。权限的作用是划分责任不是做页面控制越细的管理需求反而越难维护。5.2 Maven 构建持续卡死或下载失败现象mvn clean install时长时间没有进度随后报连接超时或依赖解析失败构建反复中断。原因Maven 默认从中央仓库拉依赖网络不稳定或内网访问受限时下载过程没有有效重试策略一个失败就中断整个构建。解决国内团队普遍的做法是配置阿里云 Maven 镜像。改设置文件或项目settings.xml加上一个 mirror把中央仓库替换掉mirror idaliyun-central/id mirrorOfcentral/mirrorOf nameAliyun Maven Central Mirror/name urlhttps://maven.aliyun.com/repository/central/url /mirror配置完成后执行mvn clean install -U强制刷新快照依赖。如果公司内网还有自己的依赖管理服务把 mirror 地址换成内网仓库即可。这里不建议只配一次镜像就万事大吉团队新成员入职后第一件事就是把本地 Maven 配置统一到同一套镜像和本地仓库路径上否则“在我机器上能编译”会变成常态化翻车现场。5.3 中文乱码界面正常但导出文件全乱现象QCADOO 页面中文显示正常导出的 Excel、PDF 或 CSV 文件打开后中文变成问号或乱码日志里的中文信息同样不可读。原因界面显示走的是 Vaadin 服务端渲染和浏览器解码导出文件用的是 JVM 字符集两套链路互不相同。JVM 默认字符集不是 UTF-8 时导出逻辑就会把中文按错误的编码写入文件。解决启动应用前设置 JVM 编码并让系统 locale 居中export JAVA_TOOL_OPTIONS-Dfile.encodingUTF-8 export LANGzh_CN.UTF-8 java -jar qcadoo-mes-app.jar同时检查 PostgreSQL 连接的 JDBC URL 是否带了characterEncodingutf8数据库端字符集也建议用 UTF-8。如果改完通过新增数据验证没问题但历史乱码数据还在那只能导出清洗后回导没有后悔药。5.4 工艺路线改了但新工单不生效现象工艺路线里调整了某道工序的标准工时新建工单后展开的作业计划还是旧数据车间按老工艺执行。原因工单创建时会快照当时的工艺路线版本后续工艺修改不会反向影响已创建或已下达的工单。这是 MES 的设计本意不是功能缺陷目的是保证执行版本的稳定和可追溯但不能不知道。解决如果工单未下达取消释放后重新展开作业计划即可如果已经下达并开始报工只能关闭旧工单按新工艺路线重新创建工单。上线初期我会提前跟计划员约定工艺变更需要提前一天通知让所有在途工单在变更前清掉或重下宁可多退一张单也别让车间同一产品按两套工艺跑。5.5 监控探针直接挂生产实例性能断崖式下跌现象看到热门话题问“SkyWalking 能部署到 MES 制造系统上面吗”有人直接把探针打进生产实例参数里重启后页面响应明显变慢甚至出现接口超时。原因SkyWalking 这类 APM 探针会拦截方法调用并上报链路数据MES 这种长生命周期业务系统接口调用链路短且密集默认采样参数偏保守是没问题的但探针版本和中间件版本不配套时会引入别的问题。解决答案是能部署但要用正确姿势。探针参数必须加在 -jar 之前并且独立指定应用名java -javaagent:/opt/skywalking-agent/skywalking-agent.jar \ -Dskywalking.agent.service_nameqcadoo-mes \ -jar qcadoo-mes-app.jar而且先在半数产线或预发环境跑满半天确认链路数据正常、GC 停顿没有明显增加再全量。MES 的价值核心是稳定执行制造流程监控永远为业务让路别为了看一张链路图把生产系统搭进去。6. 进阶玩法把 QCADOO 变成车间数据中枢的接口与追溯姿势6.1 REST 接口扩展给边缘设备一条安全的路标准版 QCADOO 的界面是给人用的设备终端要报工就得走接口。常见做法是在应用工程里新增一个 RestController把内部服务包一层防腐层暴露出来。比如设备完成一道工序后上报完工数量接口大致长这样RestController RequestMapping(/api/v1/production) public class ProductionReportController { PostMapping(/orders/{orderId}/operations/{operationId}/complete) public ResponseEntityCompletionResult completeOperation( PathVariable Long orderId, PathVariable Long operationId, RequestBody CompletionRequest request) { // 1. 校验工单状态是否允许报工 // 2. 校验上报数量不超过剩余数量 // 3. 调用内部服务完成工序报工 // 4. 返回最新总完工数和剩余数 return ResponseEntity.ok(result); } }这一步的价值是隔离。QCADOO 内部实体和领域服务不直接暴露给工控机设备侧只认 REST 接口和简单 JSON后续底层模型调整时不会炸掉前方所有采集终端。身份鉴权至少用固定 token有条件就上 OAuth2 客户端模式别图方便把接口设成匿名可访问。6.2 设备数据采集STM32Cube 采集盒配 MQTT 网关车间里很多老设备没有开放数据接口常见的低成本方案是做一个嵌入式开源项目的采集盒用 STM32Cube 生态的单片机读传感器或 PLC 点位通过有线网络把数据推到边缘网关。边缘网关收到 MQTT 消息后把数据转换成 REST 请求写入 QCADOO。# 边缘采集节点上报示例 import paho.mqtt.publish as publish payload {orderId: 10086, operationId: 20, qualifiedQty: 12} publish.single(mes/line1/machine5, payload, hostname10.10.1.8)字段要和 REST 接口的请求体对齐这些细节往往在联调时才暴露设备侧单位是“件”还是“箱”QCADOO 侧计量单位是“件”中间不做换算的话一天下来数字就能差出几十倍。解决办法是在边缘网关侧做单位归一化设备层数据尽可能原样上报业务换算集中在边缘节点完成。6.3 追溯验证用一张工单反向跑通全链路追溯是 MES 最能直观看到价值的环节。找一张已经完工的工单在界面里查看它的作业计划、工序报工记录、物料消耗批次再反向从成品批号查出用了哪批原材料、哪台设备、哪个操作工。没有界面路径也没关系用数据库验证更直接SELECT t.number AS technology_number, o.number AS operation_number, wl.planned_quantity, wl.reported_quantity FROM workplan wl JOIN technology t ON t.id wl.technology_id JOIN operation o ON o.id wl.operation_id WHERE wl.order_id :orderId ORDER BY wl.sequence;表名和字段名按实际部署的数据库结构调整。我每次上线必做这个追溯演练不是看界面好不好看而是确认真的出质量事故时能在十分钟内回答“这批货是谁在什么时候用什么料做出来的”。如果这一步跑不通前面所有上线工作都不算完成。最后说一个自己的习惯我在车间上线 QCADOO 这类开源 MES 时最深的教训不是技术细节而是低估了主数据准备的工作量。物料编码没统一、工艺路线没验证就急着开工单上线第一周全在补数据。后来我要求所有项目先花 70% 精力整理主数据和工艺业务功能反而上线顺畅。技术方案可以读文档、可以踩坑爬坑但车间的数据基础没有捷径。希望这篇笔记能帮你省掉几段弯路把开源 MES 真正落到自己的产线上。本文还有配套的精品资源点击获取
返回列表