# AxiOmron.PcbCheck 基于 `.NET 8 + WPF + MVVM Toolkit + Generic Host/DI + NLog` 的 PCB 目检上位机示例工程,包含 PLC 通信、扫码枪触发、SFTP 文件校验、安灯报警和运行态监控。 ## 项目结构 ```text Axi_Omron/ src/ AxiOmron.PcbCheck/ tests/ AxiOmron.PcbCheck.Tests/ docs/ AxiOmron.PcbCheck.slnx ``` 主程序位于 [src/AxiOmron.PcbCheck](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck),测试位于 [tests/AxiOmron.PcbCheck.Tests](d:/Dev/Codes/MFD_Solution/Axi_Omron/tests/AxiOmron.PcbCheck.Tests)。 ## 技术栈 - `.NET 8` / `WPF` - `CommunityToolkit.Mvvm` - `Microsoft.Extensions.Hosting` - `NLog` - `IoTClient` Modbus TCP - `SSH.NET` - `HandyControl` ## 配置说明 主配置文件位于 [src/AxiOmron.PcbCheck/appConfig.json](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/appConfig.json)。 当前 PLC 相关默认配置示例: - `Plc.Host`: `127.0.0.1` - `Plc.Port`: `502` - `Plc.UnitId`: `1` - `Plc.PollIntervalMs`: `200` - `Plc.ReleasePulseMs`: `500` - `Plc.ReleaseAckTimeoutMs`: `2000` 点位映射示例: - 输入点位 - `PcbArrived = 0` - `PlcReset = 1` - `PlcAckRelease = 2` - 输出点位 - `PcBusy = 51` - `ReleasePermit = 52` - 寄存器 - `ResultCode = 0` 系统设置页可修改 PLC 参数,界面入口在 [SystemSettingsPage.xaml](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Views/Pages/SystemSettingsPage.xaml#L58)。 注意:配置保存后会写入运行目录下的 `appConfig.json`,当前界面提示为“重启应用后完全生效”。 ## 构建与运行 ```powershell dotnet restore .\src\AxiOmron.PcbCheck\AxiOmron.PcbCheck.csproj dotnet build .\src\AxiOmron.PcbCheck\AxiOmron.PcbCheck.csproj -c Debug dotnet run --project .\src\AxiOmron.PcbCheck\AxiOmron.PcbCheck.csproj -c Debug dotnet test .\tests\AxiOmron.PcbCheck.Tests\AxiOmron.PcbCheck.Tests.csproj ``` ## PLC 后台轮询调用链 ### 总览 ```text App 启动 -> BuildHost 注册 WorkflowHostedService 为 HostedService -> Host.StartAsync() -> WorkflowHostedService.ExecuteAsync() ExecuteAsync 主循环 -> ProbePlcOnStartupAsync() 启动先探活 -> while (...) -> _plcService.ReadSignalsAsync() 读取 PLC 输入 -> HandleSignalSnapshot() 刷 PLC 连接状态 -> RefreshPlcMonitorSnapshotAsync() 刷监控区 -> if PlcReset = true -> ResetAsync() else if ShouldStartWorkflow() 命中上升沿 -> StartWorkflowInBackground() -> RunWorkflowOnceAsync() RunWorkflowOnceAsync 单板流程 -> InitializeBoardState() -> ApplyProcessStateAsync(Triggered, PcBusy=true) -> ExecuteScanFlowAsync() -> _scannerService.TriggerScanAsync() -> ExecuteSftpFlowAsync(barcode) -> _sftpLookupService.CheckFileAsync() -> ReleaseAndCompleteAsync() -> ApplyProcessStateAsync(Releasing, ReleasePermit=true) -> 循环 _plcService.ReadSignalsAsync() 等 PlcAckRelease -> Delay(ReleasePulseMs) -> ApplyProcessStateAsync(Completed, ReleasePermit=false, PcBusy=false) -> _stateStore.AddRecord(...) 状态/UI 更新支线 -> PublishRuntimeState() / UpdateSnapshot() -> AppStateStore.SnapshotChanged -> MainWindowViewModel.OnSnapshotChanged() -> DashboardPage / SystemSettingsPage 绑定刷新 ``` ### 关键代码入口 - 后台服务注册: [App.xaml.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/App.xaml.cs#L125) [App.xaml.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/App.xaml.cs#L127) - 轮询主循环: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L70) - PLC 输入读取: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L81) - 轮询周期: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L110) - 启动流程判定: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L366) - 启动单板流程: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L388) - 单板总流程: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L496) - 扫码流程: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L542) - SFTP 校验流程: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L630) - 放行及等待 PLC 应答: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L727) - 流程状态写回 PLC: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L942) [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L954) ### PLC 底层读写落点 - `IPlcService` 接口: [CoreInterfaces.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Interfaces/CoreInterfaces.cs#L97) - `ReadSignalsAsync` 实现: [ModbusTcpPlcService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/ModbusTcpPlcService.cs#L37) - 实际读取的输入位: [ModbusTcpPlcService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/ModbusTcpPlcService.cs#L47) [ModbusTcpPlcService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/ModbusTcpPlcService.cs#L48) [ModbusTcpPlcService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/ModbusTcpPlcService.cs#L49) - 监控区镜像读取: [ModbusTcpPlcService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/ModbusTcpPlcService.cs#L69) - 输出状态写入: [ModbusTcpPlcService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/ModbusTcpPlcService.cs#L113) ### UI 刷新链 - 后台更新运行态快照: [AppStateStore.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/AppStateStore.cs#L45) - 主界面监听快照变化: [MainWindowViewModel.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/ViewModels/MainWindowViewModel.cs#L532) - 设置页监听快照变化: [SystemSettingViewModel.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/ViewModels/SystemSettingViewModel.cs#L150) ### 常用排查入口 - `PlcReset` 触发软件复位: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L85) - 轮询异常进入故障锁存: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L103) - 流程异常进入故障锁存: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L432) - 故障状态写回: [WorkflowHostedService.cs](d:/Dev/Codes/MFD_Solution/Axi_Omron/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs#L823) ## 说明 本 README 主要补充程序整体说明与 PLC 后台轮询调用链,便于排查“PLC 轮询在哪里启动、如何触发单板流程、状态如何回写和刷新 UI”这类问题。