2026-06-15 10:56:30 +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 ;
using System.Diagnostics ;
using System.Threading.Tasks ;
using Aitex.Core.Common.DeviceData.IoDevice ;
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 Aitex.Core.RT.Device.PmDevices ;
using MECF.Framework.Common.Aitex.Core.Common.DeviceData ;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.GasFlow ;
using System.Threading ;
using Sicentury.Core.EventArgs ;
using System.Linq ;
using MECF.Framework.Common.Account.Permissions ;
using MECF.Framework.UI.Client.Core ;
using MECF.Framework.UI.Core.Accounts ;
using MECF.Framework.Common.MECF.Framework.Common.RecipeCenter.Recipe ;
using MECF.Framework.Common.Equipment ;
using static MECF . Framework . Common . Aitex . Core . RT . EMS . MaintainerItemCollection ;
using SciChart.Core.Extensions ;
namespace MECF.Framework.UI.Client.CenterViews.Modules.PM
{
public class PMProcessViewModel : SicModuleUIViewModelBase , ISupportMultipleSystem , IHandle < CommonAggregateEvents >
{
private bool _readRecipeFromLocal = true ;
private string _status = "" ;
private int _recipeStepNumber = 0 ;
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 Visibility _allowSaveRecipe = Visibility . Visible ;
private Visibility _allowRipRecipe = Visibility . Visible ;
private int x = 0 ;
private DispatcherTimer timer ;
private readonly object _lockerLoadingRecipe = new ( ) ;
private IRecipeGasFlowCalculator _recipeGasFlowCalculator ;
private string _currentProcessingRecipe ;
private string _selectedRecipe ;
private bool _needLoadRecipe = false ;
private IProgress < int > _progressRecipeStepChanged ;
private IProgress < string > _progressLoadRecipe ;
private CancellationTokenSource _cts ;
public PMProcessViewModel ( )
{
IsBusyGasFlowSum = false ;
_busyIndicatorContentExport = new Progress < ProgressUpdatingEventArgs > ( e = >
{
IsBusyGasFlowSum = e . Message = = "" ? false : true ;
BusyIndicatorContent = e . Message ;
} ) ;
_progressLoadRecipe = new Progress < string > ( ProgLoadRecipeOnUiThread ) ;
_progressRecipeStepChanged = new Progress < int > ( RecipeStepInProcessChanged ) ;
}
#region Properties
public bool ReadRecipeFromLocal
{
get = > _readRecipeFromLocal ;
set
{
_readRecipeFromLocal = value ;
NotifyOfPropertyChange ( ) ;
}
}
public string RecipeToolTip = > string . IsNullOrEmpty ( DisplayingRecipeName ) ? "" : ( ReadRecipeFromLocal ? "From Local" : "From Process" ) ;
public string RecipeToolTip2 = > string . IsNullOrEmpty ( DisplayingRecipeName ) ? "Local Recipe" : ( ReadRecipeFromLocal ? "Local Recipe" : "Processing Recipe" ) ;
public Visibility RecipeToolTip2Visibility = > string . IsNullOrEmpty ( DisplayingRecipeName ) ? Visibility . Hidden : Visibility . Visible ;
public Visibility AllowSaveRecipe
{
get = > _allowSaveRecipe ;
set
{
_allowSaveRecipe = value ;
NotifyOfPropertyChange ( ) ;
}
}
//public Visibility RecipeDifferenceVisiblity => CurrentRecipe.IsChanged ? Visibility.Visible : (_recipeDiff ? Visibility.Visible : Visibility.Hidden);
/// <summary>
/// 指示工艺中Recipe与local不同
/// </summary>
public Visibility RecipeDifferenceVisiblity
{
get
{
if ( CurrentRecipe ! = null
& & CurrentRecipe . FullName ! = "\\" )
{
if ( CurrentRecipe . HasHighLight | | CurrentRecipe . IsChanged )
{
return Visibility . Visible ;
}
else return Visibility . Hidden ;
}
else
return Visibility . Hidden ;
}
}
public Visibility AllowRipRecipe
{
get = > _allowRipRecipe ;
set
{
_allowRipRecipe = value ;
NotifyOfPropertyChange ( ) ;
}
}
public bool IsAllowPush = > IsPMProcess & & ( CurrentRecipe ? . IsCompatibleWithCurrentFormat ? ? false ) ;
public bool IsAllowSave = > CurrentRecipe ? . IsCompatibleWithCurrentFormat ? ? false ;
public string CarbonSource { get ; set ; }
[Subscription("IsBusy")]
public bool IsBusy { get ; set ; }
[Subscription("Status")]
public string Status
{
get = > _status ;
set
{
if ( _status ! = "Process" & & value = = "Process" )
{
ReLoadProcessingRecipe ( ) ;
}
_status = value ;
}
}
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 } ;
public string SelectedRecipe
{
set = > _selectedRecipe = value ;
get = > _selectedRecipe ;
}
[Subscription("SelectedRecipeName")]
public string CurrentProcessingRecipeName
{
get = > _currentProcessingRecipe ;
set
{
if ( _currentProcessingRecipe ! = value )
{
//ReadRecipeFromLocal = false;
_currentProcessingRecipe = value ;
//DisplayingRecipeName = value;
}
}
}
[Subscription("RecipeStepName")]
public string RecipeStepName { get ; set ; }
[Subscription("RecipeStepNumber")]
public int RecipeStepNumber
{
get = > _recipeStepNumber ;
set
{
if ( IsPMProcess )
{
if ( _recipeStepNumber ! = value )
{
_progressRecipeStepChanged . Report ( value ) ;
}
_recipeStepNumber = value ;
}
else if ( IsPreProcess )
_recipeStepNumber = 0 ;
else
_recipeStepNumber = - 1 ;
}
}
[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 = > RecipeStepNumber = = - 1 ? "--" : RecipeStepNumber . ToString ( ) ;
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 ;
InvokeClient . Instance . Service . DoOperation ( "System.SetConfig" , $"PM.{SystemName}.LastRecipeName" , value ) ;
_progressLoadRecipe . Report ( value ) ;
NotifyOfPropertyChange ( nameof ( DisplayingRecipeName ) ) ;
}
}
}
private bool _isRecipeLoading ;
public bool IsRecipeLoading
{
get = > _isRecipeLoading ;
set
{
if ( _isRecipeLoading ! = value )
{
_isRecipeLoading = value ;
NotifyOfPropertyChange ( ) ;
}
}
}
public RecipeData CurrentRecipe { get ; set ; }
public List < EditorDataGridTemplateColumnBase > Columns { get ; set ; } = new List < EditorDataGridTemplateColumnBase > ( ) ;
private RecipeFormatBuilder _recipeFormatBuilder = new ( ) ;
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 = > 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 ; }
#endregion
/// <summary>
/// 获取角色权限配置.
/// </summary>
/// <returns></returns>
private void InitPermissions ( )
{
var roleId = BaseApp . Instance . UserContext . Role . RoleId ;
_isHideRecipeValue = AccountClient . Instance . Service . GetMenuPermission ( roleId , "Recipe.Behaviour.ShowValueInProcessView" ) = = ( int ) MenuPermissionEnum . MP_NONE ;
AllowSaveRecipe = ( AccountClient . Instance . Service . GetMenuPermission ( roleId , "Recipe.Behaviour.AllowSaveInProcessView" ) ! = ( int ) MenuPermissionEnum . MP_NONE ) ? Visibility . Visible : Visibility . Hidden ;
AllowRipRecipe = ( AccountClient . Instance . Service . GetMenuPermission ( roleId , "Recipe.Behaviour.AllowRipInProcessView" ) ! = ( int ) MenuPermissionEnum . MP_NONE ) ? Visibility . Visible : Visibility . Hidden ;
}
protected override void OnActivate ( )
{
try
{
UpScConfig ( ) ;
InitPermissions ( ) ;
//if (string.IsNullOrEmpty(DisplayingRecipeName))
//{
// _needLoadRecipe = false;
// var recipeName =
// (string)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.LastRecipeName");
// DisplayingRecipeName = recipeName;
// _selectedRecipe = recipeName;
//}
//更新Recipe格式
UpdateRecipeFormat ( ) ;
// 更新Recipe参数值显示状态
SetRecipeValueVisibilityByCurrentRole ( ) ;
CarbonSource = ( string ) QueryDataClient . Instance . Service . GetConfig ( $"PM.{SystemName}.CarbonSource" ) ;
//若recipe已指定, 重新加载recipe
if ( CurrentRecipe ! = null
& & CurrentRecipe . FullName ! = "\\" )
{
var obj = QueryDataClient . Instance . Service . GetData ( $"{SystemName}.Status" ) ;
if ( obj is string status )
{
if ( status = = "Process" )
{
_status = "" ; //从Status执行加载
}
else
{
if ( ReadRecipeFromLocal )
{
_progressLoadRecipe . Report ( CurrentRecipe . FullName ) ;
}
else
{
ReLoadProcessingRecipe ( ) ;
}
//var obj2 = QueryDataClient.Instance.Service.GetData($"{SystemName}.SelectedRecipeName");
//if (obj2 !=null && obj2 is string currentRecipe)
//{
// if (currentRecipe == CurrentRecipe.FullName)
// {
// ReLoadProcessingRecipe();
// }
// else
// {
// ReadRecipeFromLocal = true;
// _progressLoadRecipe.Report(CurrentRecipe.FullName);
// }
//}
//else
//{
// ReadRecipeFromLocal = true;
// _progressLoadRecipe.Report(CurrentRecipe.FullName);
//}
}
}
}
base . OnActivate ( ) ;
}
catch ( Exception ex )
{ }
}
private void UpScConfig ( )
{
_recipeGasFlowCalculator = RecipeGasFlowCalculatorFactory . GetGasFlowCalculator ( SystemName ) ;
}
protected override void OnDeactivate ( bool close )
{
//if (RecipeDifferenceVisiblity == Visibility.Visible)
//{
// if (DialogBox.ShowDialog(DialogButton.Yes | DialogButton.No, DialogType.CONFIRM,
// $"Recipe {CurrentRecipe.Name} content is changed, quit will lose this changes, do you still want to quit?") == DialogButton.No)
// {
// base.OnDeactivate(false);
// return;
// }
//}
ActiveUpdateData = true ;
base . OnDeactivate ( close ) ;
}
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 ) ;
/ * // 如果在ReadOnly模式, 则禁止解锁Recipe。
( ( ( PMProcessView ) View ) ! ) . recipeLocker . IsEnabled = BaseApp . Instance . UserMode ! = UserMode . ReadOnly ; * /
}
public void SelectRecipe ( )
{
var dialog = new RecipeSelectDialogViewModel ( false , false , RecipeType . Process , SystemName ) ;
dialog . DisplayName = "Select Recipe" ;
var wm = new WindowManager ( ) ;
var bret = wm . ShowDialog ( dialog ) ;
if ( ( bool ) bret )
{
var recipeName = dialog . DialogResult ;
if ( ! ReadRecipeFromLocal )
{
_displayingRecipeName = "" ; //重新加载一下Recipe
}
ReadRecipeFromLocal = true ;
DisplayingRecipeName = recipeName ;
SelectedRecipe = recipeName ;
InvokeClient . Instance . Service . DoOperation ( $"{SystemName}.SelectRecipe" , 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 . IsCompatibleWithCurrentFormat )
{
DialogBox . ShowWarning ( "Recipe is incompatible,please wait recipe loading" ) ;
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 ; * /
}
if ( ! CurrentRecipe . GetXmlString ( out var xml , out var reason ) )
{
DialogBox . ShowError ( $"Unable to generate recipe content, {reason}" ) ;
return ;
}
CurrentRecipe . HighLight ( ) ;
InvokeClient . Instance . Service . DoOperation ( $"{SystemName}.ReloadRecipe" , xml , CurrentRecipe . HighlightDic ) ;
}
/// <summary>
/// 将数据保存到本地配方文件中
/// </summary>
public void SaveToBaselineRecipe ( )
{
if ( ! CurrentRecipe . IsCompatibleWithCurrentFormat )
{
DialogBox . ShowWarning ( "Recipe is incompatible,please wait recipe loading" ) ;
return ;
}
if ( string . IsNullOrEmpty ( CurrentRecipe . Name ) )
{
DialogBox . ShowError ( "Recipe name can't be empty" ) ;
return ;
}
// 如果配方没变,不需要推送
if ( RecipeDifferenceVisiblity ! = Visibility . Visible )
{
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 Local recipe?" ) ;
if ( ret = = DialogButton . No )
return ;
}
CurrentRecipe . Revisor = BaseApp . Instance . UserContext . LoginName ;
CurrentRecipe . ReviseTime = DateTime . Now ;
CopyRecipePm1ToPm2 ( CurrentRecipe ) ;
if ( ! CurrentRecipe . GetXmlString ( out var xml , out var reason ) )
{
DialogBox . ShowError ( $"Unable to generate recipe content, {reason}" ) ;
return ;
}
var recipeProvider = new RecipeProvider ( ) ;
var result = recipeProvider . WriteRecipeFile ( CurrentRecipe . PrefixPath , CurrentRecipe . Name , xml ) ;
if ( result )
CurrentRecipe . MarkAsSaved ( ) ;
else
DialogBox . ShowError ( "Unable to save recipe." ) ;
}
/// <summary>
/// 先同步CurrentRecipe在内存(界面所看到的, 不一定是XML)中PM1和PM2中的数据,
/// </summary>
/// <param name="recipe"></param>
private void CopyRecipePm1ToPm2 ( RecipeData recipe )
{
if ( ! recipe . SaveTo ( new string [ ] { "PM1" , "PM2" } , out var reason ) )
{
DialogBox . ShowError ( $"Unable to save recipe, {reason}" ) ;
return ;
}
}
/// <summary>
/// 重新加载配方,当前修改的参数被抛弃。
/// </summary>
public void RestoreToBaselineRecipe ( )
{
// 如果改变,提示
if ( RecipeDifferenceVisiblity = = Visibility . Visible )
{
if ( DialogBox . Confirm (
"The recipe has changed, are you sure to discard changes and reload baseline recipe?" ) = = false )
return ;
}
//若recipe已指定, 重新加载recipe
if ( CurrentRecipe ! = null
& & CurrentRecipe . FullName ! = "\\" )
{
var obj = QueryDataClient . Instance . Service . GetData ( $"{SystemName}.Status" ) ;
if ( obj is string status )
{
if ( status = = "Process" )
{
_status = "" ; //从Status执行加载
}
else
{
if ( ReadRecipeFromLocal )
{
_progressLoadRecipe . Report ( CurrentRecipe . FullName ) ;
}
else
{
ReLoadProcessingRecipe ( ) ;
}
}
}
}
}
/// <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 ( )
{
var role = AccountClient . Instance . Service . GetRoleByID ( BaseApp . Instance . UserContext . Role . RoleId ) ;
if ( CurrentRecipe = = null )
{
CurrentRecipe = new RecipeData ( _recipeGasFlowCalculator , RecipeType . Process ) ;
CurrentRecipe . BuildFormat ( $"Sic\\Process" , SystemName , role ) ;
}
else
{
CurrentRecipe . UpdatePermission ( role ) ;
CurrentRecipe . SetRecipeGasFlowCalculator ( _recipeGasFlowCalculator ) ;
}
}
/// <summary>
/// 根据权限设置Recipe参数的可见性。
/// </summary>
private void SetRecipeValueVisibilityByCurrentRole ( )
{
// 是否在编辑器中隐藏Recipe参数值
if ( _isHideRecipeValue ) // 当权限为None时隐藏, 其它时显示。
CurrentRecipe ? . Steps . HideValue ( ) ;
else
CurrentRecipe ? . Steps . ShowValue ( ) ;
// 白名单的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 is { 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 . ControlName = = controlName ) ;
if ( param ! = null )
param . IsHideValue = false ;
}
}
}
/// <summary>
/// 正在工艺中的Recipe Step发生改变。
/// </summary>
/// <param name="currentStepNum"></param>
private void RecipeStepInProcessChanged ( int currentStepNum )
{
UpdateRecipeStepProcessedStatus ( currentStepNum ) ;
}
private void ReLoadProcessingRecipe ( )
{
ReadRecipeFromLocal = false ;
var obj = ( string ) QueryDataClient . Instance . Service . GetData ( $"{SystemName}.SelectedRecipeName" ) ;
if ( obj ! = null )
{
_displayingRecipeName = obj ;
_progressLoadRecipe . Report ( obj ) ;
NotifyOfPropertyChange ( nameof ( DisplayingRecipeName ) ) ;
}
}
/// <summary>
/// 更新Recipe步骤。
/// </summary>
/// <param name="currentStepNum"></param>
private void UpdateRecipeStepProcessedStatus ( int currentStepNum )
{
if ( CurrentRecipe = = null )
return ;
// Recipe不是当前正在运行的Recipe。
if ( CurrentRecipe . FullName ! = DisplayingRecipeName )
return ;
CurrentRecipe . SetProcessDone ( currentStepNum ) ;
if ( CurrentRecipe . Steps . Count < = 0 )
return ;
// 自动滚到当前做工艺的Step
var dg = ( ( PMProcessView ) View ) ? . dgRecipeEditor ;
if ( currentStepNum > 0 )
{
var stepScrollTo = currentStepNum - 1 ;
if ( stepScrollTo < 0 )
stepScrollTo = 0 ;
if ( CurrentRecipe . Steps . Count > stepScrollTo ) //加载时滚动可能会报错
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 ) ) ;
}
//UpdateRecipeFormat();
LoadRecipe ( recipeName ) . ContinueWith ( t = >
{
if ( ! t . IsCanceled & & ! t . IsFaulted & & t . IsCompleted )
{
Application . Current ? . Dispatcher . Invoke ( ( ) = >
{
UpdateRecipeStepProcessedStatus ( RecipeStepNumber = = - 1 ? 0 : 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 [ ] { '\\' } ) ;
var recipeName = array . Last ( ) ;
int index = selectedRecipePath . LastIndexOf ( "\\" ) ;
var prefixPath = selectedRecipePath . Substring ( 0 , index ) ;
//var prefixPath = selectedRecipePath.Replace(recipeName, "").TrimEnd('\\');
var recipeProvider = new RecipeProvider ( ) ;
var recipeContent = recipeProvider . ReadRecipeFile ( prefixPath , recipeName ) ;
var obj = QueryDataClient . Instance . Service . GetData ( $"{SystemName}.RecipeStepList" ) ;
List < RecipeStepInfo > sinfos = new List < RecipeStepInfo > ( ) ;
if ( obj ! = null )
{
sinfos = obj as List < RecipeStepInfo > ;
}
CurrentRecipe . RecipeChamberType = _recipeFormatBuilder . RecipeChamberType ;
CurrentRecipe . RecipeVersion = _recipeFormatBuilder . RecipeVersion ;
var role = AccountClient . Instance . Service . GetRoleByID ( BaseApp . Instance . UserContext . Role . RoleId ) ;
if ( ReadRecipeFromLocal )
await CurrentRecipe . LoadFile ( prefixPath , recipeName , recipeContent ,
SystemName , role , GetLoadingDispatcher ( ) ) ;
else
await CurrentRecipe . LoadFile ( prefixPath , recipeName , recipeContent , sinfos ,
SystemName , role , GetLoadingDispatcher ( ) ) ;
// 显示Cell访问白名单中的参数
SetRecipeValueVisibilityByCurrentRole ( ) ;
}
public void StartProcess ( )
{
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." ) ;
var workenable = ( bool ) QueryDataClient . Instance . Service . GetConfig ( "System.MultiProcessMode" ) ;
if ( workenable )
{
var isConnect = ( bool ) QueryDataClient . Instance . Service . GetData ( "MultiProcessClient.IsConnected" ) ;
if ( ! isConnect )
{
DialogBox . ShowError ( "MultiProcessClient disconnected, can not start process." ) ;
return ;
}
else
{
var infos = ( string ) QueryDataClient . Instance . Service . GetData ( "MultiProcessClient.ServiceInfo" ) ;
if ( DialogBox . ShowDialog ( DialogButton . Yes | DialogButton . No , DialogType . CONFIRM , infos ) = = DialogButton . No )
{
return ;
}
}
}
if ( ( bool ) data [ pollBypassInterlock ] | | ( bool ) data [ pollBypassEnableTable ] )
{
DialogBox . ShowError ( "Interlock or EnableTable is bypassed, can not start process." ) ;
return ;
}
if ( ( bool ) data [ pollIsService ] )
{
DialogBox . ShowError ( $"{SystemName} is in Service Mode, can not start process." ) ;
return ;
}
if ( RecipeDifferenceVisiblity = = Visibility . Visible )
{
var ret1 = DialogBox . ShowDialog ( DialogButton . Yes | DialogButton . No , DialogType . WARNING , $"There are some differences with Local and Process Recipe({DisplayingRecipeName})\r\n\r\nAre you sure to start process?" ) ;
if ( ret1 = = DialogButton . No )
return ;
}
////确认同时Process的腔体数量是否达标; 配置中屏蔽此项可立即生效
//var workenable = (bool)QueryDataClient.Instance.Service.GetConfig("System.MultiProcessMode");
//if (workenable)
//{
// //先发送一次状态
// InvokeClient.Instance.Service.DoOperation("MultiProcessClient.UpdateChamberState");
// var r = QueryDataClient.Instance.Service.GetData($"MultiProcessClient.{SystemName}.CanEnterProcessNow");
// if (r == null || (bool)r == false)
// {
// DialogBox.ShowError("Can't Enter ProcessIdle because of MultiProcess Limit");
// }
//}
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 [ 2 ] = = "Process" )
{
InvokeClient . Instance . Service . DoOperation ( $"{SystemName}.RunRecipe" , DisplayingRecipeName , false , true ) ;
}
else if ( array [ 2 ] = = "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 = >
Enum . IsDefined ( typeof ( HeatStrategy ) , ( int ) TC1HeaterMode )
? Enum . GetName ( typeof ( HeatStrategy ) , ( int ) TC1HeaterMode )
: "Power" ;
[Subscription("TC2.HeaterModeSetPoint")]
public float TC2HeaterMode { get ; set ; }
public string TC2Mode = >
Enum . IsDefined ( typeof ( HeatStrategy ) , ( int ) TC2HeaterMode )
? Enum . GetName ( typeof ( HeatStrategy ) , ( int ) TC2HeaterMode )
: "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 = > IsPN2RunMode
? new SolidColorBrush ( Color . FromRgb ( 0 , 0 , 0 ) )
: new SolidColorBrush ( Color . FromRgb ( 255 , 0 , 0 ) ) ;
public SolidColorBrush C2H4Color = > IsC2H4RunMode
? new SolidColorBrush ( Color . FromRgb ( 0 , 0 , 0 ) )
: new SolidColorBrush ( Color . FromRgb ( 255 , 0 , 0 ) ) ;
public SolidColorBrush SIH4Color = > IsSiH4RunMode
? new SolidColorBrush ( Color . FromRgb ( 0 , 0 , 0 ) )
: new SolidColorBrush ( Color . FromRgb ( 255 , 0 , 0 ) ) ;
public SolidColorBrush HCLColor = > IsHCLRunMode
? new SolidColorBrush ( Color . FromRgb ( 0 , 0 , 0 ) )
: new SolidColorBrush ( Color . FromRgb ( 255 , 0 , 0 ) ) ;
public SolidColorBrush TMAColor = > IsTMARunMode
? new SolidColorBrush ( Color . FromRgb ( 0 , 0 , 0 ) )
: new SolidColorBrush ( Color . FromRgb ( 255 , 0 , 0 ) ) ;
public SolidColorBrush TCSColor = > IsTCSRunMode
? new SolidColorBrush ( Color . FromRgb ( 0 , 0 , 0 ) )
: new SolidColorBrush ( Color . FromRgb ( 255 , 0 , 0 ) ) ;
public SolidColorBrush PN2FlowColor = > IsPN2RunMode
? new SolidColorBrush ( Color . FromArgb ( 255 , 0 , 255 , 255 ) )
: new SolidColorBrush ( Color . FromArgb ( 255 , 190 , 190 , 190 ) ) ;
public SolidColorBrush C2H4FlowColor = > IsC2H4RunMode
? new SolidColorBrush ( Color . FromArgb ( 255 , 0 , 255 , 255 ) )
: new SolidColorBrush ( Color . FromArgb ( 255 , 190 , 190 , 190 ) ) ;
public SolidColorBrush SIH4FlowColor = > IsSiH4RunMode
? new SolidColorBrush ( Color . FromArgb ( 255 , 0 , 255 , 255 ) )
: new SolidColorBrush ( Color . FromArgb ( 255 , 190 , 190 , 190 ) ) ;
public SolidColorBrush HCLFlowColor = > IsHCLRunMode
? new SolidColorBrush ( Color . FromArgb ( 255 , 0 , 255 , 255 ) )
: new SolidColorBrush ( Color . FromArgb ( 255 , 190 , 190 , 190 ) ) ;
public SolidColorBrush TMAFlowColor = > IsTMARunMode
? new SolidColorBrush ( Color . FromArgb ( 255 , 0 , 255 , 255 ) )
: new SolidColorBrush ( Color . FromArgb ( 255 , 190 , 190 , 190 ) ) ;
public SolidColorBrush TCSFlowColor = > IsTCSRunMode
? new SolidColorBrush ( Color . FromArgb ( 255 , 0 , 255 , 255 ) )
: 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 ;
2026-08-25 14:49:11 +08:00
#region Process Data Statistic
2026-06-15 10:56:30 +08:00
2026-08-25 14:49:11 +08:00
[Subscription("ProcessDataStat.RealtimeList")]
public List < AITProcessRunData > ProcessRunDataList { get ; set ; }
2026-06-15 10:56:30 +08:00
2026-08-25 14:49:11 +08:00
#endregion
2026-06-15 10:56:30 +08:00
2026-08-25 14:49:11 +08:00
#region 真 值 表 方 式 统 计 流 量
public GasFlowData H2FlowData = > GetFlow ( "H2" ) ;
public GasFlowData N2FlowData = > GetFlow ( "N2" ) ;
public GasFlowData WCO6FlowData = > GetFlow ( "WCO6" ) ;
public GasFlowData MOFlowData = > GetFlow ( "MO" ) ;
public GasFlowData MOCO6FlowData = > GetFlow ( "MOCO6" ) ;
public GasFlowData CS2FlowData = > GetFlow ( "CS2" ) ;
public GasFlowData O2FlowData = > GetFlow ( "O2" ) ;
public GasFlowData H2SeFlowData = > GetFlow ( "H2Se" ) ;
public GasFlowData SO2FlowData = > GetFlow ( "SO2" ) ;
public GasFlowData H2SFlowData = > GetFlow ( "H2S" ) ;
private GasFlowData GetFlow ( string gasName )
{
var run = ( double ) QueryDataClient . Instance . Service . GetData ( $"{SystemName}.GasRealTimeFlow.{gasName}_Run.FeedBack" ) ;
var vent = ( double ) QueryDataClient . Instance . Service . GetData ( $"{SystemName}.GasRealTimeFlow.{gasName}_Vent.FeedBack" ) ;
2026-06-15 10:56:30 +08:00
2026-08-25 14:49:11 +08:00
GasFlowData flow = new GasFlowData
{
GasName = gasName ,
RunFlow = run ,
VentFlow = vent ,
Flow = run + vent ,
Mol = GetMol ( run )
} ;
return flow ;
}
2026-06-15 10:56:30 +08:00
private double GetMol ( double fedback )
{
return fedback / 1000 / 22.4141 ;
}
/// <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 List < GasFlowSum > _RTgasFlowSumList ;
/// <summary>
/// 从真值表中初始化集合对象
/// </summary>
[Subscription("PMGasFlowSumList")]
public List < GasFlowSum > _RTGasFlowSumList
{
get = > _RTgasFlowSumList ;
set = > _RTgasFlowSumList ? ? = value ;
}
private List < GasFlowSum > _gasFlowSumList ;
public List < GasFlowSum > GasFlowSumList
{
get
{
_gasFlowSumList ? ? = _RTGasFlowSumList ; //使用真值表初始化集合
return _gasFlowSumList ;
}
set
{
_gasFlowSumList = value ;
NotifyOfPropertyChange ( nameof ( GasFlowSumList ) ) ;
}
}
private bool _isBusyGasFlowSum ;
public bool IsBusyGasFlowSum
{
get = > _isBusyGasFlowSum ;
set
{
_isBusyGasFlowSum = value ;
NotifyOfPropertyChange ( nameof ( IsBusyGasFlowSum ) ) ;
}
}
private string _busyIndicatorMessage ;
public string BusyIndicatorContent
{
get = > _busyIndicatorMessage ;
set
{
_busyIndicatorMessage = value ;
NotifyOfPropertyChange ( nameof ( BusyIndicatorContent ) ) ;
}
}
private readonly IProgress < ProgressUpdatingEventArgs > _busyIndicatorContentExport ;
public void Query ( )
{
if ( StartDateTime > EndDateTime )
{
MessageBox . Show ( "time range invalid, start time should be early than end time." , "Error" ,
MessageBoxButton . OK ,
MessageBoxImage . Error ) ;
return ;
}
_cts = new CancellationTokenSource ( ) ;
Task . Run ( ( ) = >
{
_busyIndicatorContentExport . Report ( new ProgressUpdatingEventArgs ( 20 , 100 , "Exporting Start ..." ) ) ;
Query ( SystemName , StartDateTime , EndDateTime ) ;
} ) ;
}
public void CancelQuery ( )
{
Task . Run ( ( ) = >
{
if ( _cts ? . Token . CanBeCanceled = = true )
_cts . Cancel ( ) ;
Thread . Sleep ( 200 ) ;
_busyIndicatorContentExport . Report ( new ProgressUpdatingEventArgs ( 100 , 100 , "" ) ) ;
} ) ;
}
public void Query ( string module , DateTime start , DateTime end )
{
var daySlices = DateRangeHelper . SplitInToHours ( new DateRangeHelper ( start , end ) , 12 ) ;
List < List < GasFlowSum > > gasFlowRunVent = new List < List < GasFlowSum > > ( ) ;
//按天查询数据库, 单天返回数据类型为List<GasFlowSum>
foreach ( var daySlice in daySlices )
{
if ( _cts . IsCancellationRequested )
{
_cts ? . Dispose ( ) ;
return ;
}
gasFlowRunVent . Add ( GasFlowSqlHelp . GetDayGasFlowSum ( daySlice , SystemName , GasFlowSumList ) ) ;
_busyIndicatorContentExport . Report ( new ProgressUpdatingEventArgs ( 200 , 200 , $"{daySlice}" ) ) ;
}
List < GasFlowSum > dayGasFlowList = _RTGasFlowSumList ;
//解析数据库返回的数据
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 ;
}
}
//使用公式转换单位
double baseValue = 0.0166667 * Math . Pow ( 10 , - 6 ) ;
foreach ( var item in dayGasFlowList )
{
item . RunVolume = item . RunVolume * baseValue ;
item . VentVolume = item . VentVolume * baseValue ;
item . Volume = item . RunVolume + item . VentVolume ;
}
GasFlowSumList = dayGasFlowList ;
_busyIndicatorContentExport . Report ( new ProgressUpdatingEventArgs ( 100 , 100 , "" ) ) ;
}
#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 ) ;
}
public void Handle ( CommonAggregateEvents message )
{
switch ( message )
{
case CommonAggregateEvents . EnterReadOnlyMode :
if ( View is PMProcessView v )
v . recipeLocker . Lock ( ) ;
break ;
default :
break ;
}
}
}
}