using System.Collections.Generic; using System.Collections.ObjectModel; using Aitex.Core.Common.DeviceData; using Aitex.Core.Util; using Caliburn.Micro; using MECF.Framework.Common.OperationCenter; using System; using System.Linq; using MECF.Framework.Common.DataCenter; using MECF.Framework.UI.Client.CenterViews.Editors.Sequence; using MECF.Framework.UI.Client.CenterViews.Editors.Recipe; using MECF.Framework.UI.Client.ClientBase; using System.Windows; using RecipeEditorLib.DGExtension.CustomColumn; using RecipeEditorLib.RecipeModel.Params; using System.Windows.Controls; using Caliburn.Micro.Core; using System.Windows.Media; using SicUI.Client; using System.Windows.Threading; using MECF.Framework.UI.Client.CenterViews.Editors; using SicUI.Controls; using SicUI.Controls.Dialogs; using OpenSEMI.ClientBase; namespace SicUI.Models.PMs { public class PMProcessViewModel : SicModuleUIViewModelBase, ISupportMultipleSystem, IHandle { private double _tmaFlowRatio = 1; private double _tcsFlowRatio = 1; private double _hclFlowRatio = 1; private double _C2H4FlowRatio = 1; private double _sih4FlowRatio = 1; private double _pn2FlowRatio = 1; #region properties public bool IsPermission { get => this.Permission == 3; } [Subscription("IsBusy")] public bool IsBusy { get; set; } [Subscription("Status")] public string Status { get; set; } public bool IsPMProcess => Status == "Process" || Status == "PostProcess" || Status == "Paused" || Status == "PMMacroPause" || Status == "PMMacro" || Status == "PostPMMacro"; public bool IsPreProcess => Status == "PreProcess" || Status == "PrePMMacro"; [Subscription("IsOnline")] public bool IsOnline { get; set; } [Subscription("Recipe.DeviceData")] public AITDeviceData Recipe { get; set; } public float[] RecipeData1 => RecipeData; public float[] RecipeData = new float[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 1, 1, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 1, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; private string selectedRecipe; public string SelectedRecipe { set { selectedRecipe = value; } get { return selectedRecipe; } } public string SelectedRecipeDispaly { get { if (SelectedRecipe != null) { int index = SelectedRecipe.LastIndexOf(@"\"); if (index > 0) { return SelectedRecipe.Substring(index + 1); } } return SelectedRecipe; } } private string SelectedRecipePath { get; set; } [Subscription("RecipeStepName")] public string RecipeStepName { get; set; } [Subscription("RecipeStepNumber")] public int RecipeStepNumber { get; set; } [Subscription("ArH2Switch")] public string ArH2Switch { get; set; } [Subscription("N2FlowMode")] public string N2FlowMode { get; set; } [Subscription("RecipeStepElapseTime")] public int RecipeStepElapseTime { get; set; } [Subscription("RecipeStepTime")] public int RecipeStepTime { get; set; } [Subscription("RecipeStepElapseTime2")] public int RecipeStepElapseTime2 { get; set; } [Subscription("RecipeTotalElapseTime")] public int RecipeTotalElapseTime { get; set; } [Subscription("RecipeTotalTime")] public int RecipeTotalTime { get; set; } [Subscription("RecipeTotalElapseTime2")] public int RecipeTotalElapseTime2 { get; set; } public string StepNumber { get { if (IsPMProcess) { return $"{RecipeStepNumber}"; } else if (IsPreProcess) { return "0"; } return "--"; } set { } } public string StepName { get { if (IsPMProcess) { return $"{RecipeStepName}"; } else if (IsPreProcess) { return "0"; } return "--"; } } public string StepTime { get { if (IsPMProcess) { return $"{RecipeStepElapseTime}/{RecipeStepTime}"; } else if (IsPreProcess) { return "0"; } return "--"; } } public string RecipeTime { get { if (IsPMProcess) { return $"{RecipeTotalElapseTime}/{RecipeTotalTime}"; } else if (IsPreProcess) { return "0"; } return "--"; } } //qbh 20220523 private int x = 0; private DispatcherTimer timer; private WinProcessMonitor _winProcessMonitor = null; public event EventHandler TimerEvent; // public RecipeData CurrentRecipe { get; set; } = new RecipeData(); public ObservableCollection Columns { get; set; } = new ObservableCollection(); private RecipeFormatBuilder _columnBuilder = new RecipeFormatBuilder(); public bool IsSelectButtonEnable => !string.IsNullOrEmpty(Status) && !Status.Equals("Process") && !Status.Equals("PreProcess") && !Status.Equals("PostProcess") && !Status.Equals("Paused") && !IsOnline; public bool IsStartButtonEnable => !string.IsNullOrEmpty(SelectedRecipe) && !string.IsNullOrEmpty(Status) && !Status.Equals("Process") && !Status.Equals("PreProcess") && !Status.Equals("PostProcess") && !Status.Equals("PrePMMacro") && !Status.Equals("PMMacro") && !Status.Equals("PostPMMacro") && !Status.Equals("Paused") && !IsOnline;// !IsProcessRunning; public bool IsStopButtonEnable => !string.IsNullOrEmpty(Status) && (Status.Equals("Process") || Status.Equals("PMMacro")) && !IsOnline; public bool IsAbortButtonEnable => !string.IsNullOrEmpty(Status) && (Status.Equals("Process") || Status.Equals("PMMacro")) && !IsOnline; //|| Status.Equals("PreProcess") || Status.Equals("PostProcess") || Status.Equals("Paused"));//IsProcessRunning; public bool IsPauseButtonEnable => !string.IsNullOrEmpty(Status) && (Status.Equals("Process") || Status.Equals("PMMacro")) && !IsOnline; public bool IsSkipButtonEnable => !string.IsNullOrEmpty(Status) && Status.Equals("Process") && !IsOnline; public bool IsContinueButtonEnable => !string.IsNullOrEmpty(Status) && (Status.Equals("Paused") || Status.Equals("PMMacroPause")) && !IsOnline; public WaferInfo MLLWafer { get { if (ModuleManager.ModuleInfos["LLH"].WaferManager.Wafers.Count > 0) return ModuleManager.ModuleInfos["LLH"].WaferManager.Wafers[0]; return null; } } public bool MLLHasWafer { get { return MLLWafer.WaferStatus > 0; } } public WaferInfo PMWafer { get { if (ModuleManager.ModuleInfos[SystemName].WaferManager.Wafers.Count > 0) return ModuleManager.ModuleInfos[SystemName].WaferManager.Wafers[0]; return null; } } public bool PMHasWafer => PMWafer.WaferStatus > 0; public Dictionary DicGas { get; set; } public int MLLCurrentWafer { get; set; } public int MLLTotalWafer { get; set; } // public bool IsEnableGasMap => !IsBusy && IsMaintainMode; //public string SystemName { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public object View { get; set; } public string CurrentProcessType { get; set; } private bool needLoadRecipe = false; #endregion protected override void OnActivate() { try { if (String.IsNullOrEmpty(SelectedRecipePath)) { needLoadRecipe = false; SelectedRecipePath = (string)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.LastRecipeName"); if (!string.IsNullOrEmpty(SelectedRecipePath)) { if (SelectedRecipePath.StartsWith("Sic\\Process")) { CurrentProcessType = "Process"; } else if (SelectedRecipePath.StartsWith("Sic\\Routine")) { CurrentProcessType = "Routine"; } UpdateRecipeFormat(); LoadData(SelectedRecipePath); } } //流量需要乘以此系数 _tmaFlowRatio = (double)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.TMAFlowRatio"); _tcsFlowRatio = (double)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.TCSFlowRatio"); _hclFlowRatio = (double)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.HCLFlowRatio"); _C2H4FlowRatio = (double)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.C2H4FlowRatio"); _sih4FlowRatio = (double)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.SiH4FlowRatio"); _pn2FlowRatio = (double)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.PN2FlowRatio"); base.OnActivate(); } catch (Exception ex) { } } protected override void OnDeactivate(bool close) { ActiveUpdateData = true; base.OnDeactivate(close); } protected override void OnInitialize() { base.OnInitialize(); //权限 string roleID = BaseApp.Instance.UserContext.RoleID; stepsVisibility = RoleAccountProvider.Instance.GetMenuPermission(roleID, "PM1.Process.Steps") == 3; //qbh 20220523 TimerEvent = new EventHandler(myTimerEvent); } private bool stepsVisibility; public bool StepsVisibility { get { return stepsVisibility; } } public void UpdateRecipeFormat() { this.Columns = this._columnBuilder.Build($"Sic\\{CurrentProcessType}", SystemName, false, ClientApp.Instance.UserContext.RoleName); this.CurrentRecipe = new RecipeData(); CurrentRecipe.RecipeChamberType = _columnBuilder.RecipeChamberType; CurrentRecipe.RecipeVersion = _columnBuilder.RecipeVersion; CurrentRecipe.PopEnable.Add("Oes", _columnBuilder.OesConfig.Count > 0); CurrentRecipe.PopEnable.Add("Vat", _columnBuilder.VatConfig.Count > 0); CurrentRecipe.PopEnable.Add("FineTuning", _columnBuilder.FineTuningConfig.Count > 0); } protected override void Poll() { try { base.Poll(); string lastPath = (string)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.LastRecipeName"); if (SelectedRecipePath != lastPath) { needLoadRecipe = true; } SelectedRecipePath = lastPath; if (SelectedRecipePath.StartsWith("Sic\\Process")) { CurrentProcessType = "Process"; } else if (SelectedRecipePath.StartsWith("Sic\\Routine")) { CurrentProcessType = "Routine"; } if (!string.IsNullOrEmpty(SelectedRecipePath)) { var array = SelectedRecipePath.Split(new char[] { '\\' }); if (SelectedRecipe != array[array.Length - 1]) { SelectedRecipe = array[array.Length - 1]; //if (SelectedRecipePath.StartsWith("Sic\\Process")) //{ // InvokeClient.Instance.Service.DoOperation($"{SystemName}.Recipe.SetRecipeData", SelectedRecipePath); //} } } } catch (Exception ex) { } } protected override void InvokeAfterUpdateProperty(Dictionary data) { try { if (needLoadRecipe) { needLoadRecipe = false; UpdateRecipeFormat(); OnViewLoaded(View); LoadData(SelectedRecipePath); } base.InvokeAfterUpdateProperty(data); } catch (Exception ex) { } } // /// 展开DataGrid列组。 /// /// public void ExpandColumnsGroup(ExpanderColumn col) { foreach (var subCol in col.ChildColumns) { subCol.UpdateVisibility(); } } /// /// 折叠DataGrid列组。 /// /// public void CollapseColumnsGroup(ExpanderColumn col) { foreach (var subCol in col.ChildColumns) { subCol.Visibility = Visibility.Collapsed; } } public void ParamsExpanded(ExpanderColumn col) { int index = this.Columns.IndexOf(col); for (var i = index + 1; i < this.Columns.Count; i++) { if (this.Columns[i] is ExpanderColumn) break; this.Columns[i].Visibility = Visibility.Visible; } } public void ParamsCollapsed(ExpanderColumn col) { int index = this.Columns.IndexOf(col); for (var i = index + 1; i < this.Columns.Count; i++) { if (this.Columns[i] is ExpanderColumn) break; this.Columns[i].Visibility = Visibility.Collapsed; } } protected override void OnViewLoaded(object view) { View = view; base.OnViewLoaded(view); RecipeFormatBuilder.ApplyTemplate((UserControl)view, this.Columns); PMProcessView u = (PMProcessView)view; u.dgCustom.Columns.Clear(); this.Columns.Apply((c) => { c.Header = c; u.dgCustom.Columns.Add(c); }); u.dgCustom.ItemsSource = this.CurrentRecipe.Steps; u.dgCustom.FrozenColumnCount = 4; } public void Select() { var dialog = new RecipeSelectDialogViewModel(); dialog.DisplayName = "Select Recipe"; var recipeProvider = new RecipeProvider(); var processType = QueryDataClient.Instance.Service.GetConfig("System.Recipe.SupportedProcessType"); if (processType == null) { processType = "Process,Routine"; } var ProcessTypeFileList = new ObservableCollection(); string[] recipeProcessType = ((string)processType).Split(','); for (int i = 0; i < recipeProcessType.Length; i++) { var type = new ProcessTypeFileItem(); type.ProcessType = recipeProcessType[i]; var prefix = $"Sic\\{recipeProcessType[i]}"; var recipes = recipeProvider.GetXmlRecipeList(prefix); type.FileListByProcessType = RecipeSequenceTreeBuilder.BuildFileNode(prefix, "", false, recipes)[0].Files; ProcessTypeFileList.Add(type); } dialog.ProcessTypeFileList = ProcessTypeFileList; WindowManager wm = new WindowManager(); bool? bret = wm.ShowDialog(dialog); /* if (!this.CheckColumnDataAvalible()) { //return; }*/ if ((bool)bret) { SelectedRecipePath = dialog.DialogResult; if (SelectedRecipePath.StartsWith("Sic\\Process")) { CurrentProcessType = "Process"; } else if (SelectedRecipePath.StartsWith("Sic\\Routine")) { CurrentProcessType = "Routine"; } InvokeClient.Instance.Service.DoOperation($"{SystemName}.SelectRecipe", SelectedRecipePath); InvokeClient.Instance.Service.DoOperation("System.SetConfig", $"PM.{SystemName}.LastRecipeName", SelectedRecipePath); // 记录最后一次工艺文件名称 UpdateRecipeFormat(); OnViewLoaded(View); LoadData(SelectedRecipePath); } } public bool CheckColumnDataAvalible() { //return true; //if (CurrentProcessType == ProcessTypeFileList[1].ProcessType) //{ // return true; //} List lstNotCorrectInfo = new List(); List lstOutOfRange = new List(); List lstSplitColums = new List() { (int)RecipColNo.SHTotalFlowSplitRatio, (int)RecipColNo.SiSourceSplitRatio, (int)RecipColNo.CSourceSplitRatio, (int)RecipColNo.DopeSplitRatio }; for (var a = 0; a < this.CurrentRecipe.Steps.Count; a++) { var invalidParam = CurrentRecipe.Steps[a] .Where(param => param is IParam p && p.IsValidated == false).ToList(); lstNotCorrectInfo.AddRange(invalidParam.Cast() .Select(iparam => $"(Step {a + 1}) {iparam.DisplayName}: {iparam.ValidationError}")); /*for (int i = 0; i < this.Columns.Count; i++) { if (this.Columns[i] is DoubleColumn) { DoubleColumn column = (DoubleColumn)this.Columns[i]; double maxValue = column.Maximun; double minValue = column.Minimun; if (maxValue != minValue) { double cValue = 0; if (!double.TryParse((this.CurrentRecipe.Steps[a][i] as DoubleParam).Value, out cValue)) { if ((this.CurrentRecipe.Steps[a][i] as DoubleParam).Value != "Hold") { lstNotCorrectInfo.Add($"Step {a + 1} {column.DisplayName}: value {(this.CurrentRecipe.Steps[a][i] as DoubleParam).Value} is incorrect numerical format "); (this.CurrentRecipe.Steps[a][i] as DoubleParam).Foreground = "Red"; } } else if (cValue > maxValue || cValue < minValue) { lstOutOfRange.Add($"Step {a + 1} {column.DisplayName}: value {cValue} is out of range {minValue}-{maxValue}"); (this.CurrentRecipe.Steps[a][i] as DoubleParam).Foreground = "Red"; } } } else if (lstSplitColums.Contains(i)) { double a1 = 0; double a2 = 0; double a3 = 0; string[] arrSplitRatio = (this.CurrentRecipe.Steps[a][i] as StringParam).Value.Split(':'); if (arrSplitRatio.Length != 3 || !double.TryParse(arrSplitRatio[0], out a1) || !double.TryParse(arrSplitRatio[1], out a2) || !double.TryParse(arrSplitRatio[2], out a3) || a1 <= 0 || a2 <= 0 || a3 <= 0) { lstNotCorrectInfo.Add($"(Step {i + 1}) {this.Columns[i].DisplayName}: value is not avalible!"); } } }*/ } if (lstNotCorrectInfo.Count > 0 || lstOutOfRange.Count > 0) { string strInfo = ""; for (int i = 0; i < lstNotCorrectInfo.Count; i++) { strInfo += lstNotCorrectInfo[i] + "\r\n"; } for (int i = 0; i < lstOutOfRange.Count; i++) { strInfo += lstOutOfRange[i] + "\r\n"; } MessageBox.Show(strInfo, "Warning", MessageBoxButton.OK, MessageBoxImage.Warning); return false; } return true; } public void DeleteProcessData() { } private void LoadData(string selectedRecipePath) { CurrentRecipe.Clear(); var array = selectedRecipePath.Split(new char[] { '\\' }); string recipeName = array[array.Length - 1]; string prefixPath = SelectedRecipePath.Replace(recipeName, ""); var _recipeProvider = new RecipeProvider(); var recipeContent = _recipeProvider.ReadRecipeFile(prefixPath, recipeName); if (string.IsNullOrEmpty(recipeContent)) { MessageBox.Show($"{prefixPath}\\{recipeName} is empty, please confirm the file is valid."); return; } CurrentRecipe.RecipeChamberType = _columnBuilder.RecipeChamberType; CurrentRecipe.RecipeVersion = _columnBuilder.RecipeVersion; CurrentRecipe.InitData(prefixPath, recipeName, recipeContent, Columns, _columnBuilder.Configs, SystemName, null); } public void Start() { ChooseDialogBoxViewModel dialog = new ChooseDialogBoxViewModel(); dialog.DisplayName = "Tips"; dialog.InfoStr = "Please Check All Gas Ready Before Start Process!"; WindowManager wm = new WindowManager(); bool? bret = wm.ShowDialog(dialog); if (!bret.HasValue || !bret.Value) { return; } var array = SelectedRecipePath.Split(new char[] { '\\' }); if (array[1] == "Process") { InvokeClient.Instance.Service.DoOperation($"{SystemName}.RunRecipe", SelectedRecipePath, false, true); } else if (array[1] == "Routine") { InvokeClient.Instance.Service.DoOperation($"{SystemName}.RunPMMacro", SelectedRecipePath); } } public void Skip() { var ret = ShowYesNoDialog("Are you sure to skip the current recipe?", "Warn"); if (ret.HasValue && ret == true) { InvokeClient.Instance.Service.DoOperation($"{SystemName}.RecipeSkipStep"); } } public void Stop() { var ret = ShowYesNoDialog("Are you sure to stop the current recipe?", "Warn"); if (ret.HasValue && ret == true) { InvokeClient.Instance.Service.DoOperation($"{SystemName}.Abort"); } } public void Pause() { var ret = ShowYesNoDialog("Are you sure to pause the current recipe?", "Warn"); if (ret.HasValue && ret == true) { InvokeClient.Instance.Service.DoOperation($"{SystemName}.Pause"); } } public void Continue() { var ret = ShowYesNoDialog("Are you sure to continue to run the current recipe?", "Warn"); if (ret.HasValue && ret == true) { InvokeClient.Instance.Service.DoOperation($"{SystemName}.Continue", "Step continue"); } } public void Abort() { var ret = ShowYesNoDialog("Are you sure to abort the current recipe?", "Warn"); if (ret.HasValue && ret == true) { InvokeClient.Instance.Service.DoOperation($"{SystemName}.Abort"); } } /// /// To fix issue 6: 对运行中的Job操作时弹出提示对话框。 /// /// /// /// private static bool? ShowYesNoDialog(string message, string title) { var ret = DialogBox.ShowDialog(DialogButton.Yes | DialogButton.No, DialogType.CONFIRM, message, title); if (ret == DialogButton.Yes) return true; return null; } #region 腔体绑定数据 [Subscription("TC1.L1InputTempSetPoint")] public float L1InputTemp { get; set; } [Subscription("TC1.L2InputTempSetPoint")] public float L2InputTemp { get; set; } [Subscription("TC1.L3InputTempSetPoint")] public float L3InputTemp { get; set; } [Subscription("TC2.L3InputTempSetPoint")] public float SCRL3InputTemp { get; set; } [Subscription("TC1.L1TargetSPSetPoint")] public float L1TargetSP { get; set; } [Subscription("TC1.L2TargetSPSetPoint")] public float L2TargetSP { get; set; } [Subscription("TC1.L3TargetSPSetPoint")] public float L3TargetSP { get; set; } [Subscription("TC2.L3TargetSPSetPoint")] public float SCRL3TargetSP { get; set; } [Subscription("TC1.TempCtrlTCIN")] public float PM1Temprature { get; set; } //底部温度 [Subscription("TC1.TempCtrlTCIN")] public float TC1Temp2 { get; set; } [Subscription("TC1.HeaterModeSetPoint")] public float TC1HeaterMode { get; set; } public string TC1Mode { get { switch (TC1HeaterMode) { case 0: return "Power"; case 1: return "Pyro"; } return "Power"; } } [Subscription("TC2.HeaterModeSetPoint")] public float TC2HeaterMode { get; set; } public string TC2Mode { get { switch (TC2HeaterMode) { case 0: return "Power"; case 1: return "TC"; case 2: return "Pyro"; } return "Power"; } } [Subscription("SCR1.PowerFeedBack")] public float SCR1Power { get; set; } [Subscription("SCR2.PowerFeedBack")] public float SCR2Power { get; set; } [Subscription("SCR3.PowerFeedBack")] public float SCR3Power { get; set; } [Subscription("PSU1.OutputPowerFeedBack")] public float PSU1Power { get; set; } [Subscription("PSU2.OutputPowerFeedBack")] public float PSU2Power { get; set; } [Subscription("PSU3.OutputPowerFeedBack")] public float PSU3Power { get; set; } [Subscription("PMServo.ActualSpeedFeedback")] public float ActualSpeedFeedback { get; set; } [Subscription("PT1.FeedBack")] public float PT1Pressure { get; set; } #endregion 腔体绑定数据 #region MFC [Subscription("Mfc1.DeviceData")] public AITMfcData Mfc1Data { get; set; } [Subscription("Mfc2.DeviceData")] public AITMfcData Mfc2Data { get; set; } [Subscription("Mfc3.DeviceData")] public AITMfcData Mfc3Data { get; set; } [Subscription("Mfc4.DeviceData")] public AITMfcData Mfc4Data { get; set; } [Subscription("Mfc5.DeviceData")] public AITMfcData Mfc5Data { get; set; } [Subscription("Mfc6.DeviceData")] public AITMfcData Mfc6Data { get; set; } [Subscription("Mfc7.DeviceData")] public AITMfcData Mfc7Data { get; set; } [Subscription("Mfc8.DeviceData")] public AITMfcData Mfc8Data { get; set; } [Subscription("Mfc9.DeviceData")] public AITMfcData Mfc9Data { get; set; } [Subscription("Mfc10.DeviceData")] public AITMfcData Mfc10Data { get; set; } [Subscription("Mfc11.DeviceData")] public AITMfcData Mfc11Data { get; set; } [Subscription("Mfc12.DeviceData")] public AITMfcData Mfc12Data { get; set; } [Subscription("Mfc13.DeviceData")] public AITMfcData Mfc13Data { get; set; } [Subscription("Mfc14.DeviceData")] public AITMfcData Mfc14Data { get; set; } [Subscription("Mfc15.DeviceData")] public AITMfcData Mfc15Data { get; set; } [Subscription("Mfc16.DeviceData")] public AITMfcData Mfc16Data { get; set; } [Subscription("Mfc19.DeviceData")] public AITMfcData Mfc19Data { get; set; } [Subscription("Mfc20.DeviceData")] public AITMfcData Mfc20Data { get; set; } [Subscription("Mfc22.DeviceData")] public AITMfcData Mfc22Data { get; set; } [Subscription("Mfc23.DeviceData")] public AITMfcData Mfc23Data { get; set; } [Subscription("Mfc25.DeviceData")] public AITMfcData Mfc25Data { get; set; } [Subscription("Mfc26.DeviceData")] public AITMfcData Mfc26Data { get; set; } [Subscription("Mfc27.DeviceData")] public AITMfcData Mfc27Data { get; set; } [Subscription("Mfc28.DeviceData")] public AITMfcData Mfc28Data { get; set; } [Subscription("Mfc29.DeviceData")] public AITMfcData Mfc29Data { get; set; } [Subscription("Mfc30.DeviceData")] public AITMfcData Mfc30Data { get; set; } [Subscription("Mfc31.DeviceData")] public AITMfcData Mfc31Data { get; set; } [Subscription("Mfc32.DeviceData")] public AITMfcData Mfc32Data { get; set; } [Subscription("Mfc33.DeviceData")] public AITMfcData Mfc33Data { get; set; } [Subscription("Mfc35.DeviceData")] public AITMfcData Mfc35Data { get; set; } [Subscription("Mfc36.DeviceData")] public AITMfcData Mfc36Data { get; set; } [Subscription("Mfc37.DeviceData")] public AITMfcData Mfc37Data { get; set; } [Subscription("Mfc38.DeviceData")] public AITMfcData Mfc38Data { get; set; } [Subscription("Mfc40.DeviceData")] public AITMfcData Mfc40Data { get; set; } #endregion #region Valve [Subscription("V27.DeviceData")] public AITValveData V27 { get; set; } [Subscription("V25.DeviceData")] public AITValveData V25 { get; set; } [Subscription("V31.DeviceData")] public AITValveData V31 { get; set; } [Subscription("V32.DeviceData")] public AITValveData V32 { get; set; } [Subscription("V33.DeviceData")] public AITValveData V33 { get; set; } [Subscription("V33s.DeviceData")] public AITValveData V33s { get; set; } [Subscription("V35.DeviceData")] public AITValveData V35 { get; set; } [Subscription("V36.DeviceData")] public AITValveData V36 { get; set; } [Subscription("V37.DeviceData")] public AITValveData V37 { get; set; } [Subscription("V37s.DeviceData")] public AITValveData V37s { get; set; } [Subscription("V39.DeviceData")] public AITValveData V39 { get; set; } [Subscription("V39s.DeviceData")] public AITValveData V39s { get; set; } [Subscription("V40.DeviceData")] public AITValveData V40 { get; set; } [Subscription("V40s.DeviceData")] public AITValveData V40s { get; set; } [Subscription("V41.DeviceData")] public AITValveData V41 { get; set; } [Subscription("V41s.DeviceData")] public AITValveData V41s { get; set; } [Subscription("V42.DeviceData")] public AITValveData V42 { get; set; } [Subscription("V43.DeviceData")] public AITValveData V43 { get; set; } [Subscription("V43s.DeviceData")] public AITValveData V43s { get; set; } [Subscription("V45.DeviceData")] public AITValveData V45 { get; set; } [Subscription("V46.DeviceData")] public AITValveData V46 { get; set; } [Subscription("V46s.DeviceData")] public AITValveData V46s { get; set; } [Subscription("V48.DeviceData")] public AITValveData V48 { get; set; } [Subscription("V48s.DeviceData")] public AITValveData V48s { get; set; } [Subscription("V49.DeviceData")] public AITValveData V49 { get; set; } [Subscription("V50.DeviceData")] public AITValveData V50 { get; set; } [Subscription("V50s.DeviceData")] public AITValveData V50s { get; set; } [Subscription("V51.DeviceData")] public AITValveData V51 { get; set; } [Subscription("V51s.DeviceData")] public AITValveData V51s { get; set; } [Subscription("V52.DeviceData")] public AITValveData V52 { get; set; } [Subscription("V52s.DeviceData")] public AITValveData V52s { get; set; } [Subscription("V53.DeviceData")] public AITValveData V53 { get; set; } [Subscription("V53s.DeviceData")] public AITValveData V53s { get; set; } [Subscription("V54.DeviceData")] public AITValveData V54 { get; set; } [Subscription("V54s.DeviceData")] public AITValveData V54s { get; set; } [Subscription("V55.DeviceData")] public AITValveData V55 { get; set; } [Subscription("V56.DeviceData")] public AITValveData V56 { get; set; } [Subscription("V58.DeviceData")] public AITValveData V58 { get; set; } [Subscription("V58s.DeviceData")] public AITValveData V58s { get; set; } [Subscription("V59.DeviceData")] public AITValveData V59 { get; set; } [Subscription("V60.DeviceData")] public AITValveData V60 { get; set; } [Subscription("V61.DeviceData")] public AITValveData V61 { get; set; } [Subscription("V62.DeviceData")] public AITValveData V62 { get; set; } [Subscription("V63.DeviceData")] public AITValveData V63 { get; set; } [Subscription("V64.DeviceData")] public AITValveData V64 { get; set; } [Subscription("V65.DeviceData")] public AITValveData V65 { get; set; } [Subscription("V68.DeviceData")] public AITValveData V68 { get; set; } [Subscription("V69.DeviceData")] public AITValveData V69 { get; set; } [Subscription("V70.DeviceData")] public AITValveData V70 { get; set; } [Subscription("V72.DeviceData")] public AITValveData V72 { get; set; } [Subscription("V73.DeviceData")] public AITValveData V73 { get; set; } [Subscription("V74.DeviceData")] public AITValveData V74 { get; set; } [Subscription("V75.DeviceData")] public AITValveData V75 { get; set; } [Subscription("V76.DeviceData")] public AITValveData V76 { get; set; } [Subscription("V87.DeviceData")] public AITValveData V87 { get; set; } [Subscription("V88.DeviceData")] public AITValveData V88 { get; set; } [Subscription("V89.DeviceData")] public AITValveData V89 { get; set; } [Subscription("V90.DeviceData")] public AITValveData V90 { get; set; } [Subscription("V91.DeviceData")] public AITValveData V91 { get; set; } [Subscription("V92.DeviceData")] public AITValveData V92 { get; set; } [Subscription("V93.DeviceData")] public AITValveData V93 { get; set; } [Subscription("V94.DeviceData")] public AITValveData V94 { get; set; } [Subscription("V95.DeviceData")] public AITValveData V95 { get; set; } [Subscription("V96.DeviceData")] public AITValveData V96 { get; set; } [Subscription("V97.DeviceData")] public AITValveData V97 { get; set; } [Subscription("EPV1.DeviceData")] public AITValveData EPV1 { get; set; } [Subscription("EPV2.DeviceData")] public AITValveData EPV2 { get; set; } [Subscription("V99.DeviceData")] public AITValveData V99 { get; set; } [Subscription("V99s.DeviceData")] public AITValveData V99s { get; set; } #endregion #region Pressure [Subscription("Pressure1.DeviceData")] public AITPressureMeterData PT1Data { get; set; } [Subscription("Pressure2.DeviceData")] public AITPressureMeterData PT2Data { get; set; } [Subscription("Pressure3.DeviceData")] public AITPressureMeterData PT3Data { get; set; } [Subscription("Pressure4.DeviceData")] public AITPressureMeterData PT4Data { get; set; } [Subscription("Pressure5.DeviceData")] public AITPressureMeterData PT5Data { get; set; } [Subscription("Pressure6.DeviceData")] public AITPressureMeterData PT6Data { get; set; } [Subscription("Pressure7.DeviceData")] public AITPressureMeterData PT7Data { get; set; } [Subscription("PT1.DeviceData")] public AITPressureMeterData ChamPress { get; set; } [Subscription("PT2.DeviceData")] public AITPressureMeterData ForelinePress { get; set; } #endregion #region 特气显示颜色 public SolidColorBrush PN2Color { get { if (IsPN2RunMode) { return new SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 0, 0)); } else { return new SolidColorBrush(System.Windows.Media.Color.FromRgb(255, 0, 0)); } } } public SolidColorBrush C2H4Color { get { if (IsC2H4RunMode) { return new SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 0, 0)); } else { return new SolidColorBrush(System.Windows.Media.Color.FromRgb(255, 0, 0)); } } } public SolidColorBrush SIH4Color { get { if (IsSiH4RunMode) { return new SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 0, 0)); } else { return new SolidColorBrush(System.Windows.Media.Color.FromRgb(255, 0, 0)); } } } public SolidColorBrush HCLColor { get { if (IsHCLRunMode) { return new SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 0, 0)); } else { return new SolidColorBrush(System.Windows.Media.Color.FromRgb(255, 0, 0)); } } } public SolidColorBrush TMAColor { get { if (IsTMARunMode) { return new SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 0, 0)); } else { return new SolidColorBrush(System.Windows.Media.Color.FromRgb(255, 0, 0)); } } } public SolidColorBrush TCSColor { get { if (IsTCSRunMode) { return new SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 0, 0)); } else { return new SolidColorBrush(System.Windows.Media.Color.FromRgb(255, 0, 0)); } } } public SolidColorBrush PN2FlowColor { get { if (IsPN2RunMode) { return new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 0, 255, 255)); } else { return new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 190, 190, 190)); } } } public SolidColorBrush C2H4FlowColor { get { if (IsC2H4RunMode) { return new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 0, 255, 255)); } else { return new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 190, 190, 190)); } } } public SolidColorBrush SIH4FlowColor { get { if (IsSiH4RunMode) { return new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 0, 255, 255)); } else { return new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 190, 190, 190)); } } } public SolidColorBrush HCLFlowColor { get { if (IsHCLRunMode) { return new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 0, 255, 255)); } else { return new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 190, 190, 190)); } } } public SolidColorBrush TMAFlowColor { get { if (IsTMARunMode) { return new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 0, 255, 255)); } else { return new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 190, 190, 190)); } } } public SolidColorBrush TCSFlowColor { get { if (IsTCSRunMode) { return new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 0, 255, 255)); } else { return new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 190, 190, 190)); } } } #endregion public bool IsPN2RunMode => N2FlowMode == "Run"; public bool IsHCLRunMode => V54.IsOpen; public bool IsSiH4RunMode => V55.IsOpen && !V56.IsOpen; public bool IsC2H4RunMode => V59.IsOpen && !V60.IsOpen; public bool IsTCSRunMode => V53.IsOpen; public bool IsTMARunMode => V41.IsOpen && !V42.IsOpen; public double ArFlow => CalArFlowSum(); public double H2Flow => CalH2FlowSum(); public double PN2Flow => GetPN2MFCFlow(IsPN2RunMode) * _pn2FlowRatio; public double HCLFlow => GetHclMFCFlow(IsHCLRunMode) * _hclFlowRatio; public double SiH4Flow => GetSiH4MFCFlow(IsSiH4RunMode) * _sih4FlowRatio; public double C2H4Flow => GetC2H4MFCFlow(IsC2H4RunMode) * _C2H4FlowRatio; public double TCSFlow => GetTCSMFCFlow(IsTCSRunMode) * _tcsFlowRatio; public double TMAFlow => GetTMAMFCFlow(IsTMARunMode) * _tmaFlowRatio; public bool ISPN2Flow => PN2Flow > 0 && IsPN2RunMode; public bool ISHCLFlow => HCLFlow > 0 && IsHCLRunMode; public bool ISSiH4Flow => SiH4Flow > 0 && IsSiH4RunMode; public bool ISC2H4Flow => C2H4Flow > 0 && IsC2H4RunMode; public bool ISArFlow => ArFlow > 0; public bool ISH2Flow => H2Flow > 0; public bool ISTCSFlow => TCSFlow > 0 && IsTCSRunMode; public bool ISTMAFlow => TMAFlow > 0 && IsTMARunMode; #region 计算Ar 和 H2 总流量 private double CalArFlowSum() { // 参与计算H2流量的MFC double divFlowCount = 0; var mfcs = new List(); if (!V32.IsOpen) { return 0; } if (V64.IsOpen != V65.IsOpen) { if (V65.IsOpen) { if (V97.IsOpen) mfcs.Add(Mfc40Data); if (V91.IsOpen) mfcs.Add(Mfc33Data); if (V87.IsOpen) mfcs.Add(Mfc27Data); } } if (V33s.IsOpen && V35.IsOpen) { if (V97.IsOpen) mfcs.Add(Mfc40Data); if (V91.IsOpen) mfcs.Add(Mfc33Data); if (V90.IsOpen) mfcs.Add(Mfc31Data); if (V89.IsOpen) mfcs.Add(Mfc29Data); if (V88.IsOpen) mfcs.Add(Mfc28Data); if (V87.IsOpen) mfcs.Add(Mfc27Data); } if (V33s.IsOpen && V36.IsOpen) { if (V63.IsOpen) { if (V90.IsOpen) mfcs.Add(Mfc25Data); if (V89.IsOpen) mfcs.Add(Mfc26Data); if (V88.IsOpen) mfcs.Add(Mfc15Data); divFlowCount += IsC2H4RunMode ? GetC2H4MFCFlow(true) : 0; } if (V62.IsOpen) { if (V89.IsOpen) mfcs.Add(Mfc23Data); if (V90.IsOpen) mfcs.Add(Mfc22Data); if (V88.IsOpen) mfcs.Add(Mfc9Data); divFlowCount += IsSiH4RunMode ? GetSiH4MFCFlow(true) : 0; divFlowCount += IsHCLRunMode ? GetHclMFCFlow(true) : 0; divFlowCount += IsTCSRunMode ? GetTCSMFCFlow(true) : 0; } if (V61.IsOpen) { if (V90.IsOpen) mfcs.Add(Mfc19Data); if (V89.IsOpen) mfcs.Add(Mfc20Data); if (V88.IsOpen) mfcs.Add(Mfc2Data); divFlowCount += IsPN2RunMode ? GetPN2MFCFlow(true) : 0; divFlowCount += IsTMARunMode ? GetTMAMFCFlow(true) : 0; } } if (V68.IsOpen) { if (V96.IsOpen) mfcs.Add(Mfc38Data); if (V95.IsOpen) mfcs.Add(Mfc37Data); if (V94.IsOpen) mfcs.Add(Mfc36Data); if (V93.IsOpen) mfcs.Add(Mfc35Data); if (V92.IsOpen) mfcs.Add(Mfc32Data); } var flowCount = mfcs.Sum(mfcData => mfcData.FeedBack); return (flowCount - divFlowCount > 0)? flowCount - divFlowCount:0 ; } private double CalH2FlowSum() { // 参与计算H2流量的MFC var mfcs = new List(); if(!V31.IsOpen) { return 0; } if (V64.IsOpen != V65.IsOpen) { if (V64.IsOpen) { if (V97.IsOpen) mfcs.Add(Mfc40Data); if (V91.IsOpen) mfcs.Add(Mfc33Data); if (V87.IsOpen) mfcs.Add(Mfc27Data); } } if (V33.IsOpen && V35.IsOpen) { if (V90.IsOpen) mfcs.Add(Mfc31Data); if (V89.IsOpen) mfcs.Add(Mfc29Data); if (V88.IsOpen) mfcs.Add(Mfc28Data); } if (V33.IsOpen && V35.IsOpen && V36.IsOpen && V63.IsOpen) { if (!V59.IsOpen) { if (V90.IsOpen) mfcs.Add(Mfc26Data); if (V89.IsOpen) mfcs.Add(Mfc25Data); if (V88.IsOpen) mfcs.Add(Mfc15Data); } if (!V58.IsOpen && V59.IsOpen && !V60.IsOpen) { if (V90.IsOpen) mfcs.Add(Mfc26Data); if (V89.IsOpen) mfcs.Add(Mfc25Data); if (V88.IsOpen) mfcs.Add(Mfc15Data); } if (V61.IsOpen) { if (V90.IsOpen) mfcs.Add(Mfc19Data); if (V89.IsOpen) mfcs.Add(Mfc20Data); if (V88.IsOpen) mfcs.Add(Mfc2Data); } } var flowCount = mfcs.Sum(mfcData => mfcData.FeedBack); return flowCount; } #endregion private double GetC2H4MFCFlow(bool isRun) { double flow = 0; if (V58.IsOpen == false) // V58关闭时通载气,不计算C2H4流量 return 0; if (isRun) { // 气体进入反应腔 if (V59.IsOpen && !V60.IsOpen && V63.IsOpen && (V90.IsOpen || V89.IsOpen || V88.IsOpen)) { flow = Mfc16Data.FeedBack; } } else { // 气体直接排走 if (!V59.IsOpen && V60.IsOpen) { flow = Mfc16Data.FeedBack; } } return flow; } private double GetSiH4MFCFlow(bool isRun) { double flow = 0; if (V52.IsOpen == false) // V52关闭时通载气,不计算SiH4流量 return 0; if (isRun) { // 气体进入反应腔 if (V55.IsOpen && !V56.IsOpen && V62.IsOpen && (V90.IsOpen || V89.IsOpen || V88.IsOpen)) { flow += Mfc14Data.FeedBack; } } else { // 气体直接排走 if (!V55.IsOpen && V56.IsOpen) { flow += Mfc14Data.FeedBack; } } return flow; } private double GetHclMFCFlow(bool isRun) { double flow = 0; if (V51.IsOpen == false) // V51关闭时通载气,不计算HCL流量 return 0; if (isRun) { // 气体进入反应腔 if (V54.IsOpen && V62.IsOpen && (V90.IsOpen || V89.IsOpen || V88.IsOpen)) { flow += Mfc13Data.FeedBack; } } else { // 气体直接排走 if (V51.IsOpen && !V54.IsOpen) { flow += Mfc13Data.FeedBack; } } return flow; } private double GetPN2MFCFlow(bool isRun) { //新计算方式 double flow = 0; if (IsPMProcess) { if (N2FlowMode == "Purge") { flow = 0; } else if (N2FlowMode == "Vent") { flow = Mfc4Data.FeedBack + Mfc5Data.FeedBack; } else if (N2FlowMode == "Run") { flow = Mfc6Data.FeedBack * Mfc4Data.FeedBack / (Mfc3Data.FeedBack + Mfc4Data.FeedBack); if (V40.IsOpen) { flow += Mfc5Data.FeedBack; } } } return flow; } private double GetTCSMFCFlow(bool isRun) { double flow = 0; if (isRun) { if (!V49.IsOpen && V48.IsOpen && V53.IsOpen && V62.IsOpen && (V90.IsOpen || V89.IsOpen || V88.IsOpen)) { flow += Mfc10Data.FeedBack + Mfc11Data.FeedBack; } } else { if (!V49.IsOpen && V48.IsOpen && !V53.IsOpen) { flow += Mfc10Data.FeedBack + Mfc11Data.FeedBack; } } return flow; } private double GetTMAMFCFlow(bool isRun) { double flow = 0; if (isRun) { if (!V45.IsOpen && V43.IsOpen && V41.IsOpen && !V42.IsOpen && V61.IsOpen && (V90.IsOpen || V89.IsOpen || V88.IsOpen)) { flow += Mfc7Data.FeedBack; } } else { if (!V45.IsOpen && V43.IsOpen && !V41.IsOpen && V42.IsOpen) { flow += Mfc7Data.FeedBack; } } return flow; } // public void ShowMonitorWindow() { if (Application.Current.Windows.OfType().Any()) { _winProcessMonitor.Activate(); } else { _winProcessMonitor = new WinProcessMonitor(this) { dsFresh = new WinProcessMonitor.DataToMonitor() }; _winProcessMonitor.Show(); InitTimer(); } } private void InitTimer() { //设置定时器 timer = new DispatcherTimer { Interval = new TimeSpan(10000000) //100分之一毫秒为单位 }; timer.Tick += new EventHandler(timer_Tick); //开启定时器 timer.Start(); } private void timer_Tick(object sender, EventArgs e) { try { TimerEvent(sender, e); } catch (Exception ex) { //MessageBox.Show(ex.Message, "异常"); //EV.PostWarningLog() } //throw new NotImplementedException(); } private void myTimerEvent(object obj, System.EventArgs e) { _winProcessMonitor.dsFresh.RecipeName = SelectedRecipeDispaly; _winProcessMonitor.dsFresh.StepNumber = StepNumber; _winProcessMonitor.dsFresh.StepName = StepName; _winProcessMonitor.dsFresh.StepTime = StepTime; _winProcessMonitor.dsFresh.RecipeTime = RecipeTime; // _winProcessMonitor.dsFresh.PSUMOde = TC1Mode; _winProcessMonitor.dsFresh.SCRMOde = TC2Mode; // _winProcessMonitor.dsFresh.Inner = PSU1Power.ToString(); _winProcessMonitor.dsFresh.Middle = PSU2Power.ToString(); _winProcessMonitor.dsFresh.Outer = PSU3Power.ToString(); _winProcessMonitor.dsFresh.U = SCR1Power.ToString(); _winProcessMonitor.dsFresh.M = SCR2Power.ToString(); _winProcessMonitor.dsFresh.L = SCR3Power.ToString(); // _winProcessMonitor.dsFresh.TC1 = SCRL3InputTemp.ToString(); _winProcessMonitor.dsFresh.TC2 = L2InputTemp.ToString(); _winProcessMonitor.dsFresh.TC3 = L3InputTemp.ToString(); _winProcessMonitor.dsFresh.ChamPressFeedBack = ChamPress.FeedBack.ToString(ChamPress.FormatString);//ChamPress.ToString(); _winProcessMonitor.dsFresh.ActualSpeedFeedback = ActualSpeedFeedback.ToString(); _winProcessMonitor.dsFresh.PM1Temprature = PM1Temprature.ToString(); } public void Handle(ShowMonitorWinEvent message) { ShowMonitorWindow(); } } }