using CapMachine.Core;
using CapMachine.Wpf.Models.PPCalc;
using CapMachine.Wpf.Models.Tag;
using CapMachine.Wpf.PPCalculation;
using Prism.Mvvm;
using System;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Services
{
///
/// 鐗╂€ц绠楃殑鏈嶅姟
///
public class PPCService : BindableBase
{
///
/// 璁$畻鎵弿 Task
///
private static Task CalcTask { get; set; } = Task.CompletedTask;
public ConfigService ConfigService { get; }
public ILogService Logger { get; }
public MachineRtDataService MachineRtDataService { get; }
private readonly EnthalpyDrynessCalculator _enthalpyDrynessCalculator;
private readonly ThermodynamicSixResultsCalculator _thermodynamicSixResultsCalculator;
private readonly SuperheatSubcoolCalculator _superheatSubcoolCalculator;
///
/// 鏍囩涓績
///
public TagManager TagManager { get; set; }
///
/// 瀹炰緥鍖? ///
public PPCService(ConfigService configService, ILogService logService,
MachineRtDataService machineRtDataService)
{
ConfigService = configService;
Logger = logService;
MachineRtDataService = machineRtDataService;
_enthalpyDrynessCalculator = new EnthalpyDrynessCalculator(_refpropLock);
_thermodynamicSixResultsCalculator = new ThermodynamicSixResultsCalculator(_refpropLock);
_superheatSubcoolCalculator = new SuperheatSubcoolCalculator(_refpropLock);
TagManager = MachineRtDataService.TagManger;
if (TagManager.TryGetShortTagByName("杞€焄rpm]", out ShortValueTag? speedShortTag))
{
SpeedTag = speedShortTag!;
}
if (TagManager.TryGetShortTagByName("鎺掓皵鍘嬪姏[BarA]", out ShortValueTag? exPressShortTag))
{
ExPressTag = exPressShortTag!;
}
if (TagManager.TryGetShortTagByName("鎺掓皵娓╁害[鈩僝", out ShortValueTag? exTempShortTag))
{
ExTempTag = exTempShortTag!;
}
if (TagManager.TryGetShortTagByName("HV[W]", out ShortValueTag? hvPwShortTag))
{
HVPwTag = hvPwShortTag!;
}
if (TagManager.TryGetShortTagByName("鍚告皵鍘嬪姏[BarA]", out ShortValueTag? InhPressShortControlTag))
{
InhPressTag = InhPressShortControlTag!;
}
if (TagManager.TryGetShortTagByName("鍚告皵娓╁害[鈩僝", out ShortValueTag? InhTempShortControlTag))
{
InhTempTag = InhTempShortControlTag!;
}
//InhTempTag = TagManager.DicTags.GetValueOrDefault("鍚告皵娓╁害[鈩僝")!;
//ComCapBusVolTag = TagManager.DicTags.GetValueOrDefault("閫氳姣嶇嚎鐢靛帇[V]");
//ComCapBusCurTag = TagManager.DicTags.GetValueOrDefault("閫氳姣嶇嚎鐢垫祦[A]");
//ComCapPwTag = TagManager.DicTags.GetValueOrDefault("閫氳鍔熺巼[W]");
//OS2TempTag = TagManager.DicTags.GetValueOrDefault("鍚告皵娣峰悎鍣ㄦ俯搴鈩僝");
//TxvFrTempTag = TagManager.DicTags.GetValueOrDefault("鑶ㄨ儉闃€鍓嶆俯搴鈩僝")!;
//TxvFrPressTag = TagManager.DicTags.GetValueOrDefault("鑶ㄨ儉闃€鍓嶅帇鍔沎BarA]")!;
if (TagManager.TryGetShortTagByName("SUBCOOL鍑哄彛娓╁害[鈩僝", out ShortValueTag? TxvFrTempShortTag))
{
TxvFrTempTag = TxvFrTempShortTag!;
}
if (TagManager.TryGetShortTagByName("鑶ㄨ儉闃€鍓嶅帇鍔沎BarA]", out ShortValueTag? TxvFrPressShortTag))
{
TxvFrPressTag = TxvFrPressShortTag!;
}
if (TagManager.TryGetShortTagByName("娑插喎濯掓祦閲廩kg/h]", out ShortValueTag? LiqRefFlowShortTag))
{
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))
{
GasPreValvePressTag = gasPreP!;
}
if (TagManager.TryGetShortTagByName("姘旇矾闃€鍓嶆俯搴鈩僝", out ShortValueTag? gasPreT))
{
GasPreValveTempTag = gasPreT!;
}
//Cond1TempTag = TagManager.DicTags.GetValueOrDefault("鍐峰嚌鍣ㄥ嚭鍙f按娓鈩僝");
//CondInTempTag = TagManager.DicTags.GetValueOrDefault("鍐峰嚌鍣ㄨ繘鍙f俯搴鈩僝");
//Superheat = TagManager.DicTags.GetValueOrDefault("杩囩儹搴K]");
//Subcool = TagManager.DicTags.GetValueOrDefault("杩囧喎搴K]");
if (TagManager.TryGetShortTagByName("杩囩儹搴K]", out ShortValueTag? SuperheatShortTag))
{
Superheat = SuperheatShortTag!;
}
if (TagManager.TryGetShortTagByName("杩囧喎搴K]", out ShortValueTag? SubcoolShortTag))
{
Subcool = SubcoolShortTag!;
}
// 骞插害鏍囩锛堝涓嶅瓨鍦ㄥ垯浠呰烦杩囧啓鍏ワ紝涓嶆姏寮傚父锛夈€備紭鍏堜娇鐢ㄢ€滃共搴%]鈥濓紝鍏舵鈥滃共搴-]鈥濄€? if (TagManager.TryGetShortTagByName("骞插害[-]", out ShortValueTag? drynessPct))
{
DrynessTag = drynessPct!;
}
if (TagManager.TryGetShortTagByName("鍒剁儹閲廞h[W]", out ShortValueTag? heatingCapacityTag))
{
HeatingCapacityTag = heatingCapacityTag!;
}
if (TagManager.TryGetShortTagByName("鍘嬬缉鏈烘€ц兘绯绘暟(鍒剁儹COP)", out ShortValueTag? copHeatTag))
{
COPHeatTag = copHeatTag!;
}
if (TagManager.TryGetShortTagByName("绛夌喌鏁堢巼ns[%]", out ShortValueTag? isentrpEffTag))
{
IsentrpEffTag = isentrpEffTag!;
}
if (TagManager.TryGetShortTagByName("鍒跺喎閲廞c[W]", out ShortValueTag? coolCapacityTag))
{
CoolCapacityTag = coolCapacityTag!;
}
if (TagManager.TryGetShortTagByName("鍘嬬缉鏈烘€ц兘绯绘暟(鍒跺喎COP)", out ShortValueTag? copCoolTag))
{
COPCoolTag = copCoolTag!;
}
if (TagManager.TryGetShortTagByName("瀹圭Н鏁堢巼nv[%]", out ShortValueTag? voltricEffTag))
{
VoltricEffTag = voltricEffTag!;
}
SuperHeatCoolConfig.FluidsPath = ConfigHelper.GetValue("FluidsPath");
SuperHeatCoolConfig.Cryogen = ConfigHelper.GetValue("Cryogen");
ReloadTherdyH3TempOffset();
// 璁㈤槄 ConfigService.CurExpInfo 灞炴€у彉鍖栵紝瀹為獙鍒囨崲鏃惰嚜鍔ㄥ埛鏂版帓閲忕紦瀛? ConfigService.PropertyChanged += (sender, e) =>
{
if (e.PropertyName == nameof(ConfigService.CurExpInfo))
{
RefreshDisplacementCache();
}
};
// 棣栨鍒濆鍖栨帓閲忕紦瀛橈紙鍦ㄨ闃呬簨浠跺墠鍒濆鍖栵紝閬垮厤棣栨瑙﹀彂涓嶅繀瑕佺殑鍒锋柊锛? RefreshDisplacementCache();
RtScanDeviceStart();
}
///
/// 褰撳墠鐨勯厤缃? ///
public SuperHeatCoolConfigModel SuperHeatCoolConfig { get; set; } = new SuperHeatCoolConfigModel();
private const string TherdyH3TempOffsetConfigKey = "Therdy_H3TempOffset_C";
private double _therdyH3TempOffset_C = -10.0;
public double TherdyH3TempOffset_C
{
get { return _therdyH3TempOffset_C; }
private set
{
_therdyH3TempOffset_C = value;
RaisePropertyChanged();
}
}
///
/// 淇濆瓨閰嶇疆淇℃伅
///
public void SaveSuperHeatCoolConfig()
{
ConfigHelper.SetValue("FluidsPath", SuperHeatCoolConfig.FluidsPath ?? string.Empty);
ConfigHelper.SetValue("Cryogen", SuperHeatCoolConfig.Cryogen ?? string.Empty);
}
public void ReloadTherdyH3TempOffset()
{
double offsetC = -10.0;
try
{
string raw = ConfigHelper.GetValue(TherdyH3TempOffsetConfigKey);
if (!string.IsNullOrWhiteSpace(raw) && double.TryParse(raw, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsed))
{
offsetC = parsed;
}
}
catch
{
}
TherdyH3TempOffset_C = offsetC;
_thermodynamicSixResultsCalculator.SetH3TempOffset_C(offsetC);
}
///
/// 鍚告皵鍘嬪姏
///
public ShortValueTag InhPressTag { get; set; } = null!;
///
/// 杞€熸爣绛? ///
public ShortValueTag? SpeedTag { get; set; }
///
/// 鎺掓皵鍘嬪姏
///
public ShortValueTag? ExPressTag { get; set; }
///
/// 鎺掓皵娓╁害
///
public ShortValueTag? ExTempTag { get; set; }
///
/// 鍘嬬缉鏈哄姛鐜囷紙HV 鐢垫簮锛? ///
public ShortValueTag? HVPwTag { get; set; }
///
/// 鍚告皵娓╁害
///
public ShortValueTag InhTempTag { get; set; } = null!;
///
/// 娑蹭綋闃€鍓嶆俯搴? ///
public ShortValueTag TxvFrTempTag { get; set; } = null!;
///
/// 娑蹭綋闃€鍓嶅帇鍔? ///
public ShortValueTag TxvFrPressTag { get; set; } = null!;
///
/// 杩囩儹搴? ///
public ShortValueTag Superheat { get; set; } = null!;
///
/// 杩囧喎搴? ///
public ShortValueTag Subcool { get; set; } = null!;
///
/// 骞插害锛堟棤閲忕翰 [-]锛? ///
public ShortValueTag DrynessTag { get; set; } = null!;
public ShortValueTag? HeatingCapacityTag { get; set; }
public ShortValueTag? COPHeatTag { get; set; }
public ShortValueTag? IsentrpEffTag { get; set; }
public ShortValueTag? CoolCapacityTag { get; set; }
public ShortValueTag? COPCoolTag { get; set; }
public ShortValueTag? VoltricEffTag { get; set; }
private double _DrynessTag2Value;
///
/// 骞插害2锛堟棤閲忕翰 [-]锛? ///
public double DrynessTag2Value
{
get { return _DrynessTag2Value; }
set { _DrynessTag2Value = value; RaisePropertyChanged(); }
}
///
/// 姘旇矾闃€鍓嶅帇鍔涳紙BarA锛? ///
public ShortValueTag GasPreValvePressTag { get; set; } = null!;
///
/// 姘旇矾闃€鍓嶆俯搴︼紙鈩冿級
///
public ShortValueTag GasPreValveTempTag { get; set; } = null!;
///
/// 鍐峰獟娴侀噺kg/h
/// 姘斾綋娴侀噺+娑蹭綋娴侀噺=鍐峰獟娴侀噺
///
public ShortValueTag VRVTag { get; set; } = null!;
///
/// 娑蹭綋娴侀噺锛坘g/h锛? /// 娑插喎濯掓祦閲弅g/h=娑蹭綋娴侀噺kg/h
///
public ShortValueTag LiqRefFlowTag { get; set; } = null!;
///
/// 娑︽粦娌规祦閲忥紙kg/h锛? ///
public ShortValueTag LubeFlowTag { get; set; } = null!;
///
/// 鍚敤璁$畻
///
private bool RtCalcEnable { get; set; } = true;
///
/// PLC鎵弿绾跨▼
///
private void RtScanDeviceStart()
{
CalcTask = Task.Run(async () =>
{
while (RtCalcEnable)
{
await Task.Delay(100);
try
{
double[] x = new double[20];
double wm = 0.0;
// 骞傜瓑鍒濆鍖栵細浠呴娆℃垨宸ヨ川/璺緞鍙樺寲鏃舵墽琛?SETPATH/SETUP锛屾彁楂樻瘡绉掑惊鐜晥鐜? if (!EnsureRefpropInitialized(out var initErr))
{
// 鍒濆鍖栧け璐ワ紝璺宠繃鏈懆鏈? Logger?.Error($"REFPROP 鍒濆鍖栧け璐? {initErr}");
continue;
}
// WMOL 浠呭湪闇€瑕佹椂璋冪敤锛涜嫢璋冪敤锛岄渶璁剧疆 x[0]=1.0锛堢函宸ヨ川锛? x[0] = 1.0;
IRefProp64.WMOLdll(x, ref wm);
UpdateSuperheatAndSubcool_BySatp();
//杩欓噷鍐欐骞插害鐨勮緭鍏ユ暟鎹?
double gasPreValvePressBarA = GasPreValvePressTag.PVModel.EngValue;
double gasPreValveTempC = GasPreValveTempTag.PVModel.EngValue;
double txvFrPressBarA = TxvFrPressTag.PVModel.EngValue;
double txvFrTempC = TxvFrTempTag.PVModel.EngValue;
double inhPressBarA = InhPressTag.PVModel.EngValue;
double vrvFlowKgPerH = VRVTag.PVModel.EngValue;
double liqRefFlowKgPerH = LiqRefFlowTag.PVModel.EngValue;
double lubeFlowKgPerH = 0.0;
//骞插害鎶€鏈?
var drynessResult = _enthalpyDrynessCalculator.Calculate(
new EnthalpyDrynessCalculator.Input(
gasPreValvePressBarA,
gasPreValveTempC,
txvFrPressBarA,
txvFrTempC,
inhPressBarA,
vrvFlowKgPerH,
liqRefFlowKgPerH,
lubeFlowKgPerH));
//浠ュ墠浼氬彈 LubeFlowTag 褰卞搷锛岀幇鍦ㄧ敱浜庡浐瀹氫负 0锛屼細涓?Dryness1 鏇存帴杩?涓€鑷达紙鍙涓よ€呭叕寮忓樊寮備粎鍦ㄦ补杩欎竴椤癸級
if (drynessResult.IsDryness1Success)
{
if (DrynessTag != null)
{
//DrynessTag.PVModel.EngValue = drynessResult.Dryness1_01 * 100.0;
DrynessTag.PVModel.EngValue = Math.Round(drynessResult.Dryness1_01, 4);
}
//DrynessTag2Value = drynessResult.Dryness1_01 * 100.0;
//if (drynessResult.Dryness1_01 <= 0)
//{
// LogDrynessSnapshotIfNeeded(
// "TryComputeDrynessByEnthalpy(SuccessButZero)",
// string.Empty,
// drynessResult.Dryness1_01,
// drynessResult.HMix1_kJkg,
// drynessResult.GasEnthalpy_kJkg,
// drynessResult.LiquidEnthalpy_kJkg,
// drynessResult.SatLiquidEnthalpy_kJkg,
// drynessResult.SatVaporEnthalpy_kJkg,
// drynessResult.GasFlowKgPerH,
// 0,
// LiqRefFlowTag.PVModel.EngValue);
//}
}
else
{
//LogDrynessSnapshotIfNeeded(
// "TryComputeDrynessByEnthalpy(Fail)",
// drynessResult.Error1,
// double.NaN,
// double.NaN,
// drynessResult.GasEnthalpy_kJkg,
// drynessResult.LiquidEnthalpy_kJkg,
// drynessResult.SatLiquidEnthalpy_kJkg,
// drynessResult.SatVaporEnthalpy_kJkg,
// drynessResult.GasFlowKgPerH,
// 0,
// LiqRefFlowTag.PVModel.EngValue);
}
if (drynessResult.IsDryness2Success)
{
//DrynessTag.PVModel.EngValue = drynessResult.Dryness2_01 * 100.0;
DrynessTag2Value = Math.Round(drynessResult.Dryness2_01,4) ;
//if (drynessResult.Dryness2_01 <= 0)
//{
// LogDrynessSnapshotIfNeeded(
// "TryComputeDrynessByEnthalpy2(SuccessButZero)",
// string.Empty,
// drynessResult.Dryness2_01,
// drynessResult.HMix2_kJkg,
// drynessResult.GasEnthalpy_kJkg,
// drynessResult.LiquidEnthalpy_kJkg,
// drynessResult.SatLiquidEnthalpy_kJkg,
// drynessResult.SatVaporEnthalpy_kJkg,
// drynessResult.GasFlowKgPerH,
// LubeFlowTag.PVModel.EngValue,
// LiqRefFlowTag.PVModel.EngValue);
//}
}
else
{
//LogDrynessSnapshotIfNeeded(
// "TryComputeDrynessByEnthalpy2(Fail)",
// drynessResult.Error2,
// double.NaN,
// double.NaN,
// drynessResult.GasEnthalpy_kJkg,
// drynessResult.LiquidEnthalpy_kJkg,
// drynessResult.SatLiquidEnthalpy_kJkg,
// drynessResult.SatVaporEnthalpy_kJkg,
// drynessResult.GasFlowKgPerH,
// LubeFlowTag.PVModel.EngValue,
// LiqRefFlowTag.PVModel.EngValue);
}
#if DEBUG
//DebugRunThermoValidationCase_UsingCalculator_FromScreenshot_20260423();
//DebugRunDrynessValidationCase_FromScreenshot_20260425();
//DebugRunThermoValidationCase_UsingCalculator_FromScreenshot_20260428();
#endif
if (TryUpdateThermodynamicSixResults(out var thermoErr))
{
if (!string.IsNullOrWhiteSpace(thermoErr))
{
//Logger?.Warn($"鍏釜鐗╂€х粨鏋滆绠楄鍛? {thermoErr}");
}
}
else
{
if (!string.IsNullOrWhiteSpace(thermoErr))
{
//Logger?.Error($"鍏釜鐗╂€х粨鏋滆绠楀け璐? {thermoErr}");
}
}
}
catch (Exception ex)
{
Logger.Error(String.Format("ErrSource : {0} ErrMsg : {1}", ex.StackTrace ?? string.Empty, ex.Message));
}
}
});
}
private void UpdateSuperheatAndSubcool_BySatp()
{
_superheatSubcoolCalculator.Calculate(
inhPressBarA: InhPressTag.PVModel.EngValue,
inhTempC: InhTempTag.PVModel.EngValue,
txvFrPressBarA: TxvFrPressTag.PVModel.EngValue,
txvFrTempC: TxvFrTempTag.PVModel.EngValue,
out var superheatK,
out var subcoolK);
Superheat.PVModel.EngValue = superheatK;
Subcool.PVModel.EngValue = subcoolK;
}
// 鑻ョ被涓皻鏈畾涔夛紝璇锋坊鍔犲叏灞€浜掓枼閿侊紝涓茶鍖栨墍鏈?REFPROP 璋冪敤
private static readonly object _refpropLock = new object();
// REFPROP 鍒濆鍖栫姸鎬侊紙鍏ㄥ眬銆佸箓绛夛級
private static volatile bool _rpInitialized = false;
///
/// 骞傜瓑鍒濆鍖栵細璁剧疆娴佷綋璺緞/宸ヨ川/鍙傝€冩€侊紱纭繚鍏ㄥ眬鍙垵濮嬪寲涓€娆°€? /// 娉ㄦ剰锛氭墍鏈?REFPROP 鍘熺敓璋冪敤閮介渶鍦?_refpropLock 涓嬩覆琛屽寲锛屽寘鎷垵濮嬪寲璋冪敤銆? ///
private bool EnsureRefpropInitialized(out string error)
{
error = string.Empty;
if (_rpInitialized) return true;
try
{
lock (_refpropLock)
{
if (_rpInitialized) return true; // 鍙屾锛岄伩鍏嶅苟鍙戜簩娆″垵濮嬪寲
string hpath = ConfigHelper.GetValue("FluidsPath");
if (string.IsNullOrWhiteSpace(hpath)) hpath = @".\PPCalculation\REFPROP\FLUIDS";
string configuredCryogen = ConfigHelper.GetValue("Cryogen");
if (string.IsNullOrWhiteSpace(configuredCryogen)) configuredCryogen = "R134a";
// 鐜伴樁娈典粎浣跨敤 R134A.FLD锛涘闇€鎵╁睍锛屽彲鏍规嵁 configuredCryogen 閫夋嫨涓嶅悓鏂囦欢
string hfldCore = configuredCryogen.Equals("R134a", StringComparison.OrdinalIgnoreCase)
? "R134A.FLD"
: "R134A.FLD";
long size = hpath.Length;
string hpathPadded = hpath + new string(' ', Math.Max(0, 255 - (int)size));
IRefProp64.SETPATHdll(hpathPadded, ref size);
long numComps = 1;
string hfld = hfldCore;
size = hfld.Length;
string hfldPadded = hfld + new string(' ', Math.Max(0, 10000 - (int)size));
string hfmix = "hmx.bnc" + new string(' ', 255);
string hrf = "DEF";
string herr = new string(' ', 255);
long ierr = 0;
long hfldLen = hfldPadded.Length, hfmixLen = hfmix.Length, hrfLen = hrf.Length, herrLen = herr.Length;
IRefProp64.SETUPdll(ref numComps, ref hfldPadded, ref hfmix, ref hrf,
ref ierr, ref herr, ref hfldLen, ref hfmixLen, ref hrfLen, ref herrLen);
if (ierr != 0)
{
error = $"REFPROP 鍒濆鍖栧け璐? {herr.Trim()} (ierr={ierr})";
_rpInitialized = false;
return false;
}
_rpInitialized = true;
return true;
}
}
catch (Exception ex)
{
error = $"REFPROP 鍒濆鍖栧紓甯? {ex.Message}";
Logger.Error(error);
_rpInitialized = false;
return false;
}
}
///鍒剁儹閲忋€佸帇缂╂満鎬ц兘绯绘暟COP锛堝埗鐑級銆佺瓑鐔垫晥鐜囥€佸埗鍐烽噺銆佸帇缂╂満鎬ц兘绯绘暟COP(鍒跺喎)銆佸绉晥鐜? 璁$畻
#region
///
/// 缂撳瓨鐨勫帇缂╂満鎺掗噺鍊硷紙cc锛夛紝鍦ㄥ疄楠屽垏鎹㈡椂鑷姩鍒锋柊
///
private double _cachedDisplacement_cc = double.NaN;
///
/// 缂撳瓨鏁版嵁鏉ユ簮鏍囪瘑锛堢敤浜庤皟璇曪級锛欵xpInfo=瀹為獙淇℃伅, Config=閰嶇疆鏂囦欢, Default=榛樿鍊? ///
private string _cachedSource = string.Empty;
private int _CurDisplacementCc;
///
/// 褰撳墠鐨勬帓閲忎俊鎭紙渚?UI 灞曠ず锛? ///
public int CurDisplacementCc
{
get { return _CurDisplacementCc; }
set { _CurDisplacementCc = value; RaisePropertyChanged(); }
}
private double _HeatingCapacityQh_kW;
///
/// 鍒剁儹閲?Qh [kW]
///
public double HeatingCapacityQh_kW
{
get { return _HeatingCapacityQh_kW; }
set { _HeatingCapacityQh_kW = value; RaisePropertyChanged(); }
}
private double _COPHeating;
///
/// 鍘嬬缉鏈烘€ц兘绯绘暟 COP锛堝埗鐑級[-]
///
public double COPHeating
{
get { return _COPHeating; }
set { _COPHeating = value; RaisePropertyChanged(); }
}
private double _IsentropicEfficiencyPct;
///
/// 绛夌喌鏁堢巼 畏s [%]
///
public double IsentropicEfficiencyPct
{
get { return _IsentropicEfficiencyPct; }
set { _IsentropicEfficiencyPct = value; RaisePropertyChanged(); }
}
private double _CoolingCapacityQc_kW;
///
/// 鍒跺喎閲?Qc [kW]
///
public double CoolingCapacityQc_kW
{
get { return _CoolingCapacityQc_kW; }
set { _CoolingCapacityQc_kW = value; RaisePropertyChanged(); }
}
private double _COPCooling;
///
/// 鍘嬬缉鏈烘€ц兘绯绘暟 COP锛堝埗鍐凤級[-]
///
public double COPCooling
{
get { return _COPCooling; }
set { _COPCooling = value; RaisePropertyChanged(); }
}
private double _VolumetricEfficiencyPct;
///
/// 瀹圭Н鏁堢巼 畏v [%]
///
public double VolumetricEfficiencyPct
{
get { return _VolumetricEfficiencyPct; }
set { _VolumetricEfficiencyPct = value; RaisePropertyChanged(); }
}
///
/// 鎸夋祦绋嬪浘鏇存柊锛氬埗鐑噺銆丆OP(鍒剁儹)銆佺瓑鐔垫晥鐜囥€佸埗鍐烽噺銆丆OP(鍒跺喎)銆佸绉晥鐜囥€? ///
///
/// 閿欒/璀﹀憡淇℃伅杈撳嚭銆? /// - 褰撴柟娉曡繑鍥? 鏃讹紝 涓哄け璐ュ師鍥狅紝璋冪敤鏂瑰簲瑙嗕负鏈懆鏈熻绠楁棤鏁堛€? /// - 褰撴柟娉曡繑鍥? 浣? 闈炵┖鏃讹紝琛ㄧず浠呴儴鍒嗙粨鏋滄棤娉曡绠楋紙渚嬪缂哄皯鎺掗噺瀵艰嚧瀹圭Н鏁堢巼涓?NaN锛夈€? ///
///
/// 鏄惁鎴愬姛瀹屾垚鏈懆鏈熺殑缁撴灉鏇存柊銆? /// - 锛氳嚦灏戝凡鎴愬姛鏇存柊 Qh/Qc/COP/畏s 绛変富瑕佺粨鏋滐紱瀹圭Н鏁堢巼鍙兘鍥犵己澶辨帓閲忚€屼负 NaN銆? /// - 锛氬叧閿緭鍏ユ垨 REFPROP 璁$畻澶辫触锛屾湰鍛ㄦ湡缁撴灉涓嶆洿鏂般€? ///
private bool TryUpdateThermodynamicSixResults(out string error)
{
error = string.Empty;
if (InhPressTag == null || InhTempTag == null)
{
error = "缂哄皯鍚告皵鍘嬪姏/鍚告皵娓╁害鏍囩";
return false;
}
if (TxvFrPressTag == null || TxvFrTempTag == null)
{
error = "缂哄皯鑶ㄨ儉闃€鍓嶅帇鍔?鑶ㄨ儉闃€鍓嶆俯搴︽爣绛?;
return false;
}
if (ExPressTag == null || ExTempTag == null)
{
error = "缂哄皯鎺掓皵鍘嬪姏/鎺掓皵娓╁害鏍囩";
return false;
}
if (HVPwTag == null)
{
error = "缂哄皯 HV[W] 鍔熺巼鏍囩";
return false;
}
if (VRVTag == null)
{
error = "缂哄皯鎬绘祦閲?鍐峰獟娴侀噺)鏍囩";
return false;
}
double suctionPress_BarA = InhPressTag.PVModel.EngValue;
double suctionTemp_C = InhTempTag.PVModel.EngValue;
double dischargePress_BarA = ExPressTag.PVModel.EngValue;
double dischargeTemp_C = ExTempTag.PVModel.EngValue;
double txvFrPress_BarA = TxvFrPressTag.PVModel.EngValue;
double txvFrTemp_C = TxvFrTempTag.PVModel.EngValue;
double totalFlow_kg_h = VRVTag.PVModel.EngValue;
double w_W = HVPwTag.PVModel.EngValue;
double speed_rpm = SpeedTag?.PVModel.EngValue ?? double.NaN;
if (!TryGetCompressorDisplacement_cc(out var disp_cc, out var dispErr))
{
error = dispErr;
return false;
}
//杩欓噷鎶婅緭鍏ユ暟鎹啓姝昏绠楀嚭缁撴灉銆? //#if DEBUG
// // 闄勪欢鎴浘杈撳叆锛堝崟浣嶆崲绠楋細MPa -> BarA锛宬W -> W锛? // suctionPress_BarA = 0.3 * 10.0;
// suctionTemp_C = 10.8;
// dischargePress_BarA = 1.502 * 10.0;
// dischargeTemp_C = 88.4;
// txvFrPress_BarA = 1.494 * 10.0;
// txvFrTemp_C = 45.0;
// totalFlow_kg_h = 100.1;
// w_W = 1.289 * 1000.0;
// speed_rpm = 3004;
// disp_cc = 35;
//#endif
if (!double.IsNaN(w_W) && !double.IsInfinity(w_W) && w_W == 0)
{
HeatingCapacityQh_kW = 0;
CoolingCapacityQc_kW = 0;
COPHeating = 0;
COPCooling = 0;
IsentropicEfficiencyPct = 0;
VolumetricEfficiencyPct = 0;
if (HeatingCapacityTag != null)
{
HeatingCapacityTag.PVModel.EngValue = 0;
}
if (COPHeatTag != null)
{
COPHeatTag.PVModel.EngValue = 0;
}
if (IsentrpEffTag != null)
{
IsentrpEffTag.PVModel.EngValue = 0;
}
if (CoolCapacityTag != null)
{
CoolCapacityTag.PVModel.EngValue = 0;
}
if (COPCoolTag != null)
{
COPCoolTag.PVModel.EngValue = 0;
}
if (VoltricEffTag != null)
{
VoltricEffTag.PVModel.EngValue = 0;
}
return true;
}
var calcInput = new ThermodynamicSixResultsCalculator.Input(
suctionPress_BarA: suctionPress_BarA,
suctionTemp_C: suctionTemp_C,
dischargePress_BarA: dischargePress_BarA,
dischargeTemp_C: dischargeTemp_C,
txvFrPress_BarA: txvFrPress_BarA,
txvFrTemp_C: txvFrTemp_C,
hvPower_W: w_W,
totalFlow_kg_h: totalFlow_kg_h,
speed_rpm: speed_rpm,
displacement_cc: disp_cc);
if (!_thermodynamicSixResultsCalculator.TryCalculate(calcInput, out var r, out var calcErr))
{
error = calcErr;
return false;
}
HeatingCapacityQh_kW = r.HeatingCapacityQh_kW;
CoolingCapacityQc_kW = r.CoolingCapacityQc_kW;
COPHeating = r.COPHeating;
COPCooling = r.COPCooling;
IsentropicEfficiencyPct = r.IsentropicEfficiencyPct;
if (HeatingCapacityTag != null)
{
HeatingCapacityTag.PVModel.EngValue = HeatingCapacityQh_kW * 1000.0;
}
if (COPHeatTag != null)
{
COPHeatTag.PVModel.EngValue = COPHeating;
}
if (IsentrpEffTag != null)
{
IsentrpEffTag.PVModel.EngValue = IsentropicEfficiencyPct;
}
if (CoolCapacityTag != null)
{
CoolCapacityTag.PVModel.EngValue = CoolingCapacityQc_kW * 1000.0;
}
if (COPCoolTag != null)
{
COPCoolTag.PVModel.EngValue = COPCooling;
}
if (double.IsNaN(r.VolumetricEfficiencyPct) || double.IsInfinity(r.VolumetricEfficiencyPct))
{
VolumetricEfficiencyPct = double.NaN;
error = calcErr;
return true;
}
VolumetricEfficiencyPct = r.VolumetricEfficiencyPct;
if (VoltricEffTag != null)
{
VoltricEffTag.PVModel.EngValue = VolumetricEfficiencyPct;
}
error = calcErr;
return true;
}
///
/// 鑾峰彇鍘嬬缉鏈烘帓閲忥紙浣跨敤缂撳瓨鏈哄埗锛岄伩鍏嶆瘡娆¤绠楀懆鏈熷疄鏃惰鍙栵級
///
/// 鎺掗噺杈撳嚭锛屽崟浣?cc锛坈m鲁/rev锛夈€?/param>
/// 澶辫触鍘熷洜锛堜粎鍦ㄧ紦瀛樺紓甯告椂杩斿洖锛夈€?/param>
/// 濮嬬粓杩斿洖 true锛堝洜涓洪粯璁ゅ洖閫€ 35cc 淇濊瘉缂撳瓨濮嬬粓鏈夋晥锛夈€?/returns>
private bool TryGetCompressorDisplacement_cc(out double displacement_cc, out string error)
{
displacement_cc = _cachedDisplacement_cc;
error = string.Empty;
return true;
}
///
/// 鍒锋柊鍘嬬缉鏈烘帓閲忕紦瀛橈紝鎸変紭鍏堢骇璇诲彇锛氬疄楠屼俊鎭?鈫?閰嶇疆鏂囦欢 鈫?榛樿鍊? /// 鍦ㄥ疄楠屽垏鎹㈡椂鑷姩璋冪敤锛屼繚璇佺紦瀛樹笌褰撳墠瀹為獙淇℃伅涓€鑷? ///
private void RefreshDisplacementCache()
{
const double defaultDisplacementCc = 35d;
double displacementCc = defaultDisplacementCc;
string source = "Default";
// 浼樺厛绾?锛氫粠褰撳墠瀹為獙淇℃伅璇诲彇
if (ConfigService?.CurExpInfo != null &&
TryParseCompressorDisplacementTextToCc(ConfigService.CurExpInfo.CapDisplacement, out var expCc) &&
expCc > 0)
{
displacementCc = expCc;
source = "ExpInfo";
}
// 浼樺厛绾?锛氫粠 App.config 閰嶇疆璇诲彇
else if (ConfigHelper.IsExist("CompressorDisplacementCc") &&
TryParseCompressorDisplacementTextToCc(ConfigHelper.GetValue("CompressorDisplacementCc"), out var cfgCc) &&
cfgCc > 0)
{
displacementCc = cfgCc;
source = "Config";
}
// 浼樺厛绾?锛氫娇鐢ㄩ粯璁ゅ€? else
{
displacementCc = defaultDisplacementCc;
source = "Default";
}
// 鏇存柊缂撳瓨瀛楁
_cachedDisplacement_cc = displacementCc;
_cachedSource = source;
// 鍚屾鏇存柊 UI 灞曠ず灞炴€? CurDisplacementCc = (int)displacementCc;
// 璁板綍鏃ュ織锛堜究浜庤皟璇曪級
Logger?.Info($"鍘嬬缉鏈烘帓閲忕紦瀛樺凡鍒锋柊: {displacementCc}cc (鏉ユ簮: {source})");
}
///
/// 寮哄埗鍒锋柊鍘嬬缉鏈烘帓閲忕紦瀛橈紙渚涘閮ㄤ富鍔ㄨ皟鐢紝鐢ㄤ簬璋冭瘯鎴栫壒娈婃儏鍐靛 App.config 閰嶇疆淇敼鍚庯級
///
public void ForceRefreshDisplacementCache()
{
RefreshDisplacementCache();
}
private static bool TryParseCompressorDisplacementTextToCc(string? text, out double displacementCc)
{
displacementCc = double.NaN;
if (string.IsNullOrWhiteSpace(text))
{
return false;
}
var normalized = text.Trim().ToLowerInvariant();
normalized = normalized.Replace(',', '.');
var match = Regex.Match(normalized, @"[-+]?\d+(\.\d+)?");
if (!match.Success)
{
return false;
}
if (!double.TryParse(match.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var v))
{
return false;
}
displacementCc = v;
return true;
}
#endregion
}
}