| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 | 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:                                if(msg.Head != EfemMessage.MsgHead.ACK)                                {                                    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;                        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(), $"Receive [{context}],Analysis error [{ex.Message}]");            }            return msg;        }        public static string ToHWString(this Position pos)        {            string res = string.Empty;            if (ModuleHelper.IsAligner(pos.Module) || ModuleHelper.IsCooling(pos.Module) || ModuleHelper.IsFlipper(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",            [ModuleName.Flipper]  = "FLIPPER",            [ModuleName.Buffer]   = "BUFFER"        };        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,            ["FLIPPER"] = ModuleName.Flipper,            ["BUFFER"] = ModuleName.Buffer,        };        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" }        };    }}
 |