Files
Axi_Omron/README.md
yunxiao.zhu c67509ec82 ✨ feat(file-check): 添加 PLC 应答后命中文件删除
* 新增默认关闭的删除开关,仅在收到 PLC 放行应答后执行

* 本地与 SFTP Provider 校验根目录并支持幂等删除

* 补充工作流、设置页和文件删除相关测试与文档
2026-08-01 16:42:28 +08:00

176 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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`
- `FileCheck.DeleteMatchedFileAfterPlcAck`: `false`;启用后仅在收到 PLC 放行应答时删除本次精确命中的产品 ID 文件
点位映射示例:
- 输入点位
- `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”这类问题。