diff --git a/Cardiopulmonarybypasssystems/MainWindow.xaml b/Cardiopulmonarybypasssystems/MainWindow.xaml
index b9ae8de..c2d0dd9 100644
--- a/Cardiopulmonarybypasssystems/MainWindow.xaml
+++ b/Cardiopulmonarybypasssystems/MainWindow.xaml
@@ -204,29 +204,27 @@
TextWrapping="Wrap" />
-
-
-
-
-
-
-
-
+ ToolTip="{Binding StartActionHint}" />
+
+
diff --git a/Cardiopulmonarybypasssystems/Models/PumpControlChannel.cs b/Cardiopulmonarybypasssystems/Models/PumpControlChannel.cs
index b81b9e4..921bb68 100644
--- a/Cardiopulmonarybypasssystems/Models/PumpControlChannel.cs
+++ b/Cardiopulmonarybypasssystems/Models/PumpControlChannel.cs
@@ -198,6 +198,19 @@ public partial class PumpControlChannel : ObservableObject
: PendingRs485RunningState == true || IsRunning
? "停止"
: "启动";
+ public bool CanStartRs485Action => !IsRs485Busy
+ && PendingRs485RunningState != true
+ && !IsRunning
+ && HasConfirmedSetpointCalibration;
+ public bool CanStopRs485Action => !IsRs485Busy;
+ public string StartActionHint => IsRs485Busy
+ ? "RS485 操作中"
+ : PendingRs485RunningState == true || IsRunning
+ ? "泵已在运行"
+ : HasConfirmedSetpointCalibration
+ ? string.Empty
+ : "未配置流量换算系数";
+ public string StopActionHint => IsRs485Busy ? "RS485 操作中" : string.Empty;
public bool CanToggleRs485Action => PendingRs485RunningState == true || IsRunning || HasConfirmedSetpointCalibration;
public string ToggleActionHint => PendingRs485RunningState == true
? "启动确认中,可执行停止"
@@ -215,6 +228,10 @@ public partial class PumpControlChannel : ObservableObject
OnPropertyChanged(nameof(StateHint));
OnPropertyChanged(nameof(IndicatorColor));
OnPropertyChanged(nameof(ActionText));
+ OnPropertyChanged(nameof(CanStartRs485Action));
+ OnPropertyChanged(nameof(CanStopRs485Action));
+ OnPropertyChanged(nameof(StartActionHint));
+ OnPropertyChanged(nameof(StopActionHint));
OnPropertyChanged(nameof(CanToggleRs485Action));
OnPropertyChanged(nameof(ToggleActionHint));
OnPropertyChanged(nameof(CardPrimaryDisplay));
@@ -267,6 +284,8 @@ public partial class PumpControlChannel : ObservableObject
OnPropertyChanged(nameof(HasSetpointCalibration));
OnPropertyChanged(nameof(HasConfirmedSetpointCalibration));
OnPropertyChanged(nameof(CalibrationStatusText));
+ OnPropertyChanged(nameof(CanStartRs485Action));
+ OnPropertyChanged(nameof(StartActionHint));
OnPropertyChanged(nameof(CanToggleRs485Action));
OnPropertyChanged(nameof(ToggleActionHint));
OnPropertyChanged(nameof(SetpointReadbackDisplay));
@@ -276,6 +295,8 @@ public partial class PumpControlChannel : ObservableObject
{
OnPropertyChanged(nameof(HasConfirmedSetpointCalibration));
OnPropertyChanged(nameof(CalibrationStatusText));
+ OnPropertyChanged(nameof(CanStartRs485Action));
+ OnPropertyChanged(nameof(StartActionHint));
OnPropertyChanged(nameof(CanToggleRs485Action));
OnPropertyChanged(nameof(ToggleActionHint));
}
@@ -284,6 +305,8 @@ public partial class PumpControlChannel : ObservableObject
{
OnPropertyChanged(nameof(HasConfirmedSetpointCalibration));
OnPropertyChanged(nameof(CalibrationStatusText));
+ OnPropertyChanged(nameof(CanStartRs485Action));
+ OnPropertyChanged(nameof(StartActionHint));
OnPropertyChanged(nameof(CanToggleRs485Action));
OnPropertyChanged(nameof(ToggleActionHint));
}
@@ -319,6 +342,10 @@ public partial class PumpControlChannel : ObservableObject
OnPropertyChanged(nameof(StateText));
OnPropertyChanged(nameof(StateHint));
OnPropertyChanged(nameof(ActionText));
+ OnPropertyChanged(nameof(CanStartRs485Action));
+ OnPropertyChanged(nameof(CanStopRs485Action));
+ OnPropertyChanged(nameof(StartActionHint));
+ OnPropertyChanged(nameof(StopActionHint));
OnPropertyChanged(nameof(CanToggleRs485Action));
OnPropertyChanged(nameof(ToggleActionHint));
}
@@ -327,6 +354,10 @@ public partial class PumpControlChannel : ObservableObject
{
OnPropertyChanged(nameof(StateHint));
OnPropertyChanged(nameof(ActionText));
+ OnPropertyChanged(nameof(CanStartRs485Action));
+ OnPropertyChanged(nameof(CanStopRs485Action));
+ OnPropertyChanged(nameof(StartActionHint));
+ OnPropertyChanged(nameof(StopActionHint));
OnPropertyChanged(nameof(Rs485ReadActionText));
OnPropertyChanged(nameof(Rs485WriteActionText));
OnPropertyChanged(nameof(SetpointStatusForeground));
diff --git a/Cardiopulmonarybypasssystems/Models/ValveControlChannel.cs b/Cardiopulmonarybypasssystems/Models/ValveControlChannel.cs
index 7fc68aa..224d5b6 100644
--- a/Cardiopulmonarybypasssystems/Models/ValveControlChannel.cs
+++ b/Cardiopulmonarybypasssystems/Models/ValveControlChannel.cs
@@ -15,10 +15,10 @@ public partial class ValveControlChannel : ObservableObject
private bool stateAvailable;
public string StateText => !StateAvailable ? "未知" : IsOpen ? "开启" : "关闭";
- public string ActionText => IsOpen ? "关闭阀门" : "开启阀门";
+ public string ActionText => IsOpen ? "关闭" : "开启";
public string IndicatorColor => !StateAvailable ? "#FF94A6AE" : IsOpen ? "#FF32B06A" : "#FFC8D4DA";
- public string StateHint => !StateAvailable ? "未取得 PLC 状态" : IsOpen ? "测试回路已导通" : "测试回路已关闭";
- public bool HideRealtimeCardStateDescription => Key is "TestLoopValve1" or "TestLoopValve2";
+ public string StateHint => !StateAvailable ? "未取得 PLC 状态" : $"{Name}已{StateText}";
+ public bool HideRealtimeCardStateDescription => Key is "TestLoopValve1" or "TestLoopValve2" or "CirculatingWaterTemperature";
partial void OnIsOpenChanged(bool value)
{
diff --git a/Cardiopulmonarybypasssystems/Services/ModbusTelemetryService.cs b/Cardiopulmonarybypasssystems/Services/ModbusTelemetryService.cs
index 2eb6ad9..b065aa1 100644
--- a/Cardiopulmonarybypasssystems/Services/ModbusTelemetryService.cs
+++ b/Cardiopulmonarybypasssystems/Services/ModbusTelemetryService.cs
@@ -82,7 +82,8 @@ public sealed class ModbusTelemetryService : IModbusTelemetryService, IDisposabl
private readonly List _valveControls =
[
new() { Key = "TestLoopValve1", Name = "测试回路阀 1", StartAddress = 10 },
- new() { Key = "TestLoopValve2", Name = "测试回路阀 2", StartAddress = 11 }
+ new() { Key = "TestLoopValve2", Name = "测试回路阀 2", StartAddress = 11 },
+ new() { Key = "CirculatingWaterTemperature", Name = "循环水温", StartAddress = 12 }
];
private TcpClient? _tcpClient;
diff --git a/Cardiopulmonarybypasssystems/ViewModels/MainViewModel.Rs485.cs b/Cardiopulmonarybypasssystems/ViewModels/MainViewModel.Rs485.cs
index 711f415..d96a4dc 100644
--- a/Cardiopulmonarybypasssystems/ViewModels/MainViewModel.Rs485.cs
+++ b/Cardiopulmonarybypasssystems/ViewModels/MainViewModel.Rs485.cs
@@ -688,6 +688,33 @@ public partial class MainViewModel
await TryWriteAndStartPumpCore(pump, "RS485 快捷启动");
}
+ [RelayCommand]
+ private async Task StartSingleRs485Pump(PumpControlChannel? pump)
+ {
+ if (pump is null)
+ {
+ return;
+ }
+
+ await TryWriteAndStartPumpCore(pump, "RS485 单泵启动");
+ }
+
+ [RelayCommand]
+ private async Task StopSingleRs485Pump(PumpControlChannel? pump)
+ {
+ if (pump is null)
+ {
+ return;
+ }
+
+ if (!EnsureSessionEditable("RS485 单泵停止"))
+ {
+ return;
+ }
+
+ await TryTogglePumpControlViaRs485(pump, nextState: false);
+ }
+
[RelayCommand]
private async Task StartAllRs485Pumps()
{