PLC 型号:西门子 S7-200 Smart,通信协议:HslCommunication S7Net
恢复的 4 组代码均有明确设计意图,但实现不完整。本计划按优先级排列,逐步将它们从"占位代码"推进到"生产可用"。
目标:将 ProjectProfile 中已定义但未接线的模型字段接入到服务层/ViewModel/UI。
现状:
ProjectProfile 定义了 8 个子配置(Pump/Tank/Gauge/Sensor/DI/DO/AlarmThresholds/ViewTemplate)步骤:
| # | 任务 | 涉及文件 | 说明 |
|---|---|---|---|
| 0.1 | 通用 DI 接入 | PlcDataModel.cs + PlcPollingService.cs + ProjectViewModel.cs + ProjectView.axaml |
PlcPolling 读取 DigitalInputs → ViewModel 显示变频器故障 |
| 0.2 | 通用 DO 接入 | ProjectViewModel.cs + ProjectView.axaml |
日流量复位/复位按钮点动写入 |
| 0.3 | 泵扩展地址接入 | PumpItemViewModel.cs + PlcPollingService.cs + ProjectView.axaml |
中控/屏控状态读取、日台时清零、手自动状态 |
| 0.4 | 报警阈值接入 | ProjectViewModel.cs |
AlarmThresholds → AlarmService 超限报警 |
| 0.5 | ViewTemplate 接入 | MainViewModel.cs |
根据 Profile.ViewTemplate 选择布局 |
完成标准:
目标:让 Service 可测试、可替换,为后续阶段打好基础。
现状:
步骤:
| # | 任务 | 涉及文件 | 说明 |
|---|---|---|---|
| 1.1 | 选择 1 个低风险 Service 试点 | ConfigService |
它无状态、无并发,最适合试点 |
| 1.2 | ConfigService 从 static 改为实例类 | ConfigService.cs |
实现 IConfigService,保留 Instance 静态属性做兼容 |
| 1.3 | ServiceLocator 注册 ConfigService | ServiceCollectionExtensions.cs |
services.AddSingleton<IConfigService>(ConfigService.Instance) |
| 1.4 | 逐批替换调用方 | 所有 ViewModel/Service | ConfigService.GetConfig() → ServiceLocator.GetService<IConfigService>().GetConfig() |
| 1.5 | 重复 1.2~1.4 覆盖其他 Service | 按依赖顺序:IConfigService → IDatabaseService → IAuthService → IPlcService → IAlarmService | 每完成一个 Service 跑一次全量测试 |
| 1.6 | (可选)引入构造函数注入 | App.axaml.cs |
services.BuildServiceProvider() + ViewModel 通过构造函数接收依赖 |
完成标准:
目标:让泵/风机的状态转换有规则、可审计。
现状:
DeviceStateMachine 类已定义状态(Stopped/Running/Fault/Maintenance)和转换DeviceStateMachineManager 已实现,硬编码"5 泵 + 2 风机"步骤:
| # | 任务 | 涉及文件 | 说明 |
|---|---|---|---|
| 2.1 | 从 ProjectProfile 读设备列表 | DeviceStateMachine.cs |
InitializeDefaultDevices() 改为从 ProjectService.CurrentProfile 读设备,不再硬编码 |
| 2.2 | 接入 PLC 数据驱动状态转换 | DeviceStateMachine.cs |
订阅 PlcPollingService.DataUpdated 事件,根据 PumpRunning/PumpFault 信号触发状态转换 |
| 2.3 | 添加状态变更事件 | DeviceStateMachine.cs |
event Action<DeviceStateChange> StateChanged,供 UI/通知消费 |
| 2.4 | 接入 AlarmService | AlarmService.cs |
设备进入 Fault 状态时自动触发报警;报警恢复时自动转 Maintenance |
| 2.5 | ViewAViewModel 消费状态机 | ViewAViewModel.cs |
替换手写的 UpdateDeviceStatuses,改读 DeviceStateMachine 的状态 |
| 2.6 | 状态变更持久化 | DeviceStateMachine.cs |
写入 equipment_statuses 表,支持历史查询 |
完成标准:
目标:让污水处理的多步骤流程可控、可配置。
现状:
WorkflowService 是简化版工作流引擎(Elsa 失败后的降级方案)RegisterSampleWorkflows() 里的日志占位步骤:
| # | 任务 | 涉及文件 | 说明 |
|---|---|---|---|
| 3.1 | 定义工作流模型 | Models/WorkflowDefinition.cs |
WorkflowDefinition(步骤列表)、WorkflowStep(条件 + 动作 + 下一步) |
| 3.2 | 从 JSON 配置加载工作流 | WorkflowService.cs |
Workflows 配置节 → WorkflowDefinition 列表 |
| 3.3 | 实现工作流执行引擎 | WorkflowService.cs |
ExecuteAsync(workflowId):按步骤执行,支持条件分支、等待、超时 |
| 3.4 | 实现内置动作 | WorkflowService.cs |
预置动作:StartPump/StopPump/CheckLevel/SendNotification 等 |
| 3.5 | 与 DeviceStateMachine 联动 | WorkflowService.cs |
工作流步骤可以查询/等待设备状态 |
| 3.6 | UI 展示工作流状态 | ViewFViewModel.cs |
显示当前运行的工作流、步骤进度、历史执行记录 |
完成标准:
目标:让项目支持西门子以外的 PLC 品牌。
现状:
PlcDriverFactory 完整,但 PlcService 直接硬编码 SiemensS7NetPlcConfig 地址格式是西门子专用的(VD100, Q0.0)步骤:
| # | 任务 | 涉及文件 | 说明 |
|---|---|---|---|
| 4.1 | PlcConfig 添加协议选择 | PlcConfig.cs + yzwater-config.json |
新增 PlcProtocol 配置项,默认 SiemensS7 |
| 4.2 | PlcService 使用 PlcDriverFactory | PlcService.cs |
ConnectAsync() 中根据协议创建对应驱动,替换硬编码的 SiemensS7Net |
| 4.3 | 统一地址格式 | PlcConfig.cs + 各驱动 |
定义通用地址模型,各驱动负责转换为品牌专用地址 |
| 4.4 | UI 协议选择 | ViewBView.axaml + ViewBViewModel.cs |
参数设置页添加 PLC 品牌/协议下拉框 |
| 4.5 | 集成测试 | tests/ |
至少对 ModbusTcp 做一次真实连接测试 |
完成标准:
yzwater-config.json 可配置 PLC 协议阶段零(项目档案接线)← 扬杰二厂急需,最先做
↓
阶段一(DI 迁移)← 基础,建议最先做(可与阶段零并行)
↓
阶段二(状态机)← 需要 DI 让状态机可注入
↓
阶段三(工作流)← 依赖状态机的设备状态查询
阶段四(多品牌 PLC)← 独立,可随时启动(当前项目用 S7-200 Smart + Hsl S7 协议)
| 阶段 | 预估工作量 | 优先级 |
|---|---|---|
| 阶段零:项目档案接线 | 1~2 天 | ⭐⭐⭐ 最高(扬杰二厂急需) |
| 阶段一:DI 迁移 | 2~3 天 | ⭐⭐⭐ 最高(基础) |
| 阶段二:状态机 | 3~4 天 | ⭐⭐⭐ 高(工业控制核心) |
| 阶段三:工作流 | 4~5 天 | ⭐⭐ 中(自动化增值) |
| 阶段四:多品牌 PLC | 2~3 天 | ⭐ 按需(有新项目时) |