SunWayMessageHandler.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. using Aitex.Core.RT.Event;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.Util;
  4. using Aitex.Sorter.Common;
  5. using MECF.Framework.Common.Equipment;
  6. using CyberX8_Core;
  7. using CyberX8_RT.Devices.YASKAWA;
  8. using SecsGem.Core.Variables;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Runtime.Remoting.Contexts;
  13. using System.Text;
  14. using System.Text.RegularExpressions;
  15. using System.Threading.Tasks;
  16. namespace CyberX8_RT.Devices.EFEM
  17. {
  18. public class SunWayMessageHandler : Singleton<SunWayMessageHandler>, IEfemMessageHander
  19. {
  20. private const string ERROR_MSG = "hardware message invalid";
  21. /// <summary>
  22. /// TagId数据前缀
  23. /// </summary>
  24. private const string TAG_DATA_PRE = "INF:CSTID/LP1/";
  25. public EfemMessage ToMessage(string context)
  26. {
  27. if (string.IsNullOrEmpty(context) || context.Length < 3)
  28. throw new ArgumentNullException(ERROR_MSG);
  29. EfemMessage msg = new EfemMessage { RawString = context, Direct = MsgDirection.From, Data = new List<string>() };
  30. // remove EOT
  31. string messageBody = context.Substring(0, context.IndexOf(EfemMessage.EOF) + 1);
  32. try
  33. {
  34. // split up the string
  35. string[] sBodies = messageBody.Split(Constant.delimiters);
  36. string sHead = sBodies[0];
  37. string sBasic = sBodies[1];
  38. // Head
  39. if (Enum.TryParse(sHead, true, out EfemMessage.MsgHead msgHead))
  40. {
  41. msg.Head = msgHead;
  42. }
  43. switch (msg.Head)
  44. {
  45. case EfemMessage.MsgHead.ACK:
  46. case EfemMessage.MsgHead.MOV:
  47. case EfemMessage.MsgHead.INF:
  48. case EfemMessage.MsgHead.EVT:
  49. // Basic
  50. msg.Operation = EfemConstant.ToOperation(sBasic);
  51. string sPort = sBodies[2];
  52. // Port
  53. msg.Module = GetModule(sPort);
  54. // Data
  55. switch (msg.Operation)
  56. {
  57. case EfemOperation.StateTrack:
  58. for (int i = 2; i < sBodies.Length; i++)
  59. {
  60. msg.Data.Add(sBodies[i]);
  61. }
  62. break;
  63. case EfemOperation.GetWaferInfo:
  64. for(int i=3;i<sBodies.Length;i++)
  65. {
  66. msg.Data.Add(sBodies[i]);
  67. }
  68. break;
  69. case EfemOperation.CarrierId:
  70. if (msg.Head == EfemMessage.MsgHead.INF)
  71. {
  72. string carrierId = msg.RawString.Substring(TAG_DATA_PRE.Length);
  73. carrierId = carrierId.Remove(carrierId.Length - 1);
  74. msg.Data.Add(carrierId);
  75. }
  76. break;
  77. case EfemOperation.SigStatus:
  78. for(int i=2;i<sBodies.Length; i++)
  79. {
  80. msg.Data.Add(sBodies[i]);
  81. }
  82. break;
  83. case EfemOperation.Ready:
  84. msg.Data.Add(sBodies[2]);
  85. break;
  86. case EfemOperation.Size:
  87. for (int i = 3; i < sBodies.Length; i++)
  88. {
  89. msg.Data.Add(sBodies[i]);
  90. }
  91. break;
  92. case EfemOperation.Align:
  93. msg.Data.Add(sBodies[3]);
  94. break;
  95. default:
  96. break;
  97. }
  98. //EVT:ERROR/Param1/Param2
  99. if(msg.Head == EfemMessage.MsgHead.EVT&&sBasic.ToLower()=="error")
  100. {
  101. msg.Operation = EfemOperation.Error;
  102. msg.Data.Add(sBodies[3]);
  103. }
  104. break;
  105. case EfemMessage.MsgHead.NAK:
  106. //NAK:Factor|Message*
  107. if (sBodies.Length > 1)
  108. {
  109. msg.Factor = sBodies[1];
  110. }
  111. else
  112. {
  113. msg.Factor = "NAK 格式错误";
  114. }
  115. break;
  116. case EfemMessage.MsgHead.CAN:
  117. //CAN:Message*|Factor/Place
  118. if (sBodies.Length >= 4)
  119. {
  120. string[] canFactor = messageBody.Split('|');
  121. string[] factorandData = canFactor[1].Split(Constant.delimiters);
  122. string factor = factorandData[0];
  123. string data = canFactor[1].Replace(factor,"");
  124. msg.Data.Add(data);
  125. msg.Factor = factor;
  126. //msg.Factor = sBodies[sBodies.Length - 2];
  127. //msg.Data.Add(sBodies[sBodies.Length - 1]);
  128. }
  129. else
  130. {
  131. msg.Factor = "CAN 格式错误";
  132. }
  133. break;
  134. case EfemMessage.MsgHead.ABS:
  135. //ABS:Message*|Error|Parameter1/Parameter2
  136. if (sBodies.Length >= 5)
  137. {
  138. msg.Factor = sBodies[sBodies.Length - 3];
  139. string errorCode = sBodies[sBodies.Length - 2];
  140. if (EfemHWErrorCode2Msg.ContainsKey(errorCode))
  141. {
  142. msg.Data.Add(EfemHWErrorCode2Msg[errorCode]);
  143. }
  144. else
  145. {
  146. msg.Data.Add(errorCode);
  147. }
  148. msg.Data.Add(sBodies[sBodies.Length - 1]);
  149. }
  150. else
  151. {
  152. msg.Factor = "ABS 格式错误";
  153. }
  154. break;
  155. }
  156. }
  157. catch (Exception ex)
  158. {
  159. EV.PostAlarmLog(ModuleName.EFEM.ToString(), $"收到[{context}],解析出错[{ex.Message}]");
  160. }
  161. return msg;
  162. }
  163. private ModuleName GetModule(string sPort)
  164. {
  165. ModuleName module = ModuleName.EFEM;
  166. if (Regex.IsMatch(sPort, @"LP[123]$"))
  167. {
  168. if (sPort.Length > 3)
  169. {
  170. sPort = sPort.Remove(sPort.Length - 2);
  171. }
  172. module = StringModule[sPort];
  173. }
  174. else if (Regex.IsMatch(sPort, @"ALN\d?", RegexOptions.IgnoreCase))
  175. {
  176. if (sPort.Length > 4)
  177. {
  178. sPort = sPort.Remove(sPort.Length - 2);
  179. }
  180. module = StringModule[sPort];
  181. }
  182. else if (Regex.IsMatch(sPort, @"BF\d?", RegexOptions.IgnoreCase))
  183. {
  184. if (sPort.Length > 3)
  185. {
  186. sPort = sPort.Remove(sPort.Length - 2);
  187. }
  188. module = StringModule[sPort];
  189. }
  190. else
  191. {
  192. module = ModuleName.EFEM;
  193. }
  194. return module;
  195. }
  196. public Dictionary<ModuleName, string> ModuleString = new Dictionary<ModuleName, string>
  197. {
  198. [ModuleName.EFEM] = "ALL",
  199. [ModuleName.EfemRobot] = "ROB",
  200. [ModuleName.LP1] = "LP1",
  201. [ModuleName.LP2] = "LP2",
  202. [ModuleName.LP3] = "LP3",
  203. [ModuleName.Aligner1] = "ALN1",
  204. [ModuleName.PUF1]="PUF1",
  205. [ModuleName.PUF2]="PUF2",
  206. [ModuleName.SRD1]="SRD1",
  207. [ModuleName.SRD2]="SRD2",
  208. [ModuleName.Dummy1]="BF1",
  209. [ModuleName.Dummy2]="BF2"
  210. };
  211. public readonly Dictionary<string, ModuleName> StringModule = new Dictionary<string, ModuleName>
  212. {
  213. ["ALL"] = ModuleName.EFEM,
  214. ["System"] = ModuleName.EFEM,
  215. ["LP1"] = ModuleName.LP1,
  216. ["LP2"] = ModuleName.LP2,
  217. ["LP3"] = ModuleName.LP3,
  218. ["ALN1"] = ModuleName.Aligner1,
  219. ["BF1"]=ModuleName.Dummy1,
  220. ["BF2"]=ModuleName.Dummy2
  221. };
  222. public Dictionary<Hand, string> ArmString = new Dictionary<Hand, string>
  223. {
  224. [Hand.Blade1] = "ARM1"
  225. };
  226. public string ToHWString(Position pos)
  227. {
  228. string res = string.Empty;
  229. string sMod = ModuleString[pos.Module];
  230. int num = pos.Slot + 1;
  231. string sSlot = num.ToString("D2");
  232. //EFEM中PUF只固定一个slot
  233. if (ModuleHelper.IsPUF(pos.Module))
  234. {
  235. res = $"{sMod}01";
  236. }
  237. else {
  238. res = $"{sMod}{sSlot}";
  239. }
  240. return res;
  241. }
  242. public readonly Dictionary<string, string> EfemHWErrorCode2Msg = new Dictionary<string, string>()
  243. {
  244. {"NOREADY","通信握手未完成" },
  245. {"SORC_NOWAF","Robot 手指无片无法执行取片" },
  246. {"SORC_WAFER","Robot 手指有片,无法执行取片" },
  247. {"DEST_WAFER","目标位有片,无法执行取片" },
  248. {"VAC","真空不足" },
  249. {"AIR","大气不足" },
  250. {"MAPPARAM_NG","执行扫片失败" },
  251. {"WAFERUPDATEFAIL","晶圆状态异常" },
  252. {"NOLOCATION","未找到工位配置信息" },
  253. {"NOARM","未找到 ARM 配置信息" },
  254. {"REMOVE","未找到设备或设备已断开链接" },
  255. {"NOMAPPINGDATA","没有找到相对应的 Mapping 结果" },
  256. {"ALARM","触发 Alarm 报警" },
  257. {"NOCST","OC 上未发现 Cassette" },
  258. {"NOCLAMP","OC 未执行 Clamp" },
  259. {"NOPOD","OC 上未发现 POD" },
  260. {"PODNOTCLOSED","POD 门未关" },
  261. {"AREASENSOR","触发安全光栅" },
  262. {"EMS","触发 EMS 急停" },
  263. {"WAFERPROTRUSION","晶圆突出检测触发" },
  264. {"DOOR","安全门开启" },
  265. {"COMM","设备通信异常" },
  266. {"EXCEPTION","系统抛出异常" },
  267. {"BUSY","系统繁忙" },
  268. {"CKSUM","校验和验证失败" },
  269. {"MAINTENANCE","当前系统为维护模式" },
  270. {"MSG_NG","指令错误" },
  271. {"PARAM_NG","参数错误" },
  272. {"NODEVICEMODEL","未找到该设备型号" },
  273. {"SLOT_NG","SLOT 超出范围" },
  274. {"UNDEFINITION","未知错误" },
  275. {"NOIOSET","未找到 IO 设置信息" },
  276. {"SETFAIL","设置失败" },
  277. {"TIMEOUT","设备通信超时" },
  278. {"DEST_NOWAF","目标位无片无法执行取片" },
  279. {"CSTSIZEMISMATCH","Cassette 尺寸不匹配" },
  280. {"ROBEXEND","机械手伸手报警" },
  281. {"FUNC_ERROR","函数错误" },
  282. {"233","伸缩信号未使能" },
  283. {"304","未识别的错误码" },
  284. {"305","未识别的指令" },
  285. {"309","不支持的指令" },
  286. {"401","ZWAFER 参数错误" },
  287. {"402","非法的 slot 参数" },
  288. {"403","运动指令 RX 参数错误" },
  289. {"404","晶圆夹取失败" },
  290. {"405","晶圆释放失败" },
  291. {"406","气缸压力表检测错误" },
  292. {"407","Mapping 传感器伸出失败" },
  293. {"408","Mapping 传感器缩回失败" },
  294. {"409","Mapping 传感器位置数据不正确" },
  295. {"411","Mapping 传感器高度不一致" },
  296. {"412","工位 VIA 参数未使能" },
  297. {"413","不是有效的 Mapping 工位" },
  298. {"414","手指有晶圆无法 mapping" },
  299. {"415","采集的数据个数错误" },
  300. {"416","采集的晶圆厚度过小" },
  301. {"417","晶圆位置超出有效范围" },
  302. {"418","晶圆上下沿槽数错误" },
  303. {"550","工位号超范围" },
  304. {"552","VIA 参数错误" },
  305. {"553","MAPVIA 参数错误" },
  306. {"600","系统未上电" },
  307. {"602","指令正在执行中" },
  308. {"603","系统上电失败" },
  309. {"604","示教器控制中" },
  310. {"605","机械手运动中停止" },
  311. {"609","系统存在错误" },
  312. {"610","示教盒急停启动" },
  313. {"611","驱动器报警" },
  314. {"629","驱动器存在报警" },
  315. {"705","LOAD 状态未知" },
  316. {"712","真空吸附动作失败" },
  317. {"730","PLACE 前 LOAD 状态错误" },
  318. {"731","PLACE 后 LOAD 状态错误" },
  319. {"734","PLACE 执行 Extend 过程中未检测到晶圆" },
  320. {"736","PLACE 执行 Retract 过程中检测到晶圆" },
  321. {"740","PICK 前 LOAD 状态错误" },
  322. {"741","PICK 后 LOAD 状态错误" },
  323. {"744","PICK 执行 Extend 过程中检测到晶圆" },
  324. {"745","PICK 执行 Retract 过程中未检测到晶圆" },
  325. {"800","当前有动作暂停中" },
  326. {"801","改变运动状态发生错误" },
  327. {"802","无法获取下一个状态" },
  328. {"803","没有正在运行的指令" },
  329. {"804","没有暂停的动作" },
  330. {"805","没有可跳过的动作" },
  331. {"1006","非法的 IO 端口号" },
  332. {"1314","PITCH 轴超界" },
  333. {"1315","关节位置超界" },
  334. {"1316","关节位置超硬限" },
  335. {"1320","机械手跟踪差超限错误" },
  336. {"1321","机械手发生碰撞" },
  337. {"1322","机械手超出工作区" },
  338. {"1323","关节速度超限" },
  339. {"1400","打开 pod 失败" },
  340. {"1401","当前位置不正确" },
  341. {"1402","关闭 pod 失败" },
  342. {"1403","pod 上锁失败" },
  343. {"1404","pod 解锁失败" },
  344. {"1407","气压错误" },
  345. {"1408","pod 盒状态错误" },
  346. {"1409","当前位置不在旋转轴动作位置" },
  347. {"1410","晶圆尺寸设置错误" },
  348. {"1411","旋转轴状态错误不能伸出" },
  349. {"1412","晶圆已滑出" },
  350. {"1413","与 R3 extend 互锁" },
  351. {"1414","光栅被触发" },
  352. {"1415","Cassette 状态错误" },
  353. {"1500","打开门失败" },
  354. {"1501","关闭门失败" },
  355. {"1502","门开关状态不对" },
  356. {"1503","门松开失败" },
  357. {"1504","门夹紧失败" },
  358. {"1505","门夹紧松开状态错误" },
  359. {"1510","安全检测触发" },
  360. {"1511","R 轴未运动到位" },
  361. {"1512","使能开关未使能" },
  362. {"1514","气缸 1 状态错误" },
  363. {"1515","LATCH 失败" },
  364. {"1516","UNLATCH 失败" },
  365. {"1517","LATCH 状态错误" },
  366. {"1518","DOCK 状态错误" },
  367. {"1519","气缸 2 状态错误" },
  368. {"1520","DOCK 到位传感器状态错误" },
  369. {"1521","吸附状态错误" },
  370. {"1522","MAP 轴状态错误" },
  371. {"1523","PLACE 状态错误" },
  372. {"1524","气缸 1 伸出错误" },
  373. {"1525","气缸 1 缩回错误" },
  374. {"1527","关门时 LATCH 状态错误" },
  375. {"1528","真空吸附失败" },
  376. {"1529","真空吸附关闭失败" },
  377. {"13033","伺服驱动器初始化失败" },
  378. };
  379. }
  380. }