Sic.Framework/MECF.Framework.UI.Client/CenterViews/Modules/PM/PMProcessViewModel.cs

1724 lines
54 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections.Generic;
using Aitex.Core.Common.DeviceData;
using Aitex.Core.Util;
using Caliburn.Micro;
using MECF.Framework.Common.OperationCenter;
using System;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.UI.Client.CenterViews.Editors.Recipe;
using MECF.Framework.UI.Client.ClientBase;
using System.Windows;
using Caliburn.Micro.Core;
using System.Windows.Media;
using System.Windows.Threading;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using OpenSEMI.ClientBase;
using Sicentury.Core;
using MECF.Framework.UI.Client.CenterViews.Editors;
using MECF.Framework.UI.Client.RecipeEditorLib.DGExtension.CustomColumn;
using MECF.Framework.UI.Client.RecipeEditorLib.RecipeModel;
using MECF.Framework.UI.Client.RecipeEditorLib.RecipeModel.Params;
using Action = System.Action;
using Newtonsoft.Json;
using System.Dynamic;
using Aitex.Core.RT.Device.PmDevices;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.MfcCalculation;
using SicUI.Models.PMs;
using SciChart.Core.Messaging;
namespace MECF.Framework.UI.Client.CenterViews.Modules.PM
{
public class PMProcessViewModel : SicModuleUIViewModelBase, ISupportMultipleSystem
{
private double _tmaFlowRatio = 1;
private double _tcsFlowRatio = 1;
private double _hclFlowRatio = 1;
private double _C2H4FlowRatio = 1;
private double _sih4FlowRatio = 1;
private double _pn2FlowRatio = 1;
private bool _isHideRecipeValue = false;
private bool _allowSaveRecipe = false;
private bool _allowRipRecipe = false;
private readonly IRecipeGasFlowCalculator _recipeGasFlowCalculator;
private string _currectProcessingRecipe;
private IProgress<int> _progressRecipeStepChanged;
private IProgress<string> _progressLoadRecipe;
private readonly object _lockerLoadingRecipe = new object();
public string title { get; set; } = "123";
public PMProcessGasFlowCounterViewModel GasFlowCounterVm { get; private set; }
public PMProcessViewModel()
{
_recipeGasFlowCalculator = IoC.Get<IRecipeGasFlowCalculator>();
Subscribe("System.IsEngMode");
}
#region properties
public bool IsPermission { get => this.Permission == 3; }
public bool AllowSaveRecipe
{
get => _allowSaveRecipe;
set
{
_allowSaveRecipe = value;
NotifyOfPropertyChange();
}
}
public bool AllowRipRecipe
{
get => _allowRipRecipe;
set
{
_allowRipRecipe = value;
NotifyOfPropertyChange();
}
}
public bool IsEngMode { get; private set; }
[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;
}
}
[Subscription("SelectedRecipeName")]
public string CurrentProcessingRecipeName
{
get => _currectProcessingRecipe;
set
{
if (_currectProcessingRecipe != value)
{
_currectProcessingRecipe = value;
DisplayingRecipeName = value;
}
}
}
[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 "--";
}
}
private string _displayingRecipeName;
public string DisplayingRecipeName
{
get => _displayingRecipeName;
private set
{
if (_displayingRecipeName != value)
{
_displayingRecipeName = value;
_progressLoadRecipe.Report(value);
NotifyOfPropertyChange();
}
}
}
private bool _isRecipeLoading;
public bool IsRecipeLoading
{
get => _isRecipeLoading;
set
{
if (_isRecipeLoading != value)
{
_isRecipeLoading = value;
NotifyOfPropertyChange();
}
}
}
//qbh 20220523
private int x = 0;
private DispatcherTimer timer;
//
public RecipeData CurrentRecipe { get; set; } = new RecipeData(null);
public List<EditorDataGridTemplateColumnBase> Columns { get; set; } = new List<EditorDataGridTemplateColumnBase>();
private RecipeFormatBuilder _columnBuilder = new RecipeFormatBuilder();
public bool IsSelectButtonEnable => !string.IsNullOrEmpty(Status) && !Status.Equals("Process")
&& !Status.Equals("PreProcess") && !Status.Equals("PostProcess") && !Status.Equals("Paused")
&& !IsOnline && !IsRecipeLoading;
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 && !IsRecipeLoading;// !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<int, string> 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
/// <summary>
/// 获取角色权限配置.
/// </summary>
/// <returns></returns>
private void LoadRolePermissions()
{
var roleID = BaseApp.Instance.UserContext.RoleID;
_isHideRecipeValue = RoleAccountProvider.Instance.GetMenuPermission(roleID, "Recipe.Behaviour.ShowValueInProcessView") == (int)MenuPermissionEnum.MP_NONE;
AllowSaveRecipe = RoleAccountProvider.Instance.GetMenuPermission(roleID, "Recipe.Behaviour.AllowSaveInProcessView") != (int)MenuPermissionEnum.MP_NONE;
AllowRipRecipe = RoleAccountProvider.Instance.GetMenuPermission(roleID, "Recipe.Behaviour.AllowRipInProcessView") != (int)MenuPermissionEnum.MP_NONE;
}
protected override void OnActivate()
{
try
{
LoadRolePermissions();
if (string.IsNullOrEmpty(DisplayingRecipeName))
{
needLoadRecipe = false;
var recipeName =
(string)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.LastRecipeName");
DisplayingRecipeName = recipeName;
selectedRecipe = recipeName;
}
// 更新Recipe参数值显示状态
SetRecipeValueVisibilityByCurrentRole();
((PMProcessView)View)?.recipeLocker.Lock();
//流量需要乘以此系数
//_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();
//权限
var roleID = BaseApp.Instance.UserContext.RoleID;
stepsVisibility = RoleAccountProvider.Instance.GetMenuPermission(roleID, "PM1.Process.Steps") == 3;
_progressLoadRecipe = new Progress<string>(ProgLoadRecipeOnUiThread);
_progressRecipeStepChanged = new Progress<int>(RecipeStepInProcessChanged);
UpdateRecipeFormat();
GasFlowCounterVm = new PMProcessGasFlowCounterViewModel(this);
GasFlowCounterVm.EnableTimer(true);
}
private bool stepsVisibility;
public bool StepsVisibility
{
get { return stepsVisibility; }
}
protected override void Poll()
{
try
{
base.Poll();
}
catch (Exception ex)
{
}
}
protected override void InvokeAfterUpdateProperty(Dictionary<string, object> data)
{
try
{
if (data.TryGetValue("System.IsEngMode", out var isEngMode) && isEngMode is bool b)
IsEngMode = b;
if (needLoadRecipe)
needLoadRecipe = false;
base.InvokeAfterUpdateProperty(data);
}
catch (Exception ex)
{
}
}
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);
ViewWin = (PMProcessView)view;
StartDateTime = DateTime.Now.Date;
EndDateTime = DateTime.Now.Date.AddDays(1).AddTicks(-1);
string str = "[{\"Name\":\"Ar\",\"RunVolume\":5.8561316539732289,\"VentVolume\":0.078784436017824339},{\"Name\":\"H2\",\"RunVolume\":0.0,\"VentVolume\":0.0},{\"Name\":\"C2H4\",\"RunVolume\":0.0,\"VentVolume\":0.0},{\"Name\":\"SiH4\",\"RunVolume\":0.0,\"VentVolume\":0.0},{\"Name\":\"HCL\",\"RunVolume\":0.0,\"VentVolume\":0.0},{\"Name\":\"PN2\",\"RunVolume\":0.0,\"VentVolume\":0.0},{\"Name\":\"TCS\",\"RunVolume\":0.0,\"VentVolume\":0.0},{\"Name\":\"TMA\",\"RunVolume\":0.0,\"VentVolume\":0.0}]";
var o= JsonConvert.DeserializeObject<List<DataFlow>>(str);
}
public void SelectRecipe()
{
var dialog = new RecipeSelectDialogViewModel(false, false, ProcessTypeFileItem.ProcessFileTypes.Process);
dialog.DisplayName = "Select Recipe";
var wm = new WindowManager();
var bret = wm.ShowDialog(dialog);
if ((bool)bret)
{
var recipeName = dialog.DialogResult;
if (recipeName.StartsWith("Sic\\Process"))
{
CurrentProcessType = "Process";
}
else if (recipeName.StartsWith("Sic\\Routine"))
{
CurrentProcessType = "Routine";
}
DisplayingRecipeName = recipeName;
SelectedRecipe = recipeName;
InvokeClient.Instance.Service.DoOperation($"{SystemName}.SelectRecipe", recipeName);
InvokeClient.Instance.Service.DoOperation("System.SetConfig", $"PM.{SystemName}.LastRecipeName",
recipeName);
}
}
public void DeleteProcessData()
{
}
private static void RenderStepsWithSameValue(IReadOnlyList<Param> previousStep, IReadOnlyList<Param> currentStep)
{
for (var i = 0; i < currentStep.Count; i++)
{
if (currentStep[i] is DoubleParam currDblParam && previousStep[i] is DoubleParam prevDblParam)
{
currDblParam.IsEqualsToPrevious =
GlobalDefs.IsDoubleValueEquals(currDblParam.Value, prevDblParam.Value);
}
else if (currentStep[i] is ComboxParam currCbxParam && previousStep[i] is ComboxParam prevCbxParam)
{
if (currCbxParam.Value != prevCbxParam.Value)
{
currCbxParam.IsEqualsToPrevious = false;
}
else
{
currCbxParam.IsEqualsToPrevious = true;
}
}
}
}
/// <summary>
/// 将发生变更的配方推送到当前工艺。
/// </summary>
public void PushRecipeToCurrentProcess()
{
// 如果配方没变,不需要推送
if (!CurrentRecipe.IsChanged)
{
DialogBox.ShowWarning("The recipe does not change.");
return;
}
if (!CurrentRecipe.Validate())
{
var ret = DialogBox.ShowDialog(DialogButton.Yes | DialogButton.No, DialogType.WARNING,
$"{CurrentRecipe.ValidationErrorSummary}\r\n Are you sure to push changes to current process?");
if (ret == DialogButton.No)
return;
/*var mbr = MessageBox.Show($"{errors}\r\n Are you sure to push changes to current process", "Warning",
MessageBoxButton.YesNo, MessageBoxImage.Warning);
if (mbr == MessageBoxResult.No)
return;*/
}
var xmlRecipe = CurrentRecipe.GetXmlString();
InvokeClient.Instance.Service.DoOperation($"PM1.ReloadRecipe", xmlRecipe);
//InvokeClient.Instance.Service.DoOperation($"PM2.ReloadRecipe");
}
public void SaveToBaselineRecipe()
{
if (string.IsNullOrEmpty(CurrentRecipe.Name))
{
DialogBox.ShowError("Recipe name can't be empty");
return;
}
// 如果配方没变,不需要推送
if (!CurrentRecipe.IsChanged)
{
DialogBox.ShowInfo("The recipe does not change.");
return;
}
if (!CurrentRecipe.Validate())
{
var ret = DialogBox.ShowDialog(DialogButton.Yes | DialogButton.No, DialogType.WARNING,
$"{CurrentRecipe.ValidationErrorSummary}\r\n Are you sure to save to baseline recipe?");
if (ret == DialogButton.No)
return;
}
var result = false;
CurrentRecipe.Revisor = BaseApp.Instance.UserContext.LoginName;
CurrentRecipe.ReviseTime = DateTime.Now;
var recipeProvider = new RecipeProvider();
result = recipeProvider.WriteRecipeFile(CurrentRecipe.PrefixPath, CurrentRecipe.Name, CurrentRecipe.GetXmlString());
if (result)
{
CurrentRecipe.MarkAsSaved();
}
else
{
MessageBox.Show("Save failed!");
}
}
/// <summary>
/// 重新加载配方,当前修改的参数被抛弃。
/// </summary>
public void RestoreToBaselineRecipe()
{
// 如果改变,提示
if (CurrentRecipe.IsChanged)
{
if (DialogBox.Confirm(
"The recipe has changed, are you sure to discard changes and reload baseline recipe?") == false)
return;
}
if (CurrentRecipe != null
&& !string.IsNullOrEmpty(CurrentRecipe.FullName))
_progressLoadRecipe.Report(CurrentRecipe.FullName);
}
/// <summary>
/// 根据配置获取Cascade方式呈现Recipe的Dispatcher或返回null。
/// </summary>
/// <returns></returns>
private static Dispatcher GetLoadingDispatcher()
{
// 判断Step呈现方式
var isCascadeLoading = (bool)QueryDataClient.Instance.Service.GetConfig("System.RecipeCascadeLoading");
var dispatcher = isCascadeLoading ? Application.Current?.Dispatcher : null;
if (dispatcher == null || !dispatcher.CheckAccess())
return null;
return dispatcher;
}
#region Recipe相关控制函数
public void UpdateRecipeFormat()
{
CurrentRecipe = new RecipeData(_recipeGasFlowCalculator);
CurrentRecipe.BuildFormat($"Sic\\Process", "PM1", BaseApp.Instance.UserContext.RoleName);
}
/// <summary>
/// 根据权限设置Recipe参数的可见性。
/// </summary>
private void SetRecipeValueVisibilityByCurrentRole()
{
// 是否在编辑器中隐藏Recipe参数值
// CurrentRecipe.Steps.IsHideValue = _isHideRecipeValue; // 当权限为None时隐藏其它时显示。
// 白名单的Param显示出来
ApplyRecipeCellAccessPermissionWhitelist();
}
/// <summary>
/// 从数据库读取单元格访问白名单。
/// </summary>
/// <returns></returns>
private DataTable ReadRecipeCellAccessPermissionWhitelist()
{
if (CurrentRecipe == null)
return null;
var cmd = $"select * from recipe_cell_access_permission_whitelist where \"recipeName\" = '{CurrentRecipe.FullName}'";
var dt = QueryDataClient.Instance.Service.QueryData(cmd);
return dt;
}
/// <summary>
/// 如果Recipe参数设置为隐藏将白名单中的单元格显示出来。
/// </summary>
private void ApplyRecipeCellAccessPermissionWhitelist()
{
/*var dt = ReadRecipeCellAccessPermissionWhitelist();
if (dt != null && dt.Rows.Count > 0)
{
foreach (DataRow dataRow in dt.Rows)
{
var stepUid = dataRow["stepUid"].ToString();
var controlName = dataRow["columnName"].ToString();
var step = CurrentRecipe.Steps.FirstOrDefault(s => s.StepUid == stepUid);
var param = step?.FirstOrDefault(p => p.Name == controlName);
if (param != null)
param.IsHideValue = false;
}
}*/
}
/// <summary>
/// 正在工艺中的Recipe Step发生改变。
/// </summary>
/// <param name="currentStepNum"></param>
private void RecipeStepInProcessChanged(int currentStepNum)
{
UpdateRecipeStepProcessedStatus(currentStepNum);
}
/// <summary>
/// 更新Recipe步骤。
/// </summary>
/// <param name="currentStepNum"></param>
private void UpdateRecipeStepProcessedStatus(int currentStepNum)
{
if (CurrentRecipe == null)
return;
if (CurrentRecipe.Steps.Count <= 0)
return;
// Recipe不是当前正在运行的Recipe。
if (CurrentRecipe.FullName != DisplayingRecipeName)
return;
foreach (var step in CurrentRecipe.Steps)
{
if (step.StepNo.HasValue)
{
if (step.StepNo < currentStepNum)
step.IsProcessed = true;
else if (step.StepNo == currentStepNum)
{
if (IsPMProcess)
step.IsProcessed = false;
else
step.IsProcessed = true;
}
else
{
step.IsProcessed = false;
}
}
}
// 自动滚到当前做工艺的Step
var dg = ((PMProcessView)View)?.dgCustom;
if (currentStepNum > 0)
{
var stepScrollTo = currentStepNum - 1;
if (stepScrollTo < 0)
stepScrollTo = 0;
dg?.ScrollToRecipeStep(CurrentRecipe.Steps[stepScrollTo]);
}
}
/// <summary>
/// 在UI线程加载Recipe
/// </summary>
/// <param name="recipeName"></param>
private void ProgLoadRecipeOnUiThread(string recipeName)
{
lock (_lockerLoadingRecipe)
{
if (IsRecipeLoading)
return;
IsRecipeLoading = true;
NotifyOfPropertyChange(nameof(IsSelectButtonEnable));
}
if (recipeName.StartsWith("Sic\\Process"))
{
CurrentProcessType = "Process";
}
else if (recipeName.StartsWith("Sic\\Routine"))
{
CurrentProcessType = "Routine";
}
//UpdateRecipeFormat();
LoadRecipe(recipeName).ContinueWith(t =>
{
if (!t.IsCanceled && !t.IsFaulted && t.IsCompleted)
{
Application.Current?.Dispatcher.Invoke(() =>
{
UpdateRecipeStepProcessedStatus(RecipeStepNumber);
});
}
}).ContinueWith(t =>
{
Application.Current?.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
lock (_lockerLoadingRecipe)
{
IsRecipeLoading = false;
}
}));
});
}
#endregion
private async Task LoadRecipe(string selectedRecipePath)
{
CurrentRecipe.Clear();
var array = selectedRecipePath.Split(new char[] { '\\' });
string recipeName = array[array.Length - 1];
string prefixPath = selectedRecipePath.Replace(recipeName, "").TrimEnd('\\');
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;
await CurrentRecipe.LoadFile(prefixPath, recipeName, recipeContent,
SystemName, GetLoadingDispatcher());
// 显示Cell访问白名单中的参数
SetRecipeValueVisibilityByCurrentRole();
}
public void StartProcess()
{
if (IsEngMode)
{
DialogBox.ShowError("Interlock is bypassed, can not start process.");
return;
}
var ret = DialogBox.ShowDialog(DialogButton.Yes | DialogButton.No, DialogType.WARNING, "Please Check All Gas Ready Before Start Process!\r\n\r\nAre you sure to start process?");
if (ret == DialogButton.No)
return;
var array = DisplayingRecipeName.Split(new char[] { '\\' });
if (array[1] == "Process")
{
InvokeClient.Instance.Service.DoOperation($"{SystemName}.RunRecipe", DisplayingRecipeName, false, true);
}
else if (array[1] == "Routine")
{
InvokeClient.Instance.Service.DoOperation($"{SystemName}.RunPMMacro", DisplayingRecipeName);
}
}
public void Skip()
{
InvokeClient.Instance.Service.DoOperation($"{SystemName}.RecipeSkipStep");
}
public void Stop()
{
InvokeClient.Instance.Service.DoOperation($"{SystemName}.Abort");
}
public void Pause()
{
InvokeClient.Instance.Service.DoOperation($"{SystemName}.Pause");
}
public void Continue()
{
InvokeClient.Instance.Service.DoOperation($"{SystemName}.Continue", "Step continue");
}
public void Abort()
{
InvokeClient.Instance.Service.DoOperation($"{SystemName}.Abort");
}
#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
{
int mode = (int)TC1HeaterMode;
return Enum.GetName(typeof(DicMode.HeaterControlMode), mode);
}
}
[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(Color.FromRgb(0, 0, 0));
}
else
{
return new SolidColorBrush(Color.FromRgb(255, 0, 0));
}
}
}
public SolidColorBrush C2H4Color
{
get
{
if (IsC2H4RunMode)
{
return new SolidColorBrush(Color.FromRgb(0, 0, 0));
}
else
{
return new SolidColorBrush(Color.FromRgb(255, 0, 0));
}
}
}
public SolidColorBrush SIH4Color
{
get
{
if (IsSiH4RunMode)
{
return new SolidColorBrush(Color.FromRgb(0, 0, 0));
}
else
{
return new SolidColorBrush(Color.FromRgb(255, 0, 0));
}
}
}
public SolidColorBrush HCLColor
{
get
{
if (IsHCLRunMode)
{
return new SolidColorBrush(Color.FromRgb(0, 0, 0));
}
else
{
return new SolidColorBrush(Color.FromRgb(255, 0, 0));
}
}
}
public SolidColorBrush TMAColor
{
get
{
if (IsTMARunMode)
{
return new SolidColorBrush(Color.FromRgb(0, 0, 0));
}
else
{
return new SolidColorBrush(Color.FromRgb(255, 0, 0));
}
}
}
public SolidColorBrush TCSColor
{
get
{
if (IsTCSRunMode)
{
return new SolidColorBrush(Color.FromRgb(0, 0, 0));
}
else
{
return new SolidColorBrush(Color.FromRgb(255, 0, 0));
}
}
}
public SolidColorBrush PN2FlowColor
{
get
{
if (IsPN2RunMode)
{
return new SolidColorBrush(Color.FromArgb(255, 0, 255, 255));
}
else
{
return new SolidColorBrush(Color.FromArgb(255, 190, 190, 190));
}
}
}
public SolidColorBrush C2H4FlowColor
{
get
{
if (IsC2H4RunMode)
{
return new SolidColorBrush(Color.FromArgb(255, 0, 255, 255));
}
else
{
return new SolidColorBrush(Color.FromArgb(255, 190, 190, 190));
}
}
}
public SolidColorBrush SIH4FlowColor
{
get
{
if (IsSiH4RunMode)
{
return new SolidColorBrush(Color.FromArgb(255, 0, 255, 255));
}
else
{
return new SolidColorBrush(Color.FromArgb(255, 190, 190, 190));
}
}
}
public SolidColorBrush HCLFlowColor
{
get
{
if (IsHCLRunMode)
{
return new SolidColorBrush(Color.FromArgb(255, 0, 255, 255));
}
else
{
return new SolidColorBrush(Color.FromArgb(255, 190, 190, 190));
}
}
}
public SolidColorBrush TMAFlowColor
{
get
{
if (IsTMARunMode)
{
return new SolidColorBrush(Color.FromArgb(255, 0, 255, 255));
}
else
{
return new SolidColorBrush(Color.FromArgb(255, 190, 190, 190));
}
}
}
public SolidColorBrush TCSFlowColor
{
get
{
if (IsTCSRunMode)
{
return new SolidColorBrush(Color.FromArgb(255, 0, 255, 255));
}
else
{
return new SolidColorBrush(Color.FromArgb(255, 190, 190, 190));
}
}
}
#endregion
public bool IsPN2RunMode => V37s.IsOpen && (V39.IsOpen || V40.IsOpen);//N2FlowMode == "Run";按照洪膺要求修改 2023年6月9日10:34:54
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;
[Subscription("Flow.Ar_Run.FeedBack")]
public double ArFlow_Run { get; set; }
[Subscription("Flow.Ar_Vent.FeedBack")]
public double ArFlow_Vent { get; set; }
public double ArFlow => ArFlow_Run>0 ? ArFlow_Run : ArFlow_Vent;
public double ArMol => GetMol(ArFlow_Run);
[Subscription("Flow.H2_Run.FeedBack")]
public double H2_Run { get; set; }
[Subscription("Flow.H2_Vent.FeedBack")]
public double H2_Vent { get; set; }
public double H2Flow => H2_Run>0 ? H2_Run : H2_Vent;
public double H2Mol => GetMol(H2_Run);
[Subscription("Flow.PN2_Run.FeedBack")]
public double PN2_Run { get; set; }
[Subscription("Flow.PN2_Vent.FeedBackSpecial")]
public double PN2_Vent { get; set; }
public double PN2Flow => PN2_Run + PN2_Vent;//=> GetPN2MFCFlow(IsPN2RunMode) * _pn2FlowRatio;
public double PN2Mol => GetMol(PN2Flow);
[Subscription("Flow.HCL_Run.FeedBack")]
public double HCL_Run { get; set; }
[Subscription("Flow.HCL_Vent.FeedBack")]
public double HCL_Vent { get; set; }
public double HCLFlow => HCL_Run + HCL_Vent;
public double HCLMol => GetMol(HCLFlow);
[Subscription("Flow.SiH4_Run.FeedBack")]
public double SiH4_Run { get; set; }
[Subscription("Flow.SiH4_Vent.FeedBack")]
public double SiH4_Vent { get; set; }
public double SiH4Flow => SiH4_Run + SiH4_Vent;
public double SIH4Mol => GetMol(SiH4Flow);
[Subscription("Flow.C2H4_Run.FeedBack")]
public double C2H4_Run { get; set; }
[Subscription("Flow.C2H4_Vent.FeedBack")]
public double C2H4_Vent { get; set; }
public double C2H4Flow => C2H4_Run + C2H4_Vent;
public double C2H4Mol => GetMol(C2H4Flow);
[Subscription("Flow.TCS_Run.FeedBack")]
public double TCS_Run { get; set; }
[Subscription("Flow.TCS_Vent.FeedBack")]
public double TCS_Vent { get; set; }
public double TCSFlow => TCS_Run + TCS_Vent;
public double TCSMol => GetMol(TCSFlow);
[Subscription("Flow.TMA_Run.FeedBack")]
public double TMA_Run { get; set; }
[Subscription("Flow.TMA_Vent.FeedBack")]
public double TMA_Vent { get; set; }
public double TMAFlow => TMA_Run + TMA_Vent;
public double TMAMol => GetMol(TMAFlow);
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_Run > 0;
public bool ISH2Flow => H2_Run > 0;
public bool ISTCSFlow => TCSFlow > 0 && IsTCSRunMode;
public bool ISTMAFlow => TMAFlow > 0 && IsTMARunMode;
private double GetMol(double fedback)
{
return fedback / 1000 / 22.4141;
}
#region
/// <summary>
/// 返回ViewModel绑定的视图对象。
/// </summary>
public PMProcessView ViewWin { get; private set; }
public DateTime StartDateTime
{
get => ViewWin.wfTimeFrom.Value;
set
{
ViewWin.wfTimeFrom.Value = value;
}
}
public DateTime EndDateTime
{
get => ViewWin.wfTimeTo.Value;
set
{
ViewWin.wfTimeTo.Value = value;
}
}
private string _mfcManagerDataFlow;
[Subscription("MfcManager.DataFlow")]
public string MfcManagerDataFlow
{
get => _mfcManagerDataFlow;
set
{
if (_mfcManagerDataFlow != value && value != null)
{
DataFlowList = JsonConvert.DeserializeObject<List<DataFlow>>(value);
}
_mfcManagerDataFlow = value;
}
}
public List<DataFlow> DataFlowList { get; set; }
public List<string> FlowNameList { get; set; } = new List<string>()
{
"All",
"Ar",
"H2",
"C2H4",
"SiH4",
"HCL",
"PN2",
"TCS",
"TMA"
};
public string FlowName { get; set; }
private string CacheName;
private DateTime CacheStartDateTime;
private DateTime CacheEndDateTime;
public void Query()
{
if (FlowName is null)
{
MessageBox.Show("查询名称为空");
return;
}
if (CacheStartDateTime== StartDateTime && CacheEndDateTime == EndDateTime && CacheName == FlowName)
{
MessageBox.Show("重复查询");
return;
}
if (StartDateTime > EndDateTime)
{
MessageBox.Show("time range invalid, start time should be early than end time.", "Error",
MessageBoxButton.OK,
MessageBoxImage.Error);
return;
}
InvokeClient.Instance.Service.DoOperation($"{SystemName}.FlowName.Query", new object[] { FlowName, StartDateTime, EndDateTime });
CacheStartDateTime = StartDateTime;
CacheEndDateTime = EndDateTime;
CacheName = FlowName;
}
#endregion
/// <summary>
/// 打开 ProcessMonitor
/// </summary>
public void ShowMonitorWindow()
{
// 给 OverviewViewModel 发消息打开Monitor窗口。
if (EventAggregator?.HandlerExistsFor(typeof(ShowCloseMonitorWinEvent)) == true)
EventAggregator?.PublishOnUIThread(new ShowCloseMonitorWinEvent(true));
else
MessageBox.Show("The process has not been activated, please open Operation->Overview tab to activate the process.", "Warn",
MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
}