BufferBottleBin.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. using DBEntity;
  2. using IvfTl.Control.Entity;
  3. using IvfTl.Control.Entity.DBEntitys;
  4. using IvfTl.Control.Entity.GlobalEntitys;
  5. using IvfTl.Control.Entity.GlobalEnums;
  6. using ivf_tl_SerialHelper.Util;
  7. using ivf_tl_UtilHelper;
  8. using IvfTl.Hardware.Impl;
  9. using System.Diagnostics;
  10. namespace ivf_tl_Com
  11. {
  12. /// <summary>
  13. /// 缓冲瓶通信
  14. /// </summary>
  15. public class BufferBottleBin
  16. {
  17. public event Action<int, DateTime, string, LogEnum> HouseLogEvent;
  18. public event Action<string, LogEnum> TLLogEvent;
  19. public event Action<Exception, string, string, LogEnum> ExceptionLogEvent;
  20. /// <summary>
  21. /// 舱室运行状态上报 舱室、串口
  22. /// </summary>
  23. public event Action<int, int, int, int, int, int> HouseStateEvent;
  24. int guanbiTime = 0;
  25. public BufferBottleBin(TLSetting _setting, House _house, int guanbi)
  26. {
  27. this.PortName = _house.housePort;
  28. // M1-03 HAL: 缓冲瓶模块也向 HAL 借用该 COM 口的唯一 ComBin(杜绝同口重复 Open)。
  29. this.ComBin = (ComBin)HardwareAccessLayer.Instance.GetSerial(_house.houseSn, _house.housePort).RawComBin;
  30. this.House = _house;
  31. this.tl_Setting = _setting;
  32. ComBin.CommandLogEvent += ComBin_CommandLogEvent;
  33. ComBin.ErrorLogEvent += ComBin_ErrorLogEvent;
  34. ComBin.ExceptionLogEvent += ComBin_ExceptionLogEvent;
  35. ComBin.ComStateEvent += ComBin_ComStateEvent;
  36. guanbiTime = guanbi * 1000;
  37. }
  38. private void ComBin_ComStateEvent(int obj)
  39. {
  40. HouseStateEvent?.Invoke(House.houseSn, -1, obj, -1, -1, -1);
  41. }
  42. private void ComBin_ExceptionLogEvent(Exception arg1, string arg2, string arg3, LogEnum arg4)
  43. {
  44. ExceptionLogEvent?.Invoke(arg1, arg2, arg3, arg4);
  45. }
  46. private void ComBin_ErrorLogEvent(string arg1, LogEnum arg2)
  47. {
  48. TLLogEvent?.Invoke(arg1, arg2);
  49. }
  50. private void ComBin_CommandLogEvent(int arg1, DateTime arg2, string arg3, LogEnum arg4)
  51. {
  52. HouseLogEvent?.Invoke(arg1, arg2, arg3, arg4);
  53. }
  54. private string PortName = null;
  55. /// <summary>
  56. /// 串口通信类
  57. /// </summary>
  58. public ComBin ComBin = null;
  59. public House House = null;
  60. private TLSetting tl_Setting = null;
  61. public string RunState { get; set; }
  62. /// <summary>
  63. /// 仪器温度1
  64. /// </summary>
  65. public decimal Temperature1 = 0m;
  66. /// <summary>
  67. /// 仪器温度2
  68. /// </summary>
  69. public decimal Temperature2 = 0m;
  70. /// <summary>
  71. /// 压力
  72. /// </summary>
  73. public decimal BufferBottlePressure = 0m;
  74. /// <summary>
  75. /// 当前气压状态
  76. /// </summary>
  77. public State ValveState = State.未知;
  78. public void StartTask()
  79. {
  80. Task.Run(() =>
  81. {
  82. try
  83. {
  84. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}]开始初始化", LogEnum.HouseInfo);
  85. if (House.openPort == 0)
  86. {
  87. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}]仓室串口未打开,结束初始化", LogEnum.HouseInfo);
  88. return;
  89. }
  90. var openPort = ComBin.OpenPort();
  91. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}]仓室串口打开结果{openPort}", LogEnum.HouseInfo);
  92. if (!openPort)
  93. {
  94. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}]仓室串口打开失败,结束初始化", LogEnum.HouseInfo);
  95. return;
  96. }
  97. CommandSource commandSource = CommandSource.BufferBottleThread;
  98. this.RunState = "握手准备";
  99. //缓冲瓶握手
  100. var custom = new CustomProtocol();
  101. custom.commandSource = commandSource;
  102. ComBin.ShakeHandsWait(custom);
  103. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}] 初始化完成,缓冲瓶开始运行", LogEnum.HouseInfo);
  104. MainThread();
  105. }
  106. catch (Exception ex)
  107. {
  108. ExceptionLogEvent?.Invoke(ex, $"[{House.houseSn}][{PortName}]初始化异常", null, LogEnum.RunException);
  109. }
  110. });
  111. }
  112. public void MainThread()
  113. {
  114. Task.Factory.StartNew(() =>
  115. {
  116. var custom = new CustomProtocol();
  117. custom.commandSource = CommandSource.BufferBottleThread;
  118. (decimal, decimal, decimal) a;
  119. while (true)
  120. {
  121. try
  122. {
  123. if (StartAirSwap == true)
  124. {
  125. this.RunState = "舱室换气";
  126. IsStartAirSwap = true;
  127. a = ComBin.BufferBottleState(custom);
  128. BufferBottlePressure = a.Item1;
  129. Temperature1 = a.Item2;
  130. Temperature2 = a.Item3;
  131. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}] [缓冲瓶气压:{BufferBottlePressure}][仪器温度1:{Temperature1}][仪器温度2:{Temperature2}]【换气逻辑】", LogEnum.HouseInfo);
  132. Thread.Sleep(1000);
  133. continue;
  134. }
  135. if (IsStartAirSwap)
  136. {
  137. IsStartAirSwap = false;
  138. }
  139. this.RunState = "气压监测";
  140. a = ComBin.BufferBottleState(custom);
  141. BufferBottlePressure = a.Item1;
  142. Temperature1 = a.Item2;
  143. Temperature2 = a.Item3;
  144. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}] [缓冲瓶气压:{BufferBottlePressure}][仪器温度1:{Temperature1}][仪器温度2:{Temperature2}]", LogEnum.HouseInfo);
  145. if (BufferBottlePressure < tl_Setting.bufferBottlerPressureMin)
  146. {
  147. ValveState = State.待补气;
  148. }
  149. else
  150. {
  151. ValveState = State.正常;
  152. }
  153. if (BufferBottlePressure < (tl_Setting.bufferBottlerPressureMin + 10))
  154. {
  155. this.RunState = "缓冲瓶补气";
  156. BufferBottleAeration(CommandSource.BufferBottleThread);
  157. }
  158. this.RunState = "气压监测";
  159. Thread.Sleep(1000);
  160. }
  161. catch (Exception ex)
  162. {
  163. ExceptionLogEvent?.Invoke(ex, $"[{House.houseSn}][{PortName}]缓冲瓶气压检测", null, LogEnum.RunException);
  164. }
  165. }
  166. }, TaskCreationOptions.LongRunning);
  167. }
  168. /// <summary>
  169. /// 缓冲瓶补气流程
  170. /// </summary>
  171. public void BufferBottleAeration(CommandSource commandSource)
  172. {
  173. try
  174. {
  175. Stopwatch AerationStopwatch = Stopwatch.StartNew();
  176. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}][补气开始时间:{DateTime.Now}]", LogEnum.HouseInfo);
  177. var custom = new CustomProtocol();
  178. custom.commandSource = commandSource;
  179. decimal oldPressure = 0;
  180. ValveState = State.补气;
  181. for (int i = 1; i <= tl_Setting.bufferBottlerAerationNum; i++)
  182. {
  183. if (BufferBottlePressure >= (tl_Setting.bufferBottlerPressureMin + 10))
  184. {
  185. break;
  186. }
  187. oldPressure = BufferBottlePressure;
  188. ComBin.BufferBottleAerationWait(custom);
  189. Thread.Sleep(tl_Setting.aerationDelay * 1000);
  190. var a = ComBin.BufferBottleState(custom);
  191. BufferBottlePressure = a.Item1;
  192. Temperature1 = a.Item2;
  193. Temperature2 = a.Item3;
  194. HouseLogEvent?.Invoke(11, DateTime.Now, $"补气完成[{oldPressure}->{BufferBottlePressure}]", LogEnum.HouseInfo);
  195. }
  196. if (BufferBottlePressure < tl_Setting.bufferBottlerPressureMin)
  197. {
  198. ValveState = State.待补气;
  199. }
  200. else
  201. {
  202. ValveState = State.正常;
  203. }
  204. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}][补气结束时间:{DateTime.Now}][耗时:{StringHelper.TimeToString(AerationStopwatch.Elapsed)}]", LogEnum.HouseInfo);
  205. AerationStopwatch.Stop();
  206. }
  207. catch (Exception ex)
  208. {
  209. ExceptionLogEvent?.Invoke(ex, $"[{House.houseSn}][{PortName}]缓冲瓶补气", null, LogEnum.RunException);
  210. }
  211. }
  212. private object OpenHouseIdsLock = new object();
  213. public List<int> OpenHouseIds = new List<int>();
  214. List<HouseBin> HuanQiBinList = new List<HouseBin>();
  215. public bool IntakeState = false;
  216. /// <summary>
  217. /// 开始换气
  218. /// </summary>
  219. public bool StartAirSwap { get; set; } = false;
  220. /// <summary>
  221. /// 是否准备好开始操作进气阀
  222. /// </summary>
  223. private bool IsStartAirSwap { get; set; } = false;
  224. /// <summary>
  225. /// 舱室请求打开缓冲瓶进气阀
  226. /// </summary>
  227. /// <param name="houseid"></param>
  228. public void OpenIntakeValve(int houseid)
  229. {
  230. lock (OpenHouseIdsLock)
  231. {
  232. if (!OpenHouseIds.Contains(houseid))
  233. {
  234. OpenHouseIds.Add(houseid);
  235. }
  236. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}]{houseid}舱室请求打开缓冲瓶进气阀,当前状态:{IntakeState},当前换气:{string.Join(";", OpenHouseIds)}]", LogEnum.HouseInfo);
  237. if (IntakeState)
  238. {
  239. return;
  240. }
  241. else
  242. {
  243. StartAirSwap = true;
  244. while (true)
  245. {
  246. if (IsStartAirSwap)
  247. {
  248. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}]{houseid}号舱室请求打开缓冲瓶进气阀指令已发送", LogEnum.HouseInfo);
  249. OpenIntakeValve();
  250. return;
  251. }
  252. else
  253. {
  254. Thread.Sleep(1000);
  255. }
  256. }
  257. }
  258. }
  259. }
  260. private void OpenIntakeValve()
  261. {
  262. var custom = new CustomProtocol();
  263. custom.commandSource = CommandSource.BufferBottleThread;
  264. if (ComBin.OpenIntakeValveWait(custom, tl_Setting.valueDelay)) IntakeState = true;
  265. }
  266. /// <summary>
  267. /// 舱室请求关闭缓冲瓶进气阀
  268. /// </summary>
  269. /// <param name="houseid"></param>
  270. public void CloseIntakeValve(int houseid)
  271. {
  272. lock (OpenHouseIdsLock)
  273. {
  274. if (OpenHouseIds.Contains(houseid))
  275. {
  276. OpenHouseIds.Remove(houseid);
  277. }
  278. int count = OpenHouseIds.Count;
  279. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}]{houseid}舱室请求关闭缓冲瓶进气阀,当前状态:{IntakeState},数量:{count};当前换气:{string.Join(";", OpenHouseIds)}]", LogEnum.HouseInfo);
  280. if (IntakeState)
  281. {
  282. if (count == 0)
  283. {
  284. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}]{houseid}号舱室请求关闭缓冲瓶进气阀指令已发送]", LogEnum.HouseInfo);
  285. CloseIntakeValve();
  286. }
  287. }
  288. }
  289. }
  290. private void CloseIntakeValve()
  291. {
  292. var custom = new CustomProtocol();
  293. custom.commandSource = CommandSource.BufferBottleThread;
  294. if (ComBin.CloseIntakeValveWait(custom, tl_Setting.valueDelay))
  295. {
  296. if (guanbiTime > 0) Thread.Sleep(guanbiTime);
  297. IntakeState = false;
  298. StartAirSwap = false;
  299. }
  300. }
  301. public void HuanQiStart(HouseBin houseId)
  302. {
  303. try
  304. {
  305. lock (OpenHouseIdsLock)
  306. {
  307. houseId.StopPai = false;
  308. if (!HuanQiBinList.Contains(houseId))
  309. {
  310. HuanQiBinList.Add(houseId);
  311. }
  312. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{houseId.House.houseSn}号舱室加入队列],当前队列:{string.Join("、", HuanQiBinList.Select(x => x.House.houseSn))}", LogEnum.HouseInfo);
  313. if (HuanQiBinList.Count <= 1)
  314. {
  315. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[新舱室排队进入换气队列,缓冲瓶开始换气逻辑]", LogEnum.HouseInfo);
  316. HuanQiThread();
  317. }
  318. }
  319. return;
  320. }
  321. catch (Exception ex)
  322. {
  323. ExceptionLogEvent?.Invoke(ex, $"[{House.houseSn}][{PortName}]HuanQiStart", null, LogEnum.RunException);
  324. }
  325. }
  326. public void HuanQiEnd(HouseBin houseId)
  327. {
  328. try
  329. {
  330. lock (OpenHouseIdsLock)
  331. {
  332. if (HuanQiBinList.Contains(houseId))
  333. {
  334. HuanQiBinList.Remove(houseId);
  335. }
  336. houseId.StopPai = true;
  337. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{houseId.House.houseSn}号舱室退出队列],当前队列:{string.Join("、", HuanQiBinList.Select(x => x.House.houseSn))}", LogEnum.HouseInfo);
  338. }
  339. return;
  340. }
  341. catch (Exception ex)
  342. {
  343. ExceptionLogEvent?.Invoke(ex, $"[{House.houseSn}][{PortName}]HuanQiEnd", null, LogEnum.RunException);
  344. }
  345. }
  346. public void HuanQiThread()
  347. {
  348. Task.Run(async () =>
  349. {
  350. HouseBin currentHouseBin = null;
  351. while (true)
  352. {
  353. try
  354. {
  355. currentHouseBin = null;
  356. lock (OpenHouseIdsLock)
  357. {
  358. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"换气队列:{string.Join("、", HuanQiBinList.Select(x => x.House.houseSn))}", LogEnum.HouseInfo);
  359. if (!HuanQiBinList.Any())
  360. {
  361. return;
  362. }
  363. currentHouseBin = HuanQiBinList.First();
  364. }
  365. if (currentHouseBin == null) continue;
  366. if (!HouseIs(currentHouseBin)) continue;
  367. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{currentHouseBin.House.houseSn}号舱室开始换气,等待舱室准备完成]", LogEnum.HouseInfo);
  368. currentHouseBin.QueueAir = true;
  369. while (!currentHouseBin.ReadyAir)
  370. {
  371. if (!HouseIs(currentHouseBin)) break;
  372. Thread.Sleep(500);
  373. }
  374. if (!HouseIs(currentHouseBin)) continue;
  375. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{currentHouseBin.House.houseSn}号舱室准备完成,缓冲瓶进气阀状态:{IntakeState}]", LogEnum.HouseInfo);
  376. if (!IntakeState)
  377. {
  378. StartAirSwap = true;
  379. while (true)
  380. {
  381. if (IsStartAirSwap)
  382. {
  383. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{currentHouseBin.House.houseSn}号舱室]缓冲瓶进气阀打开指令发送", LogEnum.HouseInfo);
  384. OpenIntakeValve();
  385. break;
  386. }
  387. else
  388. {
  389. Thread.Sleep(1000);
  390. }
  391. }
  392. }
  393. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{currentHouseBin.House.houseSn}号舱室,缓冲瓶进气阀状态:{IntakeState},通知舱室缓冲瓶进气阀已打开,并等待舱室冲刷]", LogEnum.HouseInfo);
  394. currentHouseBin.OpenBuffer = true;
  395. while (currentHouseBin.ReadyAir)
  396. {
  397. Thread.Sleep(500);
  398. }
  399. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{currentHouseBin.House.houseSn}号舱室冲刷完成,检查是否关闭进气阀:{IntakeState}]", LogEnum.HouseInfo);
  400. lock (OpenHouseIdsLock)
  401. {
  402. if (HuanQiBinList.Any())
  403. {
  404. HuanQiBinList.RemoveAt(0);
  405. if (!HuanQiBinList.Any() && IntakeState)
  406. {
  407. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{currentHouseBin.House.houseSn}号舱室]关闭缓冲瓶进气阀指令发送]", LogEnum.HouseInfo);
  408. CloseIntakeValve();
  409. }
  410. }
  411. currentHouseBin.EndAir = true;
  412. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{currentHouseBin.House.houseSn}号舱室缓冲瓶相关操作完成,开始下一个舱室,缓冲瓶进气阀状态:{IntakeState},通知舱室缓冲瓶进气阀操作完成]", LogEnum.HouseInfo);
  413. if (!HuanQiBinList.Any())
  414. {
  415. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[当前换气队列清空,缓冲瓶退出换气逻辑]", LogEnum.HouseInfo);
  416. return;
  417. }
  418. }
  419. }
  420. catch (Exception ex)
  421. {
  422. ExceptionLogEvent?.Invoke(ex, $"[{House.houseSn}][{PortName}]缓冲瓶换气", null, LogEnum.RunException);
  423. }
  424. }
  425. });
  426. }
  427. /// <summary>
  428. /// ture继续 false结束
  429. /// </summary>
  430. /// <param name="currentHouseBin"></param>
  431. /// <returns></returns>
  432. public bool HouseIs(HouseBin currentHouseBin)
  433. {
  434. if (currentHouseBin.StopPai)
  435. {
  436. HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[检测到{currentHouseBin.House.houseSn}号舱室退出换气,缓冲瓶结束当前舱室换气]", LogEnum.HouseInfo);
  437. return false;
  438. }
  439. return true;
  440. }
  441. }
  442. }