From 231801ccc3a5d5783835c9ad075a66e1a5af2711 Mon Sep 17 00:00:00 2001 From: Tyrone CT Date: Thu, 27 Nov 2025 18:09:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B9=B2=E5=BA=A62=E7=9A=84=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E5=92=8C=E5=A4=9A=E6=97=A5=E6=9C=9F=E5=8E=86=E5=8F=B2=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=9A=84=E9=80=89=E6=8B=A9=E7=9A=84=E5=A2=9E=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CapMachine.Wpf/Services/PPCService.cs | 126 +++++++++++++++++- .../ViewModels/HistoryDataViewModel.cs | 118 ++++++++++------ CapMachine.Wpf/Views/HistoryDataView.xaml | 32 +++++ CapMachine.Wpf/Views/MonitorView.xaml | 28 +++- 4 files changed, 262 insertions(+), 42 deletions(-) diff --git a/CapMachine.Wpf/Services/PPCService.cs b/CapMachine.Wpf/Services/PPCService.cs index 3b6497c..5a1b1f7 100644 --- a/CapMachine.Wpf/Services/PPCService.cs +++ b/CapMachine.Wpf/Services/PPCService.cs @@ -93,12 +93,19 @@ namespace CapMachine.Wpf.Services { LiqRefFlowTag = LiqRefFlowShortTag!; } + //kg/h if (TagManager.TryGetShortTagByName("冷媒流量[kg/h]", out ShortValueTag? VRVShortTag)) { VRVTag = VRVShortTag!; } + //润滑油流量 + if (TagManager.TryGetShortTagByName("润滑油流量[kg/h]", out ShortValueTag? LubeFlowShortTag)) + { + LubeFlowTag = LubeFlowShortTag!; + } + // 气路阀前 P/T(用于质量流量加权混合焓的计算,LabVIEW 流程) if (TagManager.TryGetShortTagByName("气路阀前压力[BarA]", out ShortValueTag? gasPreP)) { @@ -185,6 +192,15 @@ namespace CapMachine.Wpf.Services /// public ShortValueTag DrynessTag { get; set; } + private double _DrynessTag2Value; + /// + /// 干度2(无量纲 [-]) + /// + public double DrynessTag2Value + { + get { return _DrynessTag2Value; } + set { _DrynessTag2Value = value; RaisePropertyChanged(); } + } /// /// 气路阀前压力(BarA) @@ -207,6 +223,10 @@ namespace CapMachine.Wpf.Services /// public ShortValueTag LiqRefFlowTag { get; set; } + /// + /// 润滑油流量(kg/h) + /// + public ShortValueTag LubeFlowTag { get; set; } /// /// 风量数据-乘以系数的后的最终结果 @@ -274,7 +294,7 @@ namespace CapMachine.Wpf.Services p1 = (TxvFrPressTag.PVModel.EngValue) * 100.0;// 保持你原有流程 //p1 = Convert.ToDouble(textBox3.Text) * 1000.0;//textBox3 Evap.膨胀阀前压力(Mpa) - // 统一放入同一把锁中,避免并发导致的 Fortran 读文件/状态竞态 + // 统一放入同一把锁中,避免并发导致的 Fortran 读文件/状态竞态 string herr = new string(' ', 255); long herrLen = 255; iErr = 0; lock (_refpropLock) { @@ -373,6 +393,26 @@ namespace CapMachine.Wpf.Services // 处理 err } + //计算干度2 + // 气相焓 h_vap_kJkg(由 TPRHO 气相 + THERM) + // 液相焓 h_liq_kJkg(由 TPRHO 液相 + THERM) + // 饱和液 / 气焓 h_l / h_v(由 SATP +THERM) + //气/液质量流量 mg/ml + if (TryComputeDrynessByEnthalpy2( + Gas_kJkgK, Liquid_kJkg,//气相质量焓 h vap [k/kg] 液相质量焓 h liq [kJ/kg] + GasFlowKgPerH, LubeFlowTag.PVModel.EngValue, //气体质量流量 mg [kg/h] 润滑油流量 + LiqRefFlowTag.PVModel.EngValue,// 液体质量流量 ml [kg/h] + Liquid_h_liq, Gas_h_vap, //饱和液质量焓 h liq [kJ/kg] 饱和气质量焓 h vap [kJ/kg] + out var GasValue2, out var hMix2, out var err2)) + { + // x 为最终干度 [0..1],hMix 为混合后比焓 + DrynessTag2Value = GasValue2 * 100.0; + } + else + { + // 处理 err2 + } + } catch (Exception ex) { @@ -902,5 +942,89 @@ namespace CapMachine.Wpf.Services return true; } + + /// + /// 按图片的最终流程计算干度2: + /// 干度2的计算:临时用作为对比使用 + /// 1) 质量流量加权混合焓 h_mix = (h_vap*mg + h_liq*ml) / (mg + ml) + /// 2) 干度 x = (h_mix - h_l) / (h_v - h_l),并限幅到 [0,1] + /// + /// 入参单位: + /// - hVap_kJkg, hLiq_kJkg, hSatL_kJkg, hSatV_kJkg 均为 kJ/kg + /// - mGas_kg_h, mLiq_kg_h 均为 kg/h + /// 返回:true 表示成功,输出 x∈[0,1] 与 h_mix;false 返回 error + /// + /// 气相质量焓 h_vap [kJ/kg] + /// 液相质量焓 h_liq [kJ/kg] + /// 气体质量流量 mg [kg/h] + /// 液体质量流量 ml [kg/h] + /// 饱和液质量焓 h_l [kJ/kg] + /// 饱和气质量焓 h_v [kJ/kg] + /// 输出干度 x ∈ [0,1] + /// 输出混合后总比焓 h_mix [kJ/kg] + /// Err + /// + public bool TryComputeDrynessByEnthalpy2( + double hVap_kJkg, // 气相质量焓 h_vap [kJ/kg] + double hLiq_kJkg, // 液相质量焓 h_liq [kJ/kg] + double mGas_kg_h, // 气体质量流量 mg [kg/h] + double lubeFlow_kg_h, // 润滑油流量 mg [kg/h] + double mLiq_kg_h, // 液体质量流量 ml [kg/h] + double hSatL_kJkg, // 饱和液质量焓 h_l [kJ/kg] + double hSatV_kJkg, // 饱和气质量焓 h_v [kJ/kg] + out double dryness, // 输出干度 x ∈ [0,1] + out double hMix_kJkg, // 输出混合后总比焓 h_mix [kJ/kg] + out string error) + { + dryness = double.NaN; + hMix_kJkg = double.NaN; + error = string.Empty; + + // 1) 合法性校验 + if (double.IsNaN(hVap_kJkg) || double.IsNaN(hLiq_kJkg) || double.IsNaN(hSatL_kJkg) || double.IsNaN(hSatV_kJkg)) + { + error = "输入焓值存在 NaN"; + return false; + } + if (double.IsNaN(mGas_kg_h) || double.IsNaN(mLiq_kg_h)) + { + error = "输入质量流量存在 NaN"; + return false; + } + // 负值处理:小于 0 视为 0(避免传感器噪声或符号错误影响) + //double mg1 = Math.Max(0.0, mGas_kg_h); + double mg = Math.Max(0.0, mGas_kg_h) + Math.Max(0.0, lubeFlow_kg_h); // 这个是改动 气体流量再加上润滑油流量 + double ml = Math.Max(0.0, mLiq_kg_h); + double mSum = mg + ml; + if (mSum <= 0) + { + error = "气液质量流量之和为 0,无法进行加权混合焓计算"; + return false; + } + + // 2) 质量流量加权混合焓(严格按图片:上、下两路相加后除以总流量) + hMix_kJkg = (hVap_kJkg * mg + hLiq_kJkg * ml) / mSum; + + // 3) 干度计算:x = (h_mix - h_l) / (h_v - h_l) + double denom = (hSatV_kJkg - hSatL_kJkg); + const double eps = 1e-9; + if (Math.Abs(denom) < eps) + { + error = "饱和气/液焓差过小,无法计算干度(可能接近临界点或输入异常)"; + return false; + } + + double x = (hMix_kJkg - hSatL_kJkg) / denom; + + // 4) 限幅到 [0,1] + if (double.IsNaN(x) || double.IsInfinity(x)) + { + error = "干度计算结果异常(NaN/Inf)"; + return false; + } + dryness = Math.Min(1.0, Math.Max(0.0, x)); + return true; + } + } } diff --git a/CapMachine.Wpf/ViewModels/HistoryDataViewModel.cs b/CapMachine.Wpf/ViewModels/HistoryDataViewModel.cs index 66152ea..36132d6 100644 --- a/CapMachine.Wpf/ViewModels/HistoryDataViewModel.cs +++ b/CapMachine.Wpf/ViewModels/HistoryDataViewModel.cs @@ -132,6 +132,20 @@ namespace CapMachine.Wpf.ViewModels set { _IsLeftDrawerOpen = value; RaisePropertyChanged(); } } + private bool _IsBusy; + public bool IsBusy + { + get { return _IsBusy; } + set { _IsBusy = value; RaisePropertyChanged(); } + } + + private string _BusyMessage = "正在加载,请稍候..."; + public string BusyMessage + { + get { return _BusyMessage; } + set { _BusyMessage = value; RaisePropertyChanged(); } + } + /// @@ -417,7 +431,7 @@ namespace CapMachine.Wpf.ViewModels /// /// 获取试验数据的命令的执行方法 /// - private void HistoryDataFileCmdMethod() + private async void HistoryDataFileCmdMethod() { if (SelectedHistoryExp == null) { @@ -449,58 +463,82 @@ namespace CapMachine.Wpf.ViewModels return; } - CsvRecordModels = new List(); + BusyMessage = "正在加载CSV数据,请稍候..."; + IsBusy = true; + + var loaded = new List(); + string errorText = string.Empty; + stopwatch.Start(); - var errors = new StringBuilder(); - foreach (var f in files) + try { - try + await Task.Run(() => { - if (f == null) continue; - if (string.IsNullOrWhiteSpace(f.FilePath)) + var errors = new StringBuilder(); + for (int i = 0; i < files.Count; i++) { - errors.AppendLine("发现空的文件地址"); - continue; - } - if (!File.Exists(f.FilePath)) - { - errors.AppendLine($"没有发现地址对应的文件: {f.FilePath}"); - continue; - } + var f = files[i]; + try + { + Application.Current.Dispatcher.Invoke(() => + { + BusyMessage = $"正在加载({i + 1}/{files.Count}):{System.IO.Path.GetFileName(f?.FilePath)}"; + }); - var rec = ReadCsvFile(f.FilePath); - if (rec != null && rec.Count > 0) - { - CsvRecordModels.AddRange(rec); + if (f == null) continue; + if (string.IsNullOrWhiteSpace(f.FilePath)) + { + errors.AppendLine("发现空的文件地址"); + continue; + } + if (!File.Exists(f.FilePath)) + { + errors.AppendLine($"没有发现地址对应的文件: {f.FilePath}"); + continue; + } + + var rec = ReadCsvFile(f.FilePath); + if (rec != null && rec.Count > 0) + { + loaded.AddRange(rec); + } + } + catch (Exception ex) + { + errors.AppendLine($"读取CSV失败: {ex.Message}"); + } } - } - catch (Exception ex) + errorText = errors.ToString(); + }); + + if (!string.IsNullOrWhiteSpace(errorText)) { - errors.AppendLine($"读取CSV失败: {ex.Message}"); + System.Windows.MessageBox.Show(errorText, "读取提示", MessageBoxButton.OK, MessageBoxImage.Warning); + } + + CsvRecordModels = new List(); + if (loaded != null && loaded.Count > 0) + { + CsvRecordModels = loaded + .Where(r => r != null) + .OrderBy(r => r.CreateTime) + .ToList(); + Application.Current.Dispatcher.Invoke(() => + { + EventAggregator.GetEvent().Publish(new HistoryDataToChartMsg() { Machine = "History", Data = CsvRecordModels }); + }); } } - - if (errors.Length > 0) + finally { - System.Windows.MessageBox.Show(errors.ToString(), "读取提示", MessageBoxButton.OK, MessageBoxImage.Warning); + stopwatch.Stop(); + Console.WriteLine("加载CSV数据耗时::{0}", stopwatch.Elapsed.TotalSeconds.ToString()); + stopwatch.Reset(); + IsBusy = false; + IsLeftDrawerOpen = false; } - if (CsvRecordModels.Count > 0) - { - CsvRecordModels = CsvRecordModels - .Where(r => r != null) - .OrderBy(r => r.CreateTime) - .ToList(); - EventAggregator.GetEvent().Publish(new HistoryDataToChartMsg() { Machine = "History", Data = CsvRecordModels }); - } - - stopwatch.Stop(); - Console.WriteLine("加载CSV数据耗时::{0}", stopwatch.Elapsed.TotalSeconds.ToString()); - stopwatch.Reset(); - - IsLeftDrawerOpen = false; - } private List ReadCsvFile(string filePath) diff --git a/CapMachine.Wpf/Views/HistoryDataView.xaml b/CapMachine.Wpf/Views/HistoryDataView.xaml index 03dfafe..c2e6860 100644 --- a/CapMachine.Wpf/Views/HistoryDataView.xaml +++ b/CapMachine.Wpf/Views/HistoryDataView.xaml @@ -26,6 +26,7 @@ + + + + + + + + + + + + + + diff --git a/CapMachine.Wpf/Views/MonitorView.xaml b/CapMachine.Wpf/Views/MonitorView.xaml index 33b593b..d80a3a8 100644 --- a/CapMachine.Wpf/Views/MonitorView.xaml +++ b/CapMachine.Wpf/Views/MonitorView.xaml @@ -211,7 +211,7 @@ + + + + + + + +