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中的数据,