还有优化空间。目前架构已经完成了基础拆分,但仍属于“渐进迁移阶段”,部分服务只是代理层,核心业务仍在StationControlViewModel中。
一、当前最需要优化的问题
- StationAutomationService 目前仍是代理服务
StationAutomationService已经提供了统一入口,但实际执行仍通过:
HandleEapStartLotAsync HandleEapSOTAsync HandleEapUnloadAsync回调到StationControlViewModel。
因此目前只是“调用路径解耦”,并没有完全实现自动化业务迁移。后续应该将以下核心逻辑迁移到独立服务:
StationAutomationService- 只负责自动化协议业务
StationLifecycleService- 初始化、停止、复位、结批
StationMaterialService- 上料、搬运、吹扫、下料
StationTestService- 预测试、正式测试、结果保存
StationUiAdapter- 只负责修改界面属性和弹窗
最终StationControlViewModel只保留按钮命令、属性绑定和服务调用。
- MainWindow 仍然知道 ViewModel
目前MainWindow.xaml.cs仍然通过主页查找:
homeView.ViewModel.Stations.FirstOrDefault(...)然后取得工站 ViewModel。
这会导致:
- 通信层依赖 WPF 页面结构
- 工站集合必须已经创建
- 页面关闭或切换时存在空引用风险
- 后续增加后台模式、无界面运行模式比较困难
建议增加独立的:
StationServiceRegistry由它维护:
StationId -> StationApplicationService通信层只根据站号查找业务服务,不再查找 ViewModel。
- 自动化业务仍然大量依赖 Dispatcher
当前自动化命令通过:
Application.Current.Dispatcher.InvokeAsync(...)进入 UI 线程。
这会有两个问题:
- PLC 同步读写可能阻塞 UI
- 自动化网络请求可能拖慢界面响应
- 多个工站同时开批时,所有业务都经过 UI Dispatcher 排队
- 后台线程异常可能无法正常返回协议层
建议明确区分:
后台业务线程: PLC、主控板、负载板、文件、数据库、协议等待 UI线程: 按钮状态、进度、灯态、弹窗、界面属性业务服务不能整体运行在 UI 线程,只能在需要更新界面时调用StationUiAdapter。
- 硬件资源仍缺少统一互斥
目前工站命令邮箱可以保证:
StartLot SOT EndLot Unload Reset之间的顺序。
但以下业务仍可能来自不同线程:
- 自动化命令
- 自动流水线 Worker
- PLC 实时采集
- 手动操作
- 停止流程
- 复位流程
- 下料流程
如果它们同时操作同一个 PLC 或主控板,仍然可能出现:
- 同时发送主控板指令
- 测试过程中被复位
- 下料过程中又写入搬运命令
- PLC 通讯响应错配
- 同一 TCP 连接被多个流程抢占
建议增加工站级资源锁:
MainBoardCommandGate PlcCommandGate LoadUnitCommandGate RfidCommandGate WorkflowGate普通读取可以并发,但动作类指令必须串行。
- SOT 预占用还没有完整实现幂等
当前AutomationSotReservation已经解决:
- 必须先
SOTReadyReq - 重复
SOTReadyReq SOTReady和SOT状态转换- 复位和解锁清理占用
但它还不能处理完整的网络重试场景。
例如:
SOTReq SN=1001 第一次已经成功 EAP没有收到回复 EAP再次发送相同的 SOTReq SN=1001当前可能返回:
当前预占用正在处理SOTReq或者重复进入业务。
工业级做法应增加请求幂等缓存:
Station + Command + SN + RequestPayloadHash保存:
请求状态 请求时间 请求结果 响应报文相同请求重复到达时直接返回原响应,不重复搬运、不重复测试、不重复写 PLC。
- AutomationBusinessHandler 职责仍然过重
目前AutomationBusinessHandler同时承担:
- 报文解析
- 参数校验
- 配方查找
- 协议日志
- 回包组装
- 工站查找
- 业务执行器调用
- 错误处理
- 请求 SN 管理
建议拆成:
AutomationTcpProtocolAdapter 负责 JSON/TCP 收发和 JSON 字段解析 AutomationCommandRouter 负责 Command 路由 AutomationRequestValidator 负责参数、配方和批次校验 StationAutomationService 负责工站自动化业务 AutomationResponseFactory 负责生成响应报文 AutomationRequestIdStore 负责请求幂等和重复报文处理这样不同客户增加命令时,不需要继续修改一个巨大的 Handler。
- 真正 EAP 和 Automation 仍需进一步隔离
当前 JSON/TCP 自动化和 SECS/GEM 已经有区别,但部分代码仍然共用:
AutomationBusinessHandlerAutomationBusinessGatewayStationControlViewModel- 部分
HandleEap...命名
建议最终结构如下:
Automation/ AutomationTcpServer AutomationProtocolAdapter AutomationCommandRouter StationAutomationService Eap/ SecsGemService EapEventService EapCommandMapper StationEapService二者可以共用:
StationLifecycleService StationMaterialService StationTestService StationRuntime但不应共用协议语义。
例如:
Automation SOTReq表示外部自动化已经放料并提供 DUTSN。
而:
SECS/GEM AcceptItem表示 Host 接受本机扫码结果。
二者不能直接互相替代。
二、当前状态机仍需要升级
当前状态机已经能够记录非法跳转,但如果所有业务仍然由 ViewModel 修改状态,状态机无法成为唯一状态来源。
建议顺序:
- 生命周期逻辑迁移完成
- 测试逻辑迁移完成
- 自动化逻辑迁移完成
- EAP 逻辑迁移完成
- 所有状态修改统一进入状态机
- 最后把“记录非法跳转”改为“拒绝非法跳转”
例如:
Idle -> StartingBatch StartingBatch -> BatchReady BatchReady -> Loading Loading -> Transferring Transferring -> PreTesting PreTesting -> Testing Testing -> Purging Purging -> Unloading Unloading -> BatchReady非法操作直接返回失败:
Testing 状态不允许 StartLot Purging 状态不允许再次 SOT Resetting 状态不允许开始测试三、PLC 信号事件化仍需完善
当前仍然主要依靠周期轮询和等待:
循环读取 PLC 判断是否满足条件 Task.Delay 继续读取推荐保留轮询,同时增加信号变化事件:
PLC轮询服务 定时读取 PLC 快照 SignalChangeDetector 只发布发生变化的信号 StationWorkflowService 订阅需要的信号事件 WaitForCondition 作为超时和异常恢复兜底不能完全删除轮询,因为工业现场必须具备:
- 周期性心跳
- 通讯断线检测
- 信号一致性校验
- 事件丢失恢复
- 初始化后的完整快照
四、生命周期释放还需要补齐
目前StationLifecycleService、StationWorkflowService、StationCommandMailbox都有释放逻辑,但需要确认:
- 工站 ViewModel 销毁时是否调用
DisposeAsync - 页面关闭时是否停止流水线
- PLC 轮询事件是否取消订阅
- 自动化回调是否解除注册
- CancellationTokenSource 是否全部释放
- TCP 连接是否等待后台线程退出
否则长时间运行或重复打开页面可能出现:
- 后台 Worker 残留
- 事件重复订阅
- 同一工站重复执行
- 内存泄漏
- 关闭软件时进程无法退出
五、日志和诊断还可以进一步统一
当前已经有自动化日志、EAP 日志、电学故障日志和辅控故障日志,但建议统一增加:
OperationId RequestId StationId LotId ProductSN PipelineStage ThreadId 当前状态 PLC信号快照尤其是 PLC 等待日志,应统一记录:
等待条件: 上料位U相器件检测 = false 上料位V相器件检测 = false 吹扫完成标志位 = 5 当前值: 上料位U相器件检测 = true 上料位V相器件检测 = false 吹扫完成标志位 = 3满足后记录:
PLC等待条件已全部满足,进入下一阶段这对现场定位“为什么一直不搬运”非常重要。
六、建议的后续优化顺序
建议按以下顺序继续,每一步完成后上机验证:
- 将
StationCommandMailbox从 ViewModel 目录迁移到Services.Workflow - 将硬件访问从 UI Dispatcher 中分离
- 增加统一
StationDeviceContext - 增加 PLC、主控板和负载板资源锁
- 将自动化命令核心逻辑迁移到
StationAutomationService - 将 JSON/TCP 协议解析从
AutomationBusinessHandler中拆出 - 增加自动化请求幂等缓存
- 将
MainWindow的工站查找改成服务注册表 - 建立独立
StationEapService - 增加完整的服务释放和异常恢复
- 统一 PLC 等待日志和状态快照
- 最后启用严格状态机,拒绝非法跳转
结论:
当前架构已经比最初明显改善,但还没有完全达到工业级标准。最优先需要处理的是:
UI线程与后台业务分离 硬件资源互斥 自动化请求幂等 MainWindow与ViewModel解耦 Automation/EAP协议彻底分离这些问题比继续拆分.partial.cs文件更重要。