EdwardsPump.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. using System;
  2. using System.Collections;
  3. using System.Text;
  4. using System.Xml;
  5. using Aitex.Core.Common.DeviceData;
  6. using Aitex.Core.RT.DataCenter;
  7. using Aitex.Core.RT.Device;
  8. using Aitex.Core.RT.Event;
  9. using Aitex.Core.RT.IOCore;
  10. using Aitex.Core.RT.Log;
  11. using Aitex.Core.RT.OperationCenter;
  12. using Aitex.Core.RT.SCCore;
  13. using Aitex.Core.RT.Tolerance;
  14. using Aitex.Core.Util;
  15. using MECF.Framework.Common.Communications;
  16. using MECF.Framework.Common.DataCenter;
  17. using MECF.Framework.Common.Device.Bases;
  18. using MECF.Framework.Common.Equipment;
  19. using Venus_Core;
  20. namespace Venus_RT.Devices
  21. {
  22. public enum EdwardsPumpState { ON = 0, OFF, Connected, Disconnected, Unknown, ERROR }
  23. static class EdwardsPumpControlSystemParameters
  24. {
  25. public const int System_Node = 1;
  26. public const int Dry_Pump_Current = 3;
  27. public const int Dry_Pump_Power = 4;
  28. public const int Booster_Current = 7;
  29. public const int Booster_Power = 8;
  30. public const int Dry_Pump_Control = 11;
  31. public const int Dry_Pump_Run_hours = 14;
  32. public const int Number_of_pump_starts = 20;
  33. }
  34. static class EdwardsPumpMessage
  35. {
  36. public const string EOF = "\r\n";
  37. public const string RESET = "/";
  38. public const string QUERY_Alarm_Status = "?A";
  39. public const string QUERY_Bitfield_Status = "?B";
  40. public const string QUERY_Control_Status = "?C";
  41. public const string QUERY_Gas_ballast_Status = "?D";
  42. public const string QUERY_Gate_valve_Status = "?G";
  43. public const string QUERY_Nitrogen_supply_Status = "?N";
  44. public const string QUERY_On_process_Status = "?O";
  45. public const string QUERY_Pump_Status = "?P";
  46. public const string QUERY_Run_til_crash_Status = "?R";
  47. public const string QUERY_Inlet_purge_Status = "?U";
  48. public const string QUERY_Pump_node_type = "?T";
  49. public const string QUERY_Value = "?V";
  50. public const string QUERY_Serial_Number = "?S";
  51. public const string QUERY_Information = "?I";
  52. public const string QUERY_Format_mode = "?F";
  53. public const string COMMAND_Release_Control = "!C0";
  54. public const string COMMAND_Take_Control = "!C1";
  55. public const string COMMAND_Gas_ballast = "!D";
  56. public const string COMMAND_Equipment = "!E";
  57. public const string COMMAND_Format_mode = "!F";
  58. public const string COMMAND_Gate_valve = "!G";
  59. public const string COMMAND_Reserved = "!L";
  60. public const string COMMAND_Simulation_mode = "!M";
  61. public const string COMMAND_Nitrogen_supply = "!N";
  62. public const string COMMAND_On_process = "!O";
  63. public const string COMMAND_Switch_on_Pump = "!P1";
  64. public const string COMMAND_Switch_off_Pump_Auto_shut_down = "!P0";
  65. public const string COMMAND_Switch_off_Pump_Fast_shut_down = "!P2";
  66. public const string COMMAND_Run_til_crash = "!R";
  67. public const string COMMAND_Reserved_do_not_use = "!T";
  68. public const string COMMAND_Inlet_purge = "!U";
  69. public const string COMMAND_Terminate_protocol = "!XO";
  70. public const string SET_SHORT_REPLY = "!F0";
  71. public const string SET_LONG_REPLY = "!F1";
  72. }
  73. class EdwardsPump : PumpBase
  74. {
  75. // ----------------------------Fields--------------------------
  76. //
  77. private const ushort CHK_ST_INTERVAL = 1000;
  78. private const ushort CHK_CONTROL_INTERVAL = 3 * 1000;
  79. private const ushort CHK_REC_INTERVAL = 20 * 1000;
  80. private const ushort CHK_PUMP_REC_INTERVAL = 10 * 1000;
  81. private double _total;
  82. private double _fromLast;
  83. private const string EOF = "\r";
  84. private const char MSG_DELIMITER = ' ';
  85. private readonly string _PortNum = "COM91";
  86. private const int _counterMax = 30;
  87. //private int _counter = 0;
  88. private static string SendData;
  89. private readonly AsyncSerialPort _serial;
  90. private readonly DeviceTimer _timerQueryStatus = new DeviceTimer();
  91. private readonly DeviceTimer _timerControlStatus = new DeviceTimer();
  92. private readonly DeviceTimer _timerReceiveStatus = new DeviceTimer();
  93. private readonly DeviceTimer _timerPumpOn = new DeviceTimer();
  94. private readonly DeviceTimer _timerPumpOff = new DeviceTimer();
  95. private readonly DeviceTimer _timerTotal = new DeviceTimer();
  96. private readonly DeviceTimer _timerFromLast = new DeviceTimer();
  97. private readonly R_TRIG _trigPumpOn = new R_TRIG();
  98. private readonly R_TRIG _trigPumpOff = new R_TRIG();
  99. private readonly R_TRIG _trigReceiveStatus = new R_TRIG();
  100. private readonly RD_TRIG _trigOnOff = new RD_TRIG();
  101. private readonly R_TRIG _trigPMNeeded = new R_TRIG();
  102. private StatsDataItemRFAndPump _statPumpOnTime;
  103. // --------------------------Properties------------------------
  104. //
  105. public EdwardsPumpState StatusDry { get; set; }
  106. public string LastPMTime
  107. {
  108. get
  109. {
  110. return _statPumpOnTime != null ? _statPumpOnTime.LastPMTime.ToString() : "";
  111. }
  112. }
  113. public double DaysFromLastPM
  114. {
  115. get
  116. {
  117. return _statPumpOnTime == null ? 0 : _statPumpOnTime.fromLastPM;
  118. }
  119. set
  120. {
  121. if (_statPumpOnTime != null)
  122. _statPumpOnTime.fromLastPM = value;
  123. }
  124. }
  125. public double TotalDays
  126. {
  127. get
  128. {
  129. return _statPumpOnTime != null ? _statPumpOnTime.Total : 0;
  130. }
  131. set
  132. {
  133. if (_statPumpOnTime != null)
  134. _statPumpOnTime.Total = value;
  135. }
  136. }
  137. public double PMIntervalDays
  138. {
  139. get
  140. {
  141. return _statPumpOnTime != null ? _statPumpOnTime.PMInterval : 0;
  142. }
  143. }
  144. public bool IsPMNeeded
  145. {
  146. get
  147. {
  148. return DaysFromLastPM > PMIntervalDays;
  149. }
  150. }
  151. public bool EnableAlarm
  152. {
  153. get
  154. {
  155. return _statPumpOnTime == null || _statPumpOnTime.AlarmEnable;
  156. }
  157. }
  158. [Subscription(AITPumpProperty.IsRunning)]
  159. public override bool IsRunning
  160. {
  161. get
  162. {
  163. return StatusDry == EdwardsPumpState.ON;
  164. }
  165. }
  166. [Subscription(AITPumpProperty.IsError)]
  167. public override bool IsError
  168. {
  169. get
  170. {
  171. return StatusDry == EdwardsPumpState.ERROR || StatusDry == EdwardsPumpState.Disconnected;
  172. }
  173. }
  174. public override AITPumpData DeviceData
  175. {
  176. get
  177. {
  178. AITPumpData deviceData = new AITPumpData
  179. {
  180. DeviceName = Name,
  181. DeviceModule = Module,
  182. DeviceSchematicId = DeviceID,
  183. DisplayName = Display,
  184. IsError = false,
  185. IsWarning = false,
  186. IsOn = IsRunning,
  187. //WaterFlow = WaterFlowValue,
  188. IsDryPumpEnable = true,
  189. IsN2PressureEnable = false,
  190. IsWaterFlowEnable = false,
  191. //WaterFlowWarning = WaterFlowWarning,
  192. //WaterFlowAlarm = WaterFlowAlarm,
  193. //N2PressureAlarm = N2PressureAlarm,
  194. //N2PressureWarning = N2PressureWarning,
  195. };
  196. return deviceData;
  197. }
  198. }
  199. // --------------------------Constructor-----------------------
  200. //
  201. public EdwardsPump(ModuleName mod) : base(mod.ToString(), VenusDevice.MainPump.ToString(), "Edwards Pump", "")
  202. {
  203. _PortNum = SC.GetStringValue($"{mod}.DryPump.Port");
  204. StatusDry = EdwardsPumpState.Unknown;
  205. _serial = new AsyncSerialPort(_PortNum, 9600, 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One, "\r\n", true);
  206. }
  207. public EdwardsPump(ModuleName mod, string name) : base(mod.ToString(), VenusDevice.MainPump.ToString(), "Edwards Pump", "")
  208. {
  209. _PortNum = SC.GetStringValue($"{mod.ToString()}.{name}.Port");
  210. StatusDry = EdwardsPumpState.Unknown;
  211. _serial = new AsyncSerialPort(_PortNum, 9600, 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One, "\r\n", true);
  212. }
  213. public override bool Initialize()
  214. {
  215. base.Initialize();
  216. if (!_serial.Open())
  217. {
  218. StatusDry = EdwardsPumpState.Disconnected;
  219. LOG.Write(eEvent.ERR_DRY_PUMP, Module, "Edwards Pump串口无法打开");
  220. return false;
  221. }
  222. _statPumpOnTime = StatsDataManager.Instance.GetItemRFAndPump($"{Module}.PumpOnTime");
  223. StatusDry = EdwardsPumpState.Connected;
  224. _trigPumpOn.RST = true;
  225. _trigPumpOff.RST = true;
  226. _trigReceiveStatus.RST = true;
  227. _serial.OnDataChanged += OnPortDataChanged;
  228. _serial.OnErrorHappened += OnErrorOccurred;
  229. SendCmd(EdwardsPumpMessage.RESET);
  230. SendCmd(EdwardsPumpMessage.SET_SHORT_REPLY);
  231. SendCmd(EdwardsPumpMessage.COMMAND_Take_Control);
  232. _timerQueryStatus.Start(CHK_ST_INTERVAL);
  233. _timerControlStatus.Start(CHK_CONTROL_INTERVAL);
  234. _timerReceiveStatus.Start(CHK_REC_INTERVAL);
  235. return true;
  236. }
  237. private void OnErrorOccurred(string obj)
  238. {
  239. StatusDry = EdwardsPumpState.ERROR;
  240. LOG.Write(eEvent.WARN_DEVICE_INFO, Module, $"[{Module}] edwards pump error: [{obj}]");
  241. }
  242. private void OnPortDataChanged(string obj)
  243. {
  244. if (string.IsNullOrEmpty(obj))
  245. LOG.Write(eEvent.WARN_DEVICE_INFO, Module, "edwards pump message IsNullOrEmpty");
  246. try
  247. {
  248. _timerReceiveStatus.Stop();
  249. _timerReceiveStatus.Start(CHK_REC_INTERVAL);
  250. string cmd = obj.ToString().Split('\n')[0].Split('\r')[0];
  251. switch (SendData)
  252. {
  253. case EdwardsPumpMessage.RESET:
  254. break;
  255. case EdwardsPumpMessage.COMMAND_Take_Control:
  256. LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Take Control Edwards Pump {QueryCmdReply(cmd)}");
  257. break;
  258. case EdwardsPumpMessage.COMMAND_Release_Control:
  259. LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Release Control Edwards Pump {QueryCmdReply(cmd)}");
  260. break;
  261. case EdwardsPumpMessage.COMMAND_Switch_on_Pump:
  262. LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Switch on Edwards Pump {QueryCmdReply(cmd)}");
  263. break;
  264. case EdwardsPumpMessage.COMMAND_Switch_off_Pump_Fast_shut_down:
  265. LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Switch off Edwards Pump {QueryCmdReply(cmd)}");
  266. break;
  267. case EdwardsPumpMessage.QUERY_Pump_Status:
  268. if (cmd == "0")
  269. {
  270. StatusDry = EdwardsPumpState.OFF;
  271. if (_trigPumpOn.Q && _timerPumpOn.IsTimeout())
  272. {
  273. _trigPumpOn.RST = true;
  274. LOG.Write(eEvent.WARN_DEVICE_INFO, Module, "Edwards Pump 无法打开");
  275. }
  276. if (_trigPumpOff.Q)
  277. {
  278. LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Edwards Pump关闭");
  279. }
  280. _trigPumpOff.RST = true;
  281. }
  282. else if (cmd == "4")
  283. {
  284. StatusDry = EdwardsPumpState.ON;
  285. if (_trigPumpOff.Q && _timerPumpOff.IsTimeout())
  286. {
  287. _trigPumpOff.RST = true;
  288. LOG.Write(eEvent.WARN_DEVICE_INFO, Module, "Edwards Pump 无法关闭");
  289. }
  290. if (_trigPumpOn.Q)
  291. {
  292. LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Edwards Pump打开");
  293. }
  294. _trigPumpOn.RST = true;
  295. }
  296. break;
  297. default:
  298. LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Edwards Pump {SendData} {QueryCmdReply(cmd)}");
  299. break;
  300. }
  301. }
  302. catch (Exception ex)
  303. {
  304. LOG.WriteExeption($"[{Module}] edwards pump error: ", ex);
  305. }
  306. }
  307. public string QueryCmdReply(string cmd)
  308. {
  309. if (cmd == "ERR 0")
  310. {
  311. return "No error";
  312. }
  313. else if (cmd == "ERR 1")
  314. {
  315. return "Invalid message";
  316. }
  317. else if (cmd == "ERR 2")
  318. {
  319. return "Number not found";
  320. }
  321. else if (cmd == "ERR 3")
  322. {
  323. return "Number Invalid";
  324. }
  325. else if (cmd == "ERR 4")
  326. {
  327. return "Parameter’s value not received";
  328. }
  329. else if (cmd == "ERR 5")
  330. {
  331. return "Command not possible";
  332. }
  333. else
  334. {
  335. return cmd;
  336. }
  337. }
  338. public override void Monitor()
  339. {
  340. try
  341. {
  342. // 状态查询
  343. if (_timerQueryStatus.IsTimeout() && this.StatusDry != EdwardsPumpState.ERROR)
  344. {
  345. this.SendCmd(EdwardsPumpMessage.QUERY_Pump_Status);
  346. _timerQueryStatus.Start(CHK_ST_INTERVAL);
  347. }
  348. if (_timerReceiveStatus.IsTimeout() && this.StatusDry != EdwardsPumpState.ERROR)
  349. {
  350. _trigReceiveStatus.CLK = true;
  351. if (_trigReceiveStatus.Q)
  352. {
  353. //EV.PostMessage(Module, EventEnum.DefaultWarning, "Edwards Pump 没有回复");
  354. //EV.PostAlarmLog(Module, "Edwards Pump 没有回复",)
  355. }
  356. }
  357. _trigOnOff.CLK = IsRunning;
  358. //第一次检测到打开了,开始计时
  359. if (_trigOnOff.R)
  360. {
  361. _total = TotalDays;
  362. _fromLast = DaysFromLastPM;
  363. _timerTotal.Start(0);
  364. _timerFromLast.Start(0);
  365. }
  366. //第一次检测到从打开到关闭状态
  367. if (_trigOnOff.T)
  368. {
  369. }
  370. //如果开着,就更新SC
  371. if (_trigOnOff.M)
  372. {
  373. TotalDays = _total + _timerTotal.GetElapseTime() / 1000 / 60 / 60;
  374. DaysFromLastPM = _fromLast + _timerFromLast.GetElapseTime() / 1000 / 60 / 60;
  375. }
  376. if (PMIntervalDays > 0)
  377. {
  378. _trigPMNeeded.CLK = IsPMNeeded;
  379. if (_trigPMNeeded.Q)
  380. {
  381. if (EnableAlarm)
  382. {
  383. EV.PostAlarmLog(Module, "pump on time value larger than setting interval days");
  384. }
  385. }
  386. }
  387. StatsDataManager.Instance.Increase($"{Module}.PumpOnTime", $"{Module} PumpOnTime", DaysFromLastPM, TotalDays);
  388. }
  389. catch (Exception ex)
  390. {
  391. throw ex;
  392. }
  393. }
  394. private bool SendCmd(string str)
  395. {
  396. SendData = str;
  397. if (SendData == "!P1")
  398. {
  399. _trigPumpOn.CLK = true;
  400. _timerPumpOn.Start(CHK_PUMP_REC_INTERVAL);
  401. LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"[{Module}] Switch on Edwards Pump");
  402. }
  403. else if (SendData == "!P2")
  404. {
  405. _trigPumpOff.CLK = true;
  406. _timerPumpOff.Start(CHK_PUMP_REC_INTERVAL);
  407. LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"[{Module}] Switch off Edwards Pump");
  408. }
  409. return _serial.Write(str + "\r");
  410. }
  411. public override void Reset()
  412. {
  413. _trigPumpOn.RST = true;
  414. _trigPumpOff.RST = true;
  415. _trigReceiveStatus.RST = true;
  416. _trigPMNeeded.RST = true;
  417. SendCmd(EdwardsPumpMessage.RESET);
  418. }
  419. public override void Terminate()
  420. {
  421. //if (StatusDry == EdwardsPumpState.ON)
  422. // SetPumpOnOff(false);
  423. _serial?.Close();
  424. }
  425. public override void SetPumpOnOff(bool on)
  426. {
  427. SendCmd(on ? EdwardsPumpMessage.COMMAND_Switch_on_Pump : EdwardsPumpMessage.COMMAND_Switch_off_Pump_Fast_shut_down);
  428. }
  429. }
  430. }