| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345 | using Aitex.Common.Util;using Aitex.Core.RT.Event;using Aitex.Core.RT.Log;using Aitex.Core.RT.RecipeCenter;using Aitex.Core.RT.SCCore;using Aitex.Core.Util;using FabConnect.SecsGemInterface.Common;using FabConnect.SecsGemInterface.Common.ToolModel;using FabConnect.SecsGemInterface.GemModel;using System;using System.Collections.Generic;using System.Threading;using System.Threading.Tasks;using System.Xml;using MECF.Framework.Common.CommonData;using Venus_RT.HostWrapper;namespace Venus_RT.FAs{    public class FaHost : IFaHost    {        public string FaCommunicationState        {            get { return _gem.CommunicationState.ToString(); }        }        public string FaControlState        {            get { return _gem.ControlState.ToString(); }        }        public string FaControlSubState        {            get            {                return _gem.ControlRemoteSwitch.ToString();            }        }        public bool IsConnected        {            get { return _gem.CommunicationState == CommunicationState.EnabledCommunicating; }        }        public int SpoolingState        {            get            {                return (int)_gem.SpoolingState;            }        }        public string SpoolingActual        {            get            {                return              _gem.GetAttribute(GEMVariables.SpoolCountActual, AttributeType.SV)              ;            }        }        public string SpoolingTotal        {            get { return _gem.GetAttribute(GEMVariables.SpoolCountTotal, AttributeType.SV); }        }        public string SpoolingFullTime        {            get { return _gem.GetAttribute(GEMVariables.SpoolFullTime, AttributeType.SV); }        }        public string SpoolingStartTime        {            get { return _gem.GetAttribute(GEMVariables.SpoolStartTime, AttributeType.SV); }        }        public bool IsSpoolingEnable        {            get { return Convert.ToBoolean(_gem.GetAttribute(GEMVariables.SpoolEnabled, AttributeType.EC)); }        }        private readonly GEMController _gem = new GEMController();        public IHostCallback _equipment;        private HashSet<string> _systemBuildInEc = new HashSet<string>();        private HashSet<string> _systemBuildInVariables = new HashSet<string>();        private PeriodicJob _faMonitorThread;        private FixSizeQueue<FaEventItem> _lstEvent = new FixSizeQueue<FaEventItem>(300);        FALogFileCleaner _logCleaner = new FALogFileCleaner();        private ControlState _state = ControlState.Unknown;        private const string EventTerminalMessage = "TerminalMessage";        public void Initialize(IHostCallback equipment, string modelFile)        {            _equipment = equipment;            _gem.CommunicationStateChanged += OnCommunicationStateChanged;            _gem.RemoteCommandS2F49In += _gem_RemoteCommandS2F49In; ;            _gem.PrimaryMessageIn += _gem_PrimaryMessageIn;            _gem.ControlStateChanged += _gem_ControlStateChanged;            _gem.ShowTrialMessageBox = false;            _gem.AutoPPDataReply = false;            _gem.Initialize(modelFile, PathManager.GetLogDir());            _gem.EquipmentModel.GemConnection.HSMS.localIPAddress = SC.GetStringValue("System.FA.LocalIpAddress");            _gem.EquipmentModel.GemConnection.HSMS.localPortNumber = SC.GetValue<int>("System.FA.LocalPortNumber");            _gem.EquipmentModel.GemConnection.HSMS.T3Timeout = SC.GetValue<int>("System.FA.T3Timeout");            _gem.EquipmentModel.GemConnection.HSMS.T5Timeout = SC.GetValue<int>("System.FA.T5Timeout");            _gem.EquipmentModel.GemConnection.HSMS.T6Timeout = SC.GetValue<int>("System.FA.T6Timeout");            _gem.EquipmentModel.GemConnection.HSMS.T7Timeout = SC.GetValue<int>("System.FA.T7Timeout");            _gem.EquipmentModel.GemConnection.HSMS.T8Timeout = SC.GetValue<int>("System.FA.T8Timeout");            _gem.ReInitialize();            //get system build in ec            _systemBuildInEc = new HashSet<string>();            _systemBuildInEc.Add("EstablishCommunicationsTimeout");            _systemBuildInEc.Add("MaxSpoolTransmit");            _systemBuildInEc.Add("OverWriteSpool");            _systemBuildInEc.Add("MaxSpoolCapacity");            _systemBuildInEc.Add("SpoolEnabled");            _systemBuildInEc.Add("TimeFormat");            //initial system build in variable            _systemBuildInVariables.Add("AlarmsEnabled");            _systemBuildInVariables.Add("AlarmsSet");            _systemBuildInVariables.Add("Clock");            _systemBuildInVariables.Add("ControlState");            _systemBuildInVariables.Add("EventsEnabled");            _systemBuildInVariables.Add("PPExecName");            _systemBuildInVariables.Add("PreviousProcessState");            _systemBuildInVariables.Add("ProcessState");            _systemBuildInVariables.Add("SpoolCountActual");            _systemBuildInVariables.Add("SpoolCountTotal");            _systemBuildInVariables.Add("SpoolFullTime");            _systemBuildInVariables.Add("SpoolStartTime");            _systemBuildInVariables.Add("SpoolState");            _systemBuildInVariables.Add("SpoolSubstate");            _logCleaner.Run();            _faMonitorThread = new PeriodicJob(200, MonitorFaTask, "Monitor FA Thread", true);            EV.Subscribe(new EventItem("Host", EventTerminalMessage, "{0}", EventLevel.Warning, EventType.EventUI_Notify));        }        private void _gem_ControlStateChanged(object sender, SECsEventArgs e)        {            if (_state != _gem.ControlState)            {                _state = _gem.ControlState;                if (_state == ControlState.OnlineRemote)                {                    //EV.PostInfoLog("FA", Aitex.RT.Properties.Resources.HostControlModeChangeTo_stateNotifySystemChangeToAutoMode);                    //Singleton<PMEntity>.Instance.PostMsg((int)PMEntity.MSG.SetAutoMode);                }            }        }        public void Invoke(string method, object[] args)        {            switch (method)            {                case "FAEnable":                    _gem.SetEnable();                    break;                case "FADisable":                    _gem.SetDisable();                    break;                case "FAOnline":                    _gem.SetOnline();                    break;                case "FAOffline":                    _gem.SetOffline();                    break;                case "FALocal":                    _gem.SetLocal();                    break;                case "FARemote":                    _gem.SetRemote();                    break;                case "FAEnableSpooling":                    SetEnableSpooling();                    break;                case "FADisableSpooling":                    SetDisableSpooling();                    break;            }        }        private bool _gem_RemoteCommandS2F41In(SECsTransaction trans)        {            try            {                bool ret = true;                string reason = string.Empty;                SECsMessage reply = _gem.Services.CustomMessage.CreateMessage(2, 42, false);                reply.DataItem.AddList();                if (ret)                {                    reply.DataItem[0].Add("HCACK", 0, SECsFormat.Binary);                }                _gem.SendReply(reply, trans.Id);            }            catch (Exception ex)            {                //LOG.Write(string.Format("Handle_S2F41 Exception: {0}", ex.Message));                SECsMessage reply = _gem.Services.CustomMessage.CreateMessage(2, 42, false);                reply.DataItem.AddList();                reply.DataItem[0].Add("HCACK", 3/*At least one parameter is invalid*/, SECsFormat.Binary);                reply.DataItem[0].AddList();                reply.DataItem[0][1].AddList();                reply.DataItem[0][1].Add("CPVALUE", ex.Message, SECsFormat.Ascii);                _gem.SendReply(reply, trans.Id);            }            return true;        }        private bool _gem_RemoteCommandS2F49In(SECsTransaction trans)        {            try            {                bool ret = true;                string reason = string.Empty;                SECsMessage reply = _gem.Services.CustomMessage.CreateMessage(2, 50, false);                string remoteCommandName = trans.Primary.DataItem[0][2].ToString();                switch (remoteCommandName.ToUpper())                {                    case "MAPCASSETTE":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "PortID")                                throw new Exception($"MAPCASSETTE Command Format Not Correct, CPNAME1 should be PortID");                            string portID = trans.Primary.DataItem[0][3][0][1].ToString();                            ret = _equipment.MapCassette(portID, out reason);                        }                        break;                    case "PP-SELECT":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "PortID")                                throw new Exception($"PP-SELECT Command Format Not Correct, CPNAME1 should be PortID");                            if (trans.Primary.DataItem[0][3][1][0].ToString() != "JobID")                                throw new Exception($"PP-SELECT Command Format Not Correct, CPNAME2 should be JobID");                            if (trans.Primary.DataItem[0][3][2][0].ToString() != "LotID")                                throw new Exception($"PP-SELECT Command Format Not Correct, CPNAME3 should be LotID");                            if (trans.Primary.DataItem[0][3][3][0].ToString() != "SequenceID")                                throw new Exception($"PP-SELECT Command Format Not Correct, CPNAME4 should be SequenceID");                            string[] slotSequence = new string[25];                            for (int i = 0; i < 25; i++)                            {                                slotSequence[i] = trans.Primary.DataItem[0][3][3][1][i].ToString();                                if (slotSequence[i].Contains("*null"))                                    slotSequence[i] = string.Empty;                            }                            string portID = trans.Primary.DataItem[0][3][0][1].ToString();                            string jobID = trans.Primary.DataItem[0][3][1][1].ToString();                            string lotID = trans.Primary.DataItem[0][3][2][1].ToString();                            ret = _equipment.PPSelect(portID, jobID, lotID, slotSequence, out reason);                        }                        break;                    case "STARTJOB":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "JobID")                                throw new Exception($"STARTJOB Command Format Not Correct, CPNAME1 should be JobID");                            string jobID = trans.Primary.DataItem[0][3][0][1].ToString();                            ret = _equipment.StartJob(jobID, out reason);                        }                        break;                    case "ABORTJOB":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "JobID")                                throw new Exception($"ABORTJOB Command Format Not Correct, CPNAME1 should be JobID");                            string jobID = trans.Primary.DataItem[0][3][0][1].ToString();                            ret = _equipment.AbortJob(jobID, out reason);                        }                        break;                    case "PAUSEJOB":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "JobID")                                throw new Exception($"PAUSEJOB Command Format Not Correct, CPNAME1 should be JobID");                            string jobID = trans.Primary.DataItem[0][3][0][1].ToString();                            ret = _equipment.PauseJob(jobID, out reason);                        }                        break;                    case "RESUMEJOB":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "JobID")                                throw new Exception($"RESUMEJOB Command Format Not Correct, CPNAME1 should be JobID");                            string jobID = trans.Primary.DataItem[0][3][0][1].ToString();                            ret = _equipment.ResumeJob(jobID, out reason);                        }                        break;                    case "STOPJOB":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "JobID")                                throw new Exception($"STOPJOB Command Format Not Correct, CPNAME1 should be JobID");                            string jobID = trans.Primary.DataItem[0][3][0][1].ToString();                            ret = _equipment.StopJob(jobID, out reason);                        }                        break;                    case "LOAD":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "PortID")                                throw new Exception($"LOAD Command Format Not Correct, CPNAME1 should be PortID");                            string portID = trans.Primary.DataItem[0][3][0][1].ToString();                            ret = _equipment.Load(portID, out reason);                        }                        break;                    case "UNLOAD":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "PortID")                                throw new Exception($"UNLOAD Command Format Not Correct, CPNAME1 should be PortID");                            string portID = trans.Primary.DataItem[0][3][0][1].ToString();                            ret = _equipment.Unload(portID, out reason);                        }                        break;                    case "LOCK":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "PortID")                                throw new Exception($"LOCK Command Format Not Correct, CPNAME1 should be PortID");                            string portID = trans.Primary.DataItem[0][3][0][1].ToString();                            ret = _equipment.Lock(portID, out reason);                        }                        break;                    case "UNLOCK":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "PortID")                                throw new Exception($"UNLOCK Command Format Not Correct, CPNAME1 should be PortID");                            string portID = trans.Primary.DataItem[0][3][0][1].ToString();                            ret = _equipment.Unlock(portID, out reason);                        }                        break;                    case "READID":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "PortID")                                throw new Exception($"READID Command Format Not Correct, CPNAME1 should be PortID");                            string portID = trans.Primary.DataItem[0][3][0][1].ToString();                            ret = _equipment.ReadID(portID, out reason);                        }                        break;                    case "WRITEID":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "PortID")                                throw new Exception($"WRITEID Command Format Not Correct, CPNAME1 should be PortID");                            if (trans.Primary.DataItem[0][3][1][0].ToString() != "CarrierID")                                throw new Exception($"WRITEID Command Format Not Correct, CPNAME2 should be CarrierID");                            string portID = trans.Primary.DataItem[0][3][0][1].ToString();                            string carrierID = trans.Primary.DataItem[0][3][1][1].ToString();                            ret = _equipment.WriteID(portID, carrierID, out reason);                        }                        break;                    case "READTAG":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "PortID")                                throw new Exception($"READTAG Command Format Not Correct, CPNAME1 should be PortID");                            string portID = trans.Primary.DataItem[0][3][0][1].ToString();                            ret = _equipment.ReadTag(portID, out reason);                        }                        break;                    case "WRITETAG":                        {                            if (trans.Primary.DataItem[0][3][0][0].ToString() != "PortID")                                throw new Exception($"WRITEID Command Format Not Correct, CPNAME1 should be PortID");                            if (trans.Primary.DataItem[0][3][1][0].ToString() != "TagData")                                throw new Exception($"WRITEID Command Format Not Correct, CPNAME2 should be TagData");                            string portID = trans.Primary.DataItem[0][3][0][1].ToString();                            string tagData = trans.Primary.DataItem[0][3][1][1].ToString();                            ret = _equipment.WriteTag(portID, tagData, out reason);                        }                        break;                }                reply.DataItem.AddList();                if (ret)                {                    reply.DataItem[0].Add("HCACK", 0, SECsFormat.Binary);                }                else                {                    reply.DataItem[0].Add("HCACK", 3, SECsFormat.Binary);                    reply.DataItem[0].Add("CPVALUE", reason, SECsFormat.Ascii);                }                _gem.SendReply(reply, trans.Id);            }            catch (Exception ex)            {                SECsMessage reply = _gem.Services.CustomMessage.CreateMessage(2, 50, false);                reply.DataItem.AddList();                reply.DataItem[0].Add("HCACK", 3/*At least one parameter is invalid*/, SECsFormat.Binary);                reply.DataItem[0].AddList();                reply.DataItem[0][1].AddList();                reply.DataItem[0][1].Add("CPVALUE", ex.Message, SECsFormat.Ascii);                _gem.SendReply(reply, trans.Id);            }            return true;        }        private void _gem_PrimaryMessageIn(object sender, SECsPrimaryInEventArgs e)        {            string SF = "S" + e.Inputs.Stream.ToString() + "F" + e.Inputs.Function.ToString();            switch (SF)            {                case "S7F1":                    Handle_S7F1(e);                    break;                case "S7F5":                    Handle_S7F5(e);                    break;                case "S7F3"://down load recipe                    Handle_S7F3(e); //Host must send S7F1/F2 and equipment application must either grant the host requests.                    break;                case "S7F17":                    Handle_S7F17(e);                    break;                case "S7F19":                    Handle_S7F19(e);                    break;                case "S7F25":                    Handle_S7F25(e);                    break;                case "S10F3"://Single terminal message                    Handle_S10F3(e);                    break;                case "S10F5"://Multiple terminal message                    Handle_S10F5(e);                    break;            }            switch (e.EventId)            {                case PrimaryEventType.ProcessProgramLoadInquire: //S7F1                    break;            }        }        /// <summary>        /// Host requests the equipment to delete the Process Program        /// L,n (Number of process programs to be deleted)        ///     1. <PPID1>        ///     .        ///     .        ///     n. <PPIDn>        /// Exception: If n=0, then delete all.        /// </summary>        /// <param name="e"></param>        private void Handle_S7F17(SECsPrimaryInEventArgs e)        {            try            {                string reason = string.Empty;                if (e.Inputs.DataItem[0].Count == 0)                {                    //LOG.Write("Handle_S7F17, delete all recipes");                    DeleteAllRecipes(out reason);                }                else // Delete the list of selected Process Program                {                    List<string> deleteRecipes = new List<string>();                    for (int i = 0; i < e.Inputs.DataItem[0].Count; i++)                    {                        string ppid = e.Inputs.DataItem[0][i].ToString();                        deleteRecipes.Add(ppid);                        //LOG.Write("Handle_S7F17, delete recipe:" + ppid);                    }                    DeleteRecipe(deleteRecipes, out reason);                }                //give reply to host                SECsMessage messageToReply = _gem.Services.ProcessProgram.DeleteProcessProgramAcknowledge(0);                _gem.SendReply(messageToReply, e.TransactionID);            }            catch (Exception ex)            {                //LOG.Write("Handle_S7F17 Exception: " + ex.Message);                LOG.WriteExeption("Handle_S7F17 Exception: ", ex);                //give reply to host                SECsMessage messageToReply = _gem.Services.ProcessProgram.DeleteProcessProgramAcknowledge(4/*error*/);                _gem.SendReply(messageToReply, e.TransactionID);            }        }        protected void DeleteAllRecipes(out string reason)        {            reason = string.Empty;            var recipes = RecipeFileManager.Instance.GetSequenceNameList();            foreach (var name in recipes)            {                if (!RecipeFileManager.Instance.DeleteSequence(name))                {                    EV.PostWarningLog("System", $"Can not delete {name}, delete all failed.");                    return;                }            }            EV.PostInfoLog("System", "All recipe deleted");        }        protected void DeleteRecipe(List<string> recipeFiles, out string reason)        {            reason = string.Empty;            foreach (var name in recipeFiles)            {                if (!RecipeFileManager.Instance.DeleteSequence(name))                {                    EV.PostWarningLog("System", $"Can not delete {name}.");                    return;                }                else                {                    EV.PostWarningLog("System", $"Delete recipe {name}.");                }            }        }        private void Handle_S7F3(SECsPrimaryInEventArgs e)        {            try            {                //LOG.Write("Handle_S7F4, Request down load recipe");                string ppid = e.Inputs.DataItem[0][0].Value.ToString();                string reason = string.Empty;                // Get the format of PPBODY                SECsFormat bodyType = e.Inputs.DataItem[0][1].Format;                bool recipeSuccess = false;                if (bodyType == SECsFormat.Binary)                {                    recipeSuccess = DownLoadRecipeInByte(ppid, (byte[])e.Inputs.DataItem[0][1].Value, out reason);                }                else                {                    recipeSuccess = DownLoadRecipe(ppid, e.Inputs.DataItem[0][1].ToString(), out reason);                }                if (recipeSuccess)                {                    SECsMessage acknowledge = _gem.Services.ProcessProgram.ProcessProgramAcknowledge(0);                    _gem.SendReply(acknowledge, e.TransactionID);                }                else                {                    //1:download recipe body fail:Permission Not Granted                    //2:download recipe body fail:Length Error                    //3:download recipe body fail:Matrix Overflow                    //4:download recipe body fail:PPID Not Found                    //5:download recipe body fail:Mode Unsupported                    SECsMessage acknowledge = _gem.Services.ProcessProgram.ProcessProgramAcknowledge(5);                    _gem.SendReply(acknowledge, e.TransactionID);                }            }            catch (Exception ex)            {                //LOG.Write("Handle_S7F4 exception:" + ex.Message);                LOG.WriteExeption("Handle_S7F4 exception:", ex);                SECsMessage acknowledge = _gem.Services.ProcessProgram.ProcessProgramAcknowledge(1);                _gem.SendReply(acknowledge, e.TransactionID);            }        }        protected bool DownLoadRecipe(string name, string content, out string reason)        {            bool ret = false;            reason = string.Empty;            ret = RecipeFileManager.Instance.SaveSequence(name, content, false);            if (!ret)            {                reason = string.Format("save recipe content failed,recipeName:{0}", name);                //LOG.Write(reason);            }            return ret;        }        protected bool DownLoadRecipeInByte(string name, byte[] content, out string reason)        {            bool ret = false;            reason = string.Empty;            ret = RecipeFileManager.Instance.SaveSequence(name, System.Text.Encoding.UTF8.GetString(content), false);            if (!ret)            {                reason = string.Format("save recipe content failed,recipeName:{0}", name);                //LOG.Write(reason);            }            return ret;        }        /// <summary>        /* 0 = OK            1 = Already have            2 = No space            3 = Invalid PPID            4 = Busy, try later            5 = Will not accept            >5 = Other error            6-63 Reserved        */        ///</summary>        /// <param name="e"></param>        private void Handle_S7F1(SECsPrimaryInEventArgs e)        {            try            {                //LOG.Write("Handle_S7F1, Process Program Load Inquire");                string ppid = e.Inputs.DataItem[0][0].Value.ToString();                var recipeList = RecipeFileManager.Instance.GetSequenceNameList();                int ppGrant = 0;                if (!recipeList.Contains(ppid))                    ppGrant = 3;                SECsMessage reply = _gem.Services.CustomMessage.CreateMessage(7, 2, false);                reply.DataItem.Add("PPGNT", ppGrant, SECsFormat.Binary);                _gem.SendReply(reply, e.TransactionID);            }            catch (Exception ex)            {                LOG.WriteExeption("Handle_S7F1 exception:", ex);                SECsMessage reply = _gem.Services.CustomMessage.CreateMessage(7, 0, false);                _gem.SendReply(reply, e.TransactionID);            }        }        private void Handle_S7F5(SECsPrimaryInEventArgs e)        {            try            {                //LOG.Write("Handle_S7F5,Used to request the transfer of a process program");                string ppid = e.Inputs.DataItem[0].ToString();                string reason = string.Empty;                string data = RecipeFileManager.Instance.GetSequence(ppid, false);                if (!string.IsNullOrEmpty(data))                {                    byte[] ppbody = System.Text.Encoding.UTF8.GetBytes(data);                    SECsMessage recipetToReply = _gem.Services.ProcessProgram.ProcessProgramData(ppid, ppbody);                    _gem.SendReply(recipetToReply, e.TransactionID);                }                else                {                    SECsMessage reply = _gem.Services.CustomMessage.CreateMessage(7, 6, false);                    reply.DataItem.AddList();                    reply.DataItem[0].Add("RVIACK", 0x01/*abnormal*/, SECsFormat.Binary);                    reply.DataItem[0].Add("CPVALUE", reason, SECsFormat.Ascii);                    _gem.SendReply(reply, e.TransactionID);                }            }            catch (Exception ex)            {                LOG.WriteExeption("Handle_S7F6 exception:", ex);                SECsMessage reply = _gem.Services.CustomMessage.CreateMessage(7, 6, false);                reply.DataItem.AddList();                _gem.SendReply(reply, e.TransactionID);            }        }        private void Handle_S7F19(SECsPrimaryInEventArgs e)        {            try            {                string reason = string.Empty;                //LOG.Write("Handle_S7F19, Request the transmission of the current equipment process program directory");                var recipeList = RecipeFileManager.Instance.GetSequenceNameList();                SECsMessage reply = _gem.Services.CustomMessage.CreateMessage(7, 20, false);                reply.DataItem.AddList();                for (int rNum = 0; rNum < recipeList.Count; rNum++)                {                    reply.DataItem[0].Add("PPID", recipeList[rNum], SECsFormat.Ascii);                }                _gem.SendReply(reply, e.TransactionID);            }            catch (Exception ex)            {                LOG.WriteExeption("Handle_S7F19 exception:", ex);                SECsMessage reply = _gem.Services.CustomMessage.CreateMessage(7, 0, false);                _gem.SendReply(reply, e.TransactionID);            }        }        private void Handle_S7F25(SECsPrimaryInEventArgs e)        {            try            {                var ppid = e.Inputs.DataItem[0].Value.ToString();                //LOG.Write("Handle_S7F25, request a particular process program from the other");                SECsMessage reply = _gem.Services.CustomMessage.CreateMessage(7, 26, false);                reply.DataItem.AddList();                var parameters = GetRecipe(ppid, out string reason);                if (parameters != null)                {                    reply.DataItem[0].Add("PPID", ppid, SECsFormat.Ascii);                    reply.DataItem[0].Add("MDLN", _gem.EquipmentModel.Nameable.model, SECsFormat.Ascii);                    reply.DataItem[0].Add("SOFTREV", _gem.EquipmentModel.Nameable.softwareRev, SECsFormat.Ascii);                    reply.DataItem[0].AddList();                    reply.DataItem[0][3].AddList();                    reply.DataItem[0][3][0].Add("CCODE", 1, SECsFormat.U1);                    reply.DataItem[0][3][0].AddList();                    for (int i = 0; i < parameters.Count; i++)                    {                        reply.DataItem[0][3][0][1].Add($"PPARM{i + 1}", parameters[i], SECsFormat.Ascii);                    }                }                else                {                    EV.PostWarningLog("FA", $"Request {ppid} failed, {reason}");                }                _gem.SendReply(reply, e.TransactionID);            }            catch (Exception ex)            {                LOG.WriteExeption("Handle_S7F25 exception:", ex);                SECsMessage reply = _gem.Services.CustomMessage.CreateMessage(7, 0, false);                _gem.SendReply(reply, e.TransactionID);            }        }        public List<string> GetRecipe(string sequenceName, out string reason)        {            List<string> result = new List<string>();            reason = string.Empty;            try            {                string content = RecipeFileManager.Instance.GetSequence(sequenceName, false);                if (string.IsNullOrEmpty(content))                {                    content = RecipeFileManager.Instance.LoadRecipe("", sequenceName, false);                }                result.Add(content);            }            catch (Exception ex)            {                LOG.WriteExeption(ex);                reason = ex.Message;            }            return result;        }        public List<string> GetFormattedSequence(string sequenceName, out string reason)        {            List<string> result = new List<string>();            try            {                string sequenceData = RecipeFileManager.Instance.GetSequence(sequenceName, false);                XmlDocument recipeDoc = new XmlDocument();                recipeDoc.LoadXml(sequenceData);                XmlNodeList stepNodeList = recipeDoc.SelectNodes("/Aitex/TableSequenceData/Step");                for (int i = 0; i < stepNodeList.Count; i++)                {                    XmlElement stepNode = stepNodeList[i] as XmlElement;                    Dictionary<string, string> dic = new Dictionary<string, string>();                    //遍历Step节点                    foreach (XmlAttribute att in stepNode.Attributes)                    {                        result.Add($"STEP{i + 1}/{att.Name}:{att.Value}");                    }                }                reason = string.Empty;            }            catch (Exception ex)            {                LOG.WriteExeption(ex);                reason = ex.Message;            }            return result;        }        public List<string> GetFormattedRecipe(string recipeName, out string reason)        {            List<string> result = new List<string>();            try            {                string sequenceData = RecipeFileManager.Instance.LoadRecipe("", recipeName, false);                XmlDocument recipeDoc = new XmlDocument();                recipeDoc.LoadXml(sequenceData);                XmlNodeList stepNodeList = recipeDoc.SelectNodes("/TableRecipeData/Step");                for (int i = 0; i < stepNodeList.Count; i++)                {                    XmlElement stepNode = stepNodeList[i] as XmlElement;                    Dictionary<string, string> dic = new Dictionary<string, string>();                    //遍历Step节点                    foreach (XmlAttribute att in stepNode.Attributes)                    {                        result.Add($"STEP{i + 1}/{att.Name}:{att.Value}");                    }                    //遍历Step子节点中所有的attribute属性节点                    foreach (XmlElement subStepNode in stepNode.ChildNodes)                    {                        foreach (XmlAttribute att in subStepNode.Attributes)                        {                            result.Add($"STEP{i + 1}/{subStepNode.Name}/{att.Name}:{att.Value}");                        }                        //遍历Step子节点的子节点中所有的attribute属性节点                        foreach (XmlElement subsubStepNode in subStepNode.ChildNodes)                        {                            foreach (XmlAttribute att in subsubStepNode.Attributes)                            {                                result.Add($"STEP{i + 1}/{subStepNode.Name}/{subsubStepNode.Name}/{att.Name}:{att.Value}");                            }                        }                    }                }                reason = string.Empty;            }            catch (Exception ex)            {                LOG.WriteExeption(ex);                reason = ex.Message;            }            return result;        }        /// <summary>        /// Single terminal message process        /// S10F3 Format        /// L,2        ///     1. <TID>        ///     2. <TEXT>        /// </summary>        /// <param name="e"></param>        private void Handle_S10F3(SECsPrimaryInEventArgs e)        {            try            {                //LOG.Write("Process host single terminal message");                string terminalMessage = e.Inputs.DataItem["Ln"]["TEXT"].ToString();                // notify equipment to show terminal message                OnReceivedSingleTerminalMessage(terminalMessage);                // acknowledge Host                SECsMessage reply = _gem.Services.TerminalDisplay.TerminalDisplayAcknowledge(0);                reply.Function = 4;                _gem.SendReply(reply, e.TransactionID);            }            catch (Exception ex)            {                LOG.WriteExeption("Handle_S10F3 Exception: ", ex);                SECsMessage reply = _gem.Services.TerminalDisplay.TerminalDisplayAcknowledge(1/*will not display*/);                reply.Function = 4;                _gem.SendReply(reply, e.TransactionID);            }        }        /// <summary>        /// Multiple terminal message process        /// S10F5 Format        /// L,2        ///      1. <TID>        ///      2. L,N        ///         1. <TEXT1>        ///         .        ///         .        ///         n.<TEXTn>        /// </summary>        /// <param name="e"></param>        private void Handle_S10F5(SECsPrimaryInEventArgs e)        {            try            {                //LOG.Write("Process host multiple terminal message");                List<string> receivedMultipleMessages = new List<string>();                string message = string.Empty;                for (int i = 0; i < e.Inputs.DataItem[0][1].Count; i++)                {                    receivedMultipleMessages.Add((string)e.Inputs.DataItem[0][1][i].Value);                }                // notify equipment to show terminal message                OnReceivedMultipleTerminalMessage(receivedMultipleMessages);                // acknowledge Host                SECsMessage reply = _gem.Services.TerminalDisplay.TerminalDisplayAcknowledge(0);                reply.Function = 6;                _gem.SendReply(reply, e.TransactionID);            }            catch (Exception ex)            {                LOG.WriteExeption("Handle_S10F5 Exception: ", ex);                SECsMessage reply = _gem.Services.TerminalDisplay.TerminalDisplayAcknowledge(1/*will not display*/);                reply.Function = 6;                _gem.SendReply(reply, e.TransactionID);            }        }        /// <summary>        /// On single terminal message received        /// </summary>        /// <param name="terminalMessage"></param>        protected virtual void OnReceivedSingleTerminalMessage(string terminalMessage)        {            EV.Notify("Host", EventTerminalMessage, terminalMessage);        }        /// <summary>        /// On multiple terminal message received        /// </summary>        /// <param name="terminalMessage"></param>        protected virtual void OnReceivedMultipleTerminalMessage(List<string> terminalMessage)        {            foreach (var message in terminalMessage)            {                EV.Notify("Host", EventTerminalMessage, message);            }        }        public void Terminate()        {            _faMonitorThread.Stop();            _logCleaner.Stop();        }        public void Enable()        {            _gem.SetEnable();        }        public void Disable()        {            _gem.SetDisable();        }        public void NotifyEvent(string eventName, Dictionary<string, string> dvid, Dictionary<string, object> objDvid)        {            _lstEvent.Enqueue(new FaEventItem() { dvid = dvid, objDvid = objDvid, EventName = eventName, IsAlarm = false });        }        public void NotifyAlarm(string alarmName, Dictionary<string, string> dvid, Dictionary<string, object> objDvid, string text)        {            _lstEvent.Enqueue(new FaEventItem() { dvid = dvid, objDvid = objDvid, EventName = alarmName, IsAlarm = true, Text = text});        }        public void NotifyEvent(string eventName, Dictionary<string, string> dvid)        {            _lstEvent.Enqueue(new FaEventItem() { dvid = dvid, EventName = eventName, IsAlarm = false });        }        public void NotifyAlarm(string alarmName, Dictionary<string, string> dvid, string text)        {            _lstEvent.Enqueue(new FaEventItem() { dvid = dvid, EventName = alarmName, IsAlarm = true, Text = text});        }        public void SetLocalControl()        {            Task.Factory.StartNew(() =>            {                _gem.SetLocal();            });        }        public void SetRemoteControl()        {            Task.Factory.StartNew(() =>            {                _gem.SetRemote();            });        }        public void SetEnableSpooling()        {            Task.Factory.StartNew(() =>            {                _gem.SetAttribute(GEMVariables.SpoolEnabled, AttributeType.EC, "true");            });        }        public void SetDisableSpooling()        {            Task.Factory.StartNew(() =>            {                _gem.SetAttribute(GEMVariables.SpoolEnabled, AttributeType.EC, "false");            });        }        public bool MonitorFaTask()        {            try            {                SynchronizeSVIDValue();                FaEventItem ev;                while (_lstEvent.TryDequeue(out ev))                {                    if (ev.dvid != null)                    {                        foreach (var dvid in ev.dvid)                        {                            SetDVIDValue(dvid.Key, dvid.Value);                        }                    }                    if (ev.objDvid != null)                    {                        foreach (var dvid in ev.objDvid)                        {                            SetDVIDValue(dvid.Key, dvid.Value);                        }                    }                    SetDVIDValue(DVIDName.EventName, ev.EventName);                    if (ev.IsAlarm)                    {                        SetAlarm(ev.EventName, ev.Text);                    }                    else                    {                        SendEvent(ev.EventName);                    }                    //Thread.Sleep(500);                }            }            catch (Exception ex)            {                System.Diagnostics.Trace.WriteLine(ex);            }            return true;        }        private void OnCommunicationStateChanged(object sender, SECsEventArgs e)        {            if (_gem.CommunicationState == CommunicationState.EnabledCommunicating)            {                if (SC.ContainsItem("System.FA.DefaultToOnline") && SC.GetValue<bool>("System.FA.DefaultToOnline"))                    _gem.SetOnline();                if (SC.ContainsItem("System.FA.DefaultToRemote") && SC.GetValue<bool>("System.FA.DefaultToRemote"))                    _gem.SetRemote();            }        }        /// <summary>        /// Send terminal message to host        /// </summary>        /// <param name="message"></param>        public void SendTerminalMessageToHost(string message)        {            if (!_gem.IsConnected || _gem.CommunicationState == CommunicationState.Disabled                                  || _gem.CommunicationState == CommunicationState.WaitDelay                                  || _gem.CommunicationState == CommunicationState.EnabledNotCommunicating)            {                EV.PostWarningLog("FA", "Host not connected, send terminal message failed.");                return;            }            //LOG.Write("Send terminal message to host:" + message);            Task.Factory.StartNew(() =>            {                SECsMessage secsMsg = _gem.Services.TerminalDisplay.TerminalRequest(message);                _gem.Send(secsMsg);            });        }        public void SynchronizeSVIDValue()        {            try            {                foreach (SVID sv in _gem.EquipmentModel.StatusVariables.SVIDCollection)                {                    if (sv != null && !_systemBuildInVariables.Contains(sv.logicalName))                    {                        if (sv.valueType == SECSFormats.List)                        {                            List<string> svData = _equipment.GetListSvidValue(sv.logicalName);                            if (svData != null && svData.Count > 0)                            {                                SECsDataItem data = new SECsDataItem(SECsFormat.List);                                foreach (var item in svData)                                {                                    data.Add(item, item);                                }                                _gem.SetListAttribute(sv.logicalName, AttributeType.SV, data);                            }                            else                            {                                SECsDataItem data = new SECsDataItem(SECsFormat.List);                                data.Clear();                                _gem.SetListAttribute(sv.logicalName, AttributeType.SV, data);                            }                        }                        else                        {                            string svDataValue = _equipment.GetSvidValue(sv.logicalName);                            if (!string.IsNullOrEmpty(svDataValue))                            {                                if (sv.valueType == SECSFormats.Boolean) svDataValue = ConvertToBoolean(svDataValue).ToString();                                _gem.SetAttribute(sv.logicalName, AttributeType.SV, svDataValue);                            }                        }                    }                }            }            catch (Exception ex)            {                LOG.WriteExeption("Synchronize FA Model Data exception:", ex);            }        }        private bool SetDVIDValue(string localName, object value)        {            if (value == null) return false;            if (_gem.EquipmentModel == null || !_gem.EquipmentModel.DataVariables.DVIDCollection.IsExistLogicalName(localName))                return false;            foreach (VariableType dv in _gem.EquipmentModel.DataVariables.DVIDCollection)            {                if (dv.logicalName == localName)                {                    if (localName == "RecipeStepEndDataSummary")                    {                        List<FdcDataItem> lwsdata = (List<FdcDataItem>)value;                        SECsDataItem ldata = new SECsDataItem(SECsFormat.List);                        foreach (FdcDataItem wsd in lwsdata)                        {                            SECsDataItem data = new SECsDataItem(SECsFormat.List);                            data.Add("Process item", wsd.Name);                            data.Add("Min", wsd.MinValue.ToString());                            data.Add("Max", wsd.MaxValue.ToString());                            data.Add("Mean", wsd.MeanValue.ToString());                            data.Add("SetPoint", wsd.SetPoint.ToString());                            data.Add("Std", wsd.StdValue.ToString());                            data.Add("SampleCount", wsd.SampleCount.ToString());                            ldata.Add(data);                        }                        _gem.SetListAttribute(localName, AttributeType.DV, ldata);                        return true;                    }                    if (dv.valueType == SECSFormats.Boolean)                    {                        value = ConvertToBoolean(Convert.ToString(value)).ToString();                    }                    break;                }            }            _gem.SetAttribute(localName, AttributeType.DV, Convert.ToString(value));            return true;        }        private bool SetDVIDValue(string localName, string value)        {            if (value == null) return false;            //if (!string.IsNullOrEmpty(value))            //{            if (_gem.EquipmentModel == null || !_gem.EquipmentModel.DataVariables.DVIDCollection.IsExistLogicalName(localName))                return false;            foreach (VariableType dv in _gem.EquipmentModel.DataVariables.DVIDCollection)            {                if (dv.logicalName == localName)                {                    if (dv.valueType == SECSFormats.Boolean)                    {                        value = ConvertToBoolean(value).ToString();                    }                    break;                }            }            _gem.SetAttribute(localName, AttributeType.DV, value);            //}            return true;        }        private bool ConvertToBoolean(string value)        {            if (value == "0" || value.ToLower() == "false") return false;            else return true;        }        private void SendEvent(string eventName)        {            try            {                if (_gem.EquipmentModel != null)                {                    var allEvents = _gem.GetAllEnabledEvents();                    if (allEvents.Contains(eventName))                    {                        _gem.SendCollectionEvent(eventName);                    }                    else                    {                        //LOG.Write(string.Format("sendEvent failed,not find:", eventName));                    }                    //LOG.Write(string.Format("【FA2SendEvent--{0}】", eventName));                }            }            catch (Exception ex)            {                LOG.WriteExeption("SendEvent Error:", ex);            }        }        public void SetAlarm(string alarmTag, string text)        {            Task.Factory.StartNew(() =>            {                //if (_gem.IsAlarmSet(alarmTag))                //{                //    _gem.ClearAlarm(alarmTag);                //}                var allAlarms = _gem.GetAllEnabledAlarms();                if (allAlarms.Contains(alarmTag))                {                    _gem.EquipmentModel.Alarms[alarmTag].description = text;                    _gem.SetAlarm(alarmTag);                }                else                {                    //WriteLog(string.Format("sendAlarm failed,not find:", alarmTag));                }                //WriteLog(string.Format("【FA3SetAlarm--{0}】", alarmTag));            });        }        public void ClearAlarm(string alarmTag)        {            try            {                var allsetalarms = _gem.GetAllSetAlarms();                if (allsetalarms != null && allsetalarms.Count > 0 && allsetalarms.Contains(alarmTag))                    _gem.ClearAlarm(alarmTag);                if (string.IsNullOrEmpty(alarmTag))                {                    foreach (var allsetalarm in allsetalarms)                    {                        _gem.ClearAlarm(allsetalarm.ToString());                    }                }            }            catch (Exception ex)            {                LOG.WriteExeption($"Clear Alarm Error : ", ex);            }        }    }}
 |