| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 | using Aitex.Core.Common;using Aitex.Core.RT.Log;using Aitex.Core.RT.SCCore;using Aitex.Core.Util;using MECF.Framework.Common.Communications;using MECF.Framework.Common.Equipment;using MECF.Framework.Common.SubstrateTrackings;using MECF.Framework.RT.ModuleLibrary.VceModules;using System;using System.Collections.Generic;using System.IO.Ports;using System.Linq;using System.Text;using System.Text.RegularExpressions;using System.Threading.Tasks;using Venus_Core;namespace Venus_RT.Devices.VCE{    //定义Vce动作    public enum VceCommand    {        Home,        DoorClose,        DoorOpen,        CheckGoto,        Goto,        GotoLP,        Load,        UnLoad,        Map,        ReadMap,    }    public enum VceMessageHead    {        Action,        Read,        Set,        Petrify    }    public sealed class VceMessage    {        private Dictionary<VceCommand, string> _Command2Msg = new Dictionary<VceCommand, string>()        {            //Action            {VceCommand.Home,       "HM"    },            {VceCommand.Load,       "LOAD"  },            {VceCommand.UnLoad,     "UNLOAD"},            {VceCommand.Map,        "MP"    },            {VceCommand.CheckGoto,  "GC"    },            {VceCommand.Goto,       "GO"    },            {VceCommand.GotoLP,     "LP"    },            {VceCommand.DoorOpen,   "DO"    },            {VceCommand.DoorClose,  "DC"    },            //Read            {VceCommand.ReadMap,    "MI" },            //Set                    };        private Dictionary<VceMessageHead, string> _Type2Head = new Dictionary<VceMessageHead, string>()        {            {VceMessageHead.Action,  "A"},            {VceMessageHead.Read,    "R"},            {VceMessageHead.Set,     "S"},            {VceMessageHead.Petrify, "P"},        };        public VceMessageHead Head { get; set; }        public VceCommand Command { get; set; }        public string Param { get; set; }        public string toString()        {            if (string.IsNullOrEmpty(Param))//含尾参                return $"00,{_Type2Head[Head]},{_Command2Msg[Command]}";            else//不含尾参 目前只允许一个                return $"00,{_Type2Head[Head]},{_Command2Msg[Command]},{Param}";        }    }    /// <summary>    /// 泓浒Vce驱动 下发指令等    /// </summary>    public class HongHuVce : VceModuleBase    {        #region 私有变量        private AsyncSerialPort _serialport;        private string _portname;        private string _newline = "\n\r";//终止符 0A 0D        private object _locker = new object();        private bool _IsAsciiMode;        private LinkedList<string> _lstAsciiMsgs = new LinkedList<string>();        private PeriodicJob _thread;        private Regex _match_ReadMsg = new Regex(@"\d\d,X,.*");        private Regex _matchErrorCode = new Regex(@"(?<=_BKGERR )(.*)");        private ModuleName _moduleName;        private RState _status;        private string _currentMsg;        private VceMessage _currentVceMessage;        private bool _HasReceiveMsg;        //待补充        private Dictionary<string, string> _ErrorCode2Reason = new Dictionary<string, string>()        {            {"A1","Action Timeout" },            {"A3","Hardware (CAN or VCN) or configuration failed" },            {"A4","Open Door Prevented Motion" },            {"A5","Platform Action Time-out" },            {"A6","Door Action Timeout" },            {"A7","The parameter value is out of range" },            {"A8","Wafer Slideout" },            {"A9","Door safety LED is blocked" },            {"A11","No cassette present" },            {"A12","Cassette present prior PICK" },            {"A13","Cassette NOT present during PICK" },            {"A14","Cassette NOT present prior PLACE" },            {"A15","Cassette present after PLACE" },            {"A16","Cassette Present on VCE platform (Servo Arm)" },            {"A17","No new cassette at station after Load" },            {"A18","Proximity sensor blocked but Cassette A not present" },            {"A19","Cassette present at station A (Fixed Buffer)" },            {"A20","Proximity sensor A is blocked (Fixed Buffer)" },            {"A21","Cassette NOT at station A" },            {"A34","Door Clamped sensor is not ON after clamp (only VCE4!)" },            {"A36","Door Not Covered (sensor)" },            {"C0","Illegal Slot Number" },            {"C1","Illegal action command: wrong attachment, no arm, etc." },            {"C2","Illegal pitch value (too big)" },            {"C3","Illegal Cassette type offset" },            {"C4","Illegal number of Slots" },            {"C5","Illegal Partial step size" },            {"C7","Illegal Find Bias" },            {"C8","Unknown Configuration" },            {"C9","Bad command: command cannot be executed with current HW configuration" },            {"C10","VCE is busy" },            {"C12","Bad Fixture Thickness" },            {"C13","Command is NOT executable (file's operation exception)" },            {"C19","VCEConfig.xml is corrupted" },            {"C20","VCEDefaultSettting.xml is corrupted" },        };        //                #endregion        #region 暴露变量        public override bool IsConnected => _serialport.IsOpen();        public override RState Status => _status;        public override bool IsReady => _status == RState.Init || _status == RState.End;        public override bool IsError => _status == RState.Failed || _status == RState.Timeout;        public override bool IsInit => _status == RState.Init;        private string[] _slotMap = new string[25];        public string SlotMap        {            get            {                WaferInfo[] wafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(Name));                string slot = "";                for (int i = 0; i < 25; i++)                {                    slot += wafers[i].IsEmpty ? "0" : "1";                }                return slot;            }        }        #endregion        //传入slot数量        public HongHuVce(int slot, ModuleName moduleName) : base(slot, moduleName)        {            _moduleName = moduleName;            _IsAsciiMode = true;            _portname = SC.GetStringValue($"{moduleName}.Port");            //_portname = "COM162";            _serialport = new AsyncSerialPort(_portname, 9600, 7, Parity.Even, StopBits.One, _newline, _IsAsciiMode);            _serialport.Open();            _status = RState.Init;            _serialport.OnDataChanged += onDataChange;            _thread = new PeriodicJob(50, fnTimer, "VCE", true);            CarrierManager.Instance.DeleteCarrier(_moduleName.ToString());            WaferManager.Instance.DeleteWafer(_moduleName, 0, 25);            CarrierManager.Instance.SubscribeLocation(_moduleName.ToString(), 1);            Action<ModuleName, int> _subscribeLoc = (ModuleName module, int waferCount) => {                if (ModuleHelper.IsInstalled(module))                {                    WaferManager.Instance.SubscribeLocation(module, waferCount);                }            };            _subscribeLoc(_moduleName, slot);        }        /// <summary>        /// 对处理过的数据list进行处理        /// 将每条数据进行解析        /// </summary>        /// <returns></returns>        private bool fnTimer()        {            lock (_locker)            {                //采用ascii传输                if (_IsAsciiMode)                {                    //有数据尚未处理                    while (_lstAsciiMsgs.Count > 0)                    {                        string _needHandle = _lstAsciiMsgs.First.Value;                        HandleSingleMsg(_needHandle);                        _lstAsciiMsgs.RemoveFirst();                    }                }                //采用binary                else                {                }            }            return true;        }        /// <summary>        /// 处理单条信息的函数        /// 1、判断结束 2、判断错误        /// </summary>        /// <param name="msg">需要处理的单条回复</param>        private void HandleSingleMsg(string msg)        {            //            msg = msg.Trim();            if (!string.IsNullOrEmpty(msg))            {                //action set petrify _BKGRDY结束                switch (_currentVceMessage.Head)                {                    case VceMessageHead.Action:                    case VceMessageHead.Set:                    case VceMessageHead.Petrify:                        switch (msg)                        {                            //设备收到 开始运行 目前状态在下发                            case "_RDY":                                LOG.Write(eEvent.EV_VCE_COMMON_INFO, _moduleName, $"vce start {_currentVceMessage.Head}");                                break;                            //设备执行完毕                            case "_BKGRDY":                                LOG.Write(eEvent.EV_VCE_COMMON_INFO, _moduleName, $"vce {_currentVceMessage.Head} over");                                _status = RState.End;                                break;                            //异常处理                            default:                                _status = RState.Failed;                                string reason;                                Errorhandle(msg, out reason);                                LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, reason);                                break;                        }                        break;                    case VceMessageHead.Read:                        //如果收到的信息符合                        if (_match_ReadMsg.IsMatch(msg))                        {                            //收到消息 用于结束                            _HasReceiveMsg = true;                            switch (_currentVceMessage.Command)                            {                                //处理wafer 信息为map数据                                case VceCommand.ReadMap:                                    ReadMapData(msg);                                    break;                            }                        }                        //_RDY查询结束                        else                        {                            if (msg == "_RDY")                            {                                if (_HasReceiveMsg)                                {                                    _status = RState.End;                                }                                else                                {                                    LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Read Message is over but not receive msg! raw message:{_currentMsg}");                                    _status = RState.Failed;                                }                            }                            else                            {                                _status = RState.Failed;                                LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Read Message is invalid: receive message {msg} and send message {_currentMsg}");                            }                        }                        break;                }            }        }        private void ReadMapData(string msg)        {            string waferinfo = "";            string[] waferitems = msg.Split(',');            //智能模式 可以识别叠片            for (int i = 3; i < waferitems.Length - 1; ++i)            {                //如果包含只需要逐个检查                if (waferitems[i].Contains('?'))                {                    foreach (char j in waferitems[i])                    {                        if (j == '?')                            break;                        else                            waferinfo += j;                    }                }                else                    waferinfo += waferitems[i];            }            for (int i = 0; i < waferinfo.Length; ++i)            {                int slotnum = i;                if (slotnum < 25)                {                    switch (waferinfo[i])                    {                        case '0':                            WaferManager.Instance.CreateWafer(_moduleName, slotnum, WaferStatus.Empty);                            break;                        case 'X':                            WaferManager.Instance.CreateWafer(_moduleName, slotnum, WaferStatus.Normal);                            break;                        case 'C':                            WaferManager.Instance.CreateWafer(_moduleName, slotnum, WaferStatus.Crossed);                            break;                    }                }            }            //2进制模式            //for (int i = 3; i < waferitems.Length - 1; i++)            //{            //    //从16进制字符转义回二进制            //    string wafersingleinfo = Convert.ToString(Convert.ToInt32(waferitems[i], 16), 2);            //    if (wafersingleinfo.Length < 4)            //        wafersingleinfo = wafersingleinfo.PadLeft(4, '0');//补位            //    waferinfo = wafersingleinfo + waferinfo;//添加到数据中            //}            ////请将数据按照反向槽位进行解析存入到wafermanager中            //for (int i = waferinfo.Length - 1; i > 0; i--)            //{            //    int slotnum = waferinfo.Length - i - 1;            //    if (slotnum < 25)            //    {            //        if (waferinfo[i] == '1')            //        {            //            WaferManager.Instance.CreateWafer(_moduleName, slotnum, WaferStatus.Normal);            //        }            //        else            //        {            //            WaferManager.Instance.CreateWafer(_moduleName, slotnum, WaferStatus.Empty);            //        }            //    }            //}        }        private void Errorhandle(string msg,out string reason)        {            if (_matchErrorCode.IsMatch(msg))            {                //若是匹配                //包含原因                string errorcode = _matchErrorCode.Match(msg).Value;                if (_ErrorCode2Reason.ContainsKey(errorcode))                {                    reason = _ErrorCode2Reason[errorcode];                }                else                {                    reason = "未找到相关Error Code";                }            }            else            {                //若不匹配                reason = "回复消息不符合标准格式";            }        }        /// <summary>        /// 处理新到的数据        /// 利用linkedlist处理拆包 粘包情况        /// </summary>        /// <param name="newline">新到数据</param>        private void onDataChange(string oneLineMessage)        {            lock (_locker)            {                if (string.IsNullOrEmpty(_newline))//没有CR                {                    _lstAsciiMsgs.AddLast(oneLineMessage);//将消息添加到最后                    return;                }                string[] array = oneLineMessage.Split(_newline.ToCharArray());//按照cr分开通讯数据                foreach (string text in array)                {                    if (!string.IsNullOrEmpty(text))                    {                        _lstAsciiMsgs.AddLast(text + _newline);//存进list中等待处理                    }                }            }        }        public override bool HomeALL()        {            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Home ,Param = "ALL" };            _currentMsg = _currentVceMessage.toString() + _newline ;            _status = RState.Running;            return _serialport.Write(_currentMsg);        }        public override bool Home(string axis)        {            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Home, Param = axis };            _currentMsg = _currentVceMessage.toString() + _newline;            _status = RState.Running;            return _serialport.Write(_currentMsg);        }        public override bool CloseDoor()        {            if (!CheckVceStatus())                return false;            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.DoorClose };            _currentMsg = _currentVceMessage.toString() + _newline;            _status = RState.Running;            return _serialport.Write(_currentMsg);        }        public override bool OpenDoor()        {            if (!CheckVceStatus())                return false;            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.DoorOpen };            _currentMsg = _currentVceMessage.toString() + _newline;            _status = RState.Running;            return _serialport.Write(_currentMsg);        }        public override bool Load()        {            if (!CheckVceStatus())                return false;            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Load };            _currentMsg = _currentVceMessage.toString() + _newline;            _status = RState.Running;            return _serialport.Write(_currentMsg);        }        public override bool UnLoad()        {            if (!CheckVceStatus())                return false;            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.UnLoad };            _currentMsg = _currentVceMessage.toString() + _newline;            _status = RState.Running;            return _serialport.Write(_currentMsg);        }        public override bool Map()        {            if (!CheckVceStatus())                return false;            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Map };            _currentMsg = _currentVceMessage.toString() + _newline;            _status = RState.Running;            return _serialport.Write(_currentMsg);        }        public override bool ReadMap()        {            if (!CheckVceStatus())                return false;            _currentVceMessage = new VceMessage { Head = VceMessageHead.Read, Command = VceCommand.ReadMap, Param = "S" };            _currentMsg = _currentVceMessage.toString() + _newline;            _status = RState.Running;            _HasReceiveMsg = false;            return _serialport.Write(_currentMsg);        }        public override bool Goto(int Targetslot)        {            if (!CheckVceStatus())                return false;            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Goto, Param = Targetslot.ToString() };            _currentMsg = _currentVceMessage.toString() + _newline;            _status = RState.Running;            return _serialport.Write(_currentMsg);        }        public override bool GotoLP()        {            if (!CheckVceStatus())                return false;            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.GotoLP };            _currentMsg = _currentVceMessage.toString() + _newline;            _status = RState.Running;            return _serialport.Write(_currentMsg);        }    }}
 |