Merge branch 'Gem'
This commit is contained in:
commit
6458fe5c9e
Binary file not shown.
|
@ -251,15 +251,24 @@ namespace Aitex.Core.RT.DataCenter
|
|||
|
||||
public Dictionary<string, object> PollData(IEnumerable<string> keys)
|
||||
{
|
||||
Dictionary<string, object> dictionary = new Dictionary<string, object>();
|
||||
foreach (string key in keys)
|
||||
try
|
||||
{
|
||||
if (_keyValueMap.ContainsKey(key))
|
||||
{
|
||||
dictionary[key] = _keyValueMap[key].Value;
|
||||
}
|
||||
Dictionary<string, object> dictionary = new Dictionary<string, object>();
|
||||
foreach (string key in keys)
|
||||
{
|
||||
if (_keyValueMap.ContainsKey(key))
|
||||
{
|
||||
dictionary[key] = _keyValueMap[key].Value;
|
||||
}
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Error(ex.Message, ex);
|
||||
return null;
|
||||
}
|
||||
return dictionary;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
@ -552,10 +553,26 @@ namespace Aitex.Core.RT.Event
|
|||
WriteEvent(module, WARNING_EVENT, message);
|
||||
}
|
||||
|
||||
public void PostAlarmLog(string module, string message)
|
||||
{
|
||||
WriteEvent(module, ALARM_EVENT, message);
|
||||
}
|
||||
public void PostAlarmLog(string module, string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
WriteEvent(module, ALARM_EVENT, message);
|
||||
|
||||
if (Enum.TryParse(module, out ModuleName moduleName))
|
||||
{
|
||||
if (GemManager.Instance.Equipment != null)
|
||||
{
|
||||
ulong alarmID = GemManager.Instance.Equipment.GetAlarm(module + ".Alarm").ALID;
|
||||
GemManager.Instance.Equipment?.SetAlarm(alarmID, "", new string[] { module + ".AlarmInfo" }, new object[] { message });
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -59,6 +59,10 @@
|
|||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Dependencies\FabConnect.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="KXGEM, Version=1.2.1.510, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Dependencies\KXGEM.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Dependencies\log4net.dll</HintPath>
|
||||
|
@ -748,6 +752,7 @@
|
|||
<Compile Include="MECF\Framework\Common\Fsm\ActiveFsm.cs" />
|
||||
<Compile Include="MECF\Framework\Common\Fsm\FsmDevice.cs" />
|
||||
<Compile Include="MECF\Framework\Common\Fsm\ModuleFsmDevice.cs" />
|
||||
<Compile Include="MECF\Framework\Common\Gem\GemManager.cs" />
|
||||
<Compile Include="MECF\Framework\Common\IOCore\IoManager.cs" />
|
||||
<Compile Include="MECF\Framework\Common\IOCore\NotifiableIoItem.cs" />
|
||||
<Compile Include="MECF\Framework\Common\Jobs\ControlJobInfo.cs" />
|
||||
|
|
|
@ -144,6 +144,12 @@ namespace MECF.Framework.Common.DataCenter
|
|||
[ServiceKnownType(typeof(ConfigChangedInfo))]
|
||||
[ServiceKnownType(typeof(List<ConfigChangedInfo>))]
|
||||
[ServiceKnownType(typeof(List<ProcessDeviceItem>))]
|
||||
[ServiceKnownType(typeof(Kxware.Connectivity.Remoting.VariableData))]
|
||||
[ServiceKnownType(typeof(List<Kxware.Connectivity.Remoting.VariableData>))]
|
||||
[ServiceKnownType(typeof(Kxware.Connectivity.Remoting.EventData))]
|
||||
[ServiceKnownType(typeof(List<Kxware.Connectivity.Remoting.EventData>))]
|
||||
[ServiceKnownType(typeof(Kxware.Connectivity.Remoting.AlarmData))]
|
||||
[ServiceKnownType(typeof(List<Kxware.Connectivity.Remoting.AlarmData>))]
|
||||
|
||||
public interface IQueryDataService
|
||||
{
|
||||
|
|
|
@ -0,0 +1,833 @@
|
|||
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;
|
||||
using Aitex.Core.RT.SCCore;
|
||||
using Aitex.Core.RT.Log;
|
||||
using SciChart.Core.Extensions;
|
||||
|
||||
namespace MECF.Framework.Common.Gem
|
||||
{
|
||||
public class GemManager : Singleton<GemManager>
|
||||
{
|
||||
public string PPIDNoExtension { 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 SequenceRecipeContent { get; set; }
|
||||
|
||||
public string RecvMsgFromHost { get; set; }
|
||||
|
||||
public string ProgramLog { get; set; }
|
||||
|
||||
public string SecsLog { get; set; }
|
||||
|
||||
public List<string> AlarmInfoList { get; set; } = new List<string>();
|
||||
|
||||
public List<string> EventInfoList { get; set; } = new List<string>();
|
||||
|
||||
public List<string> SequenceRecipeNameList => _equipment?.GetRecipeList(_equipment.MasterConnectionName);
|
||||
|
||||
public List<Kxware.Connectivity.Remoting.VariableData> 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<Kxware.Connectivity.Remoting.EventData> 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<Kxware.Connectivity.Remoting.AlarmData> 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()
|
||||
{
|
||||
try
|
||||
{
|
||||
//注册
|
||||
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.SequenceRecipeNameList", () => SequenceRecipeNameList);
|
||||
DATA.Subscribe("GEM.SequenceRecipeContent", () => SequenceRecipeContent);
|
||||
DATA.Subscribe("GEM.RecvMsgFromHost", () => RecvMsgFromHost);
|
||||
DATA.Subscribe("GEM.ProgramLog", () => ProgramLog);
|
||||
DATA.Subscribe("GEM.SecsLog", () => SecsLog);
|
||||
DATA.Subscribe("GEM.PPID", () => PPIDNoExtension);
|
||||
DATA.Subscribe("GEM.LotID", () => LotID);
|
||||
|
||||
OP.Subscribe($"GEM_SetSoftwareVersion", (string cmd, object[] args) => SetSoftwareVersion((string)args[0]));
|
||||
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_SelectSequenceRecipeChanged", (string cmd, object[] args) => SelectSequenceRecipeChanged(args[0].ToString()));
|
||||
OP.Subscribe($"GEM_TerminalMessageConfirm", (string cmd, object[] args) => TerminalMessageConfirm());
|
||||
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_ClearAllAlarm", (string cmd, object[] args) => ClearAllAlarm());
|
||||
OP.Subscribe($"GEM_ClearModuleAlarm", (string cmd, object[] args) => ClearModuleAlarm(args[0].ToString()));
|
||||
OP.Subscribe($"GEM_PPChange", (string cmd, object[] args) => PPChange(args));
|
||||
|
||||
string equipmentName = SC.GetStringValue("System.EquipmentName");
|
||||
int equipmentNo = SC.GetValue<int>("System.EquipmentNo");
|
||||
_equipment = new Kxware.ToolAutomation.Equipment("SicEquipment");
|
||||
|
||||
//_equipment.RegisteringVariables += new RegisterVariableDelegate(RegisteringVariables);
|
||||
|
||||
//_equipment.RegisteringAlarms += new RegisterAlarmDelegate(RegisteringAlarms);
|
||||
|
||||
//initialize SECS/ GEM service from configruation file
|
||||
_equipment.Initialize(PathManager.GetCfgDir() + "Gem.exml");
|
||||
|
||||
#region 设置变量
|
||||
|
||||
//设置内置名称,软件版本等SV
|
||||
_equipment.SetValue("MDLN", "Sic");
|
||||
_equipment.SetValue("Manufacturer", "Sicentury");
|
||||
_equipment.SetValue("EqpModel", equipmentName);
|
||||
_equipment.SetValue("EqpSerialNum", equipmentNo.ToString());
|
||||
|
||||
//设置Recipes路径
|
||||
_equipment.SetValue("PPDirectory", "./Recipes");
|
||||
_equipment.SetValue("PPFileExtension", "seq,rcp");
|
||||
|
||||
//设置PPFormat
|
||||
_equipment.SetValue("PPFormat", 1);
|
||||
|
||||
//设置Log路径
|
||||
//Log.SetLoggingDirectory("");
|
||||
|
||||
#endregion
|
||||
|
||||
#region 回调
|
||||
|
||||
_equipment.AlarmSET += new OnAlarmSET(AlarmSET);
|
||||
_equipment.AlarmCLEAR += new OnAlarmCLEAR(AlarmCLEAR);
|
||||
|
||||
Kxware.Common.Log.NewMessage += Log_NewMessage;
|
||||
|
||||
_equipment.DataMessageReceived += DataMessageReceived;
|
||||
_equipment.DataMessageSent += DataMessageSent;
|
||||
|
||||
_equipment.TerminalMessageReceived += TerminalMessageReceived;
|
||||
|
||||
//注册远程操作指令
|
||||
_equipment.RegisterRemoteCommandHandler("GO-LOCAL", OnReceivedRemoteCommand);
|
||||
_equipment.RegisterRemoteCommandHandler("GO-REMOTE", OnReceivedRemoteCommand);
|
||||
_equipment.RegisterRemoteCommandHandler("PP-SELECT", OnReceivedRemoteCommand);
|
||||
_equipment.RegisterRemoteCommandHandler("CREATE-JOB", OnReceivedRemoteCommand);
|
||||
_equipment.RegisterRemoteCommandHandler("START", OnReceivedRemoteCommand);
|
||||
_equipment.RegisterRemoteCommandHandler("ABORT", OnReceivedRemoteCommand);
|
||||
_equipment.RegisterRemoteCommandHandler("STOP", OnReceivedRemoteCommand);
|
||||
|
||||
_equipment.EventTriggered += EventTriggered;
|
||||
|
||||
//register custom SECS message
|
||||
_equipment.RegisterMessageHandler(7, 7, HandleS7F7);
|
||||
|
||||
//Variable value change callback
|
||||
var allHostECs = _equipment.GetVariables().FindAll(p => p.HostVisible && p.VariableType == VariableType.EC);
|
||||
allHostECs.ForEach(v =>
|
||||
{
|
||||
v.AdvancedValueChanged += Variable_AdvancedValueChanged;
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
//enable GEM
|
||||
_equipment.GemEnable();
|
||||
_equipment.OnlineLocal(_equipment.MasterConnectionName);
|
||||
|
||||
_monitorJob = new PeriodicJob(1000, Monitor, "GEM_Monitor", true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//LOG.Error(ex.Message,ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void Variable_AdvancedValueChanged(Variable variable, SecsValue oldValue, SecsValue newValue, enumSource source)
|
||||
{
|
||||
//由Host主机修改的EC
|
||||
if (source == enumSource.Host)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
SetXmlValue();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kxware.Common.Log.Error(ex.Source, ex.Message, ex);
|
||||
LOG.Error(ex.Message, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//设置GEM配置文件中变量的值
|
||||
private void SetXmlValue()
|
||||
{
|
||||
try
|
||||
{
|
||||
SortedDictionary<string, Func<object>> keyValues = Singleton<DataManager>.Instance.GetDBRecorderList();
|
||||
|
||||
foreach (Variable variable in _equipment.GetVariables())
|
||||
{
|
||||
if (variable.VariableType == VariableType.SV)
|
||||
{
|
||||
if (keyValues.ContainsKey(variable.Name))
|
||||
{
|
||||
_equipment?.SetValue(variable.Name, keyValues[variable.Name]());
|
||||
}
|
||||
else
|
||||
{
|
||||
//排除Gem 内置变量
|
||||
if (variable.Id > 10000)
|
||||
{
|
||||
//LOG.Warning($"DATA no Contain Gem Varibable name {variable.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetValue()
|
||||
{
|
||||
SortedDictionary<string, Func<object>> keyValues = Singleton<DataManager>.Instance.GetDBRecorderList();
|
||||
|
||||
foreach (KeyValuePair<string, Func<object>> 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) || type == typeof(string))
|
||||
{
|
||||
_equipment?.SetValue(item.Key, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<VariableDefinition> RegisteringVariables()
|
||||
{
|
||||
List<VariableDefinition> variableDefinitionList = new List<VariableDefinition>();
|
||||
|
||||
int index = 0;
|
||||
|
||||
SortedDictionary<string, Func<object>> keyValues = Singleton<DataManager>.Instance.GetDBRecorderList();
|
||||
|
||||
foreach (KeyValuePair<string, Func<object>> 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) || type == typeof(string))
|
||||
{
|
||||
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;
|
||||
}
|
||||
else if (type == typeof(string))
|
||||
{
|
||||
valueFormat = ValueFormat.A;
|
||||
}
|
||||
|
||||
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<AlarmDefinition> RegisteringAlarms()
|
||||
{
|
||||
List<AlarmDefinition> alarmDefinitionList = new List<AlarmDefinition>();
|
||||
|
||||
int index = 0;
|
||||
|
||||
SortedDictionary<string, Func<object>> keyValues = Singleton<DataManager>.Instance.GetDBRecorderList();
|
||||
|
||||
foreach (KeyValuePair<string, Func<object>> 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<RemoteCommandParameter> remoteCommandParameters)
|
||||
{
|
||||
//只接受从MasterConnection 收到的控制命令
|
||||
if (connectionName != _equipment.MasterConnectionName)
|
||||
return enumRemoteCommandAckCode.CannotPerformNow;
|
||||
|
||||
//判断控制状态,在Local 状态下只接受GO-REMOTE命令
|
||||
var currentCtrlState = _equipment.GetControlState();
|
||||
if (currentCtrlState != GEMControlStates.Online_Remote)
|
||||
{
|
||||
if (remoteCommand.ToUpper() != "GO-REMOTE")
|
||||
return enumRemoteCommandAckCode.CannotPerformNow;
|
||||
}
|
||||
|
||||
var result = enumRemoteCommandAckCode.NoSuchObjectExists;
|
||||
switch (remoteCommand.ToUpper())
|
||||
{
|
||||
case "GO-LOCAL":
|
||||
{
|
||||
if (currentCtrlState == GEMControlStates.Online_Remote)
|
||||
{
|
||||
_equipment.OnlineLocal(_equipment.MasterConnectionName);
|
||||
result = enumRemoteCommandAckCode.AcknowledgeCommandPerformed;
|
||||
}
|
||||
else
|
||||
result = enumRemoteCommandAckCode.RejectedAlreadyInDesiredCondition;
|
||||
}
|
||||
break;
|
||||
|
||||
case "GO-REMOTE":
|
||||
{
|
||||
if (currentCtrlState == GEMControlStates.Online_Remote)
|
||||
{
|
||||
result = enumRemoteCommandAckCode.RejectedAlreadyInDesiredCondition;
|
||||
}
|
||||
else if (!_equipment.OnlineRemote(_equipment.MasterConnectionName, out string error))
|
||||
result = enumRemoteCommandAckCode.CannotPerformNow;
|
||||
else
|
||||
result = enumRemoteCommandAckCode.AcknowledgeCommandPerformed;
|
||||
}
|
||||
break;
|
||||
|
||||
//PP-SELECT指令附加参数(PPID&LotID)
|
||||
case "PP-SELECT":
|
||||
{
|
||||
try
|
||||
{
|
||||
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
|
||||
{
|
||||
string PPID = remoteCommandParameters.Find(p => p.CPNAME == "PPID").CPVAL.GetValueAsString();
|
||||
PPIDNoExtension = PPID.Replace(@"Sequence\", "").Replace(".seq", "");
|
||||
LotID = remoteCommandParameters.Find(p => p.CPNAME == "LotID").CPVAL.GetValueAsString();
|
||||
Kxware.Common.Log.Info("GEM", $"Received 'PP-SELECT' command. PPID={PPID}, LotID={LotID}");
|
||||
|
||||
//Check if rcpID is exist. if not exist, returen enumRemoteCommandAckCode.AtLeastOneParameterIsInvalid
|
||||
|
||||
result = enumRemoteCommandAckCode.AcknowledgeCommandWillBePerformed;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
result = enumRemoteCommandAckCode.AtLeastOneParameterIsInvalid;
|
||||
}
|
||||
}
|
||||
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("yyyy-MM-dd HH:mm:ss");
|
||||
Dictionary<string, object> dictionary = new Dictionary<string, object>
|
||||
{
|
||||
{ "JobId", JobID},
|
||||
{ "Module", "LoadLock" },
|
||||
{"SlotSequence",new string[]{PPIDNoExtension} },
|
||||
{ "LotId", LotID },
|
||||
{ "AutoStart", true }
|
||||
};
|
||||
|
||||
OP.DoOperation("System.CreateJob", dictionary);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//START指令没有附加参数
|
||||
case "START":
|
||||
{
|
||||
if (RtStatus != "AutoIdle" && RtStatus != "AutoRunning")
|
||||
{
|
||||
Kxware.Common.Log.Warn("GEM", $"Cannot perform 'STRAT' command. Equipment State is not in AutoIdle or AutoRunning.");
|
||||
result = enumRemoteCommandAckCode.CannotPerformNow;
|
||||
}
|
||||
else
|
||||
{
|
||||
Kxware.Common.Log.Info("GEM", $"Received 'STRAT' command.");
|
||||
result = enumRemoteCommandAckCode.AcknowledgeCommandWillBePerformed;
|
||||
|
||||
//具体操作
|
||||
OP.DoOperation("System.StartJob", JobID);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
////ABORT指令没有附加参数
|
||||
//case "ABORT":
|
||||
//case "STOP":
|
||||
// {
|
||||
// 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.AcknowledgeCommandWillBePerformed;
|
||||
|
||||
// //具体操作
|
||||
// OP.DoOperation("System.Abort");
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
|
||||
default:
|
||||
{
|
||||
Kxware.Common.Log.Error("GEM", $"Un-handled remote command: {remoteCommand}");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool SetSoftwareVersion(string softwareVersion)
|
||||
{
|
||||
_equipment.SetValue("SOFTREV", softwareVersion);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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 SelectSequenceRecipeChanged(string sequenceRecipeName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(sequenceRecipeName))
|
||||
{
|
||||
SequenceRecipeContent = File.ReadAllText(".\\Recipes\\" + sequenceRecipeName);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ClearProgramLog()
|
||||
{
|
||||
ProgramLog = "";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ClearSecsLog()
|
||||
{
|
||||
SecsLog = "";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ClearAllAlarm()
|
||||
{
|
||||
foreach (var alarm in _equipment?.GetAlarms().Where(a => a.Active))
|
||||
{
|
||||
//获取变量名
|
||||
string variableName = alarm.Name + "Info";
|
||||
_equipment?.ClearAlarm(alarm.Name, alarm.AdditionalInfo, new string[] {variableName}, new object[] {""});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ClearModuleAlarm(string module)
|
||||
{
|
||||
foreach (var alarm in _equipment?.GetAlarms().Where(a => a.Name == $"{module}Alarm" && a.Active))
|
||||
{
|
||||
//获取变量名
|
||||
string variableName = alarm.Name + "Info";
|
||||
_equipment?.ClearAlarm(alarm.Name, alarm.AdditionalInfo, new string[] { variableName }, new object[] { "" });
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool PPChange(object[] args)
|
||||
{
|
||||
if (args != null && args.Length == 2)
|
||||
{
|
||||
//PPChangeStatus: 1:created; 2:edited; 3:deleted
|
||||
_equipment?.TriggerEvent("PPChange", new string[] { "PPChangeName", "PPChangeStatus"}, new object[] { args[0], args[1]});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//接受终端消息
|
||||
private void TerminalMessageReceived(string equipmentName, string connectionName, int terminalID, List<string> texts)
|
||||
{
|
||||
RecvMsgFromHost += $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} [{terminalID}] {string.Join("\r\n", texts)}\r\n";
|
||||
Kxware.Common.Log.Info("GEM", $"Received TERMIAL message :{connectionName} :{terminalID}, {string.Join(",", texts)}");
|
||||
}
|
||||
|
||||
//终端消息确认
|
||||
private bool TerminalMessageConfirm()
|
||||
{
|
||||
_equipment?.TriggerEvent("MessageRecognition");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//发送消息给主机
|
||||
private bool SendMessageToHost(string sendMsg)
|
||||
{
|
||||
_equipment?.TerminalRequest(_equipment.MasterConnectionName, 0, sendMsg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -795,6 +795,7 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Recipe
|
|||
return;
|
||||
|
||||
var recipeName = dialog.FileName.Trim();
|
||||
string gemRecipeName = recipeName + ".rcp";
|
||||
if (string.IsNullOrEmpty(dialog.FileName))
|
||||
{
|
||||
DialogBox.ShowWarning("Recipe file name should not be empty");
|
||||
|
@ -849,6 +850,7 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Recipe
|
|||
|
||||
ReloadRecipeFileList(CurrentChamberType, CurrentProcessType, recipeName, false);
|
||||
|
||||
InvokeClient.Instance.Service.DoOperation($"GEM_PPChange", 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", gemRecipeName, 3);
|
||||
}
|
||||
|
||||
public void RefreshRecipe()
|
||||
|
@ -1207,6 +1213,7 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Recipe
|
|||
if (isDoRecipeHistorySaveDB)
|
||||
RecipeMemorySaveDB();
|
||||
|
||||
InvokeClient.Instance.Service.DoOperation($"GEM_PPChange", CurrentRecipe.Name + ".rcp", 2);
|
||||
}
|
||||
/// <summary>
|
||||
/// 先同步CurrentRecipe在内存(界面所看到的,不一定是XML)中PM1和PM2中的数据,
|
||||
|
|
|
@ -9,6 +9,7 @@ using System.Windows.Input;
|
|||
using System.Windows.Media;
|
||||
using Caliburn.Micro;
|
||||
using Caliburn.Micro.Core;
|
||||
using MECF.Framework.Common.OperationCenter;
|
||||
using MECF.Framework.Common.RecipeCenter;
|
||||
using MECF.Framework.UI.Client.CenterViews.Editors.Recipe;
|
||||
using MECF.Framework.UI.Client.ClientBase;
|
||||
|
@ -466,6 +467,8 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Sequence
|
|||
|
||||
// 自动选中新增节点
|
||||
Files[0].Select(file.FullPath);
|
||||
|
||||
InvokeClient.Instance.Service.DoOperation($"GEM_PPChange", dialog.DialogResult + ".seq", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -531,6 +534,8 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Sequence
|
|||
if (IsChanged)
|
||||
{
|
||||
Save(CurrentSequence);
|
||||
|
||||
InvokeClient.Instance.Service.DoOperation($"GEM_PPChange", CurrentSequence.Name + ".seq", 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,9 +556,13 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Sequence
|
|||
{
|
||||
if (DialogBox.Confirm("Do you want to delete this sequence?"))
|
||||
{
|
||||
string sequenceName = CurrentSequence.Name + ".seq";
|
||||
|
||||
if (provider.Delete(CurrentSequence.Name))
|
||||
{
|
||||
CurrentFileNode.Parent.Files.Remove(CurrentFileNode);
|
||||
|
||||
InvokeClient.Instance.Service.DoOperation($"GEM_PPChange", sequenceName, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue