using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using MECF.Framework.Common.CommonData; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using Venus_Core; using Venus_RT.Modules; namespace Venus_RT.Devices.VCE { //泓浒 enum VRStep { Idle, Home, Move, Halt, Release, Goto, Pick, PickExtend, PickRetract, Place, PlaceExtend, PlaceRetract, Xfer, CheckLoad_ArmA, CheckLoad_ArmB, SetLoad, ReQueryLoad, } public class HongHuVR : ITransferRobot { private readonly AsyncSocket _socket; private const string EOF = "\r"; private RState _status; private bool _IsHomed; private VRStep _currentStep = VRStep.Idle; private Dictionary<ModuleName, int> _StationNumbers = new Dictionary<ModuleName, int>(); public RState Status { get { return _status; } } public bool IsHomed { get { return _IsHomed; } } private string Hand2Arm(Hand hand) => hand == Hand.Blade1 ? "B" : "A"; //private readonly Regex _rex_check_load = new Regex(@"LOAD\s+(A|B)\s+(\w+)\s*"); private readonly Regex _rex_check_load = new Regex(@"CHECK LOAD\s*"); private readonly Regex _rex_error_code = new Regex(@"_ERR\s+(\d+)\s*"); private RobotMoveInfo _robotMoveInfo = new RobotMoveInfo(); public RobotMoveInfo TMRobotMoveInfo { get { return _robotMoveInfo; } } public double Offset_X => 0; public double Offset_Y => 0; public double Offset_D => 0; public Dictionary<string, string> _error2msg = new Dictionary<string, string>() { { "701" , "设备检查互锁,发现无法执行"}, { "722" , "设备动作,但是发生异常"}, }; private BlockingCollection<RobotAnimationData> blockingCollection = new BlockingCollection<RobotAnimationData>(); public HongHuVR() { _socket = new AsyncSocket("", EOF); _socket.Connect(SC.GetStringValue($"SETM.IPAddress")); _socket.OnDataChanged += OnReceiveMessage; _socket.OnErrorHappened += OnErrorHappen; _status = RState.Init; _IsHomed = false; _StationNumbers[ModuleName.VCE1] = SC.GetValue<int>("SETM.VCE1StationNumber"); _StationNumbers[ModuleName.VPA] = SC.GetValue<int>("SETM.VPAStationNumber"); _StationNumbers[ModuleName.PMA] = SC.GetValue<int>("SETM.PMAStationNumber"); _StationNumbers[ModuleName.PMB] = SC.GetValue<int>("SETM.PMBStationNumber"); _StationNumbers[ModuleName.PMC] = SC.GetValue<int>("SETM.PMCStationNumber"); _StationNumbers[ModuleName.PMD] = SC.GetValue<int>("SETM.PMDStationNumber"); WaferManager.Instance.SubscribeLocation(ModuleName.TMRobot, 2); Task.Run(() => { foreach (var data in blockingCollection.GetConsumingEnumerable()) { _robotMoveInfo.Action = data.Action; _robotMoveInfo.ArmTarget = data.Hand == Hand.Blade1 ? RobotArm.ArmA : (data.Hand == Hand.Both ? RobotArm.Both : RobotArm.ArmB); _robotMoveInfo.BladeTarget = $"{_robotMoveInfo.ArmTarget}.{data.Target}"; System.Threading.Thread.Sleep(300); } }); } //初始化某个轴 //1.清错 //2.设备上电 //3.各轴按顺序运动 public bool Home() { _status = RState.Running; _currentStep = VRStep.Home; return _SendCommand("HOME ALL"); } public bool Halt() { _status = RState.Running; _currentStep = VRStep.Halt; return _SendCommand("HALT"); } public bool Release() { _status = RState.Running; _currentStep = VRStep.Release; return _SendCommand("RELEASE"); } //public bool MOVE() //{ //} public bool Pick(ModuleName station, int slot, Hand hand) { if (!CheckRobotStatus()) return false; _currentStep = VRStep.Pick; _status = RState.Running; SetRobotMovingInfo(RobotAction.Picking, hand, station); return _SendCommand($"PICK {_StationNumbers[station]} ARM {Hand2Arm(hand)}"); } public bool PickExtend(ModuleName station, int slot, Hand hand) { if (!CheckRobotStatus()) return false; _currentStep = VRStep.PickExtend; _status = RState.Running; SetRobotMovingInfo(RobotAction.Extending, hand, station); return _SendCommand($"PICK {_StationNumbers[station]} ARM {Hand2Arm(hand)} ENRT NR"); } public bool PickRetract(ModuleName station, int slot, Hand hand) { if (!CheckRobotStatus()) return false; _currentStep = VRStep.PickRetract; _status = RState.Running; SetRobotMovingInfo(RobotAction.Retracting, hand, station); return _SendCommand($"PICK {_StationNumbers[station]} ARM {Hand2Arm(hand)} STRT NR"); } public bool Place(ModuleName station, int slot, Hand hand) { if (!CheckRobotStatus()) return false; _currentStep = VRStep.Place; _status = RState.Running; SetRobotMovingInfo(RobotAction.Placing, hand, station); return _SendCommand($"PLACE {_StationNumbers[station]} ARM {Hand2Arm(hand)}"); } public bool PlaceExtend(ModuleName station, int slot, Hand hand) { if (!CheckRobotStatus()) return false; _currentStep = VRStep.Place; _status = RState.Running; SetRobotMovingInfo(RobotAction.Extending, hand, station); return _SendCommand($"PLACE {_StationNumbers[station]} ARM {Hand2Arm(hand)} ENRT NR"); } public bool PlaceRetract(ModuleName station, int slot, Hand hand) { if (!CheckRobotStatus()) return false; _currentStep = VRStep.Place; _status = RState.Running; SetRobotMovingInfo(RobotAction.Retracting, hand, station); return _SendCommand($"PLACE {_StationNumbers[station]} ARM {Hand2Arm(hand)} STRT NR"); } public bool Transfer(ModuleName fromstation, ModuleName tostation, Hand hand) { if (!CheckRobotStatus()) return false; _currentStep = VRStep.Xfer; _status = RState.Running; return _SendCommand($"XFER ARM {Hand2Arm(hand)} {_StationNumbers[fromstation]} {_StationNumbers[tostation]}"); } public bool CheckLoad(Hand hand = Hand.Blade1) { if (_currentStep != VRStep.Home && _currentStep != VRStep.CheckLoad_ArmA && !CheckRobotStatus()) return false; _currentStep = hand == Hand.Blade2 ? VRStep.CheckLoad_ArmB : VRStep.CheckLoad_ArmA; _status = RState.Running; return _SendCommand($"CHECK LOAD {Hand2Arm(hand)}"); } public bool QueryAwc() { return true; } public bool Goto(ModuleName station, int slot, Hand hand) { _currentStep = VRStep.Goto; _status = RState.Running; return _SendCommand($"GOTO N {_StationNumbers[station]} ARM {Hand2Arm(hand)}"); } public bool MoveTo(ModuleName stnFrom, ModuleName stnTo, Hand hand) { _currentStep = VRStep.Move; _status = RState.Running; return _SendCommand($"MOVE R ABS 100 ARM {Hand2Arm(hand)}"); ; } private bool _SendCommand(string cmd) { LOG.WriteSingeLine(eEvent.INFO_TM_ROBOT, ModuleName.TMRobot, $"Send Command to HongHu TMRobot: {cmd}"); return _socket.Write(cmd + EOF); } private bool CheckRobotStatus() { if (Status == RState.Init) { LOG.Write(eEvent.ERR_DEVICE_INFO, ModuleName.TMRobot, "TMRobot is not homed, please home first."); return false; } else if (Status == RState.Running) { LOG.Write(eEvent.ERR_DEVICE_INFO, ModuleName.TMRobot, "TMRobot is busy, please wait a minute"); return false; } else if (Status == RState.Failed || Status == RState.Timeout) { LOG.Write(eEvent.ERR_DEVICE_INFO, ModuleName.TMRobot, "TMRobot has a error, please check and fix the hardware issue and home it"); return false; } return true; } private void OnReceiveMessage(string RevMsg) { LOG.WriteSingeLine(eEvent.INFO_TM_ROBOT, ModuleName.TMRobot, $"Receive message from HongHu TMRobot: {RevMsg}, while {_currentStep}"); RevMsg = RevMsg.Trim(); if (_rex_error_code.IsMatch(RevMsg)) { _IsHomed = false; _status = RState.Failed; var results = _rex_error_code.Match(RevMsg); ErrorMessageHandler(results.Groups[1].Value); return; } switch (_currentStep) { case VRStep.Goto: case VRStep.Halt: case VRStep.Move: case VRStep.Xfer: case VRStep.Pick: case VRStep.PickExtend: case VRStep.PickRetract: case VRStep.Place: case VRStep.PlaceExtend: case VRStep.PlaceRetract: { if (RevMsg.Trim() == "_RDY" || (RevMsg.Contains("_RDY") && !RevMsg.Contains("_ERR"))) { _currentStep = VRStep.Idle; _status = RState.End; } else { ReportWrongMsg(RevMsg); } if (_currentStep != VRStep.PickExtend && _currentStep != VRStep.PlaceExtend) SetRobotMovingInfo(RobotAction.None, Hand.Both, ModuleName.TMRobot); } break; case VRStep.Home: { if (RevMsg.Trim() == "_RDY") { //CheckLoad(Hand.Blade1); _currentStep = VRStep.Idle; _status = RState.End; _IsHomed = true; } else ReportWrongMsg(RevMsg); } break; case VRStep.CheckLoad_ArmA: { if (_rex_check_load.IsMatch(RevMsg)) { GetCheckLoadResult(RevMsg); CheckLoad(Hand.Blade2); } else ReportWrongMsg(RevMsg); } break; case VRStep.CheckLoad_ArmB: { if (_rex_check_load.IsMatch(RevMsg)) { GetCheckLoadResult(RevMsg); _currentStep = VRStep.Idle; _status = RState.End; _IsHomed = true; } } break; default: if (!RevMsg.Contains("_EVENT")) ReportWrongMsg(RevMsg); break; } } private void GetCheckLoadResult(string revMsg) { Match result = _rex_check_load.Match(revMsg); string Arm = result.Groups[1].Value; string WaferStatus = result.Groups[2].Value; if (WaferStatus == "ON") { WaferManager.Instance.CreateWafer(ModuleName.TMRobot, Arm == "A" ? 0 : 1, Aitex.Core.Common.WaferStatus.Unknown); } } private void ErrorMessageHandler(string errorcode) { string ErrorInfo; if (_error2msg.ContainsKey(errorcode)) { ErrorInfo = _error2msg[errorcode]; LOG.Write(eEvent.ERR_DEVICE_INFO, ModuleName.TMRobot, ErrorInfo); } else { LOG.Write(eEvent.ERR_DEVICE_INFO, ModuleName.TMRobot, $"Dictionary Not Contains error code:{errorcode}"); } } private void OnErrorHappen(ErrorEventArgs args) { //Singleton<RouteManager>.Instance.SETM.PostMsg(SETMEntity.MSG.Error); LOG.Write(eEvent.ERR_DEVICE_INFO, ModuleName.TMRobot, $"HongHu TMRobot Error: {args.Reason} while {_currentStep}"); } private void ReportWrongMsg(string revMsg) { LOG.Write(eEvent.ERR_DEVICE_INFO, ModuleName.TMRobot, $"Receive wrong message:{revMsg} while {_currentStep}"); } public void SetRobotMovingInfo(RobotAction action, Hand hand, ModuleName target) { _robotMoveInfo.Action = action; _robotMoveInfo.ArmTarget = hand == Hand.Blade1 ? RobotArm.ArmA : (hand == Hand.Both ? RobotArm.Both : RobotArm.ArmB); _robotMoveInfo.BladeTarget = $"{_robotMoveInfo.ArmTarget}.{target}"; } } }