EdwardsPump.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  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 VirgoCommon;
  20. namespace VirgoRT.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(), VirgoDevice.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 override bool Initialize()
  208. {
  209. base.Initialize();
  210. if (!_serial.Open())
  211. {
  212. StatusDry = EdwardsPumpState.Disconnected;
  213. EV.PostAlarmLog(Module, "Edwards Pump串口无法打开");
  214. return false;
  215. }
  216. _statPumpOnTime = StatsDataManager.Instance.GetItemRFAndPump($"{Module}.PumpOnTime");
  217. StatusDry = EdwardsPumpState.Connected;
  218. _trigPumpOn.RST = true;
  219. _trigPumpOff.RST = true;
  220. _trigReceiveStatus.RST = true;
  221. _serial.OnDataChanged += OnPortDataChanged;
  222. _serial.OnErrorHappened += OnErrorOccurred;
  223. SendCmd(EdwardsPumpMessage.RESET);
  224. SendCmd(EdwardsPumpMessage.SET_SHORT_REPLY);
  225. SendCmd(EdwardsPumpMessage.COMMAND_Take_Control);
  226. _timerQueryStatus.Start(CHK_ST_INTERVAL);
  227. _timerControlStatus.Start(CHK_CONTROL_INTERVAL);
  228. _timerReceiveStatus.Start(CHK_REC_INTERVAL);
  229. return true;
  230. }
  231. private void OnErrorOccurred(string obj)
  232. {
  233. StatusDry = EdwardsPumpState.ERROR;
  234. LOG.Error($"[{Module}] edwards pump error: [{obj}]");
  235. }
  236. private void OnPortDataChanged(string obj)
  237. {
  238. if (string.IsNullOrEmpty(obj))
  239. LOG.Error($"[{Module}] edwards pump message IsNullOrEmpty");
  240. try
  241. {
  242. _timerReceiveStatus.Stop();
  243. _timerReceiveStatus.Start(CHK_REC_INTERVAL);
  244. string cmd = obj.ToString().Split('\n')[0].Split('\r')[0];
  245. switch (SendData)
  246. {
  247. case EdwardsPumpMessage.RESET:
  248. break;
  249. case EdwardsPumpMessage.COMMAND_Take_Control:
  250. EV.PostInfoLog(Module, $"Take Control Edwards Pump {QueryCmdReply(cmd)}");
  251. break;
  252. case EdwardsPumpMessage.COMMAND_Release_Control:
  253. EV.PostInfoLog(Module, $"Release Control Edwards Pump {QueryCmdReply(cmd)}");
  254. break;
  255. case EdwardsPumpMessage.COMMAND_Switch_on_Pump:
  256. EV.PostInfoLog(Module, $"Switch on Edwards Pump {QueryCmdReply(cmd)}");
  257. break;
  258. case EdwardsPumpMessage.COMMAND_Switch_off_Pump_Fast_shut_down:
  259. EV.PostInfoLog(Module, $"Switch off Edwards Pump {QueryCmdReply(cmd)}");
  260. break;
  261. case EdwardsPumpMessage.QUERY_Pump_Status:
  262. if (cmd == "0")
  263. {
  264. StatusDry = EdwardsPumpState.OFF;
  265. if (_trigPumpOn.Q && _timerPumpOn.IsTimeout())
  266. {
  267. _trigPumpOn.RST = true;
  268. EV.PostMessage(Module, EventEnum.DefaultWarning, "Edwards Pump 无法打开");
  269. }
  270. if (_trigPumpOff.Q)
  271. {
  272. EV.PostInfoLog(Module, $"Edwards Pump关闭");
  273. }
  274. _trigPumpOff.RST = true;
  275. }
  276. else if (cmd == "4")
  277. {
  278. StatusDry = EdwardsPumpState.ON;
  279. if (_trigPumpOff.Q && _timerPumpOff.IsTimeout())
  280. {
  281. _trigPumpOff.RST = true;
  282. EV.PostMessage(Module, EventEnum.DefaultWarning, "Edwards Pump 无法关闭");
  283. }
  284. if (_trigPumpOn.Q)
  285. {
  286. EV.PostInfoLog(Module, $"Edwards Pump打开");
  287. }
  288. _trigPumpOn.RST = true;
  289. }
  290. break;
  291. default:
  292. //EV.PostInfoLog(this.Module, $"Edwards Pump {SendData} {QueryCmdReply(cmd)}");
  293. break;
  294. }
  295. }
  296. catch (Exception ex)
  297. {
  298. LOG.Error($"[{Module}] edwards pump error: [{ex.Message}]");
  299. }
  300. }
  301. public string QueryCmdReply(string cmd)
  302. {
  303. if (cmd == "ERR 0")
  304. {
  305. return "No error";
  306. }
  307. else if (cmd == "ERR 1")
  308. {
  309. return "Invalid message";
  310. }
  311. else if (cmd == "ERR 2")
  312. {
  313. return "Number not found";
  314. }
  315. else if (cmd == "ERR 3")
  316. {
  317. return "Number Invalid";
  318. }
  319. else if (cmd == "ERR 4")
  320. {
  321. return "Parameter’s value not received";
  322. }
  323. else if (cmd == "ERR 5")
  324. {
  325. return "Command not possible";
  326. }
  327. else
  328. {
  329. return cmd;
  330. }
  331. }
  332. public override void Monitor()
  333. {
  334. try
  335. {
  336. // 状态查询
  337. if (_timerQueryStatus.IsTimeout() && this.StatusDry != EdwardsPumpState.ERROR)
  338. {
  339. this.SendCmd(EdwardsPumpMessage.QUERY_Pump_Status);
  340. _timerQueryStatus.Start(CHK_ST_INTERVAL);
  341. }
  342. if (_timerReceiveStatus.IsTimeout() && this.StatusDry != EdwardsPumpState.ERROR)
  343. {
  344. _trigReceiveStatus.CLK = true;
  345. if (_trigReceiveStatus.Q)
  346. {
  347. EV.PostMessage(Module, EventEnum.DefaultWarning, "Edwards Pump 没有回复");
  348. }
  349. }
  350. _trigOnOff.CLK = IsRunning;
  351. //第一次检测到打开了,开始计时
  352. if (_trigOnOff.R)
  353. {
  354. _total = TotalDays;
  355. _fromLast = DaysFromLastPM;
  356. _timerTotal.Start(0);
  357. _timerFromLast.Start(0);
  358. }
  359. //第一次检测到从打开到关闭状态
  360. if (_trigOnOff.T)
  361. {
  362. }
  363. //如果开着,就更新SC
  364. if (_trigOnOff.M)
  365. {
  366. TotalDays = _total + _timerTotal.GetElapseTime() / 1000 / 60 / 60;
  367. DaysFromLastPM = _fromLast + _timerFromLast.GetElapseTime() / 1000 / 60 / 60;
  368. }
  369. if (PMIntervalDays > 0)
  370. {
  371. _trigPMNeeded.CLK = IsPMNeeded;
  372. if (_trigPMNeeded.Q)
  373. {
  374. if (EnableAlarm)
  375. {
  376. EV.PostAlarmLog(Module, "pump on time value larger than setting interval days");
  377. }
  378. }
  379. }
  380. StatsDataManager.Instance.Increase($"{Module}.PumpOnTime", $"{Module} PumpOnTime", DaysFromLastPM, TotalDays);
  381. }
  382. catch (Exception ex)
  383. {
  384. throw ex;
  385. }
  386. }
  387. private bool SendCmd(string str)
  388. {
  389. SendData = str;
  390. if (SendData == "!P1")
  391. {
  392. _trigPumpOn.CLK = true;
  393. _timerPumpOn.Start(CHK_PUMP_REC_INTERVAL);
  394. LOG.Info($"[{Module}] Switch on Edwards Pump");
  395. }
  396. else if (SendData == "!P2")
  397. {
  398. _trigPumpOff.CLK = true;
  399. _timerPumpOff.Start(CHK_PUMP_REC_INTERVAL);
  400. LOG.Info($"[{Module}] Switch off Edwards Pump");
  401. }
  402. return _serial.Write(str + "\r");
  403. }
  404. public override void Reset()
  405. {
  406. _trigPumpOn.RST = true;
  407. _trigPumpOff.RST = true;
  408. _trigReceiveStatus.RST = true;
  409. _trigPMNeeded.RST = true;
  410. SendCmd(EdwardsPumpMessage.RESET);
  411. }
  412. public override void Terminate()
  413. {
  414. //if (StatusDry == EdwardsPumpState.ON)
  415. // SetPumpOnOff(false);
  416. _serial?.Close();
  417. }
  418. public override void SetPumpOnOff(bool on)
  419. {
  420. SendCmd(on ? EdwardsPumpMessage.COMMAND_Switch_on_Pump : EdwardsPumpMessage.COMMAND_Switch_off_Pump_Fast_shut_down);
  421. }
  422. }
  423. }