ReservoirDevice.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  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.Beckhoff.ModuleIO;
  10. using MECF.Framework.Common.CommonData.Reservoir;
  11. using MECF.Framework.Common.IOCore;
  12. using MECF.Framework.Common.Persistent.Reservoirs;
  13. using MECF.Framework.Common.RecipeCenter;
  14. using MECF.Framework.Common.ToolLayout;
  15. using MECF.Framework.Common.TwinCat;
  16. using MECF.Framework.Common.Utilities;
  17. using PunkHPX8_Core;
  18. using PunkHPX8_RT.Devices.Facilities;
  19. using PunkHPX8_RT.Devices.Safety;
  20. using PunkHPX8_RT.Devices.Temperature;
  21. using PunkHPX8_RT.Modules;
  22. using PunkHPX8_RT.Modules.Reservoir;
  23. using System;
  24. using System.Collections.Generic;
  25. using System.Linq;
  26. using System.Reflection;
  27. using System.ServiceModel.Security;
  28. using System.Text;
  29. using System.Threading.Tasks;
  30. namespace PunkHPX8_RT.Devices.Reservoir
  31. {
  32. public class ReservoirDevice : BaseDevice, IDevice
  33. {
  34. #region 常量
  35. protected const string AUTO = "Auto";
  36. protected const string MANUAL = "Manual";
  37. protected const string DISABLE = "Disable";
  38. protected const string CA_PUMP_RUNNING="CaPumpRunning";
  39. protected const string AN_TOWER_HIGH="AnTowerHigh";
  40. protected const string AN_TOWER_LOW="AnTowerLow";
  41. protected const string CA_LEVEL="CaLevel";
  42. protected const string CA_WATER_LEVEL="CaWaterLevel";
  43. protected const string AN_FLOW="AnFlow";
  44. protected const string AN_PUMP_ENABLE="AnPumpEnable";
  45. protected const string AN_PUMP_SPEED="AnPumpSpeed";
  46. protected const string CA_FLOW="CaFlow";
  47. protected const string CA_PUMP_ENABLE="CaPumpEnable";
  48. protected const string CA_PUMP_SPEED="CaPumpSpeed";
  49. protected const string RETURN_VALVE_OPENING="ReturnValveOpening";
  50. protected const string RETURN_VALVE="ReturnValve";
  51. protected const string RETURN_VALVE_PERCENT="ReturnValvePercent";
  52. protected const string CA_DI_REPLEN="CaDiReplen";
  53. protected const string AN_DI_REPLEN="AnDiReplen";
  54. protected const string SAMPLE_OUT="SampleOut";
  55. protected const string DEGAS_ENABLE="DegasEnable";
  56. protected const string HED_FLOW="HedFlow";
  57. protected const string HED_FLOW_ENABLE="HedFlowEnable";
  58. protected const string PH_FLOW_VALVE="PhFlowValve";
  59. protected const string PH_VALUE="PhValue";
  60. #endregion
  61. #region 内部变量
  62. /// <summary>
  63. /// Prewet 持久性数值对象
  64. /// </summary>
  65. private ReservoirsPersistentValue _persistentValue;
  66. /// <summary>
  67. /// 变量是否初始化字典
  68. /// </summary>
  69. private Dictionary<string, bool> _variableInitializeDic = new Dictionary<string, bool>();
  70. /// <summary>
  71. /// 数据
  72. /// </summary>
  73. private ReservoirData _reservoirData = new ReservoirData();
  74. /// <summary>
  75. /// 定时器
  76. /// </summary>
  77. private PeriodicJob _periodicJob;
  78. /// <summary>
  79. /// 阴极Pump速度
  80. /// </summary>
  81. private double _caPumpSpeed = 0;
  82. /// <summary>
  83. /// Return Valve比例
  84. /// </summary>
  85. private double _returnValvePercent = 0.5;
  86. /// <summary>
  87. /// CA Level取样平均值
  88. /// </summary>
  89. private double _avgCALevel;
  90. /// <summary>
  91. /// CA Level取样队列
  92. /// </summary>
  93. private Queue<double> _CALevelSamples;
  94. /// <summary>
  95. /// CA level计算平均值取样数
  96. /// </summary>
  97. private int _levelSampleCount;
  98. /// <summary>
  99. /// Recipe
  100. /// </summary>
  101. private ResRecipe _resRecipe;
  102. /// <summary>
  103. /// 累计补水是否超时
  104. /// </summary>
  105. private bool _isDIReplenMaxTimeOut = false;
  106. /// <summary>
  107. /// 单次补水是否超时
  108. /// </summary>
  109. private bool _isDIReplenPerfillTimeOut = false;
  110. /// <summary>
  111. /// 注水Helper
  112. /// </summary>
  113. private ReservoirDiReplenHelper _direplenHelper;
  114. #endregion
  115. #region Trigger
  116. /// <summary>
  117. /// low WaterLevel trigger
  118. /// </summary>
  119. private R_TRIG _caWaterLevelLowerTrigger=new R_TRIG();
  120. /// <summary>
  121. /// low WaterLevel trigger
  122. /// </summary>
  123. private R_TRIG _caWaterLevelHighTrigger = new R_TRIG();
  124. #endregion
  125. #region 共享变量
  126. protected DiReplenOperation _currentDireplenOperation = DiReplenOperation.None;
  127. /// <summary>
  128. /// 手动注水时间(秒)
  129. /// </summary>
  130. protected int _manualReplenSecond = 0;
  131. #endregion
  132. #region 属性
  133. /// <summary>
  134. /// 操作模式
  135. /// </summary>
  136. public string OperationMode { get { return _persistentValue.OperatingMode; } }
  137. /// <summary>
  138. /// 工程模式
  139. /// </summary>
  140. public string EngineerMode { get { return _persistentValue.RecipeOperatingMode; } }
  141. /// <summary>
  142. /// 是否自动
  143. /// </summary>
  144. public bool IsAuto { get { return _persistentValue.OperatingMode == AUTO; } }
  145. /// <summary>
  146. /// 数据
  147. /// </summary>
  148. public ReservoirData ReservoirData { get { return _reservoirData; } }
  149. /// <summary>
  150. /// 检验阴极是否highlevel
  151. /// </summary>
  152. public bool IsCAHighLevel { get { return CheckCAHighLevelStatus(); } }
  153. /// <summary>
  154. /// 检验阴极是否lowlevel
  155. /// </summary>
  156. public bool IsCALowLevel { get { return CheckCALowLevelStatus(); } }
  157. /// <summary>
  158. /// 当前Recipe
  159. /// </summary>
  160. public ResRecipe Recipe { get { return _resRecipe; } }
  161. #endregion
  162. /// <summary>
  163. /// 构造函数
  164. /// </summary>
  165. /// <param name="moduleName"></param>
  166. /// <param name="name"></param>
  167. public ReservoirDevice(string moduleName) : base(moduleName, moduleName, moduleName, moduleName)
  168. {
  169. _levelSampleCount = SC.GetValue<int>("Reservoir.LevelAvgSamples");
  170. _levelSampleCount = _levelSampleCount == 0 ? 20 : _levelSampleCount;
  171. _CALevelSamples = new Queue<double>(_levelSampleCount);
  172. }
  173. /// <summary>
  174. /// 初始化
  175. /// </summary>
  176. /// <returns></returns>
  177. public bool Initialize()
  178. {
  179. InitializeParameter();
  180. InitializeRoutine();
  181. SubscribeData();
  182. InitializeOperation();
  183. SubscribeValueAction();
  184. _periodicJob = new PeriodicJob(200, OnTimer, $"{Module}.Timer", true, true);
  185. return true;
  186. }
  187. /// <summary>
  188. /// 初始化参数
  189. /// </summary>
  190. private void InitializeParameter()
  191. {
  192. _persistentValue = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(Module.ToString());
  193. if (_persistentValue == null)
  194. {
  195. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module.ToString(), "Persistent Value Object is not exist");
  196. }
  197. _persistentValue = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(Module);
  198. if (_persistentValue == null)
  199. {
  200. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Persistent Value Object is not exist");
  201. }
  202. if (!string.IsNullOrEmpty(_persistentValue.Recipe))
  203. {
  204. _resRecipe = RecipeFileManager.Instance.LoadGenericityRecipe<ResRecipe>(_persistentValue.Recipe);
  205. }
  206. _direplenHelper = new ReservoirDiReplenHelper(Module, _persistentValue);
  207. }
  208. /// <summary>
  209. /// 初始化Routine
  210. /// </summary>
  211. private void InitializeRoutine()
  212. {
  213. }
  214. /// <summary>
  215. /// 订阅数据
  216. /// </summary>
  217. private void SubscribeData()
  218. {
  219. DATA.Subscribe($"{Module}.ReservoirData", () => _reservoirData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  220. }
  221. /// <summary>
  222. /// 初始化Operation
  223. /// </summary>
  224. protected virtual void InitializeOperation()
  225. {
  226. OP.Subscribe($"{Module}.DisabledAction", DisabledOperation);
  227. OP.Subscribe($"{Module}.ManualAction", ManualOperation);
  228. OP.Subscribe($"{Module}.AutoAction", AutoOperation);
  229. OP.Subscribe($"{Module}.EngineeringModeAction", EngineeringModeOperation);
  230. OP.Subscribe($"{Module}.ProductionModeAction", ProductionModeOperation);
  231. OP.Subscribe($"{Module}.CAPumpOn", CAPumpOn);
  232. OP.Subscribe($"{Module}.CAPumpSpeed", CAPumpSpeedOperation);
  233. OP.Subscribe($"{Module}.CAPumpOff", CAPumpOff);
  234. }
  235. /// <summary>
  236. /// 订阅变量数值发生变化
  237. /// </summary>
  238. protected virtual void SubscribeValueAction()
  239. {
  240. IoSubscribeUpdateVariable(CA_PUMP_RUNNING);
  241. IoSubscribeUpdateVariable(AN_TOWER_HIGH);
  242. IoSubscribeUpdateVariable(AN_TOWER_LOW);
  243. IoSubscribeUpdateVariable(CA_LEVEL);
  244. IoSubscribeUpdateVariable(CA_WATER_LEVEL);
  245. IoSubscribeUpdateVariable(CA_PUMP_ENABLE);
  246. IoSubscribeUpdateVariable(CA_PUMP_SPEED);
  247. IoSubscribeUpdateVariable(CA_DI_REPLEN);
  248. IoSubscribeUpdateVariable(RETURN_VALVE);
  249. IoSubscribeUpdateVariable(RETURN_VALVE_OPENING);
  250. IoSubscribeUpdateVariable(RETURN_VALVE_PERCENT);
  251. IoSubscribeUpdateVariable(SAMPLE_OUT);
  252. }
  253. /// <summary>
  254. /// 订阅IO变量
  255. /// </summary>
  256. /// <param name="variable"></param>
  257. protected void IoSubscribeUpdateVariable(string variable)
  258. {
  259. _variableInitializeDic[variable] = false;
  260. IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue);
  261. }
  262. /// <summary>
  263. /// 更新变量数值
  264. /// </summary>
  265. /// <param name="variable"></param>
  266. /// <param name="value"></param>
  267. private void UpdateVariableValue(string variable, object value)
  268. {
  269. if (!_reservoirData.IsDataInitialized)
  270. {
  271. _reservoirData.IsDataInitialized = true;
  272. }
  273. PropertyInfo property = _reservoirData.GetType().GetProperty(variable);
  274. if (property != null)
  275. {
  276. property.SetValue(_reservoirData, value);
  277. if (variable == CA_WATER_LEVEL)
  278. {
  279. string caLevelCurve = SC.GetStringValue($"Reservoir.{Module}.CALevelCurve");
  280. ReservoirData.CaLevel = LevelCurveManager.Instance.CalculateLevelByWaterLevel(ReservoirData.CaWaterLevel, caLevelCurve);
  281. }
  282. }
  283. if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
  284. {
  285. _variableInitializeDic[variable] = true;
  286. }
  287. }
  288. /// <summary>
  289. /// 定时器
  290. /// </summary>
  291. /// <returns></returns>
  292. protected virtual bool OnTimer()
  293. {
  294. CalculateCALevel();
  295. WaterLevelMonitor();
  296. DireplenMonitor();
  297. return true;
  298. }
  299. #region timer
  300. /// <summary>
  301. /// 计算CA
  302. /// </summary>
  303. private void CalculateCALevel()
  304. {
  305. if (ReservoirData != null)
  306. {
  307. if (_CALevelSamples.Count >= _levelSampleCount)
  308. {
  309. _CALevelSamples.Dequeue();
  310. _CALevelSamples.Enqueue(ReservoirData.CaLevel);
  311. }
  312. else
  313. {
  314. _CALevelSamples.Enqueue(ReservoirData.CaLevel);
  315. }
  316. _avgCALevel = _CALevelSamples.Count > 0 ? _CALevelSamples.Average() : 0;
  317. }
  318. }
  319. /// <summary>
  320. /// WaterLevel监控
  321. /// </summary>
  322. protected virtual void WaterLevelMonitor()
  323. {
  324. _caWaterLevelLowerTrigger.CLK = IsCALowLevel;
  325. if (_caWaterLevelLowerTrigger.Q)
  326. {
  327. ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
  328. string reason = $"Current CAWaterlevel:{ReservoirData.CaWaterLevel} is lower than CALowLevel Config:{SC.GetValue<double>($"Reservoir.{Module}.CALowLevel")}";
  329. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, reason);
  330. CALowLevelOperation();
  331. if (reservoirEntity.IsAuto && !AlarmListManager.Instance.IsContainDataError(Module, "CAWaterLevel"))
  332. {
  333. AlarmListManager.Instance.AddDataError(Module,
  334. $"CAWaterLevel", $"Current CAWaterlevel:{ReservoirData.CaWaterLevel} is lower than CALowLevel Config:{SC.GetValue<double>($"Reservoir.{Module}.CALowLevel")}");
  335. }
  336. if (!reservoirEntity.IsError) reservoirEntity.PostMsg(ReservoirMsg.Error);
  337. }
  338. _caWaterLevelLowerTrigger.CLK = IsCAHighLevel;
  339. if (_caWaterLevelHighTrigger.Q)
  340. {
  341. HighLevelOperation();
  342. }
  343. }
  344. /// <summary>
  345. /// CA Low Level触发对应操作
  346. /// </summary>
  347. private void CALowLevelOperation()
  348. {
  349. ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module);
  350. if (_reservoirData.CaPumpEnable)
  351. {
  352. CAPumpOff("", null);
  353. }
  354. //禁用TC
  355. if (!string.IsNullOrEmpty(reservoirItem.TCID))
  356. {
  357. TemperatureController temperatureController = DEVICE.GetDevice<TemperatureController>(reservoirItem.TCID);
  358. if (temperatureController != null && temperatureController.TemperatureData.ControlOperationModel == (int)TemperatureEnumData.ENABLE)
  359. {
  360. temperatureController.DisableOperation("", null);
  361. }
  362. }
  363. ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
  364. if (!reservoirEntity.IsError) reservoirEntity.PostMsg(ReservoirMsg.Error);
  365. }
  366. /// <summary>
  367. /// High Level Common Operation
  368. /// </summary>
  369. private void HighLevelOperation()
  370. {
  371. ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
  372. SystemFacilities systemFacilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
  373. if (systemFacilities != null)
  374. {
  375. if (systemFacilities.DIFillEnable) systemFacilities.DiFillDisableOperation("DIFillDisableOpeartion", null);
  376. if (systemFacilities.DIReplenEnable) systemFacilities.DiReplenDisableOperation("DiReplenDisableOperation", null);
  377. if (_reservoirData.CaDiReplen)
  378. {
  379. _currentDireplenOperation = DiReplenOperation.None;
  380. CADiReplenOff("", null);
  381. }
  382. }
  383. if (!reservoirEntity.IsError) reservoirEntity.PostMsg(ReservoirMsg.Error);
  384. if (reservoirEntity.IsAuto && !AlarmListManager.Instance.IsContainDataError(Module, "CAWaterLevel"))
  385. {
  386. AlarmListManager.Instance.AddDataError(Module,
  387. $"CAWaterLevel", $"Current CAWaterlevel:{ReservoirData.CaWaterLevel} is large than CAHighLevel Config:{SC.GetValue<double>($"Reservoir.{Module}.CAHighLevel")}");
  388. }
  389. }
  390. /// <summary>
  391. /// Direplen监控
  392. /// </summary>
  393. private void DireplenMonitor()
  394. {
  395. var facilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
  396. //补水监控
  397. if (_direplenHelper != null)
  398. {
  399. _direplenHelper.MonitorPeriodTime(ref _isDIReplenMaxTimeOut);
  400. if (!_isDIReplenMaxTimeOut && !_isDIReplenPerfillTimeOut && facilities.DIFillEnable)
  401. {
  402. AutoDireplenMonitor();
  403. }
  404. }
  405. }
  406. /// <summary>
  407. /// 自动补水
  408. /// </summary>
  409. protected virtual void AutoDireplenMonitor()
  410. {
  411. if (_currentDireplenOperation == DiReplenOperation.ManualCADiReplen)
  412. {
  413. bool result = _direplenHelper.MonitorManualDiReplenComplete(_manualReplenSecond, CADiReplenOff, ref _isDIReplenMaxTimeOut);
  414. if (result)
  415. {
  416. _currentDireplenOperation = DiReplenOperation.None;
  417. }
  418. }
  419. if (_currentDireplenOperation == DiReplenOperation.AutoCADiReplen)
  420. {
  421. AutoDiReplenMonitor(CADiReplenOff, _reservoirData.CaLevel, _resRecipe.ReservoirCALevel, _resRecipe.DIReplenEnable,
  422. _resRecipe.DIReplenTimeRate, _resRecipe.DIReplenCurrentRate);
  423. }
  424. }
  425. /// <summary>
  426. /// 自动注水监控
  427. /// </summary>
  428. /// <param name="direplenOff"></param>
  429. /// <param name="level"></param>
  430. /// <param name="recipeLevel"></param>
  431. private void AutoDiReplenMonitor(Func<string, object[], bool> direplenOff, double level, double recipeLevel, bool replenEnable,
  432. int direplenTimeRate, int direplenCurrentRate)
  433. {
  434. bool result = _direplenHelper.AutoDiReplenMonitorTimeOut(direplenOff, ref _isDIReplenMaxTimeOut, ref _isDIReplenPerfillTimeOut);
  435. if (result)
  436. {
  437. _currentDireplenOperation = DiReplenOperation.None;
  438. }
  439. else
  440. {
  441. //按液位补水
  442. result = _direplenHelper.AutoDiReplenMonitorComplete(level, recipeLevel, replenEnable, direplenTimeRate, direplenCurrentRate, direplenOff);
  443. if (result)
  444. {
  445. _currentDireplenOperation = DiReplenOperation.None;
  446. }
  447. }
  448. }
  449. #endregion
  450. #region Mode switch
  451. /// <summary>
  452. /// DisabledAction
  453. /// </summary>
  454. /// <param name="cmd"></param>
  455. /// <param name="param"></param>
  456. /// <returns></returns>
  457. private bool DisabledOperation(string cmd, object[] args)
  458. {
  459. string currentOperation = "Disabled";
  460. string preOperation = _persistentValue.OperatingMode;
  461. _persistentValue.OperatingMode = currentOperation;
  462. LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
  463. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  464. return true;
  465. }
  466. /// <summary>
  467. /// ManualAction
  468. /// </summary>
  469. /// <param name="cmd"></param>
  470. /// <param name="param"></param>
  471. /// <returns></returns>
  472. private bool ManualOperation(string cmd, object[] args)
  473. {
  474. string currentOperation = "Manual";
  475. string preOperation = _persistentValue.OperatingMode;
  476. _persistentValue.OperatingMode = currentOperation;
  477. LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
  478. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  479. return true;
  480. }
  481. /// <summary>
  482. /// AutoAction
  483. /// </summary>
  484. /// <param name="cmd"></param>
  485. /// <param name="param"></param>
  486. /// <returns></returns>
  487. private bool AutoOperation(string cmd, object[] args)
  488. {
  489. string currentOperation = "Auto";
  490. string preOperation = _persistentValue.OperatingMode;
  491. _persistentValue.OperatingMode = currentOperation;
  492. LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
  493. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  494. return true;
  495. }
  496. /// <summary>
  497. /// EngineeringModeAction
  498. /// </summary>
  499. /// <param name="cmd"></param>
  500. /// <param name="param"></param>
  501. /// <returns></returns>
  502. private bool EngineeringModeOperation(string cmd, object[] args)
  503. {
  504. string currentRecipeOperation = "Engineering";
  505. if (_persistentValue != null)
  506. {
  507. _persistentValue.RecipeOperatingMode = currentRecipeOperation;
  508. }
  509. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  510. return true;
  511. }
  512. /// <summary>
  513. /// ProductionAction
  514. /// </summary>
  515. /// <param name="cmd"></param>
  516. /// <param name="param"></param>
  517. /// <returns></returns>
  518. private bool ProductionModeOperation(string cmd, object[] args)
  519. {
  520. string currentRecipeOperation = "Production";
  521. if (_persistentValue != null)
  522. {
  523. _persistentValue.RecipeOperatingMode = currentRecipeOperation;
  524. }
  525. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  526. return true;
  527. }
  528. #endregion
  529. /// <summary>
  530. /// 监控
  531. /// </summary>
  532. public void Monitor()
  533. {
  534. }
  535. #region CA Pump
  536. /// <summary>
  537. /// CA Pump调速
  538. /// </summary>
  539. /// <param name="cmd"></param>
  540. /// <param name="args"></param>
  541. /// <returns></returns>
  542. private bool CAPumpSpeedOperation(string cmd, object[] args)
  543. {
  544. double caMaxPumpSpeed = 0;
  545. if (SC.ContainsItem("Reservoir.CAMaxPumpSpeed"))
  546. {
  547. caMaxPumpSpeed = SC.GetValue<double>("Reservoir.CAMaxPumpSpeed");
  548. }
  549. if (double.TryParse(args[0].ToString(), out double speed))
  550. {
  551. _caPumpSpeed = speed;
  552. if (_caPumpSpeed > caMaxPumpSpeed)
  553. {
  554. LOG.WriteLog(eEvent.WARN_METAL, Module, $"CA pump speed:{_caPumpSpeed} is over CA max pump speed {caMaxPumpSpeed}!");
  555. return false;
  556. }
  557. return CAPumpSpeed(_caPumpSpeed);
  558. }
  559. else
  560. {
  561. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{args[0]} is nor invalid speed");
  562. return false;
  563. }
  564. }
  565. /// <summary>
  566. /// 设置阴极泵速
  567. /// </summary>
  568. /// <param name="caPumpSpeed"></param>
  569. /// <returns></returns>
  570. public bool CAPumpSpeed(double caPumpSpeed)
  571. {
  572. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_PUMP_SPEED}");
  573. return BeckhoffIOManager.Instance.WriteIoValue(ioName, caPumpSpeed);
  574. }
  575. /// <summary>
  576. /// 阴极Pump On
  577. /// </summary>
  578. /// <param name="cmd"></param>
  579. /// <param name="args"></param>
  580. /// <returns></returns>
  581. private bool CAPumpOn(string cmd, object[] args)
  582. {
  583. double caPumpSpeed = SC.GetValue<double>("Reservoir.CADefaultPumpSpeed");
  584. bool result = CAPumpSpeed(caPumpSpeed);
  585. if (result)
  586. {
  587. string enableIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_PUMP_ENABLE}");
  588. return BeckhoffIOManager.Instance.WriteIoValue(enableIOName, true);
  589. }
  590. else
  591. {
  592. return false;
  593. }
  594. }
  595. /// <summary>
  596. /// 阴极Pump Off
  597. /// </summary>
  598. /// <param name="cmd"></param>
  599. /// <param name="args"></param>
  600. /// <returns></returns>
  601. private bool CAPumpOff(string cmd, object[] args)
  602. {
  603. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_PUMP_ENABLE}");
  604. return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
  605. }
  606. #endregion
  607. #region Return Valve
  608. /// <summary>
  609. /// Return Valve
  610. /// </summary>
  611. /// <param name="cmd"></param>
  612. /// <param name="args"></param>
  613. /// <returns></returns>
  614. private bool ReturnValvePercentOperation(string cmd, object[] args)
  615. {
  616. if (double.TryParse(args[0].ToString(), out double percent))
  617. {
  618. _returnValvePercent = percent;
  619. return CAPumpSpeed(_caPumpSpeed);
  620. }
  621. else
  622. {
  623. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{args[0]} is nor invalid speed");
  624. return false;
  625. }
  626. }
  627. /// <summary>
  628. /// 设置比例
  629. /// </summary>
  630. /// <param name="caPumpSpeed"></param>
  631. /// <returns></returns>
  632. public bool ReturnValvePercent(double percent)
  633. {
  634. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{RETURN_VALVE_PERCENT}");
  635. return BeckhoffIOManager.Instance.WriteIoValue(ioName, percent);
  636. }
  637. /// <summary>
  638. /// Return Valve On
  639. /// </summary>
  640. /// <param name="cmd"></param>
  641. /// <param name="args"></param>
  642. /// <returns></returns>
  643. private bool ReturnValveOn(string cmd, object[] args)
  644. {
  645. double percent = SC.GetValue<double>("Reservoir.ReturnOpenDefaultPercentage");
  646. bool result = ReturnValvePercent(percent);
  647. if (result)
  648. {
  649. string enableIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{RETURN_VALVE}");
  650. return BeckhoffIOManager.Instance.WriteIoValue(enableIOName, true);
  651. }
  652. else
  653. {
  654. return false;
  655. }
  656. }
  657. /// <summary>
  658. /// Return Valve Off
  659. /// </summary>
  660. /// <param name="cmd"></param>
  661. /// <param name="args"></param>
  662. /// <returns></returns>
  663. private bool ReturnValveOff(string cmd, object[] args)
  664. {
  665. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{RETURN_VALVE}");
  666. return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
  667. }
  668. #endregion
  669. #region CA DiReplen
  670. /// <summary>
  671. /// 阴极DI Replen On
  672. /// </summary>
  673. /// <param name="cmd"></param>
  674. /// <param name="args"></param>
  675. /// <returns></returns>
  676. private bool CADiReplenOnOperation(string cmd, object[] args)
  677. {
  678. return CADiReplenOn();
  679. }
  680. /// <summary>
  681. /// 阴极DI Replen On
  682. /// </summary>
  683. /// <param name="showError"></param>
  684. /// <returns></returns>
  685. private bool CADiReplenOn()
  686. {
  687. bool preCondition = CheckPreDiReplenCondition();
  688. if (!preCondition)
  689. {
  690. return false;
  691. }
  692. if (IsCAHighLevel)
  693. {
  694. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CAHighLevel is activate,Can't do CA_DIReple");
  695. return false;
  696. }
  697. if (IsCALowLevel)
  698. {
  699. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CALowLevel is activate,Can't do CA_DIReple");
  700. return false;
  701. }
  702. if (ReservoirData.AnDiReplen)
  703. {
  704. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "ANDiReplen is on");
  705. return false;
  706. }
  707. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_DI_REPLEN}");
  708. return BeckhoffIOManager.Instance.WriteIoValue(ioName, true);
  709. }
  710. /// <summary>
  711. /// 阴极DI Replen Off
  712. /// </summary>
  713. /// <param name="cmd"></param>
  714. /// <param name="args"></param>
  715. /// <returns></returns>
  716. private bool CADiReplenOff(string cmd, object[] args)
  717. {
  718. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_DI_REPLEN}");
  719. bool result = BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
  720. if (result)
  721. {
  722. _persistentValue.IsDiReplenOn = false;
  723. if (_currentDireplenOperation == DiReplenOperation.ManualCADiReplen || _currentDireplenOperation == DiReplenOperation.AutoCADiReplen)
  724. {
  725. _currentDireplenOperation = DiReplenOperation.None;
  726. _persistentValue.LastTotalReplen = _persistentValue.TotalReplen;
  727. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  728. }
  729. }
  730. return result;
  731. }
  732. /// <summary>
  733. /// 检验DiReplen前置条件
  734. /// </summary>
  735. /// <returns></returns>
  736. public bool CheckPreDiReplenCondition()
  737. {
  738. if (!CheckFacilitiesDiReplenStatus())
  739. {
  740. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Facilities DiReplen is Off, can't start auto diReplen");
  741. return false;
  742. }
  743. SafetyDevice safetyDevice = DEVICE.GetDevice<SafetyDevice>("Safety");
  744. if (safetyDevice != null && safetyDevice.SafetyData.Reservoir1CALevelHigh)
  745. {
  746. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Safety high is Activate, can't start auto diReplen");
  747. return false;
  748. }
  749. if (CheckOtherReservoirDiReplenStatus())
  750. {
  751. return false;
  752. }
  753. return true;
  754. }
  755. /// <summary>
  756. /// 检验总Di有没有开
  757. /// </summary>
  758. /// <returns></returns>
  759. private bool CheckFacilitiesDiReplenStatus()
  760. {
  761. SystemFacilities systemFacilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
  762. if (systemFacilities != null)
  763. {
  764. return systemFacilities.DIReplenEnable;
  765. }
  766. return false;
  767. }
  768. /// <summary>
  769. /// 检验是否其他Reservoir Direplen已经
  770. /// </summary>
  771. /// <returns></returns>
  772. protected bool CheckOtherReservoirDiReplenStatus()
  773. {
  774. List<string> reservoirs = ReservoirItemManager.Instance.InstalledModules;
  775. foreach (string item in reservoirs)
  776. {
  777. if (item != Module)
  778. {
  779. ReservoirDevice tmpDevice = DEVICE.GetDevice<ReservoirDevice>(item);
  780. if (tmpDevice.ReservoirData.CaDiReplen)
  781. {
  782. return true;
  783. }
  784. ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(item);
  785. if (reservoirItem.SubType == ReservoirType.DegasMembrance.ToString())
  786. {
  787. if (tmpDevice.ReservoirData.AnDiReplen)
  788. {
  789. return true;
  790. }
  791. }
  792. }
  793. }
  794. return false;
  795. }
  796. #endregion
  797. #region DiReplen Operation
  798. /// <summary>
  799. /// 重置时长
  800. /// </summary>
  801. /// <param name="cmd"></param>
  802. /// <param name="objs"></param>
  803. /// <returns></returns>
  804. private bool ResetTotalTime(string cmd, object[] objs)
  805. {
  806. _isDIReplenMaxTimeOut = false;
  807. _persistentValue.TotalReplen = 0;
  808. _persistentValue.LastTotalReplen = 0;
  809. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  810. return true;
  811. }
  812. /// <summary>
  813. /// 手动阴极注水
  814. /// </summary>
  815. /// <param name="cmd"></param>
  816. /// <param name="args"></param>
  817. /// <returns></returns>
  818. private bool ManualCADiReplen(string cmd, object[] args)
  819. {
  820. return ManualDiReplen(CADiReplenOnOperation, DiReplenOperation.ManualCADiReplen, args[0].ToString());
  821. }
  822. /// <summary>
  823. /// 手动注水
  824. /// </summary>
  825. /// <param name="direplenOn"></param>
  826. /// <param name="direplenOperation"></param>
  827. /// <returns></returns>
  828. private bool ManualDiReplen(Func<string, object[], bool> direplenOn, DiReplenOperation direplenOperation, string timeLength)
  829. {
  830. if (_currentDireplenOperation != DiReplenOperation.None)
  831. {
  832. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"current operation is {_currentDireplenOperation},cannot execute {direplenOperation}");
  833. return false;
  834. }
  835. ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
  836. if (!reservoirEntity.IsInitialized)
  837. {
  838. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} is not initialized. Can't start DiReplen");
  839. return false;
  840. }
  841. if (_isDIReplenMaxTimeOut)
  842. {
  843. double diValveMaxOnTime = SC.GetValue<double>($"Reservoir.{Module}.DIValveMaxOnTime");
  844. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"Direplen time over conifg's DIValveMaxOnTime:{diValveMaxOnTime} min");
  845. return false;
  846. }
  847. if (_isDIReplenPerfillTimeOut)
  848. {
  849. double diValveMaxOnTimePerFill = SC.GetValue<double>($"Reservoir.{Module}.DIValveMaxOnTimePerFill");
  850. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"Direplen time over conifg's DIValveMaxOnTimePerFill:{diValveMaxOnTimePerFill} min");
  851. return false;
  852. }
  853. bool result = direplenOn("", null);
  854. if (result)
  855. {
  856. _currentDireplenOperation = direplenOperation;
  857. _persistentValue.DiReplenTime = DateTime.Now;
  858. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  859. int.TryParse(timeLength, out _manualReplenSecond);
  860. }
  861. return result;
  862. }
  863. /// <summary>
  864. /// 阴极自动流水
  865. /// </summary>
  866. /// <returns></returns>
  867. public bool AutoCADiReplen()
  868. {
  869. if (IsCALowLevel)
  870. {
  871. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CALowLevel is activate,Can't AutoANDireplen");
  872. return false;
  873. }
  874. return AutoDireplen(CADiReplenOn, DiReplenOperation.AutoCADiReplen);
  875. }
  876. /// <summary>
  877. /// 自动注水
  878. /// </summary>
  879. /// <returns></returns>
  880. protected bool AutoDireplen(Func<bool> direplenOn, DiReplenOperation reservoirOperation)
  881. {
  882. if (_currentDireplenOperation != DiReplenOperation.None)
  883. {
  884. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"current operation is {_currentDireplenOperation},cannot execute {reservoirOperation}");
  885. return false;
  886. }
  887. if (_resRecipe == null)
  888. {
  889. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"recipe is null");
  890. return false;
  891. }
  892. bool result = direplenOn();
  893. if (result)
  894. {
  895. _currentDireplenOperation = reservoirOperation;
  896. _persistentValue.DiReplenTime = DateTime.Now;
  897. }
  898. return result;
  899. }
  900. #endregion
  901. /// <summary>
  902. /// 检验阴极是否highlevel
  903. /// </summary>
  904. public bool CheckCAHighLevelStatus()
  905. {
  906. return ReservoirData.CaWaterLevel > SC.GetValue<double>($"Reservoir.{Module}.CAHighLevel") ? true : false;
  907. }
  908. /// <summary>
  909. /// 检验阴极是否lowlevel
  910. /// </summary>
  911. public bool CheckCALowLevelStatus()
  912. {
  913. return ReservoirData.CaWaterLevel < SC.GetValue<double>($"Reservoir.{Module}.CALowLevel") ? true : false;
  914. }
  915. public void Reset()
  916. {
  917. }
  918. public void Terminate()
  919. {
  920. }
  921. protected enum DiReplenOperation
  922. {
  923. None,
  924. ManualANDiReplen,
  925. ManualCADiReplen,
  926. AutoANDiReplen,
  927. AutoCADiReplen
  928. }
  929. }
  930. }