|
|
@@ -0,0 +1,416 @@
|
|
|
+using CommunityToolkit.Mvvm.ComponentModel;
|
|
|
+using CommunityToolkit.Mvvm.Input;
|
|
|
+using Serilog;
|
|
|
+using YZWater.Core.Models;
|
|
|
+using YZWater.Core.Services;
|
|
|
+
|
|
|
+namespace YZWater.Core.ViewModels;
|
|
|
+
|
|
|
+/// <summary>
|
|
|
+/// 主工艺视图 ViewModel
|
|
|
+/// </summary>
|
|
|
+public partial class ViewAViewModel : ObservableObject
|
|
|
+{
|
|
|
+ // 液位数据
|
|
|
+ [ObservableProperty]
|
|
|
+ private float _tank1Level = 50f;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private float _tank2Level = 60f;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private float _tank3Level = 70f;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private float _tank4Level = 45f;
|
|
|
+
|
|
|
+ // 流量数据
|
|
|
+ [ObservableProperty]
|
|
|
+ private float _inflowRate = 25.5f;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private float _outflowRate = 22.3f;
|
|
|
+
|
|
|
+ // 泵状态
|
|
|
+ [ObservableProperty]
|
|
|
+ private bool _pump1Running;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private bool _pump2Running;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private bool _pump3Running;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private bool _pump4Running;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private bool _pump5Running;
|
|
|
+
|
|
|
+ // 风扇状态
|
|
|
+ [ObservableProperty]
|
|
|
+ private bool _fan1Running;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private bool _fan2Running;
|
|
|
+
|
|
|
+ // 阀门状态
|
|
|
+ [ObservableProperty]
|
|
|
+ private ValveStatus _valve1Status = ValveStatus.Middle;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private ValveStatus _valve2Status = ValveStatus.Middle;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private ValveStatus _valve3Status = ValveStatus.Middle;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private ValveStatus _valve4Status = ValveStatus.Middle;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private ValveStatus _valve5Status = ValveStatus.Middle;
|
|
|
+
|
|
|
+ // 模式状态
|
|
|
+ [ObservableProperty]
|
|
|
+ private ValveStatus _modeStatus = ValveStatus.Middle;
|
|
|
+
|
|
|
+ // 流动状态
|
|
|
+ [ObservableProperty]
|
|
|
+ private bool _isInflowRunning = true;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private bool _isOutflowRunning = true;
|
|
|
+
|
|
|
+ // 设备状态颜色
|
|
|
+ [ObservableProperty]
|
|
|
+ private string _pump1StatusColor = "#4CAF50";
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private string _pump2StatusColor = "#4CAF50";
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private string _pump3StatusColor = "#4CAF50";
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private string _pump4StatusColor = "#4CAF50";
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private string _pump5StatusColor = "#4CAF50";
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private string _fan1StatusColor = "#4CAF50";
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private string _fan2StatusColor = "#4CAF50";
|
|
|
+
|
|
|
+ // 报警状态
|
|
|
+ [ObservableProperty]
|
|
|
+ private bool _hasAlarm;
|
|
|
+
|
|
|
+ [ObservableProperty]
|
|
|
+ private string _alarmMessage = string.Empty;
|
|
|
+
|
|
|
+ // 连接状态
|
|
|
+ [ObservableProperty]
|
|
|
+ private bool _isPlcConnected;
|
|
|
+
|
|
|
+ public ViewAViewModel()
|
|
|
+ {
|
|
|
+ StartDataRefresh();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 启动数据刷新
|
|
|
+ /// </summary>
|
|
|
+ private void StartDataRefresh()
|
|
|
+ {
|
|
|
+ var timer = new System.Timers.Timer(1000);
|
|
|
+ timer.Elapsed += async (s, e) =>
|
|
|
+ {
|
|
|
+ await RefreshDataAsync();
|
|
|
+ };
|
|
|
+ timer.Start();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 刷新 PLC 数据
|
|
|
+ /// </summary>
|
|
|
+ [RelayCommand]
|
|
|
+ private async Task RefreshDataAsync()
|
|
|
+ {
|
|
|
+ if (!PlcService.IsConnected) return;
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // 读取液位数据
|
|
|
+ Tank1Level = await PlcService.ReadFloatAsync("VD100");
|
|
|
+ Tank2Level = await PlcService.ReadFloatAsync("VD104");
|
|
|
+ Tank3Level = await PlcService.ReadFloatAsync("VD108");
|
|
|
+ Tank4Level = await PlcService.ReadFloatAsync("VD112");
|
|
|
+
|
|
|
+ // 读取流量数据
|
|
|
+ InflowRate = await PlcService.ReadFloatAsync("VD200");
|
|
|
+ OutflowRate = await PlcService.ReadFloatAsync("VD204");
|
|
|
+
|
|
|
+ // 读取泵状态
|
|
|
+ Pump1Running = await PlcService.ReadBoolAsync("Q0.0");
|
|
|
+ Pump2Running = await PlcService.ReadBoolAsync("Q0.1");
|
|
|
+ Pump3Running = await PlcService.ReadBoolAsync("Q0.2");
|
|
|
+ Pump4Running = await PlcService.ReadBoolAsync("Q0.3");
|
|
|
+ Pump5Running = await PlcService.ReadBoolAsync("Q0.4");
|
|
|
+
|
|
|
+ // 读取风扇状态
|
|
|
+ Fan1Running = await PlcService.ReadBoolAsync("Q0.5");
|
|
|
+ Fan2Running = await PlcService.ReadBoolAsync("Q0.6");
|
|
|
+
|
|
|
+ // 更新设备状态颜色
|
|
|
+ UpdateDeviceStatusColors();
|
|
|
+
|
|
|
+ // 检查报警
|
|
|
+ CheckAlarms();
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Log.Error(ex, "刷新 PLC 数据失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 更新设备状态颜色
|
|
|
+ /// </summary>
|
|
|
+ private void UpdateDeviceStatusColors()
|
|
|
+ {
|
|
|
+ Pump1StatusColor = Pump1Running ? "#4CAF50" : "#F44336";
|
|
|
+ Pump2StatusColor = Pump2Running ? "#4CAF50" : "#F44336";
|
|
|
+ Pump3StatusColor = Pump3Running ? "#4CAF50" : "#F44336";
|
|
|
+ Pump4StatusColor = Pump4Running ? "#4CAF50" : "#F44336";
|
|
|
+ Pump5StatusColor = Pump5Running ? "#4CAF50" : "#F44336";
|
|
|
+ Fan1StatusColor = Fan1Running ? "#4CAF50" : "#F44336";
|
|
|
+ Fan2StatusColor = Fan2Running ? "#4CAF50" : "#F44336";
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 检查报警条件
|
|
|
+ /// </summary>
|
|
|
+ private void CheckAlarms()
|
|
|
+ {
|
|
|
+ var config = ConfigService.GetConfig();
|
|
|
+ if (config == null) return;
|
|
|
+
|
|
|
+ HasAlarm = false;
|
|
|
+ AlarmMessage = string.Empty;
|
|
|
+
|
|
|
+ if (Tank1Level > config.LevelHighAlarm)
|
|
|
+ {
|
|
|
+ HasAlarm = true;
|
|
|
+ AlarmMessage = "1号水池液位过高";
|
|
|
+ }
|
|
|
+ else if (Tank1Level < config.LevelLowAlarm)
|
|
|
+ {
|
|
|
+ HasAlarm = true;
|
|
|
+ AlarmMessage = "1号水池液位过低";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (InflowRate > config.FlowHighAlarm)
|
|
|
+ {
|
|
|
+ HasAlarm = true;
|
|
|
+ AlarmMessage = "进水流量过高";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 连接 PLC
|
|
|
+ /// </summary>
|
|
|
+ [RelayCommand]
|
|
|
+ private async Task ConnectPlcAsync()
|
|
|
+ {
|
|
|
+ IsPlcConnected = await PlcService.ConnectAsync();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 断开 PLC
|
|
|
+ /// </summary>
|
|
|
+ [RelayCommand]
|
|
|
+ private void DisconnectPlc()
|
|
|
+ {
|
|
|
+ PlcService.Disconnect();
|
|
|
+ IsPlcConnected = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 控制泵
|
|
|
+ /// </summary>
|
|
|
+ [RelayCommand]
|
|
|
+ private async Task TogglePumpAsync(string pumpId)
|
|
|
+ {
|
|
|
+ if (!PlcService.IsConnected)
|
|
|
+ {
|
|
|
+ Log.Warning("PLC 未连接,无法控制泵");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var address = pumpId switch
|
|
|
+ {
|
|
|
+ "P001" => "Q0.0",
|
|
|
+ "P002" => "Q0.1",
|
|
|
+ "P003" => "Q0.2",
|
|
|
+ "P004" => "Q0.3",
|
|
|
+ "P005" => "Q0.4",
|
|
|
+ _ => throw new ArgumentException($"未知的泵 ID: {pumpId}")
|
|
|
+ };
|
|
|
+
|
|
|
+ var currentState = pumpId switch
|
|
|
+ {
|
|
|
+ "P001" => Pump1Running,
|
|
|
+ "P002" => Pump2Running,
|
|
|
+ "P003" => Pump3Running,
|
|
|
+ "P004" => Pump4Running,
|
|
|
+ "P005" => Pump5Running,
|
|
|
+ _ => false
|
|
|
+ };
|
|
|
+
|
|
|
+ var success = await PlcService.WriteBoolAsync(address, !currentState);
|
|
|
+ if (success)
|
|
|
+ {
|
|
|
+ Log.Information("泵 {PumpId} 状态已切换", pumpId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 控制风扇
|
|
|
+ /// </summary>
|
|
|
+ [RelayCommand]
|
|
|
+ private async Task ToggleFanAsync(string fanId)
|
|
|
+ {
|
|
|
+ if (!PlcService.IsConnected)
|
|
|
+ {
|
|
|
+ Log.Warning("PLC 未连接,无法控制风扇");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var address = fanId switch
|
|
|
+ {
|
|
|
+ "F001" => "Q0.5",
|
|
|
+ "F002" => "Q0.6",
|
|
|
+ _ => throw new ArgumentException($"未知的风扇 ID: {fanId}")
|
|
|
+ };
|
|
|
+
|
|
|
+ var currentState = fanId switch
|
|
|
+ {
|
|
|
+ "F001" => Fan1Running,
|
|
|
+ "F002" => Fan2Running,
|
|
|
+ _ => false
|
|
|
+ };
|
|
|
+
|
|
|
+ var success = await PlcService.WriteBoolAsync(address, !currentState);
|
|
|
+ if (success)
|
|
|
+ {
|
|
|
+ Log.Information("风扇 {FanId} 状态已切换", fanId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 控制阀门
|
|
|
+ /// </summary>
|
|
|
+ [RelayCommand]
|
|
|
+ private async Task ToggleValveAsync(string valveId)
|
|
|
+ {
|
|
|
+ if (!PlcService.IsConnected)
|
|
|
+ {
|
|
|
+ Log.Warning("PLC 未连接,无法控制阀门");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var address = valveId switch
|
|
|
+ {
|
|
|
+ "V001" => "Q1.0",
|
|
|
+ "V002" => "Q1.1",
|
|
|
+ "V003" => "Q1.2",
|
|
|
+ "V004" => "Q1.3",
|
|
|
+ "V005" => "Q1.4",
|
|
|
+ _ => throw new ArgumentException($"未知的阀门 ID: {valveId}")
|
|
|
+ };
|
|
|
+
|
|
|
+ var currentStatus = valveId switch
|
|
|
+ {
|
|
|
+ "V001" => Valve1Status,
|
|
|
+ "V002" => Valve2Status,
|
|
|
+ "V003" => Valve3Status,
|
|
|
+ "V004" => Valve4Status,
|
|
|
+ "V005" => Valve5Status,
|
|
|
+ _ => ValveStatus.Middle
|
|
|
+ };
|
|
|
+
|
|
|
+ // 循环切换状态: 关闭 -> 中间 -> 打开 -> 关闭
|
|
|
+ var newStatus = currentStatus switch
|
|
|
+ {
|
|
|
+ ValveStatus.Closed => ValveStatus.Middle,
|
|
|
+ ValveStatus.Middle => ValveStatus.Open,
|
|
|
+ ValveStatus.Open => ValveStatus.Closed,
|
|
|
+ _ => ValveStatus.Middle
|
|
|
+ };
|
|
|
+
|
|
|
+ var success = await PlcService.WriteBoolAsync(address, newStatus == ValveStatus.Open);
|
|
|
+ if (success)
|
|
|
+ {
|
|
|
+ switch (valveId)
|
|
|
+ {
|
|
|
+ case "V001": Valve1Status = newStatus; break;
|
|
|
+ case "V002": Valve2Status = newStatus; break;
|
|
|
+ case "V003": Valve3Status = newStatus; break;
|
|
|
+ case "V004": Valve4Status = newStatus; break;
|
|
|
+ case "V005": Valve5Status = newStatus; break;
|
|
|
+ }
|
|
|
+ Log.Information("阀门 {ValveId} 状态已切换为 {Status}", valveId, newStatus);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 切换模式
|
|
|
+ /// </summary>
|
|
|
+ [RelayCommand]
|
|
|
+ private async Task ToggleModeAsync()
|
|
|
+ {
|
|
|
+ if (!PlcService.IsConnected)
|
|
|
+ {
|
|
|
+ Log.Warning("PLC 未连接,无法切换模式");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var newStatus = ModeStatus switch
|
|
|
+ {
|
|
|
+ ValveStatus.Closed => ValveStatus.Middle,
|
|
|
+ ValveStatus.Middle => ValveStatus.Open,
|
|
|
+ ValveStatus.Open => ValveStatus.Closed,
|
|
|
+ _ => ValveStatus.Middle
|
|
|
+ };
|
|
|
+
|
|
|
+ var success = await PlcService.WriteBoolAsync("M0.0", newStatus == ValveStatus.Open);
|
|
|
+ if (success)
|
|
|
+ {
|
|
|
+ ModeStatus = newStatus;
|
|
|
+ Log.Information("模式已切换为: {Status}", newStatus);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/// <summary>
|
|
|
+/// 阀门状态枚举
|
|
|
+/// </summary>
|
|
|
+public enum ValveStatus
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// 关闭
|
|
|
+ /// </summary>
|
|
|
+ Closed,
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 中间位置
|
|
|
+ /// </summary>
|
|
|
+ Middle,
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 打开
|
|
|
+ /// </summary>
|
|
|
+ Open
|
|
|
+}
|