SkyPump.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  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.Device.Bases;
  17. using MECF.Framework.Common.Equipment;
  18. using Virgo_DCommon;
  19. namespace Virgo_DRT.Devices
  20. {
  21. //interface IPumpControl
  22. //{
  23. // bool IsRunning { get; }
  24. // void TurnON();
  25. // void TurnOFF();
  26. //}
  27. public enum SkyPumpState { ON = 0, OFF, Connected, Disconnected, Unknown, ERROR }
  28. static class SkyPumpMessage
  29. {
  30. public const string EOF = "\r\n";
  31. public const string SET_ON = "@00CON_FDP_ON";
  32. public const string SET_OFF = "@00CON_FDP_OFF";
  33. public const string GET_ON = "@00FDP_ONOK"; // \0\r\n
  34. public const string GET_OFF = "@00FDP_OFFOK"; // \0\r\n
  35. public const string READ_DATA = "@00READ_RUN_PARA";
  36. public const string GET_DATA = "@00RUN_PARA";
  37. }
  38. class SkyPump : PumpBase
  39. {
  40. // ----------------------------Fields--------------------------
  41. //
  42. private const ushort CHK_ST_INTERVAL = 1000;
  43. private const ushort CHK_REC_INTERVAL = 20 * 1000;
  44. private const ushort CHK_PUMP_REC_INTERVAL = 10 * 1000;
  45. private const string EOF = "\r";
  46. private const char MSG_DELIMITER = ' ';
  47. private readonly string _PortNum = "COM91";
  48. private const int _counterMax = 30;
  49. private int _counter = 0;
  50. private string _fdp_Current = null;
  51. private string _roots_Current = null;
  52. private string _fdp_Temp = null;
  53. private string _roots_Temp = null;
  54. private string _n2Flow = null;
  55. private string _pressure = null;
  56. private string _runTime = null;
  57. private readonly AsyncSerialPort _serial;
  58. private readonly DeviceTimer _timerQueryStatus = new DeviceTimer();
  59. private readonly DeviceTimer _timerReceiveStatus = new DeviceTimer();
  60. private readonly DeviceTimer _timerPumpOn = new DeviceTimer();
  61. private readonly DeviceTimer _timerPumpOff = new DeviceTimer();
  62. private readonly R_TRIG _trigPumpOn = new R_TRIG();
  63. private readonly R_TRIG _trigPumpOff = new R_TRIG();
  64. private readonly R_TRIG _trigReceiveStatus = new R_TRIG();
  65. // --------------------------Properties------------------------
  66. //
  67. public SkyPumpState StatusDry { get; set; }
  68. public SkyPumpState StatusRoose { get; set; }
  69. public string FDP_Current
  70. {
  71. get
  72. {
  73. return _fdp_Current;
  74. }
  75. }
  76. public string ROOTS_Current
  77. {
  78. get
  79. {
  80. return _roots_Current;
  81. }
  82. }
  83. public string FDP_Temp
  84. {
  85. get
  86. {
  87. return _fdp_Temp;
  88. }
  89. }
  90. public string ROOTS_Temp
  91. {
  92. get
  93. {
  94. return _roots_Temp;
  95. }
  96. }
  97. public string N2Flow
  98. {
  99. get
  100. {
  101. return _n2Flow;
  102. }
  103. }
  104. public string Pressure
  105. {
  106. get
  107. {
  108. return _pressure;
  109. }
  110. }
  111. public string RunTime
  112. {
  113. get
  114. {
  115. return _runTime;
  116. }
  117. }
  118. [Subscription(AITPumpProperty.IsRunning)]
  119. public override bool IsRunning
  120. {
  121. get
  122. {
  123. return StatusDry == SkyPumpState.ON;
  124. }
  125. }
  126. [Subscription(AITPumpProperty.IsError)]
  127. public override bool IsError
  128. {
  129. get
  130. {
  131. return StatusDry == SkyPumpState.ERROR || StatusDry == SkyPumpState.Disconnected;
  132. }
  133. }
  134. public override AITPumpData DeviceData
  135. {
  136. get
  137. {
  138. AITPumpData deviceData = new AITPumpData
  139. {
  140. DeviceName = Name,
  141. DeviceModule = Module,
  142. DeviceSchematicId = DeviceID,
  143. DisplayName = Display,
  144. IsError = false,
  145. IsWarning = false,
  146. IsOn = IsRunning,
  147. //WaterFlow = WaterFlowValue,
  148. IsDryPumpEnable = true,
  149. IsN2PressureEnable = false,
  150. IsWaterFlowEnable = false,
  151. //WaterFlowWarning = WaterFlowWarning,
  152. //WaterFlowAlarm = WaterFlowAlarm,
  153. //N2PressureAlarm = N2PressureAlarm,
  154. //N2PressureWarning = N2PressureWarning,
  155. };
  156. return deviceData;
  157. }
  158. }
  159. // --------------------------Constructor-----------------------
  160. //
  161. public SkyPump(ModuleName mod) : base(mod.ToString(), Virgo_DDevice.MainPump.ToString(), "SKY pump", "")
  162. {
  163. _PortNum = SC.GetStringValue($"{mod}.DryPump.Port");
  164. StatusDry = SkyPumpState.Unknown;
  165. _serial = new AsyncSerialPort(_PortNum, 9600, 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One, "\r\n", false);
  166. }
  167. public override bool Initialize()
  168. {
  169. base.Initialize();
  170. if (!_serial.Open())
  171. {
  172. StatusDry = SkyPumpState.Disconnected;
  173. EV.PostAlarmLog(this.Module, "Sky Pump串口无法打开");
  174. return false;
  175. }
  176. StatusDry = SkyPumpState.Connected;
  177. _trigPumpOn.RST = true;
  178. _trigPumpOff.RST = true;
  179. _trigReceiveStatus.RST = true;
  180. _serial.OnDataChanged += OnPortDataChanged;
  181. _serial.OnBinaryDataChanged += OnPortBinaryDataChanged;
  182. _serial.OnErrorHappened += OnErrorOccurred;
  183. _timerQueryStatus.Start(CHK_ST_INTERVAL);
  184. _timerReceiveStatus.Start(CHK_REC_INTERVAL);
  185. return true;
  186. }
  187. private void OnPortBinaryDataChanged(byte[] obj)
  188. {
  189. try
  190. {
  191. _timerReceiveStatus.Stop();
  192. _timerReceiveStatus.Start(CHK_REC_INTERVAL);
  193. _trigReceiveStatus.RST = true;
  194. if (Encoding.ASCII.GetString(obj, 12, 2) == SkyPumpMessage.EOF
  195. || Encoding.ASCII.GetString(obj, 13, 2) == SkyPumpMessage.EOF
  196. || Encoding.ASCII.GetString(obj, 38, 2) == SkyPumpMessage.EOF)
  197. {
  198. string cmd = "";
  199. if (obj.Length == 14 || obj.Length == 40)
  200. cmd = Encoding.ASCII.GetString(obj, 0, 11);
  201. else if (obj.Length == 15)
  202. cmd = Encoding.ASCII.GetString(obj, 0, 12);
  203. if (cmd == SkyPumpMessage.GET_ON)
  204. {
  205. _trigPumpOn.CLK = true;
  206. _timerPumpOn.Start(CHK_PUMP_REC_INTERVAL);
  207. LOG.Info($"[{Module}] {SkyPumpMessage.GET_ON}");
  208. return;
  209. }
  210. if (cmd == SkyPumpMessage.GET_OFF)
  211. {
  212. _trigPumpOff.CLK = true;
  213. _timerPumpOff.Start(CHK_PUMP_REC_INTERVAL);
  214. LOG.Info($"[{Module}] {SkyPumpMessage.GET_OFF}");
  215. return;
  216. }
  217. if (cmd == SkyPumpMessage.GET_DATA)
  218. {
  219. _fdp_Current = Encoding.ASCII.GetString(obj, 11, 2);
  220. _roots_Current = Encoding.ASCII.GetString(obj, 13, 2);
  221. _fdp_Temp = Encoding.ASCII.GetString(obj, 15, 3);
  222. _roots_Temp = Encoding.ASCII.GetString(obj, 18, 3);
  223. _n2Flow = Encoding.ASCII.GetString(obj, 21, 2);
  224. _pressure = Encoding.ASCII.GetString(obj, 23, 4);
  225. _runTime = Encoding.ASCII.GetString(obj, 27, 5);
  226. ParaErrSta1(new BitArray(new byte[] { obj[32] }));
  227. ParaErrSta2(new BitArray(new byte[] { obj[33] }));
  228. ParaRunSta(new BitArray(new byte[] { obj[34] }));
  229. //ParaRunSta(new BitArray(new byte[] { obj[35] }));
  230. ParaErrSta3(new BitArray(new byte[] { obj[36] }));
  231. }
  232. }
  233. else
  234. {
  235. LOG.Info($"[{Module}] Sky Pump 数据无效");
  236. }
  237. }
  238. catch (Exception ex)
  239. {
  240. LOG.Error($"[{Module}] sky pump data para error: [{ex.Message}]");
  241. }
  242. }
  243. private void OnErrorOccurred(string obj)
  244. {
  245. StatusDry = SkyPumpState.ERROR;
  246. LOG.Error($"[{Module}] sky pump error: [{obj}]");
  247. }
  248. private void OnPortDataChanged(string obj)
  249. {
  250. if (string.IsNullOrEmpty(obj))
  251. LOG.Error($"[{Module}] sky pump message IsNullOrEmpty");
  252. try
  253. {
  254. string cmd = obj.ToString().Split('\n')[0].Split('\r')[0];
  255. if (cmd == SkyPumpMessage.GET_ON)
  256. {
  257. LOG.Info($"[{Module}] {SkyPumpMessage.GET_ON}");
  258. return;
  259. }
  260. if (cmd == SkyPumpMessage.GET_OFF)
  261. {
  262. LOG.Info($"[{Module}] {SkyPumpMessage.GET_OFF}");
  263. return;
  264. }
  265. if (cmd.Substring(0, 11) == SkyPumpMessage.GET_DATA)
  266. {
  267. _fdp_Current = cmd.Substring(11, 2);
  268. _roots_Current = cmd.Substring(13, 2);
  269. _fdp_Temp = cmd.Substring(15, 3);
  270. _roots_Temp = cmd.Substring(18, 3);
  271. _n2Flow = cmd.Substring(21, 2);
  272. _pressure = cmd.Substring(23, 4);
  273. _runTime = cmd.Substring(27, 5);
  274. ParaErrSta1(new BitArray(new byte[] { Convert.ToByte(cmd[32]) }));
  275. ParaErrSta2(new BitArray(new byte[] { Convert.ToByte(cmd[33]) }));
  276. ParaRunSta(new BitArray(new byte[] { Convert.ToByte(cmd[34]) }));
  277. //ParaRunSta(new BitArray(new byte[] { Convert.ToByte(cmd[35]) }));
  278. ParaErrSta3(new BitArray(new byte[] { Convert.ToByte(cmd[36]) }));
  279. }
  280. }
  281. catch(Exception ex)
  282. {
  283. LOG.Error($"[{Module}] sky pump error: [{ex.Message}]");
  284. }
  285. }
  286. public void ParaErrSta1(BitArray bits)
  287. {
  288. for (int i = 0; i < bits.Count; i++)
  289. {
  290. if (bits[i]) ErrSta1(i);
  291. }
  292. }
  293. public void ParaErrSta2(BitArray bits)
  294. {
  295. for (int i = 0; i < bits.Count; i++)
  296. {
  297. if (bits[i]) ErrSta2(i);
  298. }
  299. }
  300. public void ParaErrSta3(BitArray bits)
  301. {
  302. for (int i = 0; i < bits.Count; i++)
  303. {
  304. if (bits[i]) ErrSta3(i);
  305. }
  306. }
  307. public void ParaRunSta(BitArray bits)
  308. {
  309. string sRes = "sky pump status: ";
  310. for (int i = 0; i < bits.Count; i++)
  311. {
  312. if (bits[i])
  313. sRes += RunStaTure(i);
  314. else
  315. sRes += RunStaFalse(i);
  316. }
  317. _counter++;
  318. if (_counter == _counterMax)
  319. {
  320. _counter = 0;
  321. LOG.Info($"[{Module}] {sRes}");
  322. }
  323. }
  324. public string RunStaTure(int code)
  325. {
  326. switch (code)
  327. {
  328. case 7:
  329. return "远程。";
  330. case 6:
  331. StatusDry = SkyPumpState.ON;
  332. if (_trigPumpOn.Q)
  333. {
  334. EV.PostInfoLog(this.Module, $"Dry Pump打开");
  335. }
  336. if (_trigPumpOff.Q && _timerPumpOff.IsTimeout())
  337. {
  338. _trigPumpOff.RST = true;
  339. EV.PostMessage(Module, EventEnum.DefaultWarning, "Dry Pump 无法关闭");
  340. }
  341. _trigPumpOn.RST = true;
  342. return "干泵开, ";
  343. case 5:
  344. StatusRoose = SkyPumpState.ON;
  345. return "罗茨泵开, ";
  346. case 4:
  347. return "泵冷阀开, ";
  348. case 3:
  349. return "清洗阀开, ";
  350. case 2:
  351. return "有警示, ";
  352. case 1:
  353. return "有故障, ";
  354. case 0:
  355. return "无水, ";
  356. default:
  357. return "";
  358. }
  359. }
  360. public string RunStaFalse(int code)
  361. {
  362. switch (code)
  363. {
  364. case 7:
  365. return "本地。";
  366. case 6:
  367. StatusDry = SkyPumpState.OFF;
  368. if (_trigPumpOn.Q && _timerPumpOn.IsTimeout())
  369. {
  370. _trigPumpOn.RST = true;
  371. EV.PostMessage(Module, EventEnum.DefaultWarning, "Dry Pump 无法打开");
  372. }
  373. if (_trigPumpOff.Q)
  374. {
  375. EV.PostInfoLog(this.Module, $"Dry Pump关闭");
  376. }
  377. _trigPumpOff.RST = true;
  378. return "干泵关, ";
  379. case 5:
  380. StatusRoose = SkyPumpState.OFF;
  381. return "罗茨泵关, ";
  382. case 4:
  383. return "泵冷阀关, ";
  384. case 3:
  385. return "清洗阀关, ";
  386. case 2:
  387. return "无警示, ";
  388. case 1:
  389. return "无故障, ";
  390. case 0:
  391. return "有水, ";
  392. default:
  393. return "";
  394. }
  395. }
  396. public void ErrSta1(int error)
  397. {
  398. switch (error)
  399. {
  400. case 7:
  401. LOG.Error($"[{Module}]上泵变频器除通讯外故障");
  402. break;
  403. case 6:
  404. LOG.Error($"[{Module}]下泵变频器除通讯外故障");
  405. break;
  406. case 5:
  407. LOG.Error($"[{Module}]上泵接触器");
  408. break;
  409. case 4:
  410. LOG.Error($"[{Module}]下泵接触器");
  411. break;
  412. case 3:
  413. LOG.Error($"[{Module}]上泵电机过热");
  414. break;
  415. case 2:
  416. LOG.Error($"[{Module}]下泵电机过热");
  417. break;
  418. case 1:
  419. LOG.Error($"[{Module}]急停");
  420. break;
  421. case 0:
  422. LOG.Error($"[{Module}]水冷");
  423. break;
  424. default:
  425. break;
  426. }
  427. }
  428. public void ErrSta2(int error)
  429. {
  430. switch (error)
  431. {
  432. case 7:
  433. LOG.Error($"[{Module}]下泵变频器通讯故障");
  434. break;
  435. case 6:
  436. LOG.Error($"[{Module}]上泵变频器通讯故障");
  437. break;
  438. case 5:
  439. LOG.Error($"[{Module}]排气压力");
  440. break;
  441. case 4:
  442. LOG.Error($"[{Module}]氮气流量");
  443. break;
  444. case 3:
  445. LOG.Error($"[{Module}]下泵电流");
  446. break;
  447. case 2:
  448. LOG.Error($"[{Module}]上泵电流");
  449. break;
  450. case 1:
  451. LOG.Error($"[{Module}]下泵温度");
  452. break;
  453. case 0:
  454. LOG.Error($"[{Module}]上泵温度");
  455. break;
  456. default:
  457. break;
  458. }
  459. }
  460. public void ErrSta3(int error)
  461. {
  462. switch (error)
  463. {
  464. case 7:
  465. case 6:
  466. case 5:
  467. case 4:
  468. case 3:
  469. case 2:
  470. break;
  471. case 1:
  472. LOG.Error($"[{Module}]下泵温度传感器未连接");
  473. break;
  474. case 0:
  475. LOG.Error($"[{Module}]上泵温度传感器未连接");
  476. break;
  477. default:
  478. break;
  479. }
  480. }
  481. public override void Monitor()
  482. {
  483. try
  484. {
  485. // 状态查询
  486. if (_timerQueryStatus.IsTimeout() && this.StatusDry != SkyPumpState.ERROR)
  487. {
  488. this.SendCmd(SkyPumpMessage.READ_DATA);
  489. _timerQueryStatus.Start(CHK_ST_INTERVAL);
  490. }
  491. if (_timerReceiveStatus.IsTimeout() && this.StatusDry != SkyPumpState.ERROR)
  492. {
  493. _trigReceiveStatus.CLK = true;
  494. if(_trigReceiveStatus.Q)
  495. {
  496. EV.PostMessage(Module, EventEnum.DefaultWarning, "Dry Pump 没有回复");
  497. }
  498. }
  499. }
  500. catch (Exception ex)
  501. {
  502. throw ex;
  503. }
  504. }
  505. private bool SendCmd(string str)
  506. {
  507. return _serial.Write(str + "\r");
  508. }
  509. public override void Reset()
  510. {
  511. _trigPumpOn.RST = true;
  512. _trigPumpOff.RST = true;
  513. _trigReceiveStatus.RST = true;
  514. //SetPumpOnOff(false);
  515. }
  516. public override void Terminate()
  517. {
  518. //if (StatusDry == SkyPumpState.ON)
  519. // SetPumpOnOff(false);
  520. _serial?.Close();
  521. }
  522. public override void SetPumpOnOff(bool on)
  523. {
  524. SendCmd(on ? SkyPumpMessage.SET_ON : SkyPumpMessage.SET_OFF);
  525. }
  526. }
  527. }