TemperatureControllerSerialPortDevice.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. using Aitex.Common.Util;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.Util;
  4. using MECF.Framework.Common.Device.TemperatureController;
  5. using MECF.Framework.Simulator.Core.Driver;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Diagnostics;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Threading.Tasks;
  13. namespace MECF.Framework.Simulator.Core.Commons
  14. {
  15. public class TemperatureControllerSerialPortDevice : BaseSerialSimulator
  16. {
  17. #region 常量
  18. private const string PORT_NAME = "com12";
  19. private const byte ADD_FLAG = 0x30;
  20. #endregion
  21. #region 内部变量
  22. /// <summary>
  23. /// 控制字字典
  24. /// </summary>
  25. private Dictionary<byte, string> dic = new Dictionary<byte, string>()
  26. {
  27. { 0x05,"ENQ" },
  28. { 0x02,"STX" },
  29. { 0x03,"ETX" },
  30. { 0x06,"ACK" },
  31. { 0x0D,"CR" },
  32. { 0x01,"SOH" }
  33. };
  34. /// <summary>
  35. /// 命令字典
  36. /// </summary>
  37. private Dictionary<byte, string> comdic = new Dictionary<byte, string>()
  38. {
  39. { 0x31,"Target Temp" },
  40. { 0x32,"Internal" },
  41. { 0x33,"External" },
  42. { 0x34,"Alarm" },
  43. { 0x35,"Average" },
  44. { 0x36,"offset" },
  45. { 0x39,"control" },
  46. { 0x41,"PB" },
  47. { 0x42,"ARW" },
  48. { 0x43,"IConstant" },
  49. { 0x44,"DConstant" },
  50. { 0x45,"OutPutRatio" },
  51. { 0x46,"HeatingLimit" },
  52. { 0x47,"CoolingLimit" },
  53. { 0x48,"Saved" }
  54. };
  55. private double[] _reserviorValues = new double[10];
  56. private double[] _heatValues = new double[10];
  57. private double[] _targetValues = new double[10];
  58. private int _controlOperation = 0;
  59. //private byte[] alarm = new byte[12] { 0,0,0,0,1,0,0,0,0,0,0,0};
  60. private byte[] alarm = new byte[3] {0x30,0x33,0x30};
  61. System.Timers.Timer[] _timers;
  62. private int _tcCount = 4;
  63. #endregion
  64. /// <summary>
  65. /// 构造函数
  66. /// </summary>
  67. /// <param name="portName"></param>
  68. /// <param name="type"></param>
  69. public TemperatureControllerSerialPortDevice(string port) : base(port, SerialType.BUFFER)
  70. {
  71. Init(port);
  72. }
  73. /// <summary>
  74. /// 初始化
  75. /// </summary>
  76. /// <param name="port"></param>
  77. private void Init(string port)
  78. {
  79. //加载TC配置
  80. try
  81. {
  82. string oldXmlPath = PathManager.GetCfgDir();
  83. string newXmlPath = oldXmlPath.Replace("CyberX8_Simulator", "CyberX8_RT") + "Devices\\SMCCfg.xml";
  84. TemperatureConfig cfg = CustomXmlSerializer.Deserialize<TemperatureConfig>(new FileInfo(newXmlPath));
  85. if (cfg != null)
  86. {
  87. foreach (TemperatureDeviceConfig config in cfg.TemperatureDeviceConfigs)
  88. {
  89. if (int.TryParse(config.Port.Substring(3,2), out int result1) && int.TryParse(port.Substring(3, 2), out int result2))
  90. {
  91. if(result1 + 1 == result2) _tcCount = config.TemperatureDevices.Count;
  92. }
  93. }
  94. }
  95. }
  96. catch (Exception ex)
  97. {
  98. }
  99. _timers = new System.Timers.Timer[_tcCount];
  100. for(int i = 0; i < _tcCount; i++)
  101. {
  102. _heatValues[i] = 16.5;
  103. _targetValues[i] = 0;
  104. _reserviorValues[i] = 16.6;
  105. _timers[i] = new System.Timers.Timer(50);
  106. switch (i)
  107. {
  108. case 0:
  109. _timers[0].Elapsed += Timer_Elapsed0;
  110. break;
  111. case 1:
  112. _timers[1].Elapsed += Timer_Elapsed1;
  113. break;
  114. case 2:
  115. _timers[2].Elapsed += Timer_Elapsed2;
  116. break;
  117. case 3:
  118. _timers[3].Elapsed += Timer_Elapsed3;
  119. break;
  120. case 4:
  121. _timers[4].Elapsed += Timer_Elapsed4;
  122. break;
  123. default:
  124. break;
  125. }
  126. }
  127. }
  128. /// <summary>
  129. /// TC1-1的调温
  130. /// </summary>
  131. /// <param name="sender"></param>
  132. /// <param name="e"></param>
  133. private void Timer_Elapsed0(object sender, System.Timers.ElapsedEventArgs e)
  134. {
  135. if (Math.Abs(_heatValues[0] - _targetValues[0]) >= 0.2)
  136. {
  137. //内部调温
  138. if (_heatValues[0] < _targetValues[0])
  139. {
  140. _heatValues[0] += 0.1;
  141. }
  142. else
  143. {
  144. _heatValues[0] -= 0.1;
  145. }
  146. //外部调温
  147. if (_reserviorValues[0] < _targetValues[0])
  148. {
  149. _reserviorValues[0] += 0.1;
  150. }
  151. else
  152. {
  153. _reserviorValues[0] -= 0.1;
  154. }
  155. }
  156. else
  157. {
  158. _timers[0].Stop();
  159. }
  160. }
  161. /// <summary>
  162. /// TC1-2的调温
  163. /// </summary>
  164. /// <param name="sender"></param>
  165. /// <param name="e"></param>
  166. private void Timer_Elapsed1(object sender, System.Timers.ElapsedEventArgs e)
  167. {
  168. if (Math.Abs(_heatValues[1] - _targetValues[1]) >= 0.2)
  169. {
  170. //内部调温
  171. if (_heatValues[1] < _targetValues[1])
  172. {
  173. _heatValues[1] += 0.1;
  174. }
  175. else
  176. {
  177. _heatValues[1] -= 0.1;
  178. }
  179. //外部调温
  180. if (_reserviorValues[1] < _targetValues[1])
  181. {
  182. _reserviorValues[1] += 0.1;
  183. }
  184. else
  185. {
  186. _reserviorValues[1] -= 0.1;
  187. }
  188. }
  189. else
  190. {
  191. _timers[1].Stop();
  192. }
  193. }
  194. /// <summary>
  195. /// TC1-3的调温
  196. /// </summary>
  197. /// <param name="sender"></param>
  198. /// <param name="e"></param>
  199. private void Timer_Elapsed2(object sender, System.Timers.ElapsedEventArgs e)
  200. {
  201. if (Math.Abs(_heatValues[2] - _targetValues[2]) >= 0.2)
  202. {
  203. //内部调温
  204. if (_heatValues[2] < _targetValues[2])
  205. {
  206. _heatValues[2] += 0.1;
  207. }
  208. else
  209. {
  210. _heatValues[2] -= 0.1;
  211. }
  212. //外部调温
  213. if (_reserviorValues[2] < _targetValues[2])
  214. {
  215. _reserviorValues[2] += 0.1;
  216. }
  217. else
  218. {
  219. _reserviorValues[2] -= 0.1;
  220. }
  221. }
  222. else
  223. {
  224. _timers[2].Stop();
  225. }
  226. }
  227. /// <summary>
  228. /// TC1-4的调温
  229. /// </summary>
  230. /// <param name="sender"></param>
  231. /// <param name="e"></param>
  232. private void Timer_Elapsed3(object sender, System.Timers.ElapsedEventArgs e)
  233. {
  234. if (Math.Abs(_heatValues[3] - _targetValues[3]) >= 0.2)
  235. {
  236. //内部调温
  237. if (_heatValues[3] < _targetValues[3])
  238. {
  239. _heatValues[3] += 0.1;
  240. }
  241. else
  242. {
  243. _heatValues[3] -= 0.1;
  244. }
  245. //外部调温
  246. if (_reserviorValues[3] < _targetValues[3])
  247. {
  248. _reserviorValues[3] += 0.1;
  249. }
  250. else
  251. {
  252. _reserviorValues[3] -= 0.1;
  253. }
  254. }
  255. else
  256. {
  257. _timers[3].Stop();
  258. }
  259. }
  260. /// <summary>
  261. /// TC1-5的调温
  262. /// </summary>
  263. /// <param name="sender"></param>
  264. /// <param name="e"></param>
  265. private void Timer_Elapsed4(object sender, System.Timers.ElapsedEventArgs e)
  266. {
  267. if (Math.Abs(_heatValues[4] - _targetValues[4]) >= 0.2)
  268. {
  269. //内部调温
  270. if (_heatValues[4] < _targetValues[4])
  271. {
  272. _heatValues[4] += 0.1;
  273. }
  274. else
  275. {
  276. _heatValues[4] -= 0.1;
  277. }
  278. //外部调温
  279. if (_reserviorValues[4] < _targetValues[4])
  280. {
  281. _reserviorValues[4] += 0.1;
  282. }
  283. else
  284. {
  285. _reserviorValues[4] -= 0.1;
  286. }
  287. }
  288. else
  289. {
  290. _timers[4].Stop();
  291. }
  292. }
  293. protected override string MessageConvert(byte[] byt)
  294. {
  295. string str = "";
  296. for(int i=0;i<byt.Length;i++)
  297. {
  298. byte item = byt[i];
  299. if(dic.ContainsKey(item))
  300. {
  301. str += dic[item];
  302. }
  303. else if(i==1)
  304. {
  305. str += (item - 0x30).ToString("D2");
  306. }
  307. else if(i==3&&comdic.ContainsKey(item))
  308. {
  309. str += comdic[item];
  310. }
  311. else
  312. {
  313. str += item.ToString("X2");
  314. }
  315. str += " ";
  316. }
  317. return str;
  318. }
  319. protected override void ProcessMessageBuffer(byte[] data)
  320. {
  321. if (data[0] == 0x06 && data[2]==0x0D&&data.Length>7)
  322. {
  323. byte[] byt = new byte[data.Length - 3];
  324. Array.Copy(data, 3, byt, 0, byt.Length);
  325. ProcessNormalCommand(byt);
  326. }
  327. else if (data[0] == 0x01)
  328. {
  329. ProcessNormalCommand(data);
  330. }
  331. }
  332. private void ProcessNormalCommand(byte[] data)
  333. {
  334. if (data[0] == 0x01 && data[data.Length-1]==0x0D)
  335. {
  336. if (data.Length == 7)
  337. {
  338. ProcessReadCommand(data);
  339. }
  340. else if (data.Length > 7)
  341. {
  342. ProcessSetCommand(data);
  343. }
  344. }
  345. }
  346. private void ProcessReadCommand(byte[] data)
  347. {
  348. switch(data[3])
  349. {
  350. case 0x31:
  351. ReadTargetValue(data);
  352. break;
  353. case 0x32:
  354. ReadReserviorValue(data);
  355. break;
  356. case 0x33:
  357. ReadHeatValue(data);
  358. break;
  359. case 0x34:
  360. ReadAlarmValue(data);
  361. break;
  362. case 0x39:
  363. ReadControlOperationValue(data);
  364. break;
  365. }
  366. }
  367. private void ProcessSetCommand(byte[] data)
  368. {
  369. switch(data[3])
  370. {
  371. case 0x31:
  372. _targetValues[data[1] - ADD_FLAG - 1] = (data[4] - ADD_FLAG) * 10 + (data[5] - ADD_FLAG) + (data[6]-ADD_FLAG)*0.1;
  373. _timers[data[1] - ADD_FLAG -1].Start();
  374. break;
  375. case 0x39:
  376. _controlOperation = data[7] - ADD_FLAG;
  377. if(_controlOperation == 0)
  378. {
  379. //停止调温
  380. _timers[data[1] - ADD_FLAG - 1].Stop();
  381. }
  382. else
  383. {
  384. //继续调温
  385. _timers[data[1] - ADD_FLAG - 1].Start();
  386. }
  387. break;
  388. }
  389. WriteConfirmData(data[1]);
  390. }
  391. /// <summary>
  392. /// 回复确认
  393. /// </summary>
  394. /// <param name="id"></param>
  395. private void WriteConfirmData(byte id)
  396. {
  397. byte[] confirm = new byte[3];
  398. confirm[0] = 0x06;
  399. confirm[1] = id;
  400. confirm[2] = 0x0d;
  401. WriteBuffer(confirm);
  402. }
  403. private void ReadTargetValue(byte[] data)
  404. {
  405. byte[] byt = new byte[12];
  406. byt[0] = data[0];
  407. byt[1] = data[1];
  408. byt[2] = 0x02;
  409. byt[3] = data[3];
  410. byte[] decadeByte = GetDecadeBytes(_targetValues[data[1] - ADD_FLAG - 1]);
  411. Array.Copy(decadeByte, 0, byt, 4, decadeByte.Length);
  412. byt[5 + decadeByte.Length] = 0;
  413. byt[6 + decadeByte.Length] = 0;
  414. byt[11] = 0x0D;
  415. WriteBuffer(byt);
  416. }
  417. private void ReadReserviorValue(byte[] data)
  418. {
  419. byte[] byt = new byte[12];
  420. byt[0] = data[0];
  421. byt[1] = data[1];
  422. byt[2] = 0x02;
  423. byt[3] = data[3];
  424. byte[] decadeByte = GetDecadeBytes(_reserviorValues[data[1] - ADD_FLAG - 1]);
  425. Array.Copy(decadeByte, 0, byt, 4, decadeByte.Length);
  426. byt[5 + decadeByte.Length] = 0;
  427. byt[6 + decadeByte.Length] = 0;
  428. byt[11] = 0x0D;
  429. WriteBuffer(byt);
  430. }
  431. private void ReadHeatValue(byte[] data)
  432. {
  433. byte[] byt = new byte[12];
  434. byt[0] = data[0];
  435. byt[1] = data[1];
  436. byt[2] = 0x02;
  437. byt[3] = data[3];
  438. byte[] decadeByte = GetDecadeBytes(_heatValues[data[1] - ADD_FLAG - 1]);
  439. Array.Copy(decadeByte, 0, byt, 4, decadeByte.Length);
  440. byt[5 + decadeByte.Length] = 0;
  441. byt[6 + decadeByte.Length] = 0;
  442. byt[11] = 0x0D;
  443. WriteBuffer(byt);
  444. }
  445. private void ReadControlOperationValue(byte[] data)
  446. {
  447. byte[] byt = new byte[12];
  448. byt[0] = data[0];
  449. byt[1] = data[1];
  450. byt[2] = 0x02;
  451. byt[3] = data[3];
  452. byte[] decadeByte = GetKilloBytes(_controlOperation);
  453. Array.Copy(decadeByte, 0, byt, 4, decadeByte.Length);
  454. byt[5 + decadeByte.Length] = 0;
  455. byt[6 + decadeByte.Length] = 0;
  456. byt[11] = 0x0D;
  457. WriteBuffer(byt);
  458. }
  459. private void ReadAlarmValue(byte[] data)
  460. {
  461. byte[] byt = new byte[8+alarm.Length];
  462. byt[0] = data[0];
  463. byt[1] = data[1];
  464. byt[2] = 0x02;
  465. byt[3] = data[3];
  466. Array.Copy(alarm, 0, byt, 4, alarm.Length);
  467. byt[5 + alarm.Length] = 0;
  468. byt[6 + alarm.Length] = 0;
  469. byt[7+alarm.Length] = 0x0D;
  470. WriteBuffer(byt);
  471. }
  472. /// <summary>
  473. /// 获取温度数组(10|1|0.1|0.01)
  474. /// </summary>
  475. /// <param name="temperature"></param>
  476. /// <returns></returns>
  477. private byte[] GetDecadeBytes(double temperature)
  478. {
  479. byte decade = GetSendByteData((byte)Math.Floor(temperature / 10));
  480. byte unit = GetSendByteData((byte)Math.Floor(temperature % 10));
  481. byte digital = GetSendByteData((byte)Math.Floor(temperature * 10 % 10));
  482. return new byte[4] { decade, unit, digital, ADD_FLAG };
  483. }
  484. /// <summary>
  485. /// 获取千级数组(1000|100|10|1)
  486. /// </summary>
  487. /// <param name="temperature"></param>
  488. /// <returns></returns>
  489. private byte[] GetKilloBytes(double temperature)
  490. {
  491. byte kilo = GetSendByteData((byte)Math.Floor(temperature / 1000));
  492. byte hundred = GetSendByteData((byte)Math.Floor(temperature % 1000/100));
  493. byte decade = GetSendByteData((byte)Math.Floor(temperature % 100 / 10));
  494. byte unit = GetSendByteData((byte)Math.Floor(temperature % 10));
  495. return new byte[4] { kilo, hundred, decade, unit };
  496. }
  497. /// <summary>
  498. /// 获取发送位数据
  499. /// </summary>
  500. /// <param name="originalData"></param>
  501. /// <returns></returns>
  502. private byte GetSendByteData(byte originalData)
  503. {
  504. return (byte)(ADD_FLAG + originalData);
  505. }
  506. }
  507. }