diff --git a/MECF.Framework.Common/Aitex/Core/RT/Event/EventManager.cs b/MECF.Framework.Common/Aitex/Core/RT/Event/EventManager.cs index 591f8c9..44494ab 100644 --- a/MECF.Framework.Common/Aitex/Core/RT/Event/EventManager.cs +++ b/MECF.Framework.Common/Aitex/Core/RT/Event/EventManager.cs @@ -13,6 +13,7 @@ using Aitex.Core.WCF; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Event; using MECF.Framework.Common.FAServices; +using MECF.Framework.Common.Gem; namespace Aitex.Core.RT.Event { @@ -555,7 +556,14 @@ namespace Aitex.Core.RT.Event public void PostAlarmLog(string module, string message) { WriteEvent(module, ALARM_EVENT, message); - } + + if (Enum.TryParse(module, out ModuleName moduleName)) + { + ulong alarmID = 3000000 + (ulong)moduleName * 100; + + GemManager.Instance.Equipment?.SetAlarm(alarmID, "", new string[] { module + "AlarmInfo" }, new object[] { message }); + } + } #endregion } diff --git a/MECF.Framework.Common/MECF.Framework.Common.csproj b/MECF.Framework.Common/MECF.Framework.Common.csproj index 7000073..46c17db 100644 --- a/MECF.Framework.Common/MECF.Framework.Common.csproj +++ b/MECF.Framework.Common/MECF.Framework.Common.csproj @@ -59,6 +59,10 @@ False ..\Dependencies\FabConnect.dll + + False + ..\output\MECF.Framework\KXGEM.dll + False ..\Dependencies\log4net.dll @@ -774,6 +778,7 @@ + diff --git a/MECF.Framework.Common/MECF/Framework/Common/DataCenter/IQueryDataService.cs b/MECF.Framework.Common/MECF/Framework/Common/DataCenter/IQueryDataService.cs index 9b9c814..1ea0584 100644 --- a/MECF.Framework.Common/MECF/Framework/Common/DataCenter/IQueryDataService.cs +++ b/MECF.Framework.Common/MECF/Framework/Common/DataCenter/IQueryDataService.cs @@ -152,6 +152,12 @@ namespace MECF.Framework.Common.DataCenter [ServiceKnownType(typeof(List))] [ServiceKnownType(typeof(List))] [ServiceKnownType(typeof(TimeUnit))] + [ServiceKnownType(typeof(Kxware.Connectivity.Remoting.VariableData))] + [ServiceKnownType(typeof(List))] + [ServiceKnownType(typeof(Kxware.Connectivity.Remoting.EventData))] + [ServiceKnownType(typeof(List))] + [ServiceKnownType(typeof(Kxware.Connectivity.Remoting.AlarmData))] + [ServiceKnownType(typeof(List))] public interface IQueryDataService { diff --git a/MECF.Framework.Common/MECF/Framework/Common/Gem/GemManager.cs b/MECF.Framework.Common/MECF/Framework/Common/Gem/GemManager.cs new file mode 100644 index 0000000..8402593 --- /dev/null +++ b/MECF.Framework.Common/MECF/Framework/Common/Gem/GemManager.cs @@ -0,0 +1,672 @@ +using Aitex.Common.Util; +using Aitex.Core.RT.DataCenter; +using Aitex.Core.RT.OperationCenter; +using Aitex.Core.Util; +using Kxware.Automation.Secs; +using Kxware.Common; +using Kxware.Connectivity.Remoting; +using Kxware.ToolAutomation.Capabilities; +using Kxware.ToolAutomation; +using System; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using Aitex.Core.RT.Event; + +namespace MECF.Framework.Common.Gem +{ + public class GemManager : Singleton, ITerminalMessageHandler + { + public string PPID { get; set; } + + public string LotID { get; set; } + + private string JobID = ""; + + private string RtStatus => DATA.Poll("Rt.Status").ToString(); + + private Kxware.ToolAutomation.Equipment _equipment; + public Kxware.ToolAutomation.Equipment Equipment => _equipment; + + private PeriodicJob _monitorJob; + + public string CommunicationState => _equipment.GetCommunicationState().ToString(); + + public string ControlMode => _equipment.GetControlState().ToString(); + + public string RecipeContent { get; set; } + + public string RecvMsgFromHost { get; set; } + + public string ProgramLog { get; set; } + + public string SecsLog { get; set; } + + public List AlarmInfoList { get; set; } = new List(); + + public List EventInfoList { get; set; } = new List(); + + public List RecipeNameList + { + get + { + return _equipment?.GetRecipeList(_equipment.MasterConnectionName); + } + } + + public List VariableList + { + get + { + var result = _equipment?.GetVariables()?.Select(p => new Kxware.Connectivity.Remoting.VariableData() + { + ConnectionName = p.ConnectionName, + SmlValue = p.GetSecsValue().ToSML(SmlFormat.RoundBracket), + Default = p.Default?.ToString(), + Description = p.Description, + HostVisible = p.HostVisible, + Id = p.Id, + IsCommonVariable = p.IsCommonVariable, + LimitEventName = p.LimitEvent?.Name, + Name = p.Name, + Max = p.Max?.ToString(), + Min = p.Min?.ToString(), + Persistent = p.Persistent, + Unit = p.Unit, + VariableType = (enumVariableTypes)p.VariableType + }).ToList(); + + return result; + } + } + + public List EventList + { + get + { + var result = _equipment?.GetEvents()?.Select(p => new Kxware.Connectivity.Remoting.EventData() + { + EventName = p.Name, + EventId = p.Id, + Description = p.Description + }).ToList(); + + return result; + } + } + + public List AlarmList + { + get + { + var result = _equipment?.GetAlarms()?.Select(p => new Kxware.Connectivity.Remoting.AlarmData() + { + Name = p.Name, + AlarmID = p.ALID, + ALCD = p.ALCD, + AlarmText = p.ALTX, + Description = p.Description + }).ToList(); + + return result; + } + } + + public void Initialize() + { + _equipment = new Kxware.ToolAutomation.Equipment("SicMachine"); + + _equipment.RegisteringVariables += new RegisterVariableDelegate(RegisteringVariables); + + //_equipment.RegisteringAlarms += new RegisterAlarmDelegate(RegisteringAlarms); + + _equipment.AlarmSET += new OnAlarmSET(AlarmSET); + + _equipment.AlarmCLEAR += new OnAlarmCLEAR(AlarmCLEAR); + + Kxware.Common.Log.NewMessage += Log_NewMessage; + + _equipment.DataMessageReceived += DataMessageReceived; + _equipment.DataMessageSent += DataMessageSent; + + //initialize SECS/ GEM service from configruation file + _equipment.Initialize(PathManager.GetCfgDir() + "Gem.exml"); + + //设置Recipes路径 + _equipment.SetValue("PPDirectory", "./Recipes"); + _equipment.SetValue("PPFileExtension", "seq,rcp"); + + //设置Log路径 + //Log.SetLoggingDirectory(""); + + //register terminal message handler + _equipment.RegisterTerminalMessageHandler(this); + + //注册远程操作指令 + _equipment.RegisterRemoteCommandHandler("PP-SELECT", OnReceivedRemoteCommand); + _equipment.RegisterRemoteCommandHandler("CREATE-JOB", OnReceivedRemoteCommand); + _equipment.RegisterRemoteCommandHandler("START", OnReceivedRemoteCommand); + _equipment.RegisterRemoteCommandHandler("ABORT", OnReceivedRemoteCommand); + + _equipment.EventTriggered += EventTriggered; + + //register custom SECS message S7F7 message handler + _equipment.RegisterMessageHandler(7, 7, HandleS7F7); + + //enable GEM + _equipment.GemEnable(); + _equipment.OnlineLocal(_equipment.MasterConnectionName); + + //注册 + DATA.Subscribe("GEM.CommunicationState", () => CommunicationState); + DATA.Subscribe("GEM.ControlMode", () => ControlMode); + DATA.Subscribe("GEM.VariableList", () => VariableList); + DATA.Subscribe("GEM.EventList", () => EventList); + DATA.Subscribe("GEM.EventInfoList", () => EventInfoList); + DATA.Subscribe("GEM.AlarmList", () => AlarmList); + DATA.Subscribe("GEM.AlarmInfoList", () => AlarmInfoList); + DATA.Subscribe("GEM.RecipeNameList", () => RecipeNameList); + DATA.Subscribe("GEM.RecipeContent", () => RecipeContent); + DATA.Subscribe("GEM.RecvMsgFromHost", () => RecvMsgFromHost); + DATA.Subscribe("GEM.ProgramLog", () => ProgramLog); + DATA.Subscribe("GEM.SecsLog", () => SecsLog); + DATA.Subscribe("GEM.PPID", () => PPID); + DATA.Subscribe("GEM.LotID", () => LotID); + + OP.Subscribe($"GEM_SetEnable", (string cmd, object[] args) => SetEnable((bool)args[0])); + OP.Subscribe($"GEM_SetControlMode", (string cmd, object[] args) => SetControlMode(args[0].ToString())); + OP.Subscribe($"GEM_SelectRecipeChanged", (string cmd, object[] args) => SelectRecipeChanged(args[0].ToString())); + OP.Subscribe($"GEM_SendMessageToHost", (string cmd, object[] args) => SendMessageToHost(args[0].ToString())); + OP.Subscribe($"GEM_ClearProgramLog", (string cmd, object[] args) => ClearProgramLog()); + OP.Subscribe($"GEM_ClearSecsLog", (string cmd, object[] args) => ClearSecsLog()); + OP.Subscribe($"GEM_ClearAlarm", (string cmd, object[] args) => ClearAlarm()); + OP.Subscribe($"GEM_PPChange", (string cmd, object[] args) => PPChange(args)); + + _monitorJob = new PeriodicJob(1000, Monitor, "GEM_Monitor", true); + } + + private void HandleS7F7(DataMessage message) + { + //实现对S7F7的解析处理 + var node = (SecsAscii)message.Body; + var MID = node.GetValueAsString(); + Kxware.Common.Log.Info("GEM", $"Received S7F7:\r\n{message.ToSML(SmlFormat.Standard)}"); + + //回复消息分类 + { + //无异常 + var s7f8 = new ReplyMessage(message); + var l = new SecsList(); + //l.AddChild(new SecsU4(0)); + //l.AddChild(new SecsBoolean(true)); + s7f8.Body = l; + _equipment?.SendMessage(_equipment.MasterConnectionName, s7f8); + } + + //{ + // //Unrecognized device ID(无法识别的设备ID) + // var s9f1 = new ReplyMessage(message); + // _equipment.SendMessage(_equipment.MasterConnectionName, s9f1); + //} + + //{ + // //Unrecognized stream type(无法识别的流类型) + // var s9f3 = new ReplyMessage(message); + // _equipment.SendMessage(_equipment.MasterConnectionName, s9f3); + //} + + //{ + // //Unrecognized function type(无法识别的函数类型) + // var s9f5 = new ReplyMessage(message); + // _equipment.SendMessage(_equipment.MasterConnectionName, s9f5); + //} + + //{ + // //Illegal data(非法数据) + // var s9f7 = new ReplyMessage(message); + // _equipment.SendMessage(_equipment.MasterConnectionName, s9f7); + //} + + //{ + // //Transaction timer timeout(事务定时器超时) + // var s9f5 = new ReplyMessage(message); + // _equipment.SendMessage(_equipment.MasterConnectionName, s9f5); + //} + + //{ + // //Conversation timeout(会话超时) + // var s9f5 = new ReplyMessage(message); + // _equipment.SendMessage(_equipment.MasterConnectionName, s9f5); + //} + } + + //private void HandleS7F65(DataMessage message) + //{ + // //实现对S7F65的解析处理 + // var listNode = (SecsList)message.Body; + // var ppID = listNode[0].GetValueAsString(); + // var pmID = listNode[1].GetValueAsString(); + // //TODO: perform the command + // var s7f66 = new ReplyMessage(message); + // s7f66.Body = new SecsBinary(0); + // _equipment.SendMessage(_equipment.MasterConnectionName, s7f66); + //} + + //private void SendCustomMessage() + //{ + // var s99f1 = new DataMessage(99, 1, true); + // var list1 = new SecsList(); + // list1.AddChild(new SecsAscii("SMIFReady")); + // list1.AddChild(new SecsList()); + // s99f1.Body = list1; + + // _equipment.SendMessage(_equipment.MasterConnectionName, s99f1); + //} + + private bool Monitor() + { + try + { + //设置变量值 + SetValue(); + + return true; + } + catch (Exception) + { + return false; + } + } + + private void SetValue() + { + SortedDictionary> keyValues = Singleton.Instance.GetDBRecorderList(); + + foreach (KeyValuePair> item in keyValues) + { + //判断类型,排除引用类型 + object obj = item.Value(); + if (obj != null) + { + Type type = obj.GetType(); + if (type == typeof(bool) || type == typeof(double) || type == typeof(float) || type == typeof(int) || type == typeof(ushort) || + type == typeof(short) || type == typeof(long)) + { + _equipment?.SetValue(item.Key, obj); + } + } + } + } + + private IEnumerable RegisteringVariables() + { + List variableDefinitionList = new List(); + + int index = 0; + + SortedDictionary> keyValues = Singleton.Instance.GetDBRecorderList(); + + foreach (KeyValuePair> item in keyValues) + { + //判断类型,排除引用类型 + object obj = item.Value(); + if (obj != null) + { + Type type = obj.GetType(); + if (type == typeof(bool) || type == typeof(double) || type == typeof(float) || type == typeof(int) || type == typeof(ushort) || + type == typeof(short) || type == typeof(long)) + { + ValueFormat valueFormat = ValueFormat.F8; + + if (type == typeof(bool)) + { + valueFormat = ValueFormat.BOOLEAN; + } + else if (type == typeof(int)) + { + valueFormat = ValueFormat.I8; + } + else if (type == typeof(long)) + { + valueFormat = ValueFormat.I8; + } + else if (type == typeof(short)) + { + valueFormat = ValueFormat.I8; + } + else if (type == typeof(ushort)) + { + valueFormat = ValueFormat.U8; + } + else if (type == typeof(float)) + { + valueFormat = ValueFormat.F4; + } + else if (type == typeof(double)) + { + valueFormat = ValueFormat.F4; + } + + variableDefinitionList.Add(new VariableDefinition(Kxware.Common.VariableType.SV, valueFormat, (ulong)(1100000 + index), item.Key, (string)null, (string)null, (string)null, (string)null, (string)null, false, true, "")); + + index++; + } + } + } + + return variableDefinitionList; + } + + private IEnumerable RegisteringAlarms() + { + List alarmDefinitionList = new List(); + + int index = 0; + + SortedDictionary> keyValues = Singleton.Instance.GetDBRecorderList(); + + foreach (KeyValuePair> item in keyValues) + { + //alarmDefinitionList.Add(new AlarmDefinition((ulong)(1000000 + index),)); + + index++; + } + + return alarmDefinitionList; + } + + private void AlarmSET(string equipmentName, string connectionName, ulong alarmID, string alarmName, string altx, Kxware.Common.AlarmCode alcd, string alarmDescription, string alarmAdditionalInformation, string setEvent, string clearEvent, DateTime occurredTime, Kxware.Common.VariableData[] associatedVariables, DataMessage alarmSecsMessage) + { + if (connectionName == _equipment.MasterConnectionName) + { + AlarmInfoList.Add($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} 【触发】 ID:{alarmID} {altx}"); + while (AlarmInfoList.Count > 100) + { + AlarmInfoList.RemoveAt(0); + } + } + } + + private void AlarmCLEAR(string equipmentName, string connectionName, ulong alarmID, string alarmName, string altx, Kxware.Common.AlarmCode alcd, string alarmDescription, string alarmAdditionalInformation, string setEvent, string clearEvent, DateTime occurredTime, Kxware.Common.VariableData[] associatedVariables, DataMessage alarmSecsMessage) + { + if (connectionName == _equipment.MasterConnectionName) + { + AlarmInfoList.Add($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} 【清除】 ID:{alarmID} {altx}"); + while (AlarmInfoList.Count > 100) + { + AlarmInfoList.RemoveAt(0); + } + } + } + + private void DataMessageSent(string equipmentName, string connectionName, DateTime time, Kxware.Automation.Secs.DataMessage message) + { + if (connectionName == _equipment.MasterConnectionName) + { + string msg = $"{time.ToString("yyyy/MM/dd HH:mm:ss.fff")} 【发送】\r\n{message.ToSML()}\r\n"; + Kxware.Common.Log.Info("GEM", msg); + SecsLog += msg; + + //if (SecsLog.Length > 10000) + //{ + // SecsLog = SecsLog.Substring(SecsLog.Length - 10000); + //} + } + } + + private void Log_NewMessage(LogType loggingType, string customizedLogTypeName, DateTime timeStamp, string processName, int threadID, string source, string message) + { + // make a filter, do not show SML logging message at current window + if (message.Contains("SECS MSG Recv]") || message.Contains("SECS MSG Sent]")) + { + return; + } + + ProgramLog += $"{timeStamp.ToString("yyyy/MM/dd HH:mm:ss,fff")} {source} 线程ID:{threadID} 内容:{message}\r\n"; + } + + private void DataMessageReceived(string equipmentName, string connectionName, DateTime time, Kxware.Automation.Secs.DataMessage message) + { + if (connectionName == _equipment.MasterConnectionName) + { + string msg = $"{time.ToString("yyyy/MM/dd HH:mm:ss.fff")} 【接受】\r\n{message.ToSML()}\r\n"; + Kxware.Common.Log.Info("GEM", msg); + SecsLog += msg; + + //if (SecsLog.Length > 10000) + //{ + // SecsLog = SecsLog.Substring(SecsLog.Length - 10000); + //} + } + } + + private void EventTriggered(string equipmentName, string connectionName, ulong eventID, string eventName, string eventDescription, Kxware.Common.VariableData[] associatedVariables, Kxware.Automation.Secs.DataMessage eventSecsMessage) + { + if (connectionName == _equipment.MasterConnectionName) + { + var associatedDataInfo = ""; + if (associatedVariables.Length > 0) + { + associatedDataInfo = "关联数据:" + string.Join(",", associatedVariables.Select(p => p.Name + " " + p.Value.ToSML(Kxware.Common.SmlFormat.RoundBracket))); + } + EventInfoList.Add($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} 编号:{eventID} 事件名:{eventName} {associatedDataInfo}"); + } + } + + private enumRemoteCommandAckCode OnReceivedRemoteCommand(string connectionName, string objSpec, string remoteCommand, List remoteCommandParameters) + { + var result = enumRemoteCommandAckCode.CommandDoesNotExist; + switch (remoteCommand) + { + //PP-SELECT指令附加参数(PPID&LotID) + case "PP-SELECT": + { + if (RtStatus != "AutoIdle") + { + Kxware.Common.Log.Warn("GEM", $"Cannot perform 'PP-SELECT' command. Equipment State is not in AutoIdle."); + result = enumRemoteCommandAckCode.CannotPerformNow; + } + else if (remoteCommandParameters.Find(p => p.CPNAME == "PPID") == null) + { + Kxware.Common.Log.Warn("GEM", $"Cannot perform 'PP-SELECT' command. PPID is not specified."); + result = enumRemoteCommandAckCode.AtLeastOneParameterIsInvalid; + } + else if (remoteCommandParameters.Find(p => p.CPNAME == "LotID") == null) + { + Kxware.Common.Log.Warn("GEM", $"Cannot perform 'PP-SELECT' command. LotID is not specified."); + result = enumRemoteCommandAckCode.AtLeastOneParameterIsInvalid; + } + else + { + PPID = remoteCommandParameters.Find(p => p.CPNAME == "PPID").CPVAL.GetValueAsString().Replace(".seq", ""); + LotID = remoteCommandParameters.Find(p => p.CPNAME == "LotID").CPVAL.GetValueAsString(); + Kxware.Common.Log.Info("GEM", $"Received 'PP-SELECT' command. PPID={PPID}.seq, LotID={LotID}"); + result = enumRemoteCommandAckCode.AcknowledgeCommandWillBePerformed; + } + } + break; + + //CREATE-JOB指令没有附加参数 + case "CREATE-JOB": + { + if (RtStatus != "AutoIdle") + { + Kxware.Common.Log.Warn("GEM", $"Cannot perform 'CREATE-JOB' command. Equipment State is not in AutoIdle."); + result = enumRemoteCommandAckCode.CannotPerformNow; + } + else + { + Kxware.Common.Log.Info("GEM", $"Received 'CREATE-JOB' command."); + result = enumRemoteCommandAckCode.AcknowledgeCommandPerformed; + + //具体操作 + JobID = "CJ_Local_Load" + "_" + DateTime.Now.ToString("HHmmss"); + Dictionary dictionary = new Dictionary + { + { "JobId", JobID}, + { "Module", "LoadLock" }, + {"SlotSequence",new string[]{PPID} }, + { "LotId", LotID }, + { "AutoStart", true } + }; + + OP.DoOperation("System.CreateJob", dictionary); + } + } + break; + + //START指令没有附加参数 + case "START": + { + if (RtStatus != "AutoIdle") + { + Kxware.Common.Log.Warn("GEM", $"Cannot perform 'STRAT' command. Equipment State is not in AutoIdle."); + result = enumRemoteCommandAckCode.CannotPerformNow; + } + else + { + Kxware.Common.Log.Info("GEM", $"Received 'STRAT' command."); + result = enumRemoteCommandAckCode.AcknowledgeCommandPerformed; + + //具体操作 + OP.DoOperation("System.StartJob", JobID); + } + } + break; + + //ABORT指令没有附加参数 + case "ABORT": + { + if (RtStatus != "AutoRunning") + { + Kxware.Common.Log.Warn("GEM", $"Cannot perform 'ABORT' command. Equipment State is not in AutoRunning."); + result = enumRemoteCommandAckCode.CannotPerformNow; + } + else + { + Kxware.Common.Log.Info("GEM", $"Received 'ABORT' command."); + result = enumRemoteCommandAckCode.AcknowledgeCommandPerformed; + + //具体操作 + OP.DoOperation("System.Abort"); + } + } + break; + + default: + { + Kxware.Common.Log.Error("GEM", $"Un-handled remote command: {remoteCommand}"); + } + + break; + } + return result; + } + + private bool SetEnable(bool enable) + { + if (enable) + { + _equipment.GemEnable(); + } + else + { + _equipment.GemDisable(); + } + + return true; + } + + private bool SetControlMode(string mode) + { + switch (mode) + { + case "OnlineRemote": + { + _equipment?.OnlineRemote(_equipment.MasterConnectionName); + } + break; + + case "OnlineLocal": + { + _equipment?.OnlineLocal(_equipment.MasterConnectionName); + } + break; + + case "Offline": + { + _equipment?.Offline(_equipment.MasterConnectionName); + } + break; + } + + return true; + } + + private bool SelectRecipeChanged(string recipeName) + { + if (!string.IsNullOrEmpty(recipeName)) + { + RecipeContent = File.ReadAllText(".\\Recipes\\" + recipeName); + } + + return true; + } + + private bool ClearProgramLog() + { + ProgramLog = ""; + + return true; + } + + private bool ClearSecsLog() + { + SecsLog = ""; + + EV.PostAlarmLog("PM1", "PM1 Alarm Test"); + + return true; + } + + private bool ClearAlarm() + { + foreach (var alarm in _equipment?.GetAlarms().Where((a) => a.Active)) + { + _equipment?.ClearAlarm(alarm.Name, alarm.AdditionalInfo); + } + + return true; + } + + private bool PPChange(object[] args) + { + if (args != null && args.Length == 4) + { + _equipment?.TriggerEvent("PPChange", new string[] { args[0].ToString(), args[1].ToString() }, new object[] { args[2], args[3] }); + } + + return true; + } + + private bool SendMessageToHost(string sendMsg) + { + _equipment?.TerminalRequest(_equipment.MasterConnectionName, 0, sendMsg); + + return true; + } + + + public enumACKC10 TerminalMessageReceived(Kxware.ToolAutomation.Equipment equipment, string connectionName, int tid, List texts) + { + RecvMsgFromHost += $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} [{tid}] {string.Join("\r\n", texts)}\r\n"; + Kxware.Common.Log.Info("GEM", $"Received TERMIAL message :{connectionName} :{tid}, {string.Join(",", texts)}"); + return enumACKC10.AcceptedForDisplay; + } + + public void Terminate() + { + + } + } +} diff --git a/MECF.Framework.UI.Client/CenterViews/Editors/Recipe/RecipeEditorViewModel.cs b/MECF.Framework.UI.Client/CenterViews/Editors/Recipe/RecipeEditorViewModel.cs index 6876600..ad43f1f 100644 --- a/MECF.Framework.UI.Client/CenterViews/Editors/Recipe/RecipeEditorViewModel.cs +++ b/MECF.Framework.UI.Client/CenterViews/Editors/Recipe/RecipeEditorViewModel.cs @@ -796,6 +796,7 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Recipe return; var recipeName = dialog.FileName.Trim(); + string gemRecipeName = recipeName; if (string.IsNullOrEmpty(dialog.FileName)) { DialogBox.ShowWarning("Recipe file name should not be empty"); @@ -850,6 +851,7 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Recipe ReloadRecipeFileList(CurrentChamberType, CurrentProcessType, recipeName, false); + InvokeClient.Instance.Service.DoOperation($"GEM_PPChange", new object[] { "PPChangeName", "PPChangeStatus", gemRecipeName, 1 }); } public void NewRecipeRoot() @@ -1119,6 +1121,8 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Recipe if (selection == DialogButton.No) return; + string gemRecipeName = CurrentFileNode.FullPath; + var nextFocus = CurrentFileNode.Parent.FullPath; var isFolder = true; if (CurrentFileNode.Parent.Files.Count > 1) @@ -1145,6 +1149,8 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Recipe CurrentRecipe.DeleteAccessibleWhiteList(); ReloadRecipeFileList(CurrentChamberType, CurrentProcessType, nextFocus, isFolder); + + InvokeClient.Instance.Service.DoOperation($"GEM_PPChange", new object[] { "PPChangeName", "PPChangeStatus", gemRecipeName, 3 }); } public void RefreshRecipe() @@ -1206,7 +1212,8 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Recipe if (isDoRecipeHistorySaveDB) RecipeMemorySaveDB(); - + + InvokeClient.Instance.Service.DoOperation($"GEM_PPChange", new object[] { "PPChangeName", "PPChangeStatus", CurrentRecipe.Name, 2 }); } /// /// 先同步CurrentRecipe在内存(界面所看到的,不一定是XML)中PM1和PM2中的数据,