ReservoirDevice.cs 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279
  1. using Aitex.Core.RT.DataCenter;
  2. using Aitex.Core.RT.Device;
  3. using Aitex.Core.RT.Log;
  4. using Aitex.Core.RT.OperationCenter;
  5. using Aitex.Core.RT.RecipeCenter;
  6. using Aitex.Core.RT.SCCore;
  7. using Aitex.Core.Util;
  8. using MECF.Framework.Common.Alarm;
  9. using MECF.Framework.Common.Algorithm;
  10. using MECF.Framework.Common.Beckhoff.ModuleIO;
  11. using MECF.Framework.Common.CommonData.Prewet;
  12. using MECF.Framework.Common.CommonData.Reservoir;
  13. using MECF.Framework.Common.IOCore;
  14. using MECF.Framework.Common.Persistent.Reservoirs;
  15. using MECF.Framework.Common.RecipeCenter;
  16. using MECF.Framework.Common.ToolLayout;
  17. using MECF.Framework.Common.TwinCat;
  18. using MECF.Framework.Common.Utilities;
  19. using PunkHPX8_Core;
  20. using PunkHPX8_RT.Devices.Facilities;
  21. using PunkHPX8_RT.Devices.Safety;
  22. using PunkHPX8_RT.Devices.Temperature;
  23. using PunkHPX8_RT.Modules;
  24. using PunkHPX8_RT.Modules.Reservoir;
  25. using System;
  26. using System.Collections.Generic;
  27. using System.Linq;
  28. using System.Reflection;
  29. using System.ServiceModel.Security;
  30. using System.Text;
  31. using System.Threading.Tasks;
  32. namespace PunkHPX8_RT.Devices.Reservoir
  33. {
  34. public class ReservoirDevice : BaseDevice, IDevice
  35. {
  36. protected enum DiReplenOperation
  37. {
  38. None,
  39. ManualANDiReplen,
  40. ManualCADiReplen,
  41. AutoANDiReplen,
  42. AutoCADiReplen
  43. }
  44. #region 常量
  45. protected const string AUTO = "Auto";
  46. protected const string MANUAL = "Manual";
  47. protected const string DISABLE = "Disable";
  48. protected const string CA_PUMP_RUNNING="CaPumpRunning";
  49. protected const string AN_TOWER_HIGH="AnTowerHigh";
  50. protected const string AN_TOWER_LOW="AnTowerLow";
  51. protected const string CA_LEVEL="CaLevel";
  52. protected const string CA_WATER_LEVEL="CaWaterLevel";
  53. protected const string AN_FLOW="AnFlow";
  54. protected const string AN_PUMP_ENABLE="AnPumpEnable";
  55. protected const string AN_PUMP_SPEED="AnPumpSpeed";
  56. protected const string CA_FLOW="CaFlow";
  57. protected const string CA_PUMP_ENABLE="CaPumpEnable";
  58. protected const string CA_PUMP_SPEED="CaPumpSpeed";
  59. protected const string RETURN_VALVE_OPENING="ReturnValveOpening";
  60. protected const string RETURN_VALVE= "ReturnValveEnable";
  61. protected const string RETURN_VALVE_PERCENT="ReturnValvePercent";
  62. protected const string CA_DI_REPLEN="CaDiReplen";
  63. protected const string AN_DI_REPLEN="AnDiReplen";
  64. protected const string SAMPLE_OUT="SampleOut";
  65. protected const string DEGAS_ENABLE="DegasEnable";
  66. protected const string CA_ISOLATION="CaIsolation";
  67. protected const string AN_ISOLATION="AnIsolation";
  68. protected const string HED_FLOW="HedFlow";
  69. protected const string HED_FLOW_ENABLE="HedFlowEnable";
  70. protected const string PH_FLOW_VALVE="PhFlowValve";
  71. protected const string PH_VALUE="PhValue";
  72. #endregion
  73. #region 内部变量
  74. /// <summary>
  75. /// 变量是否初始化字典
  76. /// </summary>
  77. private Dictionary<string, bool> _variableInitializeDic = new Dictionary<string, bool>();
  78. /// <summary>
  79. /// 定时器
  80. /// </summary>
  81. private PeriodicJob _periodicJob;
  82. /// <summary>
  83. /// 阴极Pump速度
  84. /// </summary>
  85. private double _caPumpSpeed = 0;
  86. /// <summary>
  87. /// Return Valve比例
  88. /// </summary>
  89. private double _returnValvePercent = 0.5;
  90. /// <summary>
  91. /// CA Level取样平均值
  92. /// </summary>
  93. private double _avgCALevel;
  94. /// <summary>
  95. /// CA Level取样队列
  96. /// </summary>
  97. private Queue<double> _CALevelSamples;
  98. /// <summary>
  99. /// CA level计算平均值取样数
  100. /// </summary>
  101. private int _levelSampleCount;
  102. /// <summary>
  103. /// Recipe
  104. /// </summary>
  105. private ResRecipe _resRecipe;
  106. /// <summary>
  107. /// 累计补水是否超时
  108. /// </summary>
  109. private bool _isDIReplenMaxTimeOut = false;
  110. /// <summary>
  111. /// 单次补水是否超时
  112. /// </summary>
  113. private bool _isDIReplenPerfillTimeOut = false;
  114. /// <summary>
  115. /// 注水Helper
  116. /// </summary>
  117. private ReservoirDiReplenHelper _direplenHelper;
  118. /// <summary>
  119. /// 上一时刻platingcell的overflow level
  120. /// </summary>
  121. private double _lastOverFlow;
  122. /// <summary>
  123. /// platingcell的overflow status
  124. /// </summary>
  125. private string _overFlowStatus = "Empty";
  126. /// <summary>
  127. /// 当前调节return valve的时间
  128. /// </summary>
  129. private DateTime _adjustReturnvalveStartTime = DateTime.Now;
  130. /// <summary>
  131. /// 首次发现ca flow 满足条件的时间,用于自动打开degas valve
  132. /// </summary>
  133. private DateTime _caFlowOKTime = DateTime.Now;
  134. /// <summary>
  135. /// ca flow 是否首次达到条件
  136. /// </summary>
  137. private bool _isFirstCaFlowOK = false;
  138. #endregion
  139. #region Trigger
  140. /// <summary>
  141. /// Low WaterLevel trigger
  142. /// </summary>
  143. private R_TRIG _caWaterLevelLowerTrigger=new R_TRIG();
  144. /// <summary>
  145. /// High WaterLevel trigger
  146. /// </summary>
  147. private R_TRIG _caWaterLevelHighTrigger = new R_TRIG();
  148. #endregion
  149. #region 共享变量
  150. protected DiReplenOperation _currentDireplenOperation = DiReplenOperation.None;
  151. /// <summary>
  152. /// 手动注水时间(秒)
  153. /// </summary>
  154. protected int _manualReplenSecond = 0;
  155. /// <summary>
  156. /// 数据
  157. /// </summary>
  158. protected ReservoirData _reservoirData = new ReservoirData();
  159. /// <summary>
  160. /// Prewet 持久性数值对象
  161. /// </summary>
  162. protected ReservoirsPersistentValue _persistentValue;
  163. #endregion
  164. #region 属性
  165. /// <summary>
  166. /// 操作模式
  167. /// </summary>
  168. public string OperationMode { get { return _persistentValue.OperatingMode; } }
  169. /// <summary>
  170. /// 工程模式
  171. /// </summary>
  172. public string EngineerMode { get { return _persistentValue.RecipeOperatingMode; } }
  173. /// <summary>
  174. /// 是否自动
  175. /// </summary>
  176. public bool IsAuto { get { return _persistentValue.OperatingMode == AUTO; } }
  177. /// <summary>
  178. /// 数据
  179. /// </summary>
  180. public ReservoirData ReservoirData { get { return _reservoirData; } }
  181. /// <summary>
  182. /// 检验阴极是否highlevel
  183. /// </summary>
  184. public bool IsCAHighLevel { get { return CheckCAHighLevelStatus(); } }
  185. /// <summary>
  186. /// 检验阴极是否lowlevel
  187. /// </summary>
  188. public bool IsCALowLevel { get { return CheckCALowLevelStatus(); } }
  189. /// <summary>
  190. /// 当前Recipe
  191. /// </summary>
  192. public ResRecipe Recipe { get { return _resRecipe; } }
  193. /// <summary>
  194. /// 阴极是否需要补水
  195. /// </summary>
  196. public bool CANeedDiReplen { get { return CheckCANeedDiReplen(); } }
  197. /// <summary>
  198. /// 正在补水
  199. /// </summary>
  200. public bool IsDireplenOn { get { return _reservoirData.AnDiReplen || _reservoirData.CaDiReplen; } }
  201. /// <summary>
  202. /// 单次补水是否超时
  203. /// </summary>
  204. public bool IsDIReplenPerfillTimeOut { get { return _isDIReplenPerfillTimeOut; } }
  205. /// <summary>
  206. /// 累计补水是否超时
  207. /// </summary>
  208. public bool IsDIReplenMaxTimeOut { get { return _isDIReplenMaxTimeOut; } }
  209. /// <summary>
  210. /// 是否启动retrun valve自动调节开闭
  211. /// </summary>
  212. public bool IsStartAutoReturnValve { get; set; }
  213. #endregion
  214. /// <summary>
  215. /// 构造函数
  216. /// </summary>
  217. /// <param name="moduleName"></param>
  218. /// <param name="name"></param>
  219. public ReservoirDevice(string moduleName) : base(moduleName, moduleName, moduleName, moduleName)
  220. {
  221. _levelSampleCount = SC.GetValue<int>("Reservoir.LevelAvgSamples");
  222. _levelSampleCount = _levelSampleCount == 0 ? 20 : _levelSampleCount;
  223. _CALevelSamples = new Queue<double>(_levelSampleCount);
  224. }
  225. /// <summary>
  226. /// 初始化
  227. /// </summary>
  228. /// <returns></returns>
  229. public bool Initialize()
  230. {
  231. InitializeParameter();
  232. InitializeRoutine();
  233. SubscribeData();
  234. InitializeOperation();
  235. SubscribeValueAction();
  236. _periodicJob = new PeriodicJob(200, OnTimer, $"{Module}.Timer", true, true);
  237. return true;
  238. }
  239. /// <summary>
  240. /// 初始化参数
  241. /// </summary>
  242. private void InitializeParameter()
  243. {
  244. _persistentValue = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(Module.ToString());
  245. if (_persistentValue == null)
  246. {
  247. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module.ToString(), "Persistent Value Object is not exist");
  248. }
  249. if (!string.IsNullOrEmpty(_persistentValue.Recipe))
  250. {
  251. _resRecipe = RecipeFileManager.Instance.LoadGenericityRecipe<ResRecipe>(_persistentValue.Recipe);
  252. }
  253. _direplenHelper = new ReservoirDiReplenHelper(Module, _persistentValue);
  254. }
  255. /// <summary>
  256. /// 初始化Routine
  257. /// </summary>
  258. private void InitializeRoutine()
  259. {
  260. }
  261. /// <summary>
  262. /// 订阅数据
  263. /// </summary>
  264. private void SubscribeData()
  265. {
  266. DATA.Subscribe($"{Module}.ReservoirData", () => _reservoirData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  267. DATA.Subscribe($"{Module}.PersistentValue", () => _persistentValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  268. DATA.Subscribe($"{Module}.CurrentRecipe", () => _resRecipe, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  269. DATA.Subscribe($"{Module}.IsCAHighLevel", () => IsCAHighLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  270. DATA.Subscribe($"{Module}.IsCALowLevel", () => IsCALowLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  271. DATA.Subscribe($"{Module}.AvgCALevel", () => _avgCALevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  272. DATA.Subscribe($"{Module}.DIValveMaxOnTime", () => SC.GetValue<double>($"Reservoir.{Module}.DIValveMaxOnTime") * 60, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  273. DATA.Subscribe($"{Module}.IsManualCAReplen", () => { return _currentDireplenOperation == DiReplenOperation.ManualCADiReplen; }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  274. DATA.Subscribe($"{Module}.IsDIReplenPerfillTimeOut", () => _isDIReplenPerfillTimeOut, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  275. DATA.Subscribe($"{Module}.IsDIReplenMaxTimeOut", () => _isDIReplenMaxTimeOut, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  276. }
  277. /// <summary>
  278. /// 初始化Operation
  279. /// </summary>
  280. protected virtual void InitializeOperation()
  281. {
  282. OP.Subscribe($"{Module}.DisabledAction", DisabledOperation);
  283. OP.Subscribe($"{Module}.ManualAction", ManualOperation);
  284. OP.Subscribe($"{Module}.AutoAction", AutoOperation);
  285. OP.Subscribe($"{Module}.EngineeringModeAction", EngineeringModeOperation);
  286. OP.Subscribe($"{Module}.ProductionModeAction", ProductionModeOperation);
  287. OP.Subscribe($"{Module}.CAPumpEnable", CAPumpOn);
  288. OP.Subscribe($"{Module}.CAPumpSpeed", CAPumpSpeedOperation);
  289. OP.Subscribe($"{Module}.CAPumpDisable", CAPumpOff);
  290. OP.Subscribe($"{Module}.LoadRecipe", LoadRecipeOperation);
  291. OP.Subscribe($"{Module}.ReturnValveOn", ReturnValveOn);
  292. OP.Subscribe($"{Module}.ReturnValveOff", (cmd, para) => { return ReturnValveOff();});
  293. OP.Subscribe($"{Module}.ReturnValvePercent", ReturnValvePercentOperation);
  294. OP.Subscribe($"{Module}.CAIsolationOn", (cmd, para) => { return CAIsolationOn(); });
  295. OP.Subscribe($"{Module}.CAIsolationOff", (cmd, para) => { return CAIsolationOff(); });
  296. OP.Subscribe($"{Module}.SampleOutValveOn", (cmd, para) => { return SampleOutValveOn(); });
  297. OP.Subscribe($"{Module}.SampleOutValveOff", (cmd, para) => { return SampleOutValveOff(); });
  298. OP.Subscribe($"{Module}.DegasValveOn", (cmd, para) => { return DegasValveOn(); });
  299. OP.Subscribe($"{Module}.DegasValveOff", (cmd, para) => { return DegasValveOff(); });
  300. OP.Subscribe($"{Module}.PhValveOn", (cmd, para) => { return PhValveOn(); });
  301. OP.Subscribe($"{Module}.PhValveOff", (cmd, para) => { return PhValveOff(); });
  302. OP.Subscribe($"{Module}.HedValveOn", (cmd, para) => { return HedValveOn(); });
  303. OP.Subscribe($"{Module}.HedValveOff", (cmd, para) => { return HedValveOff(); });
  304. OP.Subscribe($"{Module}.ResetTotalTime", ResetTotalTime);
  305. OP.Subscribe($"{Module}.ManualCADiReplen", ManualCADiReplen);
  306. }
  307. /// <summary>
  308. /// 订阅变量数值发生变化
  309. /// </summary>
  310. protected virtual void SubscribeValueAction()
  311. {
  312. IoSubscribeUpdateVariable(CA_PUMP_RUNNING);
  313. IoSubscribeUpdateVariable(AN_TOWER_HIGH);
  314. IoSubscribeUpdateVariable(AN_TOWER_LOW);
  315. IoSubscribeUpdateVariable(CA_LEVEL);
  316. IoSubscribeUpdateVariable(CA_WATER_LEVEL);
  317. IoSubscribeUpdateVariable(CA_PUMP_ENABLE);
  318. IoSubscribeUpdateVariable(CA_PUMP_SPEED);
  319. IoSubscribeUpdateVariable(CA_DI_REPLEN);
  320. IoSubscribeUpdateVariable(RETURN_VALVE);
  321. IoSubscribeUpdateVariable(RETURN_VALVE_OPENING);
  322. IoSubscribeUpdateVariable(RETURN_VALVE_PERCENT);
  323. IoSubscribeUpdateVariable(SAMPLE_OUT);
  324. IoSubscribeUpdateVariable(CA_ISOLATION);
  325. IoSubscribeUpdateVariable(AN_ISOLATION);
  326. IoSubscribeUpdateVariable(DEGAS_ENABLE);
  327. IoSubscribeUpdateVariable(CA_FLOW);
  328. }
  329. /// <summary>
  330. /// 订阅IO变量
  331. /// </summary>
  332. /// <param name="variable"></param>
  333. protected void IoSubscribeUpdateVariable(string variable)
  334. {
  335. _variableInitializeDic[variable] = false;
  336. IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue);
  337. }
  338. /// <summary>
  339. /// 更新变量数值
  340. /// </summary>
  341. /// <param name="variable"></param>
  342. /// <param name="value"></param>
  343. private void UpdateVariableValue(string variable, object value)
  344. {
  345. if (!_reservoirData.IsDataInitialized)
  346. {
  347. _reservoirData.IsDataInitialized = true;
  348. }
  349. PropertyInfo property = _reservoirData.GetType().GetProperty(variable);
  350. if (property != null)
  351. {
  352. property.SetValue(_reservoirData, value);
  353. if (variable == CA_WATER_LEVEL)
  354. {
  355. string caLevelCurve = SC.GetStringValue($"Reservoir.{Module}.CALevelCurve");
  356. ReservoirData.CaLevel = LevelCurveManager.Instance.CalculateLevelByWaterLevel(ReservoirData.CaWaterLevel, caLevelCurve);
  357. }
  358. }
  359. if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
  360. {
  361. _variableInitializeDic[variable] = true;
  362. }
  363. }
  364. /// <summary>
  365. /// 写变量
  366. /// </summary>
  367. /// <param name="variable"></param>
  368. /// <param name="value"></param>
  369. /// <returns></returns>
  370. protected bool WriteVariableValue(string variable, object value)
  371. {
  372. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{variable}");
  373. return IOModuleManager.Instance.WriteIoValue(ioName, value);
  374. }
  375. /// <summary>
  376. /// 定时器
  377. /// </summary>
  378. /// <returns></returns>
  379. protected virtual bool OnTimer()
  380. {
  381. CalculateCALevel();
  382. AdjustPumpSpeed();
  383. WaterLevelMonitor();
  384. DireplenMonitor();
  385. AutoOpenDegasValve();
  386. return true;
  387. }
  388. #region timer
  389. /// <summary>
  390. /// safety和ca flow满足条件,自动打开degas valve
  391. /// </summary>
  392. public void AutoOpenDegasValve()
  393. {
  394. if(ReservoirData.CaFlow >= Recipe.CAFlowSetPoint) //缺了safety的条件,待补充
  395. {
  396. int degasValveOpenIdlePeriod = SC.GetValue<int>($"Reservoir.DegasValveOpenIdlePeriod");
  397. if (!_isFirstCaFlowOK)
  398. {
  399. _isFirstCaFlowOK = true;
  400. _caFlowOKTime = DateTime.Now;
  401. }
  402. else
  403. {
  404. if(DateTime.Now.Subtract(_caFlowOKTime).TotalMinutes >= degasValveOpenIdlePeriod && !ReservoirData.DegasEnable)
  405. {
  406. DegasValveOn();
  407. _caFlowOKTime = DateTime.Now;//开启后重置一下检测到ca flow ok的时间
  408. }
  409. }
  410. }
  411. else
  412. {
  413. _isFirstCaFlowOK = false;
  414. }
  415. }
  416. /// <summary>
  417. /// 自动调节retrun valve 开闭
  418. /// </summary>
  419. public void AdjustPumpSpeed()
  420. {
  421. ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
  422. if (reservoirEntity != null)
  423. {
  424. //retrun valve打开
  425. if (ReservoirData.ReturnValveEnable && (!reservoirEntity.IsInit && !reservoirEntity.IsError))
  426. {
  427. double overflow = new Random().NextDouble() * 6 + 10;//模拟platingcell的液位;
  428. int _overflowLevelDelta = SC.GetValue<int>($"Reservoir.{Module}.OverflowLevelDelta");
  429. int _overflowLevelCheckTime = SC.GetValue<int>($"Reservoir.{Module}.OverflowLevelCheckTime");
  430. int _retrunOpenHoldStep = SC.GetValue<int>($"Reservoir.{Module}.RetrunOpenHoldStep");
  431. int _retrunOpenRampStep = SC.GetValue<int>($"Reservoir.{Module}.RetrunOpenRampStep");
  432. int adjustNumber = "Full".Equals(_overFlowStatus) ? _retrunOpenHoldStep : _retrunOpenRampStep;//判断当前overflow状态
  433. if (overflow > _lastOverFlow)//液位升高的情况
  434. {
  435. if (overflow - _lastOverFlow > _overflowLevelDelta && DateTime.Now.Subtract(_adjustReturnvalveStartTime).TotalMilliseconds > _overflowLevelCheckTime)
  436. {
  437. double percent = ReservoirData.ReturnValveOpening - adjustNumber;
  438. percent = percent >= 0 ? percent : 0;
  439. ReturnValvePercent(percent);
  440. _lastOverFlow = overflow;
  441. _adjustReturnvalveStartTime = DateTime.Now;
  442. }
  443. }
  444. else
  445. {
  446. if (_lastOverFlow - overflow > _overflowLevelDelta && DateTime.Now.Subtract(_adjustReturnvalveStartTime).TotalMilliseconds > _overflowLevelCheckTime)
  447. {
  448. double percent = ReservoirData.ReturnValveOpening + adjustNumber;
  449. ReturnValvePercent(percent);
  450. _lastOverFlow = overflow;
  451. _adjustReturnvalveStartTime = DateTime.Now;
  452. }
  453. }
  454. }
  455. }
  456. }
  457. /// <summary>
  458. /// 计算CA
  459. /// </summary>
  460. private void CalculateCALevel()
  461. {
  462. if (ReservoirData != null)
  463. {
  464. if (_CALevelSamples.Count >= _levelSampleCount)
  465. {
  466. _CALevelSamples.Dequeue();
  467. _CALevelSamples.Enqueue(ReservoirData.CaLevel);
  468. }
  469. else
  470. {
  471. _CALevelSamples.Enqueue(ReservoirData.CaLevel);
  472. }
  473. _avgCALevel = _CALevelSamples.Count > 0 ? _CALevelSamples.Average() : 0;
  474. }
  475. }
  476. /// <summary>
  477. /// WaterLevel监控
  478. /// </summary>
  479. protected virtual void WaterLevelMonitor()
  480. {
  481. _caWaterLevelLowerTrigger.CLK = IsCALowLevel;
  482. if (_caWaterLevelLowerTrigger.Q)
  483. {
  484. ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
  485. string reason = $"Current CAWaterlevel:{ReservoirData.CaWaterLevel} is lower than CALowLevel Config:{SC.GetValue<double>($"Reservoir.{Module}.CALowLevel")}";
  486. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, reason);
  487. CALowLevelOperation();
  488. if (reservoirEntity.IsAuto && !AlarmListManager.Instance.IsContainDataError(Module, "CAWaterLevel"))
  489. {
  490. AlarmListManager.Instance.AddDataError(Module,
  491. $"CAWaterLevel", $"Current CAWaterlevel:{ReservoirData.CaWaterLevel} is lower than CALowLevel Config:{SC.GetValue<double>($"Reservoir.{Module}.CALowLevel")}");
  492. }
  493. if (!reservoirEntity.IsError) reservoirEntity.PostMsg(ReservoirMsg.Error);
  494. }
  495. _caWaterLevelHighTrigger.CLK = IsCAHighLevel;
  496. if (_caWaterLevelHighTrigger.Q)
  497. {
  498. HighLevelOperation();
  499. }
  500. }
  501. /// <summary>
  502. /// CA Low Level触发对应操作
  503. /// </summary>
  504. private void CALowLevelOperation()
  505. {
  506. ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module);
  507. if (_reservoirData.CaPumpEnable)
  508. {
  509. CAPumpOff("", null);
  510. }
  511. if (_reservoirData.CaIsolation)// 不确定是否是关闭cell flow
  512. {
  513. CAIsolationOff();
  514. }
  515. //禁用TC
  516. if (!string.IsNullOrEmpty(reservoirItem.TCID))
  517. {
  518. TemperatureController temperatureController = DEVICE.GetDevice<TemperatureController>(reservoirItem.TCID);
  519. if (temperatureController != null && temperatureController.TemperatureData.ControlOperationModel == (int)TemperatureEnumData.ENABLE)
  520. {
  521. temperatureController.DisableOperation("", null);
  522. }
  523. }
  524. ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
  525. if (!reservoirEntity.IsError) reservoirEntity.PostMsg(ReservoirMsg.Error);
  526. }
  527. /// <summary>
  528. /// High Level Common Operation
  529. /// </summary>
  530. private void HighLevelOperation()
  531. {
  532. ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
  533. SystemFacilities systemFacilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
  534. if (systemFacilities != null)
  535. {
  536. if (systemFacilities.DIFillEnable) systemFacilities.DiFillDisableOperation("DIFillDisableOpeartion", null);
  537. if (systemFacilities.DIReplenEnable) systemFacilities.DiReplenDisableOperation("DiReplenDisableOperation", null);
  538. if (_reservoirData.CaDiReplen)
  539. {
  540. _currentDireplenOperation = DiReplenOperation.None;
  541. CADiReplenOff("", null);
  542. }
  543. }
  544. if (!reservoirEntity.IsError) reservoirEntity.PostMsg(ReservoirMsg.Error);
  545. if (reservoirEntity.IsAuto && !AlarmListManager.Instance.IsContainDataError(Module, "CAWaterLevel"))
  546. {
  547. AlarmListManager.Instance.AddDataError(Module,
  548. $"CAWaterLevel", $"Current CAWaterlevel:{ReservoirData.CaWaterLevel} is large than CAHighLevel Config:{SC.GetValue<double>($"Reservoir.{Module}.CAHighLevel")}");
  549. }
  550. }
  551. /// <summary>
  552. /// Direplen监控
  553. /// </summary>
  554. private void DireplenMonitor()
  555. {
  556. var facilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
  557. //补水监控
  558. if (_direplenHelper != null)
  559. {
  560. _direplenHelper.MonitorPeriodTime(ref _isDIReplenMaxTimeOut);
  561. if (!_isDIReplenMaxTimeOut && !_isDIReplenPerfillTimeOut && facilities.DIFillEnable)
  562. {
  563. AutoDireplenMonitor();
  564. }
  565. }
  566. }
  567. /// <summary>
  568. /// 自动补水
  569. /// </summary>
  570. protected virtual void AutoDireplenMonitor()
  571. {
  572. if (_currentDireplenOperation == DiReplenOperation.ManualCADiReplen)
  573. {
  574. bool result = _direplenHelper.MonitorManualDiReplenComplete(_manualReplenSecond, CADiReplenOff, ref _isDIReplenMaxTimeOut);
  575. if (result)
  576. {
  577. _currentDireplenOperation = DiReplenOperation.None;
  578. }
  579. }
  580. if (_currentDireplenOperation == DiReplenOperation.ManualANDiReplen)
  581. {
  582. //bool result = _direplenHelper.MonitorManualDiReplenComplete(_manualReplenSecond, ANDiReplenOff, ref _isDIReplenMaxTimeOut);
  583. //if (result)
  584. //{
  585. // _currentDireplenOperation = DiReplenOperation.None;
  586. //}
  587. }
  588. if (_currentDireplenOperation == DiReplenOperation.AutoCADiReplen)
  589. {
  590. AutoDiReplenMonitor(CADiReplenOff, _reservoirData.CaLevel, _resRecipe.ReservoirCALevel, _resRecipe.DIReplenEnable,
  591. _resRecipe.DIReplenTimeRate, _resRecipe.DIReplenCurrentRate);
  592. }
  593. //阳极没有水位,自动补水监控逻辑待修正
  594. if (_currentDireplenOperation == DiReplenOperation.AutoANDiReplen)
  595. {
  596. }
  597. }
  598. /// <summary>
  599. /// 自动注水监控
  600. /// </summary>
  601. /// <param name="direplenOff"></param>
  602. /// <param name="level"></param>
  603. /// <param name="recipeLevel"></param>
  604. private void AutoDiReplenMonitor(Func<string, object[], bool> direplenOff, double level, double recipeLevel, bool replenEnable,
  605. int direplenTimeRate, int direplenCurrentRate)
  606. {
  607. //判断是否注水超时(包括单次和累计)
  608. bool result = _direplenHelper.AutoDiReplenMonitorTimeOut(direplenOff, ref _isDIReplenMaxTimeOut, ref _isDIReplenPerfillTimeOut);
  609. if (result)
  610. {
  611. _currentDireplenOperation = DiReplenOperation.None;
  612. }
  613. else
  614. {
  615. //按液位补水
  616. result = _direplenHelper.AutoDiReplenMonitorComplete(level, recipeLevel, replenEnable, direplenTimeRate, direplenCurrentRate, direplenOff);
  617. if (result)
  618. {
  619. _currentDireplenOperation = DiReplenOperation.None;
  620. }
  621. }
  622. }
  623. #endregion
  624. #region Mode switch
  625. /// <summary>
  626. /// DisabledAction
  627. /// </summary>
  628. /// <param name="cmd"></param>
  629. /// <param name="param"></param>
  630. /// <returns></returns>
  631. private bool DisabledOperation(string cmd, object[] args)
  632. {
  633. string currentOperation = "Disabled";
  634. string preOperation = _persistentValue.OperatingMode;
  635. _persistentValue.OperatingMode = currentOperation;
  636. LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
  637. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  638. return true;
  639. }
  640. /// <summary>
  641. /// ManualAction
  642. /// </summary>
  643. /// <param name="cmd"></param>
  644. /// <param name="param"></param>
  645. /// <returns></returns>
  646. private bool ManualOperation(string cmd, object[] args)
  647. {
  648. string currentOperation = "Manual";
  649. string preOperation = _persistentValue.OperatingMode;
  650. _persistentValue.OperatingMode = currentOperation;
  651. LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
  652. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  653. return true;
  654. }
  655. /// <summary>
  656. /// AutoAction
  657. /// </summary>
  658. /// <param name="cmd"></param>
  659. /// <param name="param"></param>
  660. /// <returns></returns>
  661. private bool AutoOperation(string cmd, object[] args)
  662. {
  663. string currentOperation = "Auto";
  664. string preOperation = _persistentValue.OperatingMode;
  665. _persistentValue.OperatingMode = currentOperation;
  666. LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
  667. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  668. return true;
  669. }
  670. /// <summary>
  671. /// EngineeringModeAction
  672. /// </summary>
  673. /// <param name="cmd"></param>
  674. /// <param name="param"></param>
  675. /// <returns></returns>
  676. private bool EngineeringModeOperation(string cmd, object[] args)
  677. {
  678. string currentRecipeOperation = "Engineering";
  679. if (_persistentValue != null)
  680. {
  681. _persistentValue.RecipeOperatingMode = currentRecipeOperation;
  682. }
  683. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  684. return true;
  685. }
  686. /// <summary>
  687. /// ProductionAction
  688. /// </summary>
  689. /// <param name="cmd"></param>
  690. /// <param name="param"></param>
  691. /// <returns></returns>
  692. private bool ProductionModeOperation(string cmd, object[] args)
  693. {
  694. string currentRecipeOperation = "Production";
  695. if (_persistentValue != null)
  696. {
  697. _persistentValue.RecipeOperatingMode = currentRecipeOperation;
  698. }
  699. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  700. return true;
  701. }
  702. #endregion
  703. /// <summary>
  704. /// 加载Recipe
  705. /// </summary>
  706. /// <param name="cmd"></param>
  707. /// <param name="args"></param>
  708. /// <returns></returns>
  709. private bool LoadRecipeOperation(string cmd, object[] args)
  710. {
  711. _persistentValue.Recipe = args[0].ToString();
  712. string[] fileRoute = _persistentValue.Recipe.Split('\\');
  713. string recipeRoute = "";
  714. if (fileRoute.Length > 2)
  715. {
  716. recipeRoute = fileRoute[fileRoute.Length - 2];
  717. }
  718. _resRecipe = RecipeFileManager.Instance.LoadGenericityRecipe<ResRecipe>(_persistentValue.Recipe);
  719. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module.ToString());
  720. LOG.WriteLog(eEvent.INFO_RESERVOIR, Module.ToString(), $"Load {recipeRoute} Recipe {_resRecipe.Ppid} Success");
  721. return true;
  722. }
  723. /// <summary>
  724. /// 监控
  725. /// </summary>
  726. public void Monitor()
  727. {
  728. }
  729. #region CA Pump
  730. /// <summary>
  731. /// CA Pump调速
  732. /// </summary>
  733. /// <param name="cmd"></param>
  734. /// <param name="args"></param>
  735. /// <returns></returns>
  736. private bool CAPumpSpeedOperation(string cmd, object[] args)
  737. {
  738. double caMaxPumpSpeed = 0;
  739. if (SC.ContainsItem("Reservoir.CAMaxPumpSpeed"))
  740. {
  741. caMaxPumpSpeed = SC.GetValue<double>("Reservoir.CAMaxPumpSpeed");
  742. }
  743. if (double.TryParse(args[0].ToString(), out double speed))
  744. {
  745. _caPumpSpeed = speed;
  746. if (_caPumpSpeed > caMaxPumpSpeed)
  747. {
  748. LOG.WriteLog(eEvent.WARN_METAL, Module, $"CA pump speed:{_caPumpSpeed} is over CA max pump speed {caMaxPumpSpeed}!");
  749. return false;
  750. }
  751. return CAPumpSpeed(_caPumpSpeed);
  752. }
  753. else
  754. {
  755. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{args[0]} is nor invalid speed");
  756. return false;
  757. }
  758. }
  759. /// <summary>
  760. /// 设置阴极泵速
  761. /// </summary>
  762. /// <param name="caPumpSpeed"></param>
  763. /// <returns></returns>
  764. public bool CAPumpSpeed(double caPumpSpeed)
  765. {
  766. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_PUMP_SPEED}");
  767. return BeckhoffIOManager.Instance.WriteIoValue(ioName, caPumpSpeed);
  768. }
  769. /// <summary>
  770. /// 阴极Pump On
  771. /// </summary>
  772. /// <param name="cmd"></param>
  773. /// <param name="args"></param>
  774. /// <returns></returns>
  775. private bool CAPumpOn(string cmd, object[] args)
  776. {
  777. double caPumpSpeed = SC.GetValue<double>("Reservoir.CADefaultPumpSpeed");
  778. bool result = CAPumpSpeed(caPumpSpeed);
  779. if (result)
  780. {
  781. string enableIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_PUMP_ENABLE}");
  782. return BeckhoffIOManager.Instance.WriteIoValue(enableIOName, true);
  783. }
  784. else
  785. {
  786. return false;
  787. }
  788. }
  789. /// <summary>
  790. /// 阴极Pump Off
  791. /// </summary>
  792. /// <param name="cmd"></param>
  793. /// <param name="args"></param>
  794. /// <returns></returns>
  795. private bool CAPumpOff(string cmd, object[] args)
  796. {
  797. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_PUMP_ENABLE}");
  798. return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
  799. }
  800. #endregion
  801. #region Return Valve
  802. /// <summary>
  803. /// Return Valve
  804. /// </summary>
  805. /// <param name="cmd"></param>
  806. /// <param name="args"></param>
  807. /// <returns></returns>
  808. private bool ReturnValvePercentOperation(string cmd, object[] args)
  809. {
  810. if (double.TryParse(args[0].ToString(), out double percent))
  811. {
  812. _returnValvePercent = percent;
  813. return ReturnValvePercent(_returnValvePercent);
  814. }
  815. else
  816. {
  817. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{args[0]} is invalid percent");
  818. return false;
  819. }
  820. }
  821. /// <summary>
  822. /// 设置比例
  823. /// </summary>
  824. /// <param name="caPumpSpeed"></param>
  825. /// <returns></returns>
  826. public bool ReturnValvePercent(double percent)
  827. {
  828. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{RETURN_VALVE_OPENING}");
  829. return BeckhoffIOManager.Instance.WriteIoValue(ioName, percent);
  830. }
  831. /// <summary>
  832. /// Return Valve On
  833. /// </summary>
  834. /// <param name="cmd"></param>
  835. /// <param name="args"></param>
  836. /// <returns></returns>
  837. private bool ReturnValveOn(string cmd, object[] args)
  838. {
  839. double percent = SC.GetValue<int>("Reservoir.ReturnOpenDefaultPercentage");
  840. bool result = ReturnValvePercent(percent);
  841. if (result)
  842. {
  843. //string enableIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{RETURN_VALVE}");
  844. //return BeckhoffIOManager.Instance.WriteIoValue(enableIOName, true);
  845. return WriteVariableValue(RETURN_VALVE, true);
  846. }
  847. else
  848. {
  849. return false;
  850. }
  851. }
  852. /// <summary>
  853. /// Return Valve Off
  854. /// </summary>
  855. /// <param name="cmd"></param>
  856. /// <param name="args"></param>
  857. /// <returns></returns>
  858. public bool ReturnValveOff()
  859. {
  860. //string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{RETURN_VALVE}");
  861. //return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
  862. return WriteVariableValue(RETURN_VALVE, false);
  863. }
  864. #endregion
  865. /// <summary>
  866. /// CAIsolationOn
  867. /// </summary>
  868. /// <returns></returns>
  869. public bool CAIsolationOn()
  870. {
  871. return WriteVariableValue(CA_ISOLATION, true);
  872. }
  873. /// <summary>
  874. /// CAIsolationOff
  875. /// </summary>
  876. /// <returns></returns>
  877. public bool CAIsolationOff()
  878. {
  879. return WriteVariableValue(CA_ISOLATION, false);
  880. }
  881. /// <summary>
  882. /// DegasValveOn
  883. /// </summary>
  884. /// <returns></returns>
  885. public bool DegasValveOn()
  886. {
  887. return WriteVariableValue(DEGAS_ENABLE, true);
  888. }
  889. /// <summary>
  890. /// DegasValveOff
  891. /// </summary>
  892. /// <returns></returns>
  893. public bool DegasValveOff()
  894. {
  895. return WriteVariableValue(DEGAS_ENABLE, false);
  896. }
  897. /// <summary>
  898. /// HedValveOn
  899. /// </summary>
  900. /// <returns></returns>
  901. public bool HedValveOn()
  902. {
  903. return WriteVariableValue(HED_FLOW_ENABLE, true);
  904. }
  905. /// <summary>
  906. /// HedValveOff
  907. /// </summary>
  908. /// <returns></returns>
  909. public bool HedValveOff()
  910. {
  911. return WriteVariableValue(HED_FLOW_ENABLE, false);
  912. }
  913. /// <summary>
  914. /// PhValveOn
  915. /// </summary>
  916. /// <returns></returns>
  917. public bool PhValveOn()
  918. {
  919. return WriteVariableValue(PH_FLOW_VALVE, true);
  920. }
  921. /// <summary>
  922. /// PhValveOff
  923. /// </summary>
  924. /// <returns></returns>
  925. public bool PhValveOff()
  926. {
  927. return WriteVariableValue(PH_FLOW_VALVE, false);
  928. }
  929. /// <summary>
  930. /// SampleOutValveOn
  931. /// </summary>
  932. /// <returns></returns>
  933. public bool SampleOutValveOn()
  934. {
  935. return WriteVariableValue(SAMPLE_OUT, true);
  936. }
  937. /// <summary>
  938. /// SampleOutValveOff
  939. /// </summary>
  940. /// <returns></returns>
  941. public bool SampleOutValveOff()
  942. {
  943. return WriteVariableValue(SAMPLE_OUT, false);
  944. }
  945. #region CA DiReplen
  946. /// <summary>
  947. /// 阴极DI Replen On
  948. /// </summary>
  949. /// <param name="cmd"></param>
  950. /// <param name="args"></param>
  951. /// <returns></returns>
  952. private bool CADiReplenOnOperation(string cmd, object[] args)
  953. {
  954. return CADiReplenOn();
  955. }
  956. /// <summary>
  957. /// 阴极DI Replen On
  958. /// </summary>
  959. /// <param name="showError"></param>
  960. /// <returns></returns>
  961. private bool CADiReplenOn()
  962. {
  963. bool preCondition = CheckPreDiReplenCondition();
  964. if (!preCondition)
  965. {
  966. return false;
  967. }
  968. if (IsCAHighLevel)
  969. {
  970. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CAHighLevel is activate,Can't do CA_DIReple");
  971. return false;
  972. }
  973. if (IsCALowLevel)
  974. {
  975. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CALowLevel is activate,Can't do CA_DIReple");
  976. return false;
  977. }
  978. if (ReservoirData.AnDiReplen)
  979. {
  980. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "ANDiReplen is on");
  981. return false;
  982. }
  983. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_DI_REPLEN}");
  984. return BeckhoffIOManager.Instance.WriteIoValue(ioName, true);
  985. }
  986. /// <summary>
  987. /// 阴极DI Replen Off
  988. /// </summary>
  989. /// <param name="cmd"></param>
  990. /// <param name="args"></param>
  991. /// <returns></returns>
  992. private bool CADiReplenOff(string cmd, object[] args)
  993. {
  994. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_DI_REPLEN}");
  995. bool result = BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
  996. if (result)
  997. {
  998. _persistentValue.IsDiReplenOn = false;
  999. if (_currentDireplenOperation == DiReplenOperation.ManualCADiReplen || _currentDireplenOperation == DiReplenOperation.AutoCADiReplen)
  1000. {
  1001. _currentDireplenOperation = DiReplenOperation.None;
  1002. _persistentValue.LastTotalReplen = _persistentValue.TotalReplen;
  1003. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  1004. }
  1005. }
  1006. return result;
  1007. }
  1008. /// <summary>
  1009. /// 检验DiReplen前置条件
  1010. /// </summary>
  1011. /// <returns></returns>
  1012. public bool CheckPreDiReplenCondition()
  1013. {
  1014. if (!CheckFacilitiesDiReplenStatus())
  1015. {
  1016. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Facilities DiReplen is Off, can't start auto diReplen");
  1017. return false;
  1018. }
  1019. SafetyDevice safetyDevice = DEVICE.GetDevice<SafetyDevice>("Safety");
  1020. if (safetyDevice != null && safetyDevice.SafetyData.Reservoir1CALevelHigh)
  1021. {
  1022. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Safety high is Activate, can't start auto diReplen");
  1023. return false;
  1024. }
  1025. if (CheckOtherReservoirDiReplenStatus())
  1026. {
  1027. return false;
  1028. }
  1029. return true;
  1030. }
  1031. /// <summary>
  1032. /// 检验总Di有没有开
  1033. /// </summary>
  1034. /// <returns></returns>
  1035. private bool CheckFacilitiesDiReplenStatus()
  1036. {
  1037. SystemFacilities systemFacilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
  1038. if (systemFacilities != null)
  1039. {
  1040. return systemFacilities.DIReplenEnable;
  1041. }
  1042. return false;
  1043. }
  1044. /// <summary>
  1045. /// 检验是否其他Reservoir Direplen已经
  1046. /// </summary>
  1047. /// <returns></returns>
  1048. protected bool CheckOtherReservoirDiReplenStatus()
  1049. {
  1050. List<string> reservoirs = ReservoirItemManager.Instance.InstalledModules;
  1051. foreach (string item in reservoirs)
  1052. {
  1053. if (item != Module)
  1054. {
  1055. ReservoirDevice tmpDevice = DEVICE.GetDevice<ReservoirDevice>(item);
  1056. if (tmpDevice.ReservoirData.CaDiReplen)
  1057. {
  1058. return true;
  1059. }
  1060. ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(item);
  1061. if (reservoirItem.SubType == ReservoirType.DegasMembrance.ToString())
  1062. {
  1063. if (tmpDevice.ReservoirData.AnDiReplen)
  1064. {
  1065. return true;
  1066. }
  1067. }
  1068. }
  1069. }
  1070. return false;
  1071. }
  1072. #endregion
  1073. #region DiReplen Operation
  1074. /// <summary>
  1075. /// 重置时长
  1076. /// </summary>
  1077. /// <param name="cmd"></param>
  1078. /// <param name="objs"></param>
  1079. /// <returns></returns>
  1080. private bool ResetTotalTime(string cmd, object[] objs)
  1081. {
  1082. _isDIReplenMaxTimeOut = false;
  1083. _isDIReplenPerfillTimeOut = false;
  1084. _persistentValue.TotalReplen = 0;
  1085. _persistentValue.LastTotalReplen = 0;
  1086. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  1087. return true;
  1088. }
  1089. /// <summary>
  1090. /// 手动阴极注水
  1091. /// </summary>
  1092. /// <param name="cmd"></param>
  1093. /// <param name="args"></param>
  1094. /// <returns></returns>
  1095. private bool ManualCADiReplen(string cmd, object[] args)
  1096. {
  1097. return ManualDiReplen(CADiReplenOnOperation, DiReplenOperation.ManualCADiReplen, args[0].ToString());
  1098. }
  1099. /// <summary>
  1100. /// 手动注水
  1101. /// </summary>
  1102. /// <param name="direplenOn"></param>
  1103. /// <param name="direplenOperation"></param>
  1104. /// <returns></returns>
  1105. protected bool ManualDiReplen(Func<string, object[], bool> direplenOn, DiReplenOperation direplenOperation, string timeLength)
  1106. {
  1107. if (_currentDireplenOperation != DiReplenOperation.None)
  1108. {
  1109. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"current operation is {_currentDireplenOperation},cannot execute {direplenOperation}");
  1110. return false;
  1111. }
  1112. ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
  1113. if (!reservoirEntity.IsInitialized)
  1114. {
  1115. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} is not initialized. Can't start DiReplen");
  1116. return false;
  1117. }
  1118. if (_isDIReplenMaxTimeOut)
  1119. {
  1120. double diValveMaxOnTime = SC.GetValue<double>($"Reservoir.{Module}.DIValveMaxOnTime");
  1121. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"Direplen time over conifg's DIValveMaxOnTime:{diValveMaxOnTime} min");
  1122. return false;
  1123. }
  1124. if (_isDIReplenPerfillTimeOut)
  1125. {
  1126. double diValveMaxOnTimePerFill = SC.GetValue<double>($"Reservoir.{Module}.DIValveMaxOnTimePerFill");
  1127. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"Direplen time over conifg's DIValveMaxOnTimePerFill:{diValveMaxOnTimePerFill} min");
  1128. return false;
  1129. }
  1130. bool result = direplenOn("", null);
  1131. if (result)
  1132. {
  1133. _currentDireplenOperation = direplenOperation;
  1134. _persistentValue.DiReplenTime = DateTime.Now;
  1135. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  1136. int.TryParse(timeLength, out _manualReplenSecond);
  1137. }
  1138. return result;
  1139. }
  1140. /// <summary>
  1141. /// 阴极自动流水
  1142. /// </summary>
  1143. /// <returns></returns>
  1144. public bool AutoCADiReplen()
  1145. {
  1146. if (IsCALowLevel)
  1147. {
  1148. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CALowLevel is activate,Can't AutoANDireplen");
  1149. return false;
  1150. }
  1151. return AutoDireplen(CADiReplenOn, DiReplenOperation.AutoCADiReplen);
  1152. }
  1153. /// <summary>
  1154. /// 自动注水
  1155. /// </summary>
  1156. /// <returns></returns>
  1157. protected bool AutoDireplen(Func<bool> direplenOn, DiReplenOperation reservoirOperation)
  1158. {
  1159. if (_currentDireplenOperation != DiReplenOperation.None)
  1160. {
  1161. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"current operation is {_currentDireplenOperation},cannot execute {reservoirOperation}");
  1162. return false;
  1163. }
  1164. if (_resRecipe == null)
  1165. {
  1166. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"recipe is null");
  1167. return false;
  1168. }
  1169. bool result = direplenOn();
  1170. if (result)
  1171. {
  1172. _currentDireplenOperation = reservoirOperation;
  1173. _persistentValue.DiReplenTime = DateTime.Now;
  1174. }
  1175. return result;
  1176. }
  1177. #endregion
  1178. /// <summary>
  1179. /// 检验阴极是否highlevel
  1180. /// </summary>
  1181. public bool CheckCAHighLevelStatus()
  1182. {
  1183. return ReservoirData.CaWaterLevel > SC.GetValue<double>($"Reservoir.{Module}.CAHighLevel") ? true : false;
  1184. }
  1185. /// <summary>
  1186. /// 检验阴极是否lowlevel
  1187. /// </summary>
  1188. public bool CheckCALowLevelStatus()
  1189. {
  1190. return ReservoirData.CaWaterLevel < SC.GetValue<double>($"Reservoir.{Module}.CALowLevel") ? true : false;
  1191. }
  1192. /// <summary>
  1193. /// 检验CA是否需要注水
  1194. /// </summary>
  1195. /// <returns></returns>
  1196. public bool CheckCANeedDiReplen()
  1197. {
  1198. if (IsAuto && _resRecipe != null)
  1199. {
  1200. if (_resRecipe.DIReplenEnable && _resRecipe.DIReplenTimeRate == 0 && _resRecipe.DIReplenCurrentRate == 0)
  1201. {
  1202. double levelHysteresis = SC.GetValue<double>("Reservoir.LevelHysteresis");
  1203. return _reservoirData.CaLevel < _resRecipe.ReservoirCALevel - levelHysteresis;
  1204. }
  1205. return false;
  1206. }
  1207. else
  1208. {
  1209. return false;
  1210. }
  1211. }
  1212. public void Reset()
  1213. {
  1214. }
  1215. public void Terminate()
  1216. {
  1217. }
  1218. }
  1219. }