RevtechGenerator.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. using System;
  2. using System.Collections;
  3. using System.Text.RegularExpressions;
  4. using Aitex.Core.Common.DeviceData;
  5. using Aitex.Core.RT.DataCenter;
  6. using Aitex.Core.RT.Event;
  7. using Aitex.Core.RT.IOCore;
  8. using Aitex.Core.RT.Log;
  9. using Aitex.Core.RT.OperationCenter;
  10. using Aitex.Core.RT.SCCore;
  11. using Aitex.Core.RT.Tolerance;
  12. using Aitex.Core.Util;
  13. using MECF.Framework.Common.Communications;
  14. using MECF.Framework.Common.DataCenter;
  15. using MECF.Framework.Common.Device.Bases;
  16. using MECF.Framework.Common.Equipment;
  17. using VirgoCommon;
  18. using VirgoRT.Modules;
  19. namespace VirgoRT.Devices
  20. {
  21. class RevtechGenerator : RfPowerBase
  22. {
  23. // ----------------------------Fields--------------------------
  24. //
  25. private int QUERY_INTERVAL = 5000;
  26. private const string INFO_PATTERN = @"(\d{7})\s(\d{5})\s(\d{5})\s(\d{5})\s(\d{5})";
  27. private double _total;
  28. private double _fromLast;
  29. private bool _cmdRFPowerOn = false;
  30. private readonly AsyncSerialPort _serial;
  31. private readonly DeviceTimer _timerQueryStatus = new DeviceTimer();
  32. private readonly DeviceTimer _timerTotal = new DeviceTimer();
  33. private readonly DeviceTimer _timerFromLast = new DeviceTimer();
  34. private readonly DeviceTimer _timerRFTurnOn = new DeviceTimer();
  35. private DateTime _powerOnStartTime;
  36. private TimeSpan _powerOnElapsedTime;
  37. private readonly RD_TRIG _rfOnTrigger = new RD_TRIG();
  38. private readonly R_TRIG _ErrTrigger = new R_TRIG();
  39. private readonly R_TRIG _trigPMNeeded = new R_TRIG();
  40. private readonly RD_TRIG _trigOnOff = new RD_TRIG();
  41. private ToleranceChecker _checkerPower;
  42. private ToleranceChecker _checkerReflectPower;
  43. private readonly double _scPowerAlarmTime;
  44. private readonly double _scPowerAlarmRange;
  45. private readonly double _scPowerWarningTime;
  46. private readonly double _scPowerWarningRange;
  47. private readonly double _scReflectPowerAlarmTime;
  48. private readonly double _scReflectPowerAlarmRange;
  49. private readonly double _scPowerRange;
  50. private readonly DIAccessor _diIntlk;
  51. private StatsDataItemRFAndPump _statRFOnTime;
  52. private object _lockerCmdPowerOn = new object();
  53. private string _title = "Revtech TEC";
  54. // --------------------------Properties------------------------
  55. //
  56. public bool ConnectedStatus { get; set; }
  57. public override float ScalePower => (float)_scPowerRange;
  58. public GeneratorStatus Status { get; set; }
  59. public string LastPMTime
  60. {
  61. get
  62. {
  63. return _statRFOnTime != null ? _statRFOnTime.LastPMTime.ToString() : "";
  64. }
  65. }
  66. public double DaysFromLastPM
  67. {
  68. get
  69. {
  70. return _statRFOnTime == null ? 0 : _statRFOnTime.fromLastPM;
  71. }
  72. set
  73. {
  74. if (_statRFOnTime != null)
  75. _statRFOnTime.fromLastPM = value;
  76. }
  77. }
  78. public double TotalDays
  79. {
  80. get
  81. {
  82. return _statRFOnTime != null ? _statRFOnTime.Total : 0;
  83. }
  84. set
  85. {
  86. if (_statRFOnTime != null)
  87. _statRFOnTime.Total = value;
  88. }
  89. }
  90. public double PMIntervalDays
  91. {
  92. get
  93. {
  94. return _statRFOnTime != null ? _statRFOnTime.PMInterval : 0;
  95. }
  96. }
  97. public bool IsPMNeeded
  98. {
  99. get
  100. {
  101. return DaysFromLastPM > PMIntervalDays;
  102. }
  103. }
  104. public bool EnableAlarm
  105. {
  106. get
  107. {
  108. return _statRFOnTime == null || _statRFOnTime.AlarmEnable;
  109. }
  110. }
  111. public override bool IsPowerOn
  112. {
  113. get => Status == GeneratorStatus.ON;
  114. set { }
  115. }
  116. public override bool IsError
  117. {
  118. get => Status == GeneratorStatus.ERROR;
  119. set { }
  120. }
  121. [Subscription("PowerOnTime")]
  122. public string PowerOnTime
  123. {
  124. get
  125. {
  126. if (_cmdRFPowerOn)
  127. _powerOnElapsedTime = DateTime.Now - _powerOnStartTime;
  128. return $"{(int)_powerOnElapsedTime.TotalHours:00}:{_powerOnElapsedTime.Minutes:00}:{(_powerOnElapsedTime.Seconds > 0 ? (_powerOnElapsedTime.Seconds + 1) : 0):00}";
  129. }
  130. }
  131. public bool RFInterlock => _diIntlk == null || _diIntlk.Value;
  132. private float _forwardPower;
  133. public override float ForwardPower
  134. {
  135. get
  136. {
  137. return _forwardPower;
  138. }
  139. set
  140. {
  141. _forwardPower = CalibrationData(value, false);
  142. }
  143. }
  144. public new AITRfData DeviceData =>
  145. new AITRfData
  146. {
  147. Module = Module,
  148. DeviceName = Name,
  149. ScalePower = ScalePower,
  150. ForwardPower = ForwardPower,
  151. ReflectPower = ReflectPower,
  152. IsRfOn = IsPowerOn,
  153. PowerSetPoint = PowerSetPoint,
  154. PowerOnElapsedTime = PowerOnTime,
  155. IsInterlockOk = RFInterlock,
  156. WorkMode = (int)RfMode.ContinuousWaveMode,
  157. DisplayName = "Source RF",
  158. };
  159. // --------------------------Constructor-----------------------
  160. //
  161. public RevtechGenerator(ModuleName mod, string name) : base(mod.ToString(), name)
  162. {
  163. var portNum = SC.GetStringValue($"{mod}.{name}.Port");
  164. this.Status = GeneratorStatus.Unknown;
  165. _serial = new AsyncSerialPort(portNum, 9600, 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One, "\r\r");
  166. _scPowerAlarmTime = SC.GetValue<double>($"{Module}.{Name}.PowerAlarmTime");
  167. _scPowerAlarmRange = SC.GetValue<double>($"{Module}.{Name}.PowerAlarmRange");
  168. _scPowerWarningTime = SC.GetValue<double>($"{Module}.{Name}.PowerWarningTime");
  169. _scPowerWarningRange = SC.GetValue<double>($"{Module}.{Name}.PowerWarningRange");
  170. _scReflectPowerAlarmTime = SC.GetValue<double>($"{Module}.{Name}.ReflectPowerAlarmTime");
  171. _scReflectPowerAlarmRange = SC.GetValue<double>($"{Module}.{Name}.ReflectPowerAlarmRange");
  172. _scPowerRange = SC.GetValue<double>($"{Module}.{Name}.PowerRange");
  173. _scEnableCalibration = SC.GetConfigItem($"{Module}.{Name}.EnableCalibration");
  174. _scCalibrationTable = SC.GetConfigItem($"{Module}.{Name}.CalibrationTable");
  175. _scRFPhysicalMaxPower = SC.GetConfigItem($"{Module}.{Name}.RFPhysicalMaxPower");
  176. _scCurrentRFMaxPower = SC.GetConfigItem($"{Module}.{Name}.CurrentRFMaxPower");
  177. _diIntlk = IO.DI[$"{Module}.DI_Generator_Hardware_Interlock"];
  178. }
  179. ~RevtechGenerator()
  180. {
  181. _serial?.Close();
  182. }
  183. public override bool Initialize()
  184. {
  185. base.Initialize();
  186. DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
  187. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetPowerOnOff}", (out string reason, int time, object[] param) =>
  188. {
  189. SetPowerOnOff(Convert.ToBoolean((string)param[0]), out reason);
  190. return true;
  191. });
  192. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetPower}", (out string reason, int time, object[] param) =>
  193. {
  194. reason = "";
  195. ushort val = Convert.ToUInt16(param[0]);
  196. SetPower(val);
  197. return true;
  198. });
  199. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetContinuousPower}", (out string reason, int time, object[] param) =>
  200. {
  201. reason = "";
  202. ushort val = Convert.ToUInt16(param[0]);
  203. SetPower(val);
  204. return true;
  205. });
  206. if (_serial.Open())
  207. {
  208. this.ConnectedStatus = true;
  209. _serial.OnDataChanged += SerialPortDataReceived;
  210. _serial.OnErrorHappened += SerialPortErrorOccurred;
  211. }
  212. else
  213. {
  214. this.ConnectedStatus = false;
  215. EV.PostAlarmLog(this.Module, $"{_title} 射频发生器串口无法打开");
  216. return false;
  217. }
  218. _statRFOnTime = StatsDataManager.Instance.GetItemRFAndPump($"{Module}.RfOnTime");
  219. _timerQueryStatus.Start(QUERY_INTERVAL);
  220. _checkerPower = new ToleranceChecker(_scPowerAlarmTime);
  221. _checkerReflectPower = new ToleranceChecker(_scReflectPowerAlarmTime);
  222. SetCommunicationMode(1);
  223. return true;
  224. }
  225. public override void Monitor()
  226. {
  227. // 状态查询
  228. if (_timerQueryStatus.IsTimeout())
  229. {
  230. this.SendCmd(AdTecRfMessage.QUERY);
  231. _timerQueryStatus.Start(QUERY_INTERVAL);
  232. }
  233. // power on triggered
  234. _rfOnTrigger.CLK = IsPowerOn;
  235. if (_rfOnTrigger.R)
  236. {
  237. _total = TotalDays;
  238. _fromLast = DaysFromLastPM;
  239. _timerTotal.Start(0);
  240. _timerFromLast.Start(0);
  241. _powerOnStartTime = DateTime.Now;
  242. _checkerPower.Reset(_scPowerAlarmTime);
  243. _checkerReflectPower.Reset(_scReflectPowerAlarmTime);
  244. _alarmChecker.Reset(_scPowerAlarmTime);
  245. _warningChecker.Reset(_scPowerWarningTime);
  246. }
  247. if (_rfOnTrigger.M)
  248. {
  249. TotalDays = _total + _timerTotal.GetElapseTime() / 1000 / 60 / 60;
  250. DaysFromLastPM = _fromLast + _timerFromLast.GetElapseTime() / 1000 / 60 / 60;
  251. //_checkerPower.Monitor(ForwardPower, PowerSetPoint - _scPowerAlarmRange, PowerSetPoint + _scPowerAlarmRange, _scPowerAlarmTime);
  252. //if (_checkerPower.Trig)
  253. //{
  254. // EV.PostAlarmLog($"{Module}",
  255. // $"{Display} Forward power {ForwardPower:0} out of range[{PowerSetPoint - _scPowerAlarmRange:0},{PowerSetPoint + _scPowerAlarmRange:0}] in {_scPowerAlarmTime:0} seconds");
  256. // SetPowerOnOff(false, out _);
  257. //}
  258. if (_recipeAlarmRange > 0 && _recipeAlarmRange / 100.0 * PowerSetPoint < _scPowerAlarmRange)
  259. {
  260. if (_recipeIgnoreTimer.GetElapseTime() > _recipeIgnoreTimeMS)
  261. {
  262. _recipeAlarmChecker.Monitor(ForwardPower, PowerSetPoint - Math.Abs(_recipeAlarmRange / 100.0 * PowerSetPoint), PowerSetPoint + Math.Abs(_recipeAlarmRange / 100.0 * PowerSetPoint), _scPowerAlarmTime);
  263. if (_recipeAlarmChecker.Trig)
  264. {
  265. EV.PostAlarmLog(Module, Display + $" out of tolerance in {_scPowerAlarmTime:0} seconds");
  266. SetPowerOnOff(false, out _);
  267. }
  268. }
  269. }
  270. else
  271. {
  272. _alarmChecker.Monitor(ForwardPower, PowerSetPoint - Math.Abs(_scPowerAlarmRange), PowerSetPoint + Math.Abs(_scPowerAlarmRange), _scPowerAlarmTime);
  273. if (_alarmChecker.Trig)
  274. {
  275. EV.PostAlarmLog(Module, Display + $" out of tolerance in {_scPowerAlarmTime:0} seconds");
  276. }
  277. }
  278. if (_recipeWarningRange > 0 && _recipeWarningRange / 100.0 * PowerSetPoint < _scPowerWarningRange)
  279. {
  280. if (_recipeIgnoreTimer.GetElapseTime() > _recipeIgnoreTimeMS)
  281. {
  282. _recipeWarningChecker.Monitor(ForwardPower, PowerSetPoint - Math.Abs(_recipeWarningRange / 100.0 * PowerSetPoint), PowerSetPoint + Math.Abs(_recipeWarningRange / 100.0 * PowerSetPoint), _scPowerWarningTime);
  283. if (_recipeWarningChecker.Trig)
  284. {
  285. EV.PostWarningLog(Module, Display + $" out of tolerance in {_scPowerWarningTime:0} seconds");
  286. }
  287. }
  288. }
  289. else
  290. {
  291. _warningChecker.Monitor(ForwardPower, PowerSetPoint - Math.Abs(_scPowerWarningRange), PowerSetPoint + Math.Abs(_scPowerWarningRange), _scPowerWarningTime);
  292. if (_warningChecker.Trig)
  293. {
  294. EV.PostWarningLog(Module, Display + $" out of tolerance in {_scPowerWarningTime:0} seconds");
  295. }
  296. }
  297. _checkerReflectPower.Monitor(ReflectPower, double.MinValue, _scReflectPowerAlarmRange, _scReflectPowerAlarmTime);
  298. if (_checkerReflectPower.Trig)
  299. {
  300. EV.PostAlarmLog($"{Module}",
  301. $"{Display} Reflect power {ReflectPower:0} out of range[0,{_scReflectPowerAlarmRange:0}] in {_scReflectPowerAlarmTime:0} seconds");
  302. SetPowerOnOff(false, out _);
  303. }
  304. }
  305. if (PMIntervalDays > 0)
  306. {
  307. _trigPMNeeded.CLK = IsPMNeeded;
  308. if (_trigPMNeeded.Q)
  309. {
  310. if (EnableAlarm)
  311. {
  312. EV.PostAlarmLog($"{Module}", "rf on time value larger than setting interval days");
  313. }
  314. }
  315. }
  316. if (_rfOnTrigger.T)
  317. StatsDataManager.Instance.Increase($"{Module}.RfOnTime", $"{Module} RfOnTime", DaysFromLastPM, TotalDays);
  318. if (!_rfOnTrigger.CLK)
  319. {
  320. ForwardPower = 0;
  321. ReflectPower = 0;
  322. }
  323. // 通信 checking, 2 second 一次
  324. //if (_timerComm.IsTimeout() && !_bQueryComm)
  325. //{
  326. // this.SendCmd(AdTecRfMessage.CHK_COMM);
  327. // _bQueryComm = true;
  328. // _timerComm.Start(CHK_COMM_INTERVAL);
  329. //}
  330. // RF Turn On & Off Timeout Check
  331. lock (_lockerCmdPowerOn)
  332. {
  333. if (IsPowerOn)
  334. {
  335. _timerRFTurnOn.Stop();
  336. }
  337. else
  338. {
  339. if (_cmdRFPowerOn && _timerRFTurnOn.IsTimeout())
  340. {
  341. EV.PostAlarmLog($"{Module}", "RF Turn On Failed");
  342. _timerRFTurnOn.Stop();
  343. }
  344. }
  345. }
  346. base.Monitor();
  347. }
  348. public override void Terminate()
  349. {
  350. _serial?.Close();
  351. }
  352. public override void Reset()
  353. {
  354. _rfOnTrigger.RST = true;
  355. _ErrTrigger.RST = true;
  356. _trigPMNeeded.RST = true;
  357. this.SendCmd(AdTecRfMessage.RESET);
  358. this.Status = GeneratorStatus.OFF;
  359. _cmdRFPowerOn = false;
  360. base.Reset();
  361. }
  362. public void SetRfMode(RfMode mode)
  363. {
  364. throw new NotImplementedException();
  365. }
  366. public override void SetCommunicationMode(int mode)
  367. {
  368. CommunicationType t1 = (CommunicationType)mode;
  369. switch (t1)
  370. {
  371. case CommunicationType.Analogue:
  372. this.SendCmd(AdTecRfMessage.ANALOG);
  373. break;
  374. case CommunicationType.RS232:
  375. this.SendCmd(AdTecRfMessage.RS232);
  376. break;
  377. default:
  378. throw new ArgumentOutOfRangeException("Communication mode error");
  379. }
  380. }
  381. public override void SetPower(float val)
  382. {
  383. if (!(this.ControlMode == EnumRfPowerControlMode.RS232Mode)) SetCommunicationMode(1);
  384. ushort a = !_scEnableCalibration.BoolValue ? (ushort)val : (ushort)CalibrationData(val, true);
  385. if (SendCmd($"{a:D4}{AdTecRfMessage.SET_POWER}"))
  386. {
  387. PowerSetPoint = val;
  388. }
  389. }
  390. public override bool SetPowerOnOff(bool on, out string str)
  391. {
  392. if (!(this.ControlMode == EnumRfPowerControlMode.RS232Mode)) SetCommunicationMode(1);
  393. str = "";
  394. if (on)
  395. {
  396. lock (_lockerCmdPowerOn)
  397. {
  398. _cmdRFPowerOn = true;
  399. _timerRFTurnOn.Start(SC.GetValue<int>($"{Module}.Rf.RFTurnOnTimeout") * 1000);
  400. }
  401. SendCmd(AdTecRfMessage.RF_ON);
  402. QUERY_INTERVAL = 500;
  403. }
  404. else
  405. {
  406. lock (_lockerCmdPowerOn)
  407. {
  408. _cmdRFPowerOn = false;
  409. _timerRFTurnOn.Stop();
  410. }
  411. SendCmd(AdTecRfMessage.RF_OFF);
  412. ForwardPower = 0;
  413. ReflectPower = 0;
  414. QUERY_INTERVAL = 500;
  415. _ErrTrigger.RST = true;
  416. }
  417. _timerQueryStatus.Start(QUERY_INTERVAL);
  418. return true;
  419. }
  420. //----------------------------------Private Method-------------------------------
  421. //
  422. private void SerialPortDataReceived(string str)
  423. {
  424. if (string.IsNullOrEmpty(str))
  425. {
  426. EV.PostAlarmLog(Module, $"{_title} RFG 无数据反馈");
  427. return;
  428. }
  429. string str2 = str.Trim('\r');
  430. if (str2 == AdTecRfMessage.ERR_RES)
  431. {
  432. EV.PostWarningLog(Module, $"{_title} 收到 [{str2}]");
  433. return;
  434. }
  435. try
  436. {
  437. //LOG.Info($"{Module} Generator rec [{str2}]");
  438. Match match1 = Regex.Match(str2, INFO_PATTERN);
  439. if (!match1.Success)
  440. {
  441. //EV.PostWarningLog(Module, "AdTec 数据格式错误");
  442. if (!SC.GetValue<bool>("System.IsSimulatorMode"))
  443. {
  444. LOG.Write($"{Module}, {_title} 数据格式错误");
  445. }
  446. return;
  447. }
  448. string[] str1 =
  449. {
  450. match1.Groups[1].Value,
  451. match1.Groups[2].Value,
  452. match1.Groups[3].Value,
  453. match1.Groups[4].Value,
  454. match1.Groups[5].Value
  455. };
  456. this.ParseQueryData(str1);
  457. }
  458. catch (Exception ex)
  459. {
  460. LOG.Write(ex);
  461. }
  462. }
  463. private void ParseQueryData(string[] strInfo)
  464. {
  465. // Control mode
  466. string s2 = strInfo[0].Substring(0, 1);
  467. this.ControlMode = (EnumRfPowerControlMode)Convert.ToUInt16(s2);
  468. // output mode
  469. string s0 = strInfo[0].Substring(1, 1);
  470. this.WorkMode = (EnumRfPowerWorkMode)Convert.ToUInt16(s0);
  471. // ON/OFF
  472. char s1 = strInfo[0][2];
  473. if (s1 == '1')
  474. {
  475. Status = GeneratorStatus.ON;
  476. }
  477. else if (s1 == '0')
  478. {
  479. Status = GeneratorStatus.OFF;
  480. }
  481. string errCode = strInfo[0].Substring(5, 2);
  482. _ErrTrigger.CLK = errCode != "00";
  483. if (_ErrTrigger.Q)
  484. {
  485. string code = errCode == "88" ? "EEPROM or FPGA.... Error" :
  486. errCode == "99" ? "ITLK Error" :
  487. errCode == "26" ? "Humidity Alarm" :
  488. errCode == "05" ? "High Temperature Alarm" :
  489. errCode == "12" ? "Amplifier Unbalance" :
  490. errCode == "17" ? "Abnormal Power" : $"Unkown error code:{errCode}";
  491. if (!string.IsNullOrWhiteSpace(code))
  492. {
  493. if (errCode == "99")
  494. EV.PostInfoLog(Module, "Source Generator " + code);
  495. else
  496. EV.PostAlarmLog(Module, "Source Generator " + code);
  497. }
  498. }
  499. // forward power
  500. this.ForwardPower = Convert.ToUInt64(strInfo[2]);
  501. // reflect power
  502. this.ReflectPower = Convert.ToUInt64(strInfo[3]);
  503. }
  504. private void SerialPortErrorOccurred(string obj)
  505. {
  506. Status = GeneratorStatus.ERROR;
  507. EV.PostAlarmLog(Module, $"{_title} RFG serial port error, [{obj}]");
  508. }
  509. private bool SendCmd(string str)
  510. {
  511. if (str != AdTecRfMessage.QUERY)
  512. {
  513. EV.PostInfoLog(Module, $"{_title} Generator send [{str}]");
  514. }
  515. return _serial.Write(str + "\r");
  516. }
  517. }
  518. }