123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Reflection;
- using System.Runtime.Serialization;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.Text.RegularExpressions;
- using Aitex.Core.RT.Event;
- using Aitex.Sorter.Common;
- using MECF.Framework.Common.Equipment;
- using VirgoCommon;
- namespace VirgoRT.Device.YASKAWA
- {
- [Serializable]
- public sealed class EfemMessage : IEfemMessage, ICloneable
- {
- public enum MsgHead
- {
- MOV, GET, ACK, INF, SET, CAN, ABS, EVT, NAK
- }
- public const char EOF = ';';
- public EfemOperation Operation { get; set; }
- public MsgHead Head { get; set; }
- public ModuleName Port { get; set; }
- public IList<string> Data { get; set; }
- public MsgDirection Direct { get; set; } = MsgDirection.To;
- public IList<string> Parameters { get; set; }
- public string RawString { get; set; }
- public string Factor { get; set; } // NAK, CAN
- public override string ToString()
- {
- string sPara = ToParamString();
- string sOP = EfemConstant.OperationString[Operation];
- string context = $"{Head}:{sOP}{sPara}";
- context += EOF;
- return context;
- }
- public string ToParamString()
- {
- string res = string.Empty;
- if (Parameters == null || Parameters.Count <= 0)
- return res;
- foreach (var para in Parameters)
- {
- res += '/' + para;
- }
- return res;
- }
- public object Clone()
- {
- using (Stream objStream = new MemoryStream())
- {
- IFormatter formatter = new BinaryFormatter();
- formatter.Serialize(objStream, this);
- objStream.Seek(0, SeekOrigin.Begin);
- return formatter.Deserialize(objStream) as EfemMessage ?? throw new InvalidOperationException();
- }
- }
- }
- [AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field)]
- public class HardwareCmdAttribute : Attribute
- {
- public string Member { get; set; }
- public HardwareCmdAttribute(string str) { this.Member = str; }
- }
- [AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field)]
- public class InterpretationAttribute : Attribute
- {
- public string Comment { get; set; }
- public InterpretationAttribute(string str) { this.Comment = str; }
- }
- public static class Extension
- {
- private const string ERROR_MSG = "hardware message invalid";
- /// <summary>
- /// NAK:FACTOR|Message*;
- /// ACK:Message*;
- /// CAN:Message*|Factor/Place;
- /// ABS:Message*|Error/Parameter1/Parameter2;
- /// EVT:Message*;
- /// </summary>
- public static EfemMessage ToMessage(this string context)
- {
- if (string.IsNullOrEmpty(context) || context.Length < 3)
- throw new ArgumentNullException(ERROR_MSG);
- EfemMessage msg = new EfemMessage { RawString = context, Direct = MsgDirection.From, Data = new List<string>() };
- // remove EOT
- string messageBody = context.Substring(0, context.IndexOf(EfemMessage.EOF) + 1);
- try
- {
- // split up the string
- string[] sBodies = messageBody.Split(Constant.delimiters);
- string sHead = sBodies[0];
- string sBasic = sBodies[1];
- string sPort = sBodies[2];
- // Head
- if (Enum.TryParse(sHead, true, out EfemMessage.MsgHead msgHead))
- {
- msg.Head = msgHead;
- }
- switch (msg.Head)
- {
- case EfemMessage.MsgHead.ACK:
- case EfemMessage.MsgHead.MOV:
- case EfemMessage.MsgHead.INF:
- case EfemMessage.MsgHead.EVT:
- // Basic
- msg.Operation = EfemConstant.ToOperation(sBasic);
- // Port
- if (Regex.IsMatch(sPort, @"P[123]$"))
- {
- msg.Port = sPort.ToModule();
- }
- else if (Regex.IsMatch(sPort, @"ALIGN\d?", RegexOptions.IgnoreCase))
- {
- msg.Port = sPort.ToModule();
- }
- else
- {
- msg.Port = ModuleName.EFEM;
- }
- // Data
- switch (msg.Operation)
- {
- case EfemOperation.StateTrack:
- case EfemOperation.GetWaferInfo:
- msg.Data.Add(sBodies[3]);
- break;
- case EfemOperation.CarrierId:
- msg.Data.Add(msg.RawString.Substring("INF:CSTID/P1/".Length));
- break;
- case EfemOperation.SigStatus:
- msg.Data.Add(sBodies[2]);
- msg.Data.Add(sBodies[3]);
- msg.Data.Add(sBodies[4]);
- break;
- case EfemOperation.Ready:
- msg.Data.Add(sBodies[2]);
- break;
- default:
- break;
- }
- break;
- case EfemMessage.MsgHead.NAK:
- msg.Operation = EfemConstant.ToOperation(sBasic);
- // Port
- if (Regex.IsMatch(sPort, @"P[123]$"))
- {
- msg.Port = sPort.ToModule();
- }
- else if (Regex.IsMatch(sPort, @"ALIGN\d?", RegexOptions.IgnoreCase))
- {
- msg.Port = sPort.ToModule();
- }
- else
- {
- msg.Port = ModuleName.EFEM;
- }
- msg.Factor = sBodies[1];
- msg.Data.Add(sBodies[2]);
- msg.Operation = EfemConstant.ToOperation(sBasic);
- break;
- case EfemMessage.MsgHead.CAN:
- msg.Operation = EfemConstant.ToOperation(sBasic);
- // Port
- if (Regex.IsMatch(sPort, @"P[123]$"))
- {
- msg.Port = sPort.ToModule();
- }
- else if (Regex.IsMatch(sPort, @"ALIGN\d?", RegexOptions.IgnoreCase))
- {
- msg.Port = sPort.ToModule();
- }
- else
- {
- msg.Port = ModuleName.EFEM;
- }
- // CAN:ERROR/CLEAR;
- int a1 = messageBody.IndexOf(':');
- int a3 = messageBody.IndexOf(';');
- int a2 = messageBody.IndexOf('|');
- if (a2 > 0)
- {
- msg.Data.Add(messageBody.Substring(a1 + 1, a2 - a1 - 1));
- msg.Factor = messageBody.Substring(a2 + 1, a3 - a2 - 1);
- }
- else
- {
- int a8 = messageBody.IndexOf('/');
- msg.Factor = sBodies[2];
- }
- break;
- case EfemMessage.MsgHead.ABS:
- msg.Operation = EfemConstant.ToOperation(sBasic);
- // Port
- if (Regex.IsMatch(sPort, @"P[123]$"))
- {
- msg.Port = sPort.ToModule();
- }
- else if (Regex.IsMatch(sPort, @"ALIGN\d?", RegexOptions.IgnoreCase))
- {
- msg.Port = sPort.ToModule();
- }
- else
- {
- msg.Port = ModuleName.EFEM;
- }
- // ABS:INIT/ALL|ERROR/SYSTEM_FF10/UNDEFINITION;
- //ABS: UNLOAD / ALIGN3 / ARM2 / WS4 | ERROR / RB | 2B90
- int a4 = messageBody.IndexOf('|');
- int a5 = messageBody.IndexOf(';');
-
- string errStr = messageBody.Substring(a4 + 1, a5 - a4 - 1);
- string[] a6 = errStr.Split('/', '|');
- if (a6.Length < 3)
- {
- throw new ApplicationException($"ABS 格式错误 {errStr}");
- }
- msg.Factor = a6[0];
- msg.Data.Add(a6[1]);
- msg.Data.Add(a6[2]);
- break;
- }
- }
- catch (Exception ex)
- {
- EV.PostAlarmLog(ModuleName.EFEM.ToString(), $"收到[{context}],解析出错[{ex.Message}]");
- }
- return msg;
- }
- public static string ToHWString(this Position pos)
- {
- string res = string.Empty;
- if (ModuleHelper.IsAligner(pos.Module) || ModuleHelper.IsCooling(pos.Module))
- {
- res = Constant.ModuleString[pos.Module];
- }
- else
- {
- string sMod = Constant.ModuleString[pos.Module];
- int num = pos.Slot + 1;
- string sSlot = num.ToString("D2");
- res = $"{sMod}{sSlot}";
- }
- return res;
- }
- public static string ToHWString(this ModuleName mod)
- {
- return Constant.ModuleString[mod];
- }
- public static ModuleName ToModule(this string str)
- {
- if (Constant.StringModule.ContainsKey(str))
- return Constant.StringModule[str];
- throw new ApplicationException($"Cannot translate {str}");
- }
- public static string HardwareCmd(this Enum val)
- {
- FieldInfo fi = val.GetType().GetField(val.ToString());
- return fi.GetCustomAttributes(typeof(HardwareCmdAttribute), false) is HardwareCmdAttribute[] attrs
- && attrs.Length > 0 ? attrs[0].Member : val.ToString();
- }
- public static string Interpretation(this Enum val)
- {
- FieldInfo fi = val.GetType().GetField(val.ToString());
- return fi.GetCustomAttributes(typeof(InterpretationAttribute), false) is InterpretationAttribute[] attrs
- && attrs.Length > 0 ? attrs[0].Comment : val.ToString();
- }
- }
- /// <summary>
- /// constant define
- /// </summary>
- public class Constant
- {
- public static readonly char[] delimiters = { ':', '/', '>', '|', ';' };
- public const string ALL = "ALL";
- public const string MAP = "MAPDT";
- public const string SYS = "SYSTEM";
- public const string STOWER = "STOWER";
- public static readonly Dictionary<ModuleName, string> ModuleString = new Dictionary<ModuleName, string>
- {
- [ModuleName.EFEM] = "ALL",
- [ModuleName.EfemRobot]= "ROB",
- [ModuleName.LP1] = "P1",
- [ModuleName.LP2] = "P2",
- [ModuleName.PMA] = "LLA",
- [ModuleName.PMB] = "LLB",
- [ModuleName.Aligner1] = "ALIGN3",
- [ModuleName.Aligner2] = "ALIGN4",
- [ModuleName.Cooling1] = "ALIGN",
- [ModuleName.Cooling2] = "ALIGN2"
- };
- public static readonly Dictionary<string, ModuleName> StringModule = new Dictionary<string, ModuleName>
- {
- ["ALL"] = ModuleName.EFEM,
- ["System"] = ModuleName.EFEM,
- ["P1"] = ModuleName.LP1,
- ["P2"] = ModuleName.LP2,
- ["LLA"] = ModuleName.PMA,
- ["LLB"] = ModuleName.PMB,
- ["ALIGN"] = ModuleName.Cooling1,
- ["ALIGN2"] = ModuleName.Cooling2,
- ["ALIGN3"] = ModuleName.Aligner1,
- ["ALIGN4"] = ModuleName.Aligner2,
- };
- public static readonly Dictionary<Hand, string> ArmString = new Dictionary<Hand, string>
- {
- [Hand.Blade1] = "ARM2",
- [Hand.Blade2] = "ARM1",
- [Hand.Both] = "ARM3"
- };
- public static readonly Dictionary<ExtendPos, string> ExtendPosString = new Dictionary<ExtendPos, string>
- {
- //[ExtendPos.GetReady] = "G1",
- //[ExtendPos.GetTarget] = "GB",
- //[ExtendPos.GetBack] = "G4",
- //[ExtendPos.PutReady] = "P1",
- //[ExtendPos.PutTarget] = "PB",
- //[ExtendPos.PutBack] = "P4"
- };
- public static readonly Dictionary<string, string> FactorString = new Dictionary<string, string>
- {
- { "MSG", "Message error" },
- { "NOREAD", "Communication not established" },
- { "NOINITCMPL", "Initialization not completed" },
- { "NOORGCMPL", "Not org finished" },
- { "VAC", "Vac error" },
- { "AIR", "Air error" },
- { "EMS", "EMS pushed" },
- { "ERROR", "Has Error" },
- { "BUSY", "Busy (Module in use)" },
- { "CMPL", "Already Completed" },
- { "NOMAPCMPL", "Not Mapped" },
- { "NONWAF", "NO wafer on the position" },
- { "WAFER", "Wafer already existed" },
- { "NONPOD", "No Pod" },
- { "POD", "Pod Exist" },
- { "NOTINMOTION","Not in Motion" },
- { "HOLD", "Holded" },
- { "NOHOLD", "Not hold" },
- { "LLCLOSE", "LL door closed state" },
- { "LLNOEXTEND", "LL not extended" },
- { "REMOVE", "remove" },
- { "MAINTENANCE","In maintain mode or EFEM offline" },
- { "NOLINK", "not config" },
- { "ARMEXTEND", "arm extended" },
- { "POWER", "power off" },
- { "PRTWAF", "TODO" },
- { "NOPOS", "Not at valid position" },
- { "NOFUNC", "not support" },
- { "PARAM_NG", "Invalid parameters are included" }
- };
- public static readonly Dictionary<string, string> ABS_PARA1 = new Dictionary<string, string>
- {
- { "SYSTEM_FF01", "No specific route data or malfunction" },
- { "SYSTEM_FF10", "Operation time out" },
- { "SYSTEM_FF11", "Communication time out between PC for robot control and controller" },
- { "SYSTEM_FF12", "Encoder battery error" },
- { "SYSTEM_FF13", "Loss of encoder information" },
- { "SYSTEM_FF20", "No data file of route" },
- { "SYSTEM_FF21", "Serial number in route data is wrong" },
- { "SYSTEM_FF22", "No line for serial number in route data" },
- { "SYSTEM_FF23", "Discrepancy in serial number between route data and teaching data" },
- { "SYSTEM_FF30", "Failure of pre-operation movement at the wrist in the robot" },
- { "SYSTEM_FF83", "Inability of the robot to return origin" },
- { "SYSTEM_FFB0", "Operation malfunction at fan in robot" },
- { "SYSTEM_FFF0", "Alarm at Z-axis driver in the robot" },
- { "SYSTEM_FFFF", "Robot control program malfunction" }
- };
- }
- }
|