项目概览
PVD 上下料 MES 桥接与追溯系统是一套已经投入生产使用的 Windows 工业软件。它部署在设备侧,在 PLC 与外部 MES 之间承担业务桥接:持续读取设备状态和待执行命令,把上料、下料、查询与解绑动作编排成可验证的 MES 调用链,并将处理结果写回 PLC,同时在本地保留可追溯的会话、关系、命令与接口事务。
这类系统的难点并不在于完成一次 Modbus 读取或 HTTP 请求,而在于两个状态系统之间没有天然事务。PLC 关心指令是否被接收和执行,MES 关心物料、载具和工序关系是否符合业务约束;网络超时、设备重发、应用重启或多步骤调用部分成功,都可能让两侧状态产生分歧。因此,系统需要显式保存流程上下文、活动关系、TraceId、响应结果和接口事务,使异常能够被定位和人工恢复。
本文以已经确认的生产版本为基线:主应用标签和 Windows x64 安装包版本均为 1.0.6,对应源码提交 46a7649。当前工作区存在后续开发内容,本文不会把这些未提交修改描述为生产能力。
匿名化与公开边界
本文会说明 PVD 上下料、料盘、目标工装、排产、扣料、绑定、过站和解绑等通用业务概念,但不会公开:
- 客户、公司、产品、产线和设备厂商名称;
- 设备型号、工位编码、现场拓扑和安装位置;
- 网络地址、端口、寄存器地址、命令值和响应编码;
- MES 接口地址、字段名称、请求或响应样本;
- 产品 SN、Token、账号、密码、连接字符串和配置值;
- 数据库内容、日志样本、导出文件和现场截图;
- 本地绝对路径、安装路径和发布目录;
- 产量、节拍、良率、停机时间和未经记录的稳定性指标。
下文的架构图和流程使用抽象名称,只用于说明工程设计,不能还原真实设备或协议。
项目目标
系统围绕“可靠桥接、状态可解释、生产可追溯”建立以下目标:
- 稳定轮询 PLC 设备状态和业务命令,并串行化同一通信通道上的访问;
- 将上料、下料、查询和解绑命令转换为明确的 MES 业务步骤;
- 在执行前校验来源、目标和当前活动关系,降低错误绑定与重复操作风险;
- 将成功或失败结果及时写回 PLC,形成设备侧可识别的命令闭环;
- 保存载具会话、活动关系、绑定历史、命令记录和 MES 事务;
- 通过 TraceId 把一次设备命令关联到本地记录和外部请求;
- 为操作人员提供设备监控、历史时间线、事务筛选、导出和配置维护界面;
- 支持 Windows x64 安装交付、数据库迁移、日志诊断和离线 Mock 联调。
技术栈与职责
| 层次 | 技术与组件 | 主要职责 |
|---|---|---|
| 桌面界面 | .NET 8、WPF、CommunityToolkit.Mvvm | 设备监控、事务查询、历史时间线、导出和配置维护 |
| 应用宿主 | Generic Host、依赖注入、Options | 生命周期、配置、日志、后台服务和应用服务装配 |
| 设备接入 | Modbus TCP、轮询服务、字节序适配 | 状态读取、命令读取、参数读取和响应写回 |
| 业务编排 | 命令处理器、工作流引擎 | 上料、下料、查询、解绑和流程上下文管理 |
| 外部集成 | HttpClient、JSON、Token、重试处理器 | 排产、来源/目标、SN、扣料、绑定、过站和解绑调用 |
| 追溯模型 | 会话、活动关系、绑定/解绑、命令记录 | 设备动作、业务关系和异常结果的本地证据链 |
| 数据访问 | EF Core、SQLite、迁移 | 运行数据持久化、查询、筛选和历史时间线 |
| 状态通知 | MVVM Messaging | 连接状态、设备状态和界面刷新消息 |
| 可观测性 | NLog、MES 事务、请求耗时 | 运行日志、外部调用结果和故障定位 |
| 验证与交付 | xUnit、Mock、Inno Setup | 开发验证、无现场系统联调和 Windows x64 安装 |
Generic Host 统一管理配置、日志、依赖注入和后台服务。WPF ViewModel 只消费应用服务和消息,设备通信与外部 MES 适配位于基础设施层,工作流负责组织业务步骤,EF Core 仓储保存可恢复的本地状态。
总体架构
┌────────────────────────── 现场设备层 ──────────────────────────┐
│ PLC:设备状态、业务命令、参数与处理响应 │
└──────────────────────────────┬─────────────────────────────────┘
│ 受控工业网络 / Modbus TCP
▼
┌────────────────────────────────────────────────────────────────┐
│ .NET 8 / Generic Host │
│ │
│ 状态轮询服务 ───────────────→ 运行状态 / MVVM Messaging │
│ 命令轮询服务 → 命令分发器 → 上料 / 下料 / 查询 / 解绑处理器 │
│ │ │ │
│ ▼ ▼ │
│ 工作流上下文 EF Core / SQLite │
│ │ 会话 / 关系 / 命令 / MES 事务 │
│ ▼ │
│ HTTP MES 适配器 / 重试 / Mock │
└──────────────────────────────┬─────────────────────────────────┘
│ HTTP / JSON
▼
┌───────────────────┐
│ 外部 MES │
└───────────────────┘
系统把“设备事实”“业务事实”和“操作界面”分开:PLC 读写由单一客户端串行完成,工作流负责业务顺序,SQLite 保存追溯证据,界面通过消息和查询展示状态。这样能够避免 WPF 页面直接持有现场通信资源,也让设备掉线或界面切换不至于破坏业务对象的生命周期。
启动与运行生命周期
应用启动时先加载 JSON 配置和 NLog,创建 Generic Host,注册 PLC、MES、工作流、仓储与消息组件,随后执行 EF Core 迁移。数据库准备完成后,状态轮询和命令轮询后台服务开始运行,WPF 主窗口展示设备与 MES 状态。
启动进程
→ 加载配置与日志
→ 构建 Generic Host / 依赖注入
→ 执行 EF Core 数据库迁移
→ 启动 PLC 状态与命令轮询
→ 显示 WPF 监控界面
→ 停止时取消后台任务并释放资源
启动顺序保证数据库早于业务轮询就绪。配置中的一部分通过 Options 监视机制读取更新,但数据库、日志路径和已经实例化的客户端参数仍属于启动时边界,不能把整个应用描述为完全热重载。
PLC 状态轮询与串行访问
状态后台服务按固定周期读取自动/手动、运行和报警等设备状态,并把结果发布为运行状态消息,同时保存必要的设备快照。命令后台服务轮询多个业务命令组,只对非空闲命令进行分发。
Modbus TCP 客户端通过异步锁串行化连接、读取和写入,避免状态轮询与命令处理同时操作同一连接。数值和字符串分别支持可配置字节序,以兼容不同 PLC 数据布局。连接、读写和 HTTP 调用都有独立超时,取消信号会贯穿后台服务和业务处理器。
状态轮询 ─┐
├─→ 异步锁 → Modbus TCP 连接 → PLC
命令轮询 ─┘
当前重连延时配置没有形成真正的退避策略。故障期间,后台服务仍可能按照轮询周期反复尝试并持续写日志,属于需要收敛的运行风险。
命令分发与响应闭环
命令处理链按照“识别命令、读取参数、执行业务、写回响应、保存记录”的方向推进。为避免 PLC 持续保持命令值造成重复触发,处理器会在进入业务步骤前清理当前指令,再读取并校验参数。
发现非空闲命令
→ 清理当前命令
→ 读取并校验参数
→ 创建 TraceId 与执行上下文
→ 调用对应工作流
→ 写回成功或失败响应
→ 保存命令执行记录
该链路具有清晰的诊断步骤,但 PLC 指令清理、外部业务调用、响应写回和本地执行记录不是单一原子操作。进程在中间退出时,仍需要结合 PLC 当前状态、MES 事务和历史记录判断是否可以安全重试。
料盘到 PVD 的上料流程
上料工作流先获取外部 MES 访问上下文,再读取当天排产和来源载具状态,校验来源与目标是否匹配当前业务。校验通过后,系统依次完成产品标识生成、物料扣减、载具绑定和工序过站,并在本地建立活动关系和会话记录。
料盘 → PVD
→ 获取 MES 访问上下文
→ 查询当日排产
→ 查询并校验来源载具
→ 查询并校验目标载具
→ 生成产品 SN
→ 扣减物料
→ 建立载具绑定
→ 完成工序过站
→ 保存会话、活动关系和绑定记录
公开流程只表达步骤顺序,不展示实际接口字段、产品编码规则、工装身份、请求载荷或结果码。每一步的外部调用都会记录成功状态、耗时和经过限制的错误信息,供现场排障使用。
PVD 到目标工装的下料流程
下料方向以 PVD 侧的当前产品和活动关系为起点,查询目标工装状态并校验是否允许转移。工作流完成对应的 MES 业务步骤后,关闭旧关系、建立或结束目标侧关系,并保存下料会话与解绑记录。
PVD → 目标工装
→ 查询 PVD 当前上下文
→ 查询并校验目标工装
→ 执行下料业务步骤
→ 更新或关闭活动关系
→ 保存解绑记录和会话结果
→ 向 PLC 写回处理状态
上下料不是两个互不相关的接口调用:它们共享载具关系和产品上下文。只有持续维护当前活动关系,才能解释“某个产品从哪里来、当前在哪里、经过了什么动作”。
查询命令与流程预加载
PLC 在正式发起上料或下料前,可以通过查询命令预加载业务上下文。查询处理器读取当前载具关系、外部 MES 信息和本地会话,把经过校验的上下文保存到工作流状态中,后续命令可以复用同一组关键数据。
这种设计减少正式动作执行时的重复查询,也可以更早发现来源、目标或关系冲突。但预加载结果存在时效性,正式业务仍应对关键状态做最终校验,不能把一次查询当作长期锁定。
会话、活动关系与重复绑定防护
追溯模型由多个相互关联的记录组成:
| 记录 | 作用 |
|---|---|
| 载具转移会话 | 表示一次上料或下料流程的开始、结束和最终状态 |
| 活动关系 | 表示产品与载具当前仍有效的关联 |
| 绑定/解绑记录 | 保存关系建立和关闭的历史事实 |
| 命令执行记录 | 保存 PLC 命令、处理结果、错误摘要和耗时 |
| MES 事务 | 保存外部调用方向、状态、耗时和关联 TraceId |
| 设备状态快照 | 保存必要的设备运行状态变化 |
业务处理前会检查当前活动关系:相同关系的重复请求可以按已有状态处理,冲突关系会被拒绝,降低设备重发造成重复绑定的风险。所有记录通过 TraceId 串联,使一次 PLC 指令可以追踪到业务会话和外部调用。
当前活动关系检查主要依赖应用层查询,没有对应的数据库唯一约束。跨线程竞争或未来多实例运行时,两个请求仍可能同时通过检查,因此后续需要把业务唯一性下沉到数据库约束,并对冲突设计明确的幂等返回。
外部 MES 适配、重试与 Mock
外部适配器使用 HttpClient 和 JSON 调用 MES,区分超时、主动取消、HTTP 失败、空响应和解析失败。Token 与请求超时由配置提供,调用结果会转换为有限的业务结果,避免工作流直接依赖外部响应的全部结构。
重试处理器对超时、限流、服务器错误和瞬时网络异常使用固定间隔重试。它能够缓解短时抖动,但多步骤工作流没有跨系统事务或补偿机制,对非幂等 POST 自动重试还可能产生重复副作用。正式改进方向应是为每个业务动作提供幂等键、可查询状态和补偿策略,而不是无限增加重试次数。
开发环境可以切换到 Mock MES,在没有现场接口时验证 PLC 轮询、命令分发、工作流和 WPF 状态展示。Mock 是开发工具,不代表真实 MES 的认证、并发、限流和失败语义,也不能替代现场联调。
SQLite 追溯与数据展示
EF Core 与 SQLite 保存命令、会话、活动关系、绑定/解绑、设备快照和 MES 事务。应用启动时执行迁移,仓储为各业务操作提供独立数据库上下文。WPF 界面围绕这些记录提供:
- 设备监控:连接状态、运行模式、报警和最近命令;
- MES 事务:按时间、方向和结果筛选外部调用,并查看请求耗时;
- 历史追溯:从载具会话展开绑定、解绑和 MES 事务时间线;
- 数据导出:导出经过筛选的运行记录,用于受控排障;
- 配置维护:校验并保存 PLC、MES、轮询、日志和数据库相关设置。
SQLite 适合当前单机部署,但设备快照和 MES 事务当前缺少自动清理与分级保留。数据库备份、异机副本和实际恢复演练也尚未固化,必须作为后续运维工作处理。
配置、日志与消息通知
JSON 配置用于保存连接、超时、轮询、字节序和运行路径等参数。保存配置后,部分 Options 消费者可以接收变化;需要重建客户端或在启动时绑定的参数仍应通过重启生效,并在界面中明确提示。
NLog 记录启动、连接、命令和异常。MVVM Messaging 把 PLC 连接状态、设备状态与业务结果从后台服务传递到界面,降低后台线程与窗口对象的直接耦合。
生产数据治理仍有明显边界:MES Token、请求和响应、产品码以及 PLC 参数可能进入 SQLite、界面导出或调试日志。当前没有统一的字段级脱敏和保留策略,排障便利性不能替代最小化记录、访问控制和到期清理。
Windows 安装与现场交付
应用面向 Windows x64,通过 Inno Setup 生成版本化安装程序。当前现场确认使用 1.0.6,安装包包含应用文件和初始配置,支持桌面应用的标准安装与卸载流程。
确认源码标签与依赖
→ Release 构建
→ 发布 Windows x64
→ 生成 Inno Setup 安装包
→ 备份现场数据库与配置
→ 安装或升级
→ 验证 PLC、MES、上下料与追溯
现有安装工程仍依赖开发机绝对发布路径,并可能覆盖现场配置;聚合仓库 Gitlink、源码标签、测试仓库和安装包也没有通过统一 manifest 对齐。因此当前交付可以使用,但尚未形成完全可复现、可审计和可自动回滚的发布链路。
版本与验证基线
本案例严格区分生产标签和正在开发的工作区:
| 验证项 | 结果与边界 |
|---|---|
| 生产主应用 | 标签 1.0.6,源码提交 46a7649,已确认用于现场生产 |
| Windows x64 安装包 | 版本 1.0.6,已确认用于现场生产 |
| 生产标签 Release 构建 | 通过临时只读导出单独验证:2 个项目,0 error、0 warning |
| 当前开发工作区 | 0 error、0 warning;包含未提交的后续修改,不属于生产标签 |
| 当前开发测试快照 | 36 项通过;测试依赖未提交修改,不能作为 1.0.6 的测试认证 |
| 发布版本追溯 | 测试仓库缺少与生产标签严格对应的发布标记,也没有统一版本 manifest |
| 源码仓库 CI | 当前没有持续集成工作流 |
标签构建使用独立临时导出完成,没有 stash、checkout、清理或改写当前工作区。未提交的 MES 接口测试界面、Token 刷新修正及相关测试属于后续开发内容,本文不将其写成生产能力。
生产使用结果
根据已经确认的现场事实,可以做出以下定性描述:
- 主应用和安装包
1.0.6已投入生产使用; - PLC 状态、命令轮询和响应写回形成了设备侧闭环;
- 料盘到 PVD、PVD 到目标工装的业务步骤已接入外部 MES;
- 会话、活动关系、绑定/解绑、命令和接口事务形成了本地追溯链;
- 设备监控、历史时间线、事务筛选和配置维护为现场排障提供了入口;
- Mock MES 支持脱离现场接口的开发与演示。
本文不披露客户或现场数据,也不虚构节拍、产量、良率、成功率和长期稳定性指标。生产确认覆盖系统整体使用,不表示每个源码分支或开发中的界面都已部署到现场。
已知边界与风险
版本与发布治理
- 聚合仓库 Gitlink、源码标签、测试仓库和安装包尚未通过统一 manifest 对齐;
- 测试仓库没有与
1.0.6严格对应的发布标记,36 项测试只能代表当前开发快照; - 安装脚本依赖开发机绝对发布路径,构建过程难以在干净环境中复现;
- 升级可能覆盖现场配置,缺少配置 schema 迁移、安装前备份和自动回滚;
- 源码仓库没有持续集成工作流,发布质量依赖人工步骤。
跨系统一致性
- MES 多步骤调用没有分布式事务或补偿机制,部分成功后可能留下中间状态;
- 对非幂等 POST 的自动重试可能造成重复扣料、绑定或过站副作用;
- 活动关系缺少数据库唯一约束,跨线程或多实例并发仍可能竞争;
- PLC 指令清零、业务处理、响应写回和执行记录不是单一原子操作;
- 查询预加载与正式执行之间存在状态变化窗口,需要最终校验和幂等键。
认证、Token 与数据安全
1.0.6对持久化 Token 的有效期和刷新处理不完整;- MES Token、请求、响应、产品码和 PLC 参数可能进入数据库、界面导出和调试日志;
- 当前没有统一日志脱敏、数据分级、导出审批和保留策略;
- 桌面端没有登录、RBAC 或操作审计,配置维护依赖主机与现场权限;
- PLC 通信没有加密或应用层鉴权,只适合受控工业网络。
运行与恢复
- PLC 重连延时没有形成真正退避,故障期间可能高频重试并持续写日志;
- 设备快照和 MES 事务缺少自动清理,长期运行需要监控数据库和磁盘增长;
- SQLite 备份、异机复制和恢复演练尚未固化;
- 普通单元测试与 Mock 不能替代真实 PLC、外部 MES、断网和硬件在环验收;
- 单机 SQLite 与桌面进程构成当前运行边界,多实例部署需要重新设计并发控制。
后续路线
- 为扣料、绑定、过站和解绑设计跨系统幂等键、状态查询与补偿流程;
- 在数据库中增加活动关系唯一约束,并定义并发冲突的幂等响应;
- 完成 Token 有效期、刷新、失效重试和安全存储的完整生命周期;
- 对请求、响应、产品码、PLC 参数和导出数据实施字段级脱敏与分级保留;
- 增加本地登录、细粒度 RBAC、配置变更审计和高风险操作确认;
- 实现指数退避、抖动、熔断和可观测的 PLC/MES 重连策略;
- 建立设备快照与事务数据保留策略、SQLite 热备份、异机副本和恢复演练;
- 建立 CI,固定 SDK 与依赖,执行 Release 构建、测试、静态分析和安装包验证;
- 用发布 manifest 关联源码、测试、数据库迁移、安装包、配置 schema 和现场验收;
- 改造可复现安装工程,支持配置迁移、安装前备份、健康检查和版本回滚;
- 建立 PLC 仿真、外部 MES 沙箱、网络故障和真实硬件在环的分层回归。
项目复盘
这个项目的核心价值,是把一次看似简单的“PLC 命令”转换为可以解释和追踪的跨系统业务链:
- 设备状态和命令通过串行 Modbus 通道稳定读取;
- 上下料动作在执行前获得排产、来源、目标和关系上下文;
- 每个外部步骤都有 TraceId、耗时、结果和本地事务记录;
- 活动关系描述产品与载具的当前事实,绑定/解绑记录保留历史;
- PLC 收到明确响应,操作人员可以从界面还原处理过程;
- Mock 与测试提升开发效率,生产标签和开发快照则保持清晰边界。
生产运行说明该设计已经能够承担实际上下料业务,但也暴露出工业桥接系统最关键的工程债务:跨系统幂等与补偿、发布可追溯、Token 与日志安全、数据保留以及可恢复交付。下一阶段应优先补齐这些边界,而不是继续增加更多未经治理的接口步骤。