2023-06-29 11:58:56 +08:00
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 ;
2023-08-31 15:22:18 +08:00
using System.Diagnostics ;
2023-06-29 11:58:56 +08:00
using System.Threading.Tasks ;
2023-08-01 17:09:30 +08:00
using Aitex.Core.Common.DeviceData.IoDevice ;
2023-06-29 11:58:56 +08:00
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 Aitex.Core.RT.Device.PmDevices ;
2023-07-16 16:24:26 +08:00
using MECF.Framework.Common.Aitex.Core.Common.DeviceData ;
2023-08-08 21:15:05 +08:00
using MECF.Framework.Common.Equipment ;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.GasFlow ;
using System.Threading ;
2023-08-09 16:12:12 +08:00
using Sicentury.Core.EventArgs ;
2023-08-10 10:05:26 +08:00
using System.Linq ;
2023-08-15 15:36:38 +08:00
using Aitex.Core.RT.DataCenter ;
2023-06-29 11:58:56 +08:00
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 ( ) ;
2023-08-10 16:18:48 +08:00
CancellationTokenSource cts = new CancellationTokenSource ( ) ;
2023-06-29 11:58:56 +08:00
public string title { get ; set ; } = "123" ;
public PMProcessViewModel ( )
{
_recipeGasFlowCalculator = IoC . Get < IRecipeGasFlowCalculator > ( ) ;
2023-08-09 16:12:12 +08:00
IsBusyGasFlowSum = false ;
_busyIndicatorContentExport = new Progress < ProgressUpdatingEventArgs > ( e = >
{
IsBusyGasFlowSum = e . Message = = "" ? false : true ;
BusyIndicatorContent = e . Message ;
} ) ;
2023-06-29 11:58:56 +08:00
}
#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 ( ) ;
}
}
2023-08-15 15:36:38 +08:00
2023-06-29 11:58:56 +08:00
[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" ;
2023-08-08 21:15:05 +08:00
2023-06-29 11:58:56 +08:00
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 ;
/ /
2023-08-22 16:48:45 +08:00
public RecipeData CurrentRecipe { get ; set ; } = new RecipeData ( null , RecipeType . Process ) ;
2023-06-29 11:58:56 +08:00
public List < EditorDataGridTemplateColumnBase > Columns { get ; set ; } = new List < EditorDataGridTemplateColumnBase > ( ) ;
private RecipeFormatBuilder _columnBuilder = new RecipeFormatBuilder ( ) ;
public bool IsSelectButtonEnable = > ! string . IsNullOrEmpty ( Status ) & & ! Status . Equals ( "Process" )
2023-08-08 21:15:05 +08:00
& & ! Status . Equals ( "PreProcess" ) & & ! Status . Equals ( "PostProcess" ) & & ! Status . Equals ( "Paused" )
2023-07-03 15:14:14 +08:00
& & ! IsOnline & & ! IsRecipeLoading ;
2023-08-08 21:15:05 +08:00
2023-06-29 11:58:56 +08:00
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" ) & &
2023-07-03 15:15:20 +08:00
! Status . Equals ( "Paused" ) & & ! IsOnline & & ! IsRecipeLoading ; // !IsProcessRunning;
2023-08-08 21:15:05 +08:00
2023-06-29 11:58:56 +08:00
public bool IsStopButtonEnable = > ! string . IsNullOrEmpty ( Status ) & & ( Status . Equals ( "Process" ) | | Status . Equals ( "PMMacro" ) ) & & ! IsOnline ;
2023-08-08 21:15:05 +08:00
2023-06-29 11:58:56 +08:00
public bool IsAbortButtonEnable = > ! string . IsNullOrEmpty ( Status ) & & ( Status . Equals ( "Process" ) | | Status . Equals ( "PMMacro" ) ) & & ! IsOnline ; //|| Status.Equals("PreProcess") || Status.Equals("PostProcess") || Status.Equals("Paused"));//IsProcessRunning;
2023-08-08 21:15:05 +08:00
2023-06-29 11:58:56 +08:00
public bool IsPauseButtonEnable = > ! string . IsNullOrEmpty ( Status ) & & ( Status . Equals ( "Process" ) | | Status . Equals ( "PMMacro" ) ) & & ! IsOnline ;
2023-08-08 21:15:05 +08:00
2023-06-29 11:58:56 +08:00
public bool IsSkipButtonEnable = > ! string . IsNullOrEmpty ( Status ) & & Status . Equals ( "Process" ) & & ! IsOnline ;
2023-08-08 21:15:05 +08:00
2023-06-29 11:58:56 +08:00
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 ;
2023-07-03 15:02:44 +08:00
selectedRecipe = recipeName ;
2023-06-29 11:58:56 +08:00
}
// 更新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 ( ) ;
}
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 ( 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 ) ;
}
public void SelectRecipe ( )
{
2023-08-22 16:48:45 +08:00
var dialog = new RecipeSelectDialogViewModel ( false , false , RecipeType . Process ) ;
2023-06-29 11:58:56 +08:00
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 ( ) ;
2023-08-28 09:14:06 +08:00
InvokeClient . Instance . Service . DoOperation ( $"{SystemName}.ReloadRecipe" , xmlRecipe ) ;
2023-06-29 11:58:56 +08:00
//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 ( )
{
2023-08-22 16:48:45 +08:00
CurrentRecipe = new RecipeData ( _recipeGasFlowCalculator , RecipeType . Process ) ;
2023-08-16 10:28:19 +08:00
CurrentRecipe . BuildFormat ( $"Sic\\Process" , SystemName , BaseApp . Instance . UserContext . RoleName ) ;
2023-06-29 11:58:56 +08:00
}
/// <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 ( ) ;
}
2023-07-03 15:02:44 +08:00
public void StartProcess ( )
2023-06-29 11:58:56 +08:00
{
2023-08-31 15:22:18 +08:00
var pollBypassInterlock = $"{SystemName}.IsBypassInterlock" ;
var pollBypassEnableTable = $"{SystemName}.IsBypassEnableTable" ;
var pollIsService = $"{SystemName}.IsService" ;
var data = QueryDataClient . Instance . Service . PollData ( new [ ]
{ pollBypassInterlock , pollBypassEnableTable , pollIsService } ) ;
Debug . Assert ( data ! = null , "Unable to poll data from RT." ) ;
Debug . Assert ( data . Count = = 3 , "The count of polled data is incorrect." ) ;
if ( ( bool ) data [ pollBypassInterlock ] | | ( bool ) data [ pollBypassEnableTable ] )
{
DialogBox . ShowError ( "Interlock or EnableTable is bypassed, can not start process." ) ;
return ;
}
if ( ( bool ) data [ pollIsService ] )
2023-07-03 15:02:44 +08:00
{
2023-08-31 15:22:18 +08:00
DialogBox . ShowError ( $"{SystemName} is in Service Mode, can not start process." ) ;
2023-07-03 15:02:44 +08:00
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?" ) ;
2023-06-29 11:58:56 +08:00
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 ;
2023-07-16 16:24:26 +08:00
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.Ar_Run.FeedBack")]
2023-06-29 11:58:56 +08:00
public double ArFlow_Run { get ; set ; }
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.Ar_Vent.FeedBack")]
2023-06-29 11:58:56 +08:00
public double ArFlow_Vent { get ; set ; }
2023-08-08 21:15:05 +08:00
public double ArFlow = > ArFlow_Run > 0 ? ArFlow_Run : ArFlow_Vent ;
2023-06-29 11:58:56 +08:00
public double ArMol = > GetMol ( ArFlow_Run ) ;
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.H2_Run.FeedBack")]
2023-06-29 11:58:56 +08:00
public double H2_Run { get ; set ; }
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.H2_Vent.FeedBack")]
2023-06-29 11:58:56 +08:00
public double H2_Vent { get ; set ; }
2023-08-08 21:15:05 +08:00
public double H2Flow = > H2_Run > 0 ? H2_Run : H2_Vent ;
2023-06-29 11:58:56 +08:00
public double H2Mol = > GetMol ( H2_Run ) ;
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.PN2_Run.FeedBack")]
2023-06-29 11:58:56 +08:00
public double PN2_Run { get ; set ; }
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.PN2_Vent.FeedBackSpecial")]
2023-06-29 11:58:56 +08:00
public double PN2_Vent { get ; set ; }
public double PN2Flow = > PN2_Run + PN2_Vent ; //=> GetPN2MFCFlow(IsPN2RunMode) * _pn2FlowRatio;
public double PN2Mol = > GetMol ( PN2Flow ) ;
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.HCL_Run.FeedBack")]
2023-06-29 11:58:56 +08:00
public double HCL_Run { get ; set ; }
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.HCL_Vent.FeedBack")]
2023-06-29 11:58:56 +08:00
public double HCL_Vent { get ; set ; }
public double HCLFlow = > HCL_Run + HCL_Vent ;
public double HCLMol = > GetMol ( HCLFlow ) ;
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.SiH4_Run.FeedBack")]
2023-06-29 11:58:56 +08:00
public double SiH4_Run { get ; set ; }
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.SiH4_Vent.FeedBack")]
2023-06-29 11:58:56 +08:00
public double SiH4_Vent { get ; set ; }
public double SiH4Flow = > SiH4_Run + SiH4_Vent ;
public double SIH4Mol = > GetMol ( SiH4Flow ) ;
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.C2H4_Run.FeedBack")]
2023-06-29 11:58:56 +08:00
public double C2H4_Run { get ; set ; }
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.C2H4_Vent.FeedBack")]
2023-06-29 11:58:56 +08:00
public double C2H4_Vent { get ; set ; }
public double C2H4Flow = > C2H4_Run + C2H4_Vent ;
public double C2H4Mol = > GetMol ( C2H4Flow ) ;
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.TCS_Run.FeedBack")]
2023-06-29 11:58:56 +08:00
public double TCS_Run { get ; set ; }
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.TCS_Vent.FeedBack")]
2023-06-29 11:58:56 +08:00
public double TCS_Vent { get ; set ; }
public double TCSFlow = > TCS_Run + TCS_Vent ;
public double TCSMol = > GetMol ( TCSFlow ) ;
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.TMA_Run.FeedBack")]
2023-06-29 11:58:56 +08:00
public double TMA_Run { get ; set ; }
2023-07-15 10:37:45 +08:00
[Subscription("GasRealTimeFlow.TMA_Vent.FeedBack")]
2023-06-29 11:58:56 +08:00
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 ;
}
2023-08-01 17:09:30 +08:00
#region Process Data Statistic
[Subscription("ProcessDataStat.RealtimeList")]
public List < AITProcessRunData > ProcessRunDataList { get ; set ; }
#endregion
2023-06-29 11:58:56 +08:00
#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 ;
}
}
2023-07-16 21:26:41 +08:00
private List < string > _gasNameList ;
[Subscription("PMGasNameList")]
public List < string > GasNameList
2023-06-29 11:58:56 +08:00
{
2023-07-16 21:26:41 +08:00
get = > _gasNameList ;
2023-06-29 11:58:56 +08:00
set
{
2023-08-10 16:18:48 +08:00
_gasNameList ? ? = value ;
2023-07-16 21:26:41 +08:00
}
}
2023-06-29 11:58:56 +08:00
2023-08-08 21:15:05 +08:00
private List < GasFlowSum > _RTgasFlowSumList ;
/// <summary>
/// 从真值表中初始化集合对象
/// </summary>
2023-07-16 21:26:41 +08:00
[Subscription("PMGasFlowSumList")]
2023-08-08 21:15:05 +08:00
public List < GasFlowSum > _RTGasFlowSumList
2023-07-16 21:26:41 +08:00
{
2023-08-08 21:15:05 +08:00
get = > _RTgasFlowSumList ;
2023-07-16 21:26:41 +08:00
set
{
2023-08-10 16:18:48 +08:00
_RTgasFlowSumList ? ? = value ;
2023-08-08 21:15:05 +08:00
}
}
2023-07-17 16:30:42 +08:00
2023-08-08 21:15:05 +08:00
private List < GasFlowSum > _gasFlowSumList ;
public List < GasFlowSum > GasFlowSumList
{
get
{
2023-08-10 16:18:48 +08:00
_gasFlowSumList ? ? = _RTGasFlowSumList ; //使用真值表初始化集合
2023-08-08 21:15:05 +08:00
return _gasFlowSumList ;
}
set
{
_gasFlowSumList = value ;
2023-08-10 16:18:48 +08:00
NotifyOfPropertyChange ( nameof ( GasFlowSumList ) ) ;
2023-06-29 11:58:56 +08:00
}
}
2023-08-09 16:12:12 +08:00
private bool _isBusyGasFlowSum ;
public bool IsBusyGasFlowSum
{
get = > _isBusyGasFlowSum ;
set
{
_isBusyGasFlowSum = value ;
NotifyOfPropertyChange ( nameof ( IsBusyGasFlowSum ) ) ;
}
}
2023-08-08 21:15:05 +08:00
2023-06-29 11:58:56 +08:00
2023-08-09 16:12:12 +08:00
private string _busyIndicatorMessage ;
public string BusyIndicatorContent
2023-06-29 11:58:56 +08:00
{
2023-08-09 16:12:12 +08:00
get = > _busyIndicatorMessage ;
set
{
_busyIndicatorMessage = value ;
NotifyOfPropertyChange ( nameof ( BusyIndicatorContent ) ) ;
}
}
2023-07-17 15:22:15 +08:00
2023-08-09 16:12:12 +08:00
private readonly IProgress < ProgressUpdatingEventArgs > _busyIndicatorContentExport ;
2023-07-17 15:22:15 +08:00
2023-08-09 16:12:12 +08:00
public void Query ( )
{
2023-06-29 11:58:56 +08:00
if ( StartDateTime > EndDateTime )
{
MessageBox . Show ( "time range invalid, start time should be early than end time." , "Error" ,
MessageBoxButton . OK ,
MessageBoxImage . Error ) ;
return ;
}
2023-08-09 16:12:12 +08:00
cts = new CancellationTokenSource ( ) ;
2023-08-10 16:18:48 +08:00
Task . Run ( ( ) = >
2023-08-09 16:12:12 +08:00
{
2023-08-10 16:18:48 +08:00
_busyIndicatorContentExport . Report ( new ProgressUpdatingEventArgs ( 20 , 100 , "Exporting Start ..." ) ) ;
Query ( SystemName , StartDateTime , EndDateTime ) ;
} ) ;
2023-08-08 21:15:05 +08:00
}
public void CancelQuery ( )
{
2023-08-09 16:12:12 +08:00
Task . Run ( ( ) = >
{
if ( cts ? . Token . CanBeCanceled = = true )
{
cts . Cancel ( ) ;
}
Thread . Sleep ( 200 ) ;
_busyIndicatorContentExport . Report ( new ProgressUpdatingEventArgs ( 100 , 100 , "" ) ) ;
} ) ;
2023-08-08 21:15:05 +08:00
}
2023-08-10 16:18:48 +08:00
public void Query ( string module , DateTime start , DateTime end )
2023-08-09 16:12:12 +08:00
{
var daySlices = DateRangeHelper . SplitInToHours ( new DateRangeHelper ( start , end ) , 12 ) ;
2023-08-10 16:18:48 +08:00
List < List < GasFlowSum > > gasFlowRunVent = new List < List < GasFlowSum > > ( ) ;
2023-08-08 21:15:05 +08:00
2023-08-10 16:18:48 +08:00
//按天查询数据库, 单天返回数据类型为List<GasFlowSum>
2023-08-09 16:12:12 +08:00
foreach ( var daySlice in daySlices )
{
if ( cts . IsCancellationRequested )
2023-08-10 16:18:48 +08:00
return ;
gasFlowRunVent . Add ( GasFlowSqlHelp . GetDayGasFlowSum ( daySlice , SystemName , GasFlowSumList ) ) ;
_busyIndicatorContentExport . Report ( new ProgressUpdatingEventArgs ( 200 , 200 , $"{daySlice}" ) ) ;
2023-08-09 16:12:12 +08:00
}
2023-08-10 16:18:48 +08:00
List < GasFlowSum > dayGasFlowList = _RTGasFlowSumList ;
2023-08-08 21:15:05 +08:00
2023-08-10 16:18:48 +08:00
//解析数据库返回的数据
foreach ( var items in gasFlowRunVent )
{
foreach ( var item in items )
{
var gasFlowSum = dayGasFlowList . Where ( obj = > item . Name . Contains ( obj . Name ) ) . First ( ) ;
if ( item . Name . Contains ( "Run" ) )
gasFlowSum . RunVolume + = item . Volume ;
else
gasFlowSum . VentVolume + = item . Volume ;
}
}
2023-08-10 10:05:26 +08:00
2023-08-10 16:18:48 +08:00
//使用公式转换单位
2023-09-11 13:37:12 +08:00
double baseValue = 0.0166667 * Math . Pow ( 10 , - 6 ) ;
2023-08-10 16:18:48 +08:00
foreach ( var item in dayGasFlowList )
{
item . RunVolume = item . RunVolume * baseValue ;
item . VentVolume = item . VentVolume * baseValue ;
item . Volume = item . RunVolume + item . VentVolume ;
}
2023-08-08 21:15:05 +08:00
2023-08-10 16:18:48 +08:00
GasFlowSumList = dayGasFlowList ;
_busyIndicatorContentExport . Report ( new ProgressUpdatingEventArgs ( 100 , 100 , "" ) ) ;
}
2023-08-09 16:12:12 +08:00
2023-08-10 16:18:48 +08:00
2023-06-29 11:58:56 +08:00
#endregion
/// <summary>
/// 打开 ProcessMonitor
/// </summary>
public void ShowMonitorWindow ( )
{
2023-07-03 17:07:43 +08:00
// 给 OverviewViewModel 发消息, 打开Monitor窗口。
if ( EventAggregator ? . HandlerExistsFor ( typeof ( ShowCloseMonitorWinEvent ) ) = = true )
EventAggregator ? . PublishOnUIThread ( new ShowCloseMonitorWinEvent ( true ) ) ;
2023-06-29 11:58:56 +08:00
else
2023-07-03 17:07:43 +08:00
MessageBox . Show ( "The process has not been activated, please open Operation->Overview tab to activate the process." , "Warn" ,
MessageBoxButton . OK , MessageBoxImage . Warning ) ;
2023-06-29 11:58:56 +08:00
}
}
}