AdTecRF.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Concurrent;
  4. using System.Text.RegularExpressions;
  5. using Aitex.Core.Common.DeviceData;
  6. using Aitex.Core.RT.DataCenter;
  7. using Aitex.Core.RT.Event;
  8. using Aitex.Core.RT.IOCore;
  9. using Aitex.Core.RT.Log;
  10. using Aitex.Core.RT.OperationCenter;
  11. using Aitex.Core.RT.SCCore;
  12. using Aitex.Core.RT.Tolerance;
  13. using Aitex.Core.Util;
  14. using MECF.Framework.Common.Communications;
  15. using MECF.Framework.Common.DataCenter;
  16. using MECF.Framework.Common.Device.Bases;
  17. using MECF.Framework.Common.Equipment;
  18. using VirgoCommon;
  19. using VirgoRT.Modules;
  20. namespace VirgoRT.Devices
  21. {
  22. #region RFG
  23. static class AdTecRfMessage
  24. {
  25. public static string ANALOG = "";
  26. public const string EOF = "\r";
  27. public const char DELIMITER = ' ';
  28. public const string MANUAL = "MANUAL";
  29. public const string RS232 = "***";
  30. public const string SET_POWER = " W";
  31. public const string RF_ON = "G";
  32. public const string RF_OFF = "S";
  33. public const string ERR_RES = "N";
  34. public const string QUERY = "Q";
  35. public const string RESET = "RESET";
  36. public const string CHK_COMM = "HS";
  37. }
  38. class AdTecGenerator : RfPowerBase
  39. {
  40. // ----------------------------Fields--------------------------
  41. //
  42. private int QUERY_INTERVAL = 5000;
  43. private const string INFO_PATTERN = @"(\d{7})\s(\d{5})\s(\d{5})\s(\d{5})\s(\d{5})";
  44. private double _total;
  45. private double _fromLast;
  46. private bool _bRFPowerOn = false;
  47. private readonly AsyncSerialPort _serial;
  48. private readonly DeviceTimer _timerQueryStatus = new DeviceTimer();
  49. private readonly DeviceTimer _timerTotal = new DeviceTimer();
  50. private readonly DeviceTimer _timerFromLast = new DeviceTimer();
  51. private readonly DeviceTimer _timerRFTurnOn = new DeviceTimer();
  52. private DateTime _powerOnStartTime;
  53. private TimeSpan _powerOnElapsedTime;
  54. private readonly RD_TRIG _rfOnTrigger = new RD_TRIG();
  55. private readonly R_TRIG _ErrTrigger = new R_TRIG();
  56. private readonly R_TRIG _trigPMNeeded = new R_TRIG();
  57. private readonly RD_TRIG _trigOnOff = new RD_TRIG();
  58. private ToleranceChecker _checkerPower;
  59. private ToleranceChecker _checkerReflectPower;
  60. private readonly double _scPowerAlarmTime;
  61. private readonly double _scPowerAlarmRange;
  62. private readonly double _scReflectPowerAlarmTime;
  63. private readonly double _scReflectPowerAlarmRange;
  64. private readonly double _scPowerRange;
  65. private readonly DIAccessor _diIntlk;
  66. private StatsDataItemRFAndPump _statRFOnTime;
  67. // --------------------------Properties------------------------
  68. //
  69. public bool ConnectedStatus { get; set; }
  70. public override float ScalePower => (float)_scPowerRange;
  71. public GeneratorStatus Status { get; set; }
  72. public string LastPMTime
  73. {
  74. get
  75. {
  76. return _statRFOnTime != null ? _statRFOnTime.LastPMTime.ToString() : "";
  77. }
  78. }
  79. public double DaysFromLastPM
  80. {
  81. get
  82. {
  83. return _statRFOnTime == null ? 0 : _statRFOnTime.fromLastPM;
  84. }
  85. set
  86. {
  87. if (_statRFOnTime != null)
  88. _statRFOnTime.fromLastPM = value;
  89. }
  90. }
  91. public double TotalDays
  92. {
  93. get
  94. {
  95. return _statRFOnTime != null ? _statRFOnTime.Total : 0;
  96. }
  97. set
  98. {
  99. if (_statRFOnTime != null)
  100. _statRFOnTime.Total = value;
  101. }
  102. }
  103. public double PMIntervalDays
  104. {
  105. get
  106. {
  107. return _statRFOnTime != null ? _statRFOnTime.PMInterval : 0;
  108. }
  109. }
  110. public bool IsPMNeeded
  111. {
  112. get
  113. {
  114. return DaysFromLastPM > PMIntervalDays;
  115. }
  116. }
  117. public bool EnableAlarm
  118. {
  119. get
  120. {
  121. return _statRFOnTime == null || _statRFOnTime.AlarmEnable;
  122. }
  123. }
  124. public override bool IsPowerOn
  125. {
  126. get => Status == GeneratorStatus.ON;
  127. set { }
  128. }
  129. public override bool IsError
  130. {
  131. get => Status == GeneratorStatus.ERROR;
  132. set { }
  133. }
  134. [Subscription("PowerOnTime")]
  135. public string PowerOnTime
  136. {
  137. get
  138. {
  139. if (_bRFPowerOn)
  140. _powerOnElapsedTime = DateTime.Now - _powerOnStartTime;
  141. return $"{(int)_powerOnElapsedTime.TotalHours:00}:{_powerOnElapsedTime.Minutes:00}:{(_powerOnElapsedTime.Seconds > 0 ? (_powerOnElapsedTime.Seconds + 1) : 0):00}";
  142. }
  143. }
  144. public bool RFInterlock => _diIntlk == null || _diIntlk.Value;
  145. private float _forwardPower;
  146. public override float ForwardPower
  147. {
  148. get
  149. {
  150. return _forwardPower;
  151. }
  152. set
  153. {
  154. _forwardPower = CalibrationData(value, false);
  155. }
  156. }
  157. public new AITRfData DeviceData =>
  158. new AITRfData
  159. {
  160. Module = Module,
  161. DeviceName = Name,
  162. ScalePower = ScalePower,
  163. ForwardPower = ForwardPower,
  164. ReflectPower = ReflectPower,
  165. IsRfOn = IsPowerOn,
  166. PowerSetPoint = PowerSetPoint,
  167. PowerOnElapsedTime = PowerOnTime,
  168. IsInterlockOk = RFInterlock,
  169. WorkMode = (int)RfMode.ContinuousWaveMode,
  170. DisplayName ="Source RF",
  171. };
  172. // --------------------------Constructor-----------------------
  173. //
  174. public AdTecGenerator(ModuleName mod, string name = "Rf") : base(mod.ToString(), name)
  175. {
  176. var portNum = SC.GetStringValue($"{mod}.{name}.Port");
  177. this.Status = GeneratorStatus.Unknown;
  178. _serial = new AsyncSerialPort(portNum, 9600, 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One, "\r\r");
  179. _scPowerAlarmTime = SC.GetValue<double>($"{Module}.{Name}.PowerAlarmTime");
  180. _scPowerAlarmRange = SC.GetValue<double>($"{Module}.{Name}.PowerAlarmRange");
  181. _scReflectPowerAlarmTime = SC.GetValue<double>($"{Module}.{Name}.ReflectPowerAlarmTime");
  182. _scReflectPowerAlarmRange = SC.GetValue<double>($"{Module}.{Name}.ReflectPowerAlarmRange");
  183. _scPowerRange = SC.GetValue<double>($"{Module}.{Name}.PowerRange");
  184. _scEnableCalibration = SC.GetConfigItem($"{Module}.{Name}.EnableCalibration");
  185. _scCalibrationTable = SC.GetConfigItem($"{Module}.{Name}.CalibrationTable");
  186. _scRFPhysicalMaxPower = SC.GetConfigItem($"{Module}.{Name}.RFPhysicalMaxPower");
  187. _scCurrentRFMaxPower = SC.GetConfigItem($"{Module}.{Name}.CurrentRFMaxPower");
  188. _diIntlk = IO.DI[$"{Module}.DI_Generator_Hardware_Interlock"];
  189. }
  190. ~AdTecGenerator()
  191. {
  192. _serial?.Close();
  193. }
  194. public override bool Initialize()
  195. {
  196. ClearSendOrReceiveLog();
  197. base.Initialize();
  198. DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
  199. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetPowerOnOff}", (out string reason, int time, object[] param) =>
  200. {
  201. SetPowerOnOff(Convert.ToBoolean((string)param[0]), out reason);
  202. return true;
  203. });
  204. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetPower}", (out string reason, int time, object[] param) =>
  205. {
  206. reason = "";
  207. ushort val = Convert.ToUInt16(param[0]);
  208. SetPower(val);
  209. return true;
  210. });
  211. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetContinuousPower}", (out string reason, int time, object[] param) =>
  212. {
  213. reason = "";
  214. ushort val = Convert.ToUInt16(param[0]);
  215. SetPower(val);
  216. return true;
  217. });
  218. if (_serial.Open())
  219. {
  220. this.ConnectedStatus = true;
  221. _serial.OnDataChanged += SerialPortDataReceived;
  222. _serial.OnErrorHappened += SerialPortErrorOccurred;
  223. }
  224. else
  225. {
  226. this.ConnectedStatus = false;
  227. EV.PostAlarmLog(this.Module, "Open AD TEC serial port failed");
  228. return false;
  229. }
  230. _statRFOnTime = StatsDataManager.Instance.GetItemRFAndPump($"{Module}.RfOnTime");
  231. _timerQueryStatus.Start(QUERY_INTERVAL);
  232. _checkerPower = new ToleranceChecker(_scPowerAlarmTime);
  233. _checkerReflectPower = new ToleranceChecker(_scReflectPowerAlarmTime);
  234. SetCommunicationMode(1);
  235. return true;
  236. }
  237. public override void Monitor()
  238. {
  239. // 状态查询
  240. if (_timerQueryStatus.IsTimeout())
  241. {
  242. this.SendCmd(AdTecRfMessage.QUERY);
  243. _timerQueryStatus.Start(QUERY_INTERVAL);
  244. }
  245. // power on triggered
  246. _rfOnTrigger.CLK = IsPowerOn;
  247. if (_rfOnTrigger.R)
  248. {
  249. _total = TotalDays;
  250. _fromLast = DaysFromLastPM;
  251. _timerTotal.Start(0);
  252. _timerFromLast.Start(0);
  253. _powerOnStartTime = DateTime.Now;
  254. _checkerPower.Reset(_scPowerAlarmTime);
  255. _checkerReflectPower.Reset(_scReflectPowerAlarmTime);
  256. }
  257. if (_rfOnTrigger.M)
  258. {
  259. TotalDays = _total + _timerTotal.GetElapseTime() / 1000 / 60 / 60;
  260. DaysFromLastPM = _fromLast + _timerFromLast.GetElapseTime() / 1000 / 60 / 60;
  261. _checkerPower.Monitor(ForwardPower, PowerSetPoint - _scPowerAlarmRange, PowerSetPoint + _scPowerAlarmRange, _scPowerAlarmTime);
  262. if (_checkerPower.Trig)
  263. {
  264. EV.PostAlarmLog($"{Module}",
  265. $"{Display} Forward power {ForwardPower:0} out of range[{PowerSetPoint - _scPowerAlarmRange:0},{PowerSetPoint + _scPowerAlarmRange:0}] in {_scPowerAlarmTime:0} seconds");
  266. SetPowerOnOff(false, out _);
  267. }
  268. _checkerReflectPower.Monitor(ReflectPower, double.MinValue, _scReflectPowerAlarmRange, _scReflectPowerAlarmTime);
  269. if (_checkerReflectPower.Trig)
  270. {
  271. EV.PostAlarmLog($"{Module}",
  272. $"{Display} Reflect power {ReflectPower:0} out of range[0,{_scReflectPowerAlarmRange:0}] in {_scReflectPowerAlarmTime:0} seconds");
  273. SetPowerOnOff(false, out _);
  274. }
  275. }
  276. if (PMIntervalDays > 0)
  277. {
  278. _trigPMNeeded.CLK = IsPMNeeded;
  279. if (_trigPMNeeded.Q)
  280. {
  281. if (EnableAlarm)
  282. {
  283. EV.PostAlarmLog($"{Module}", "rf on time value larger than setting interval days");
  284. }
  285. }
  286. }
  287. if (_rfOnTrigger.T)
  288. StatsDataManager.Instance.Increase($"{Module}.RfOnTime", $"{Module} RfOnTime", DaysFromLastPM, TotalDays);
  289. if (!_rfOnTrigger.CLK)
  290. {
  291. ForwardPower = 0;
  292. ReflectPower = 0;
  293. }
  294. // 通信 checking, 2 second 一次
  295. //if (_timerComm.IsTimeout() && !_bQueryComm)
  296. //{
  297. // this.SendCmd(AdTecRfMessage.CHK_COMM);
  298. // _bQueryComm = true;
  299. // _timerComm.Start(CHK_COMM_INTERVAL);
  300. //}
  301. // RF Turn On & Off Timeout Check
  302. _trigOnOff.CLK = _bRFPowerOn;
  303. if (_trigOnOff.R) //RF Turn On
  304. {
  305. _timerRFTurnOn.Start(SC.GetValue<int>($"{Module}.Rf.RFTurnOnTimeout") * 1000);
  306. }
  307. if (_trigOnOff.M) //RF Stay On
  308. {
  309. if (_timerRFTurnOn.IsTimeout())
  310. {
  311. if (!IsPowerOn)
  312. {
  313. string sendOrReceivelog = string.Join("\r", _sendOrReceiveLog.ToArray());
  314. ClearSendOrReceiveLog();
  315. EV.PostInfoLog(Module, $"RF Turn On Failed logs, {sendOrReceivelog}");
  316. EV.PostAlarmLog($"{Module}", "RF Turn On Failed");
  317. _timerRFTurnOn.Stop();
  318. }
  319. }
  320. }
  321. if (_trigOnOff.T)
  322. {
  323. _timerRFTurnOn.Stop();
  324. }
  325. base.Monitor();
  326. }
  327. public override void Terminate()
  328. {
  329. _serial?.Close();
  330. }
  331. public override void Reset()
  332. {
  333. _rfOnTrigger.RST = true;
  334. _ErrTrigger.RST = true;
  335. _trigPMNeeded.RST = true;
  336. this.SendCmd(AdTecRfMessage.RESET);
  337. this.Status = GeneratorStatus.OFF;
  338. _bRFPowerOn = false;
  339. ClearSendOrReceiveLog();
  340. }
  341. public void SetRfMode(RfMode mode)
  342. {
  343. throw new NotImplementedException();
  344. }
  345. public override void SetCommunicationMode(int mode)
  346. {
  347. CommunicationType t1 = (CommunicationType)mode;
  348. switch (t1)
  349. {
  350. case CommunicationType.Analogue:
  351. this.SendCmd(AdTecRfMessage.ANALOG);
  352. break;
  353. case CommunicationType.RS232:
  354. this.SendCmd(AdTecRfMessage.RS232);
  355. break;
  356. default:
  357. throw new ArgumentOutOfRangeException("Communication mode error");
  358. }
  359. }
  360. public override void SetPower(float val)
  361. {
  362. if (!(this.ControlMode == EnumRfPowerControlMode.RS232Mode)) SetCommunicationMode(1);
  363. ushort a = !_scEnableCalibration.BoolValue ? (ushort)val : (ushort)CalibrationData(val, true);
  364. if (SendCmd($"{a:D4}{AdTecRfMessage.SET_POWER}"))
  365. {
  366. PowerSetPoint = val;
  367. }
  368. }
  369. public override bool SetPowerOnOff(bool on, out string str)
  370. {
  371. if (!(this.ControlMode == EnumRfPowerControlMode.RS232Mode)) SetCommunicationMode(1);
  372. str = "";
  373. if (on)
  374. {
  375. SendCmd(AdTecRfMessage.RF_ON);
  376. _bRFPowerOn = true;
  377. _powerOnStartTime = DateTime.Now;
  378. QUERY_INTERVAL = 500;
  379. }
  380. else
  381. {
  382. SendCmd(AdTecRfMessage.RF_OFF);
  383. _bRFPowerOn = false;
  384. ForwardPower = 0;
  385. ReflectPower = 0;
  386. QUERY_INTERVAL = 500;
  387. _ErrTrigger.RST = true;
  388. }
  389. _timerQueryStatus.Start(QUERY_INTERVAL);
  390. return true;
  391. }
  392. //----------------------------------Private Method-------------------------------
  393. //
  394. private void SerialPortDataReceived(string str)
  395. {
  396. if (string.IsNullOrEmpty(str))
  397. {
  398. EV.PostAlarmLog(Module, "AdTec RFG receive message is empty");
  399. return;
  400. }
  401. string str2 = str.Trim('\r');
  402. AppendSendOrReceiveLog("Receive", str2);
  403. if (str2 == AdTecRfMessage.ERR_RES)
  404. {
  405. EV.PostWarningLog(Module, $"AdTEC receive [{str2}]");
  406. return;
  407. }
  408. try
  409. {
  410. //LOG.Info($"{Module} Generator rec [{str2}]");
  411. Match match1 = Regex.Match(str2, INFO_PATTERN);
  412. if (!match1.Success)
  413. {
  414. //EV.PostWarningLog(Module, "AdTec 数据格式错误");
  415. if (!SC.GetValue<bool>("System.IsSimulatorMode"))
  416. {
  417. LOG.Write($"{Module}, AdTec 数据格式错误");
  418. }
  419. return;
  420. }
  421. string[] str1 =
  422. {
  423. match1.Groups[1].Value,
  424. match1.Groups[2].Value,
  425. match1.Groups[3].Value,
  426. match1.Groups[4].Value,
  427. match1.Groups[5].Value
  428. };
  429. this.ParseQueryData(str1);
  430. }
  431. catch (Exception ex)
  432. {
  433. LOG.Write(ex);
  434. }
  435. }
  436. private void ParseQueryData(string[] strInfo)
  437. {
  438. // Control mode
  439. string s2 = strInfo[0].Substring(0, 1);
  440. this.ControlMode = (EnumRfPowerControlMode)Convert.ToUInt16(s2);
  441. // output mode
  442. string s0 = strInfo[0].Substring(1, 1);
  443. this.WorkMode = (EnumRfPowerWorkMode)Convert.ToUInt16(s0);
  444. // ON/OFF
  445. char s1 = strInfo[0][2];
  446. if (s1 == '1')
  447. {
  448. Status = GeneratorStatus.ON;
  449. }
  450. else if (s1 == '0')
  451. {
  452. Status = GeneratorStatus.OFF;
  453. }
  454. // error code
  455. string alarm = strInfo[0].Substring(5, 2);
  456. byte errCode = Convert.ToByte(alarm);
  457. _ErrTrigger.CLK = errCode > 0;
  458. if (_ErrTrigger.Q)
  459. {
  460. string code = errCode == 1 ? "Ref Over" :
  461. errCode == 2 ? "Ref Limit" :
  462. errCode == 3 ? "Cur Over" :
  463. errCode == 4 ? "Cur Limit" :
  464. errCode == 5 ? "Temp Over" :
  465. errCode == 6 ? "Temp Sensor Short" :
  466. errCode == 7 ? "Temp Sensor Open" :
  467. errCode == 8 ? "Sensor Error" :
  468. errCode == 9 ? "Fwd Power Over" :
  469. errCode == 10 ? "RF ON Timer" :
  470. errCode == 11 ? "RS232C error" :
  471. errCode == 12 ? "Amp Unbalance" :
  472. errCode == 14 ? "Fan error" :
  473. errCode == 15 ? "Coolant Error" :
  474. errCode == 16 ? "Voltage Error" :
  475. errCode == 17 ? "Fwd Power Down" :
  476. errCode == 22 ? "PD Over" :
  477. errCode == 23 ? "PD Limit" :
  478. errCode == 26 ? "Dew Condensation" :
  479. errCode == 29 ? "SW Failure" :
  480. errCode == 99 ? "Safety Lock" : string.Empty;
  481. if (!string.IsNullOrEmpty(code))
  482. {
  483. if (errCode == 99)
  484. EV.PostInfoLog(Module, "Source Generator " + code);
  485. else
  486. EV.PostAlarmLog(Module, "Source Generator " + code);
  487. }
  488. }
  489. // forward power
  490. this.ForwardPower = Convert.ToUInt64(strInfo[2]);
  491. // reflect power
  492. this.ReflectPower = Convert.ToUInt64(strInfo[3]);
  493. }
  494. private void SerialPortErrorOccurred(string obj)
  495. {
  496. Status = GeneratorStatus.ERROR;
  497. EV.PostAlarmLog(Module, $"AdTec RFG serial port error, [{obj}]");
  498. }
  499. private ConcurrentQueue<string> _sendOrReceiveLog = new ConcurrentQueue<string>();
  500. private void AppendSendOrReceiveLog(string sendOrRecFlag, string content)
  501. {
  502. var count = _sendOrReceiveLog.Count;
  503. for (var i= count; i > 99; i--)
  504. {
  505. _sendOrReceiveLog.TryDequeue(out string _);
  506. }
  507. _sendOrReceiveLog.Enqueue($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} {sendOrRecFlag} [{content}]");
  508. }
  509. private void ClearSendOrReceiveLog()
  510. {
  511. if(!_sendOrReceiveLog.IsEmpty)
  512. {
  513. var count = _sendOrReceiveLog.Count;
  514. for (var i = 0; i < count; i++)
  515. {
  516. _sendOrReceiveLog.TryDequeue(out string _);
  517. }
  518. }
  519. }
  520. private bool SendCmd(string str)
  521. {
  522. if (str != AdTecRfMessage.QUERY)
  523. {
  524. EV.PostInfoLog(Module, $"Generator send [{str}]");
  525. }
  526. AppendSendOrReceiveLog("Send", str);
  527. return _serial.Write(str + "\r");
  528. }
  529. }
  530. #endregion RFG
  531. #region match
  532. static class AdTecMatchMessage
  533. {
  534. public const string PRESET = "G";
  535. public const string AUTO = "L";
  536. public const string MANUAL = "M";
  537. public const string PRESET_MEM = "P";
  538. public const string START_QUERY = "S3";
  539. public const string STOP_QUERY = "SP";
  540. public const string WRITE_POS = "$APGR";
  541. public const string READ_POS = "$APRR";
  542. }
  543. class AdTecMatch : RfMatchBase
  544. {
  545. // ----------------------------Fields--------------------------
  546. //
  547. private readonly AsyncSerialPort _serial;
  548. private const ushort S3_HEAD_LENGTH = 2;
  549. private readonly DeviceTimer _timerQueryStatus = new DeviceTimer();
  550. private int QUERY_INTERVAL = 1000;
  551. //private int _scMatchPresetMode;
  552. //private int _scMatchMode;
  553. //private readonly SCConfigItem _scMatchPositionC1;
  554. //private readonly SCConfigItem _scMatchPositionC2;
  555. //private readonly bool _scEnableC1C2Position;
  556. // --------------------------Properties------------------------
  557. //
  558. [Subscription("MatchWorkMode")]
  559. public EnumRfMatchTuneMode WorkMode { get; set; }
  560. public float C1 { get; set; }
  561. public float C2 { get; set; }
  562. [Subscription("VPP")]
  563. public ushort VPP { get; set; }
  564. public override AITRfMatchData DeviceData
  565. {
  566. get
  567. {
  568. return new AITRfMatchData
  569. {
  570. };
  571. }
  572. }
  573. // --------------------------Constructor-----------------------
  574. //
  575. public AdTecMatch(ModuleName mod) : base(mod.ToString(), VirgoDevice.Match.ToString())
  576. {
  577. var portNum = SC.GetStringValue($"{mod}.match.Port");
  578. _serial = new AsyncSerialPort(portNum, 9600, 8);
  579. //_scMatchPresetMode = SC.GetValue<int>($"{Module}.Rf.PresetMode");
  580. //_scMatchMode = SC.GetValue<int>($"{Module}.Rf.MatchMode");
  581. //_scMatchPositionC1 = SC.GetConfigItem($"{Module}.Rf.MatchPositionC1");
  582. //_scMatchPositionC2 = SC.GetConfigItem($"{Module}.Rf.MatchPositionC2");
  583. //_scEnableC1C2Position = SC.GetValue<bool>($"{Module}.Rf.EnableC1C2Position");
  584. }
  585. ~AdTecMatch()
  586. {
  587. _serial?.Close();
  588. }
  589. public override bool Initialize()
  590. {
  591. base.Initialize();
  592. if (_serial.Open())
  593. {
  594. _serial.OnDataChanged += SerialPortDataReceived;
  595. _serial.OnErrorHappened += SerialPortErrorOccurred;
  596. }
  597. else
  598. {
  599. EV.PostAlarmLog(Module, "Open match serial port failed");
  600. return false;
  601. }
  602. DATA.Subscribe($"{Module}.{Name}.C1", () => C1);
  603. DATA.Subscribe($"{Module}.{Name}.C2", () => C2);
  604. OP.Subscribe($"{Module}.{Name}.SetC1", (func, args) =>
  605. {
  606. return true;
  607. });
  608. OP.Subscribe($"{Module}.{Name}.SetC2", (func, args) =>
  609. {
  610. return true;
  611. });
  612. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPositionC1}", (out string reason, int time, object[] param) =>
  613. {
  614. SetMatchPositionC1((float)Convert.ToDouble(param[0]), out reason);
  615. return true;
  616. });
  617. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPositionC2}", (out string reason, int time, object[] param) =>
  618. {
  619. SetMatchPositionC2((float)Convert.ToDouble(param[0]), out reason);
  620. return true;
  621. });
  622. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPosition}", (out string reason, int time, object[] param) =>
  623. {
  624. SetMatchPosition((float)Convert.ToDouble(param[0]), (float)Convert.ToDouble(param[1]), out reason);
  625. return true;
  626. });
  627. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchProcessMode}", (out string reason, int time, object[] param) =>
  628. {
  629. SetMatchMode((string)param[0], out reason);
  630. return true;
  631. });
  632. _timerQueryStatus.Start(QUERY_INTERVAL);
  633. this.SendCmd(AdTecMatchMessage.START_QUERY);
  634. return true;
  635. }
  636. public override void Monitor()
  637. {
  638. try
  639. {
  640. if (_timerQueryStatus.IsTimeout())
  641. {
  642. this.SendCmd(AdTecMatchMessage.READ_POS);
  643. _timerQueryStatus.Start(QUERY_INTERVAL);
  644. }
  645. }
  646. catch (Exception ex)
  647. {
  648. LOG.Write(ex);
  649. }
  650. }
  651. public override void Terminate()
  652. {
  653. this.SendCmd(AdTecMatchMessage.STOP_QUERY);
  654. }
  655. public override void Reset()
  656. {
  657. //SendCmd(AdTecMatchMessage.STOP_QUERY);
  658. }
  659. /// <summary>
  660. ///
  661. /// </summary>
  662. /// <param name="c1,c2">百分比数字</param>
  663. /// <param name="c2"></param>
  664. public override void SetMatchPosition(float c1, float c2, out string reason)
  665. {
  666. //base.SetMatchPosition(c1, c2, out reason);
  667. ////this.SetWorkMode(EnumRfMatchTuneMode.Manual);
  668. //this.SetPosition(c1, c2);
  669. ////this.SetPresetMemory(0);
  670. ////this.SetWorkMode(EnumRfMatchTuneMode.Auto);
  671. //TunePosition1 = c1;
  672. //TunePosition2 = c2;
  673. reason = "";
  674. }
  675. public void SetPresetMode(RfMatchPresetMode mode)
  676. {
  677. }
  678. // -----------------------Private Method-------------------------
  679. //
  680. private void SerialPortDataReceived(string strOrg)
  681. {
  682. if (string.IsNullOrWhiteSpace(strOrg))
  683. {
  684. EV.PostAlarmLog(Module, "Match receive message is empty");
  685. return;
  686. }
  687. string[] sContent = strOrg.Split('\r');
  688. foreach (var sItem in sContent)
  689. {
  690. string sItem1 = sItem.TrimStart('\n');
  691. if (sItem1.Contains(AdTecMatchMessage.START_QUERY))
  692. {
  693. // BYTE 3,4; bit 7
  694. string s0 = sItem1.Substring(2 + S3_HEAD_LENGTH, 2);
  695. ushort status0 = Convert.ToUInt16(s0);
  696. byte[] a1 = BitConverter.GetBytes(status0);
  697. BitArray ba1 = new BitArray(a1);
  698. this.WorkMode = ba1[7] ? EnumRfMatchTuneMode.Manual : EnumRfMatchTuneMode.Auto;
  699. TuneMode1 = WorkMode;
  700. TuneMode2 = WorkMode;
  701. string sVpp = sItem1.Substring(42 + S3_HEAD_LENGTH, 3);
  702. this.VPP = Convert.ToUInt16(sVpp, 16);
  703. }
  704. else if (sItem1.Contains(AdTecMatchMessage.READ_POS))
  705. {
  706. string s1 = sItem1.Substring(5);
  707. string sLoad = s1.Substring(0, 3);
  708. string sPhase = s1.Substring(3, 3);
  709. this.TunePosition1 = Convert.ToUInt64(sLoad, 16) * 0.1f;
  710. this.TunePosition2 = Convert.ToUInt64(sPhase, 16) * 0.1f;
  711. }
  712. }
  713. }
  714. private void SerialPortErrorOccurred(string str)
  715. {
  716. EV.PostAlarmLog(Module, $"AdTec Match error [{str}]");
  717. }
  718. private void SendCmd(string str)
  719. {
  720. _serial?.Write(str + "\r");
  721. //EV.PostInfoLog(Module.ToString(), $"Match send [{str}]");
  722. }
  723. private void SetPosition(float c1val, float c2val)
  724. {
  725. ushort val1 = (ushort)(c1val * 10);
  726. ushort val2 = (ushort)(c2val * 10);
  727. string cmd = AdTecMatchMessage.WRITE_POS + val1.ToString("X3") + val2.ToString("X3");
  728. this.SendCmd(cmd);
  729. }
  730. private void SetWorkMode(EnumRfMatchTuneMode mode)
  731. {
  732. this.SendCmd(mode == EnumRfMatchTuneMode.Auto ? AdTecMatchMessage.AUTO :
  733. mode == EnumRfMatchTuneMode.Manual ? AdTecMatchMessage.MANUAL : "");
  734. }
  735. private void SetPresetMemory(byte gear)
  736. {
  737. this.SendCmd(AdTecMatchMessage.PRESET_MEM + gear.ToString());
  738. }
  739. }
  740. #endregion match
  741. }