RisshiChiller.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO.Ports;
  4. using System.Linq;
  5. using Aitex.Core.Common;
  6. using Aitex.Core.Common.DeviceData;
  7. using Aitex.Core.RT.Device;
  8. using Aitex.Core.RT.Device.Unit;
  9. using Aitex.Core.RT.Event;
  10. using Aitex.Core.RT.Log;
  11. using Aitex.Core.RT.OperationCenter;
  12. using Aitex.Core.RT.SCCore;
  13. using Aitex.Core.Util;
  14. using MECF.Framework.Common.Communications;
  15. using MECF.Framework.Common.Device.Bases;
  16. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Common;
  17. using Newtonsoft.Json;
  18. namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Chillers.RisshiChiller
  19. {
  20. public class RisshiChiller : SerialPortDevice, IConnection
  21. {
  22. public string Address { get; }
  23. public bool IsConnected { get; }
  24. public bool Connect()
  25. {
  26. return true;
  27. }
  28. public bool Disconnect()
  29. {
  30. return true;
  31. }
  32. public string PortStatus { get; set; } = "Closed";
  33. private RisshiChillerConnection _connection;
  34. public RisshiChillerConnection Connection
  35. {
  36. get { return _connection; }
  37. }
  38. private R_TRIG _trigError = new R_TRIG();
  39. private R_TRIG _trigCommunicationError = new R_TRIG();
  40. private R_TRIG _trigRetryConnect = new R_TRIG();
  41. private PeriodicJob _thread;
  42. private LinkedList<HandlerBase> _lstHandler = new LinkedList<HandlerBase>();
  43. private LinkedList<HandlerBase> _lstMonitorHandler = new LinkedList<HandlerBase>();
  44. public List<IOResponse> IOResponseList { get; set; } = new List<IOResponse>();
  45. private object _locker = new object();
  46. private bool _enableLog;
  47. private string _scRoot;
  48. public RisshiChiller(string module, string name, string scRoot, string portName) : base(module, name)
  49. {
  50. _scRoot = scRoot;
  51. PortName = portName;
  52. }
  53. private void ResetPropertiesAndResponses()
  54. {
  55. foreach (var ioResponse in IOResponseList)
  56. {
  57. ioResponse.ResonseContent = null;
  58. ioResponse.ResonseRecievedTime = DateTime.Now;
  59. }
  60. }
  61. public override bool Initialize(string portName)
  62. {
  63. base.Initialize(portName);
  64. ResetPropertiesAndResponses();
  65. if (_connection != null && _connection.IsConnected && PortName == portName)
  66. return true;
  67. if (_connection != null && _connection.IsConnected)
  68. _connection.Disconnect();
  69. PortName = portName;
  70. _enableLog = SC.GetValue<bool>($"{_scRoot}.{Module}.{Name}.EnableLogMessage");
  71. _connection = new RisshiChillerConnection(PortName);
  72. _connection.EnableLog(_enableLog);
  73. if (_connection.Connect())
  74. {
  75. PortStatus = "Open";
  76. EV.PostInfoLog(Module, $"{Module}.{Name} connected");
  77. }
  78. _thread = new PeriodicJob(100, OnTimer, $"{Module}.{Name} MonitorHandler", true);
  79. return true;
  80. }
  81. public bool InitConnection(string portName, int bautRate, int dataBits, Parity parity, StopBits stopBits)
  82. {
  83. _connection = new RisshiChillerConnection(portName, bautRate, dataBits, parity, stopBits);
  84. if (_connection.Connect())
  85. {
  86. EV.PostInfoLog(Module, $"{Module}.{Name} connected");
  87. }
  88. _thread = new PeriodicJob(100, OnTimer, $"{Module}.{Name} MonitorHandler", true);
  89. return true;
  90. }
  91. private bool OnTimer()
  92. {
  93. try
  94. {
  95. //_connection.MonitorTimeout();
  96. if (!_connection.IsConnected || _connection.IsCommunicationError)
  97. {
  98. lock (_locker)
  99. {
  100. _lstHandler.Clear();
  101. }
  102. _trigRetryConnect.CLK = !_connection.IsConnected;
  103. if (_trigRetryConnect.Q)
  104. {
  105. _connection.SetPortAddress(SC.GetStringValue($"{ScBasePath}.{Name}.Address"));
  106. if (!_connection.Connect())
  107. {
  108. EV.PostAlarmLog(Module, $"Can not connect with {_connection.Address}, {Module}.{Name}");
  109. }
  110. else
  111. {
  112. //_lstHandler.AddLast(new RisshiChillerQueryPinHandler(this, _deviceAddress));
  113. //_lstHandler.AddLast(new RisshiChillerSetCommModeHandler(this, _deviceAddress, EnumRfPowerCommunicationMode.Host));
  114. }
  115. }
  116. return true;
  117. }
  118. HandlerBase handler = null;
  119. if (!_connection.IsBusy)
  120. {
  121. lock (_locker)
  122. {
  123. if (_lstHandler.Count == 0)
  124. {
  125. foreach (var monitorHandler in _lstMonitorHandler)
  126. {
  127. _lstHandler.AddLast(monitorHandler);
  128. }
  129. }
  130. if (_lstHandler.Count > 0)
  131. {
  132. handler = _lstHandler.First.Value;
  133. _lstHandler.RemoveFirst();
  134. }
  135. }
  136. if (handler != null)
  137. {
  138. _connection.Execute(handler);
  139. }
  140. }
  141. }
  142. catch (Exception ex)
  143. {
  144. LOG.Write(ex);
  145. }
  146. return true;
  147. }
  148. public override void Monitor()
  149. {
  150. try
  151. {
  152. //_connection.EnableLog(_enableLog);
  153. _trigCommunicationError.CLK = _connection.IsCommunicationError;
  154. if (_trigCommunicationError.Q)
  155. {
  156. EV.PostAlarmLog(Module, $"{Module}.{Name} communication error, {_connection.LastCommunicationError}");
  157. }
  158. }
  159. catch (Exception ex)
  160. {
  161. LOG.Write(ex);
  162. }
  163. }
  164. public override void Reset()
  165. {
  166. _trigError.RST = true;
  167. _connection.SetCommunicationError(false, "");
  168. _trigCommunicationError.RST = true;
  169. //_enableLog = SC.GetValue<bool>($"{ScBasePath}.{Name}.EnableLogMessage");
  170. _trigRetryConnect.RST = true;
  171. base.Reset();
  172. }
  173. public override bool Home(out string reason)
  174. {
  175. return base.Home(out reason);
  176. }
  177. #region Command Functions
  178. public void PerformRawCommand(string command, string comandArgument)
  179. {
  180. lock (_locker)
  181. {
  182. _lstHandler.AddLast(new RisshiChillerRawCommandHandler(this, command, comandArgument));
  183. }
  184. }
  185. public void PerformRawCommand(string command)
  186. {
  187. lock (_locker)
  188. {
  189. _lstHandler.AddLast(new RisshiChillerRawCommandHandler(this, command));
  190. }
  191. }
  192. public void SetTemperature(string angle)
  193. {
  194. lock (_locker)
  195. {
  196. _lstHandler.AddLast(new RisshiChillerSimpleSetHandler(this, "SWAA", angle));
  197. }
  198. }
  199. public void SetTempHighWarning(string angle)
  200. {
  201. lock (_locker)
  202. {
  203. _lstHandler.AddLast(new RisshiChillerSimpleSetHandler(this, "SWAA", angle));
  204. }
  205. }
  206. public void SetTempLowWarning(string angle)
  207. {
  208. lock (_locker)
  209. {
  210. _lstHandler.AddLast(new RisshiChillerSimpleSetHandler(this, "SWAA", angle));
  211. }
  212. }
  213. public void SetRemoteMode(string angle)
  214. {
  215. lock (_locker)
  216. {
  217. _lstHandler.AddLast(new RisshiChillerSimpleSetHandler(this, "SWS", angle));
  218. }
  219. }
  220. public void SetRunMode(string waferSize)
  221. {
  222. lock (_locker)
  223. {
  224. _lstHandler.AddLast(new RisshiChillerSimpleSetHandler(this, "SWS", waferSize));
  225. }
  226. }
  227. internal void NoteActionCompleted(string command)
  228. {
  229. if(command == "ALIGN")
  230. {
  231. AlignCompleted = true;
  232. }
  233. else if(command == "ROTATE")
  234. {
  235. RotatedCompleted = true;
  236. }
  237. else if(command == "XFER")
  238. {
  239. XferCompleted = true;
  240. }
  241. else if(command == "ALIGNER HOME/SCAN/ALGN")
  242. {
  243. HomeCompleted = true;
  244. }
  245. }
  246. internal void NoteQueryResult(string command, string parameter, string queryResult)
  247. {
  248. if (command == "HELLO")
  249. {
  250. if(queryResult == "AG")
  251. {
  252. CommunicationIsOK = true;
  253. }
  254. else
  255. {
  256. CommunicationIsOK = false;
  257. }
  258. }
  259. else if (command == "RWAA")
  260. {
  261. var resultArray = queryResult.Split(',');
  262. if(resultArray.Count() == 1)
  263. {
  264. AlignedAngle = double.Parse(queryResult);
  265. }
  266. }
  267. else if (command == "RWS")
  268. {
  269. var resultArray = queryResult.Split(',');
  270. if (resultArray.Count() == 1)
  271. {
  272. WaferSize = double.Parse(queryResult);
  273. }
  274. }
  275. else if (command == "RBIASXY")
  276. {
  277. var resultArray = queryResult.Split(',');
  278. if (resultArray.Count() == 2)
  279. {
  280. BaisX = double.Parse(queryResult.Split(',')[0]);
  281. BaisY = double.Parse(queryResult.Split(',')[1]);
  282. }
  283. }
  284. else if (command == "RBIASRT")
  285. {
  286. var resultArray = queryResult.Split(',');
  287. if (resultArray.Count() == 2)
  288. {
  289. BaisR = double.Parse(queryResult.Split(',')[0]);
  290. BaisT = double.Parse(queryResult.Split(',')[1]);
  291. }
  292. }
  293. else if (command == "RNOTCH")
  294. {
  295. var resultArray = queryResult.Split(',');
  296. if (resultArray.Count() == 1)
  297. {
  298. Notch = double.Parse(queryResult);
  299. }
  300. }
  301. else if (command == "REER")
  302. {
  303. var resultArray = queryResult.Split(',');
  304. if (resultArray.Count() == 1)
  305. {
  306. Error = "_ERR " + queryResult;
  307. }
  308. }
  309. else if (command == "RWK")
  310. {
  311. var resultArray = queryResult.Split(',');
  312. if (resultArray.Count() == 1)
  313. {
  314. WafeOnOff = queryResult == "1";
  315. }
  316. }
  317. else if (command == "RAR")
  318. {
  319. var resultArray = queryResult.Split(',');
  320. if (resultArray.Count() == 1)
  321. {
  322. IsReady = queryResult == "1";
  323. }
  324. }
  325. }
  326. internal void NoteSetCompleted(string command, string parameter)
  327. {
  328. if(command == "SWAA")
  329. {
  330. AlignAngleSet = double.Parse(parameter);
  331. }
  332. else if(command == "SWS")
  333. {
  334. WaferSizeSet = double.Parse(parameter);
  335. }
  336. }
  337. public void MonitorRawCommand(bool isSelected, string command, string comandArgument)
  338. {
  339. lock (_locker)
  340. {
  341. var existHandlers = _lstMonitorHandler.Where(handler => handler.GetType() == typeof(RisshiChillerRawCommandHandler) && ((RisshiChillerHandler)handler)._command == command);
  342. if (isSelected)
  343. {
  344. if (!existHandlers.Any())
  345. _lstMonitorHandler.AddFirst(new RisshiChillerRawCommandHandler(this, command, comandArgument));
  346. }
  347. else
  348. {
  349. if (existHandlers.Any())
  350. {
  351. _lstMonitorHandler.Remove(existHandlers.First());
  352. }
  353. }
  354. }
  355. }
  356. public void MonitorRawCommand(bool isSelected, string command)
  357. {
  358. lock (_locker)
  359. {
  360. var existHandlers = _lstMonitorHandler.Where(handler => handler.GetType() == typeof(RisshiChillerRawCommandHandler) && ((RisshiChillerHandler)handler)._command == command);
  361. if (isSelected)
  362. {
  363. if (!existHandlers.Any())
  364. _lstMonitorHandler.AddFirst(new RisshiChillerRawCommandHandler(this, command));
  365. }
  366. else
  367. {
  368. if (existHandlers.Any())
  369. {
  370. _lstMonitorHandler.Remove(existHandlers.First());
  371. }
  372. }
  373. }
  374. }
  375. public void RequestTemprature(bool isSelected)
  376. {
  377. SimpleRequest(isSelected, "RWAA");
  378. }
  379. public void RequestCoolFlowRate(bool isSelected)
  380. {
  381. SimpleRequest(isSelected, "RWS");
  382. }
  383. public void RequestResistivity(bool isSelected)
  384. {
  385. SimpleRequest(isSelected, "RBIASXY");
  386. }
  387. public void RequestOperationStatus(bool isSelected)
  388. {
  389. SimpleRequest(isSelected, "RBIASRT");
  390. }
  391. public void RequestAlarmStatus(bool isSelected)
  392. {
  393. SimpleRequest(isSelected, "RNOTCH");
  394. }
  395. public void RequestWarningStatus(bool isSelected)
  396. {
  397. SimpleRequest(isSelected, "REER");
  398. }
  399. private void SimpleRequest(bool isSelected, string command)
  400. {
  401. lock (_locker)
  402. {
  403. var existHandlers = _lstMonitorHandler.Where(handler => handler.GetType() == typeof(RisshiChillerSimpleQueryHandler) && ((RisshiChillerSimpleQueryHandler)handler)._command == command);
  404. if (isSelected)
  405. {
  406. if (!existHandlers.Any())
  407. _lstMonitorHandler.AddFirst(new RisshiChillerSimpleQueryHandler(this, command));
  408. }
  409. else
  410. {
  411. if (existHandlers.Any())
  412. {
  413. _lstMonitorHandler.Remove(existHandlers.First());
  414. }
  415. }
  416. }
  417. }
  418. #endregion
  419. #region Properties
  420. public string Error { get; private set; }
  421. public bool SevoOnOff { get; private set; }
  422. public bool AlignCompleted { get; private set; }
  423. public bool RotatedCompleted { get; private set; }
  424. public double AlignAngleSet { get; private set; }
  425. public double WaferSizeSet { get; private set; }
  426. public double WaferSize { get; private set; }
  427. public bool XferCompleted { get; private set; }
  428. public bool HomeCompleted { get; private set; }
  429. public bool CommunicationIsOK { get; private set; }
  430. public double AlignedAngle { get; private set; }
  431. public double BaisX { get; private set; }
  432. public double BaisY { get; private set; }
  433. public double BaisR { get; private set; }
  434. public double BaisT { get; private set; }
  435. public double Notch { get; private set; }
  436. public bool WafeOnOff { get; private set; }
  437. public bool IsReady { get; private set; }
  438. public string LastPickInfo { get; private set; }
  439. public string LastPlaceInfo { get; private set; }
  440. #endregion
  441. #region Note Functions
  442. private R_TRIG _trigWarningMessage = new R_TRIG();
  443. public void NoteError(string reason)
  444. {
  445. CommunicationIsOK = false;
  446. if (reason != null)
  447. {
  448. _trigWarningMessage.CLK = true;
  449. if (_trigWarningMessage.Q)
  450. {
  451. EV.PostWarningLog(Module, $"{Module}.{Name} error, {reason}");
  452. }
  453. Error = reason;
  454. }
  455. else
  456. {
  457. Error = null;
  458. }
  459. }
  460. internal void NoteLastPickInfo(string sendText)
  461. {
  462. LastPickInfo = sendText;
  463. }
  464. internal void NoteLastPlaceInfo(string sendText)
  465. {
  466. LastPlaceInfo = sendText;
  467. }
  468. internal void NoteSevoOnOff(bool isOn)
  469. {
  470. SevoOnOff = isOn;
  471. }
  472. internal void NoteRawCommandInfo(string command, string data)
  473. {
  474. var curIOResponse = IOResponseList.Find(res => res.SourceCommandName == command);
  475. if (curIOResponse != null)
  476. {
  477. IOResponseList.Remove(curIOResponse);
  478. }
  479. IOResponseList.Add(new IOResponse() { SourceCommand = command, ResonseContent = data, ResonseRecievedTime = DateTime.Now });
  480. }
  481. #endregion
  482. }
  483. public class XferArgument
  484. {
  485. public string Arm { get; set; }
  486. public int FromStation { get; set; }
  487. public int FromSlot { get; set; }
  488. public int ToStation { get; set; }
  489. public int ToSlot { get; set; }
  490. public string AlignCommand { get; set; }
  491. }
  492. public class PickPlaceArgument
  493. {
  494. /// <summary>
  495. ///
  496. /// </summary>
  497. public int Station { get; set; }
  498. /// <summary>
  499. ///
  500. /// </summary>
  501. public int Slot { get; set; }
  502. /// <summary>
  503. ///
  504. /// </summary>
  505. public string Arm { get; set; }
  506. /// <summary>
  507. ///
  508. /// </summary>
  509. public int Step { get; set; }
  510. /// <summary>
  511. ///
  512. /// </summary>
  513. public string Offset { get; set; }
  514. public string AlignCommand { get; set; }
  515. }
  516. }